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 then expr2. If it fails, match expr3 and then expr4!
[ 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 and z.
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 as pyrser.parsing.node.Node, "p2" as str, 3 as int.
@foo expr:
Apply the directive foo to the expression expr.
@foo(p1, "p2", 3) expr:
Apply the directive foo to the expression expr 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
__init__(self, content= '', sname= None)[source]

Define the DSL parser.

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