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
expr1
and thenexpr2
. If it fails, matchexpr3
and 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
a
in the input. "foo"
:- Read the text
foo
in the input. 'a'..'z'
:- Read the next character if its value is between
a
andz
. expr:node
:- Fetch the result of expr, create the variable
node
and 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
p1
aspyrser.parsing.node.Node
,"p2"
asstr
,3
asint
. @foo expr
:- Apply the directive
foo
to the expressionexpr
. @foo(p1, "p2", 3) expr
:- Apply the directive
foo
to the expressionexpr
with 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.Parser
Basic 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
-