The Grammar¶
Timepiece is based off an EBNF grammar using the awesome parsimonious library.
The idea is that the grammar parses the specification into arbitrary sections
and then we turn those arbitrary sections into objects using the sections
specified in timepiece.sections
. As in, the definition of the grammar and
the definition of the valid sections and their arguments are separate.
The grammar can be seen below:
EBNF grammar¶
time_spec = grouped_funcs?
grouped_funcs = grouped_funcs_first grouped_with_joiner*
grouped_with_joiner = joiner grouped_funcs
grouped_funcs_first = wrapped_grouped_funcs / func
wrapped_grouped_funcs = start_bracket grouped_funcs end_bracket
func = func_name "(" func_sig ")"
func_sig = key_pairs?
key_pairs = key_pair commad_key_pair*
commad_key_pair = "," key_pair
key_pair = key_name ":" func_or_value
func_or_value = arbitrary_string / number / func
start_bracket = "("
end_bracket = ")"
joiner = "&" / "|"
key_name = ~r"[a-zA-Z][a-zA-Z0-9]+"
func_name = ~r"[a-zA-Z][a-zA-Z0-9_]+"
number = ~r"[0-9]+" &~r"[\),]"
arbitrary_string = ~r"[\s\.a-zA-Z0-9;_-]+" !"("
Essentially we can create groups with parenthesis, sections are combined with
|
and &
operators and sections are like functions with
name(arg1: val1, arg2: val2(arg3: val3, arg:4: val4))
.
For speed concerns, the grammar contains no white space and all white space is stripped from the specification before parsing.