Writing a BNF grammar¶
BNF Syntax¶
Pyrser use the following DSL to describe a grammar.
R = [ expr1 expr2 ... ]:- Define a rule named R as a sequence of clauses defined by
expr.[]are mandatory at this level. expr:- expr is one of the following statements.
expr1 expr2:- Match expr1, and then match expr2 if it succeeds. Like python’s
and. expr1 | expr2:- Try to match expr1. If it fails, match expr2 instead. Like python’s
or. expr1 expr2 | expr3 expr4:- Try to match
expr1and thenexpr2. If it fails, matchexpr3and thenexpr4! [ expr1 expr2 expr3 ... ]:- Group some clauses. Allow to inverse priority.
expr*:- Match expr zero or more times.
expr+:- Match expr one or more times.
expr?:- Try to match expr.
!expr:- Negative lookahead. Fails if the next item in the input matches expr. Consumes no input.
!!expr:- Positive lookahead. Fails if the next item in the input does not matches expr. Consumes no input.
~expr:- Complement of expr. Consumes one character if the next item in the input matches does not matches expr.
->expr:- Read until expr. Consumes N character until the next item in the input matches expr.
A:- Call the rule
A. 'a':- Read the character
ain the input. "foo":- Read the text
fooin the input. 'a'..'z':- Read the next character if its value is between
aandz. expr:node:- Fetch the result of expr, create the variable
nodeand bind the result to it. __scope__:node:- Create the variable
node. This variable is attach to the scope of the rule. expr:>node:- Bind the result of the expr to the existing variable
node. #hook_without_parameter:- Call a hook without parameter.
#hook(p1, "p2", 3):- Call a hook with
p1aspyrser.parsing.node.Node,"p2"asstr,3asint. @foo expr:- Apply the directive
footo the expressionexpr. @foo(p1, "p2", 3) expr:- Apply the directive
footo the expressionexprwith parameter to the directive (as hooks).
Note: expr is compose of all basics expression except for pipe (|) operator.
Python API: class EBNF¶
-
class
pyrser.dsl.EBNF(content='', sname=None)[source]¶ Bases:
pyrser.parsing.base.ParserBasic class for BNF DSL PARSING.
A full parser for the BNF is provided by this class. We construct a tree to represents, thru functors, BNF semantics.
-
get_rules(self) → Node[source]¶ Parse the DSL and provide a dictionnaries of all resulting rules. Call by the MetaGrammar class.
TODO: could be done in the rules property of parsing.BasicParser???
-
rules¶
-
add_0N(self, repeat)¶ Create a tree.Rep0N
-
add_1N(self, repeat)¶ Create a tree.Rep1N
-
add_alt(self, alternatives, alt) → bool¶ Create a tree.Alt
-
add_bind(self, sequence, cpt)¶ Create a tree.Bind
-
add_capture(self, sequence, cpt)¶ Create a tree.Capture
-
add_char(self, sequence, c)¶ Add a read_char primitive
-
add_directive(self, sequence, d, s)¶ Add a directive in the sequence
-
add_directive2(self, sequence, d, s)¶ Add a directive in the sequence
-
add_hook(self, sequence, h)¶ Create a tree.Hook
-
add_mod(self, seq, mod)¶ Create a tree.{Complement, LookAhead, Neg, Until}
-
add_optional(self, repeat)¶ Create a tree.RepOptional
-
add_range(self, sequence, begin, end)¶ Add a read_range primitive
-
add_rpt(self, sequence, mod, pt)¶ Add a repeater to the previous sequence
-
add_rule(self, rule, rn, alts) → bool¶ Add the rule name
-
add_ruleclause_name(self, ns_name, rid) → bool¶ Create a tree.Rule
-
add_rules(self, bnf, r) → bool¶ Attach a parser tree to the dict of rules
-
add_sequences(self, sequences, cla) → bool¶ Create a tree.Seq
-
add_subsequence(self, sequence, subsequence)¶ Add a subsequence into a sequence
-
add_text(self, sequence, txt)¶ Add a read_text primitive
-
hook_name(self, hook, n)¶ Parse a hook name
-
hook_param(self, hook, p)¶ Parse a hook parameter
-
param_char(self, param, c)¶ Parse a char in parameter list
-
param_id(self, param, i)¶ Parse a node name in parameter list
-
param_num(self, param, n)¶ Parse a int in parameter list
-
param_str(self, param, s)¶ Parse a str in parameter list
-