Base of all parser

When you inherit from pyrser.grammar.Grammar, you get namespace in your grammar called Base that provide a lot of default rules. This namespace follows the grammars aggregation principle of pyrser.

Grammar composition

rules of thumb:

  • You could inherit from N grammar to create a new one, but the first base class must be grammar.Grammar:

    from pyrser import grammar
    from other import A, B, C
    
    class MyGrammar(grammar.Grammar, A, B, C):
        pass
    
  • Each inherited rules from a base class is prefixed by the base class name. This is the namespace.

  • Each inherited rules exists with and without the namespace prefix in your child class:

    class A(grammar.Grammar):
        grammar="rule = [ id eof ]"
    
    class B(grammar.Grammar, A):
        # here exist ``A.rule`` and ``rule``.
        pass
    
  • A rule name in a child class could clash with the raw rule name from a base class (without namespace prefix).

  • So the prefixed rule name always exists:

    class A(grammar.Grammar):
        grammar="rule = [ id eof ]"
    
    class B(grammar.Grammar, A):
        grammar="rule = [ A.rule | string eof ]"
    

Default rules

So the namespace Base provide a lot of basic rules.

Base.eof:
Read a End-of-File.
Base.eol:
Read a portable End-of-Line.
Base.id:
Read an identifier [‘a’..’z’|’A’..’Z’|’_’][‘a’..’z’|’A’..’Z’|‘0’..‘9’|’_’]*
Base.num:
Read a [‘0’..‘9’]+
Base.char:
Read a something surrounded by ‘ like in C programming language for char.
Base.string:
Read a something surrounded by ” like in C programming language for string.
Base.read_char:
Read one arbitrary char.

Python API: class parserBase

class pyrser.parsing.base.MetaBasicParser[source]

Bases: type

Metaclass for all parser.

static __new__(metacls, name, bases, namespace)[source]
class pyrser.parsing.base.BasicParser(content: str='', stream_name: str=None, raise_diagnostic=True)[source]

Bases: object

Empty basic parser, contains no rule nor hook.

Unless you know what you are doing, use Parser instead of this class.

__init__(self, content: str= '', stream_name: str= None, raise_diagnostic= True)[source]
__bool__(self)[source]
_stream

The current Stream.

rules

Return the grammar dict

push_rule_nodes(self) → bool[source]

Push context variable to store rule nodes.

pop_rule_nodes(self) → bool[source]

Pop context variable that store rule nodes

value(self, n: Node) → str[source]

Return the text value of the node

parsed_stream(self, content: str, name: str= None)[source]

Push a new Stream into the parser. All subsequent called functions will parse this new stream, until the ‘popStream’ function is called.

pop_stream(self)[source]

Pop the last Stream pushed on to the parser stack.

begin_tag(self, name: str) → Node[source]

Save the current index under the given name.

end_tag(self, name: str) → Node[source]

Extract the string between saved and current index.

get_tag(self, name: str) → Tag[source]

Extract the string previously saved.

tag_node(self, name: str, node: Node)[source]
classmethod set_rules(rules: dict) → bool[source]

Merge internal rules set with the given rules

classmethod set_hooks(hooks: dict) → bool[source]

Merge internal hooks set with the given hooks

classmethod set_directives(directives: dict) → bool[source]

Merge internal directives set with the given directives. For working directives, attach it only in the dsl.Parser class

eval_rule(self, name: str) → Node[source]

Evaluate a rule by name.

eval_hook(self, name: str, ctx: list) → Node[source]

Evaluate the hook by its name

peek_char(self, c: str) → bool[source]
peek_text(self, text: str) → bool[source]

Same as readText but doesn’t consume the stream.

read_char(self, c: str) → bool[source]

Consume the c head byte, increment current index and return True else return False. It use peekchar and it’s the same as ‘’ in BNF.

read_until(self, c: str, inhibitor= '\') → bool[source]

Consume the stream while the c byte is not read, else return false ex : if stream is ” abcdef ”, read_until(“d”); consume “abcd”.

read_until_eof(self) → bool[source]

Consume all the stream. Same as EOF in BNF.

read_text(self, text: str) → bool[source]

Consume a strlen(text) text at current position in the stream else return False. Same as “” in BNF ex : read_text(“ls”);.

read_range(self, begin: str, end: str) → int[source]

Consume head byte if it is >= begin and <= end else return false Same as ‘a’..’z’ in BNF

ignore_null(self) → bool[source]

Empty ignore convention for notignore

ignore_blanks(self) → bool[source]

Consume whitespace characters.

push_ignore(self, ignoreConvention) → bool[source]

Set the ignore convention

pop_ignore(self) → bool[source]

Remove the last ignore convention

skip_ignore(self) → bool[source]
undo_last_ignore(self) → bool[source]
bind(self, dst: str, src: Node) → bool

Allow to alias a node to another name.

Useful to bind a node to _ as return of Rule:

R = [
    __scope__:L [item:I #add_item(L, I]* #bind('_', L)
]

It’s also the default behaviour of ‘:>’

dump_nodes(self)

Dump tag,rule,id and value cache. For debug.

example:

R = [
    #dump_nodes
]
echo_nodes(self, rest)

Print nodes.

example:

R = [
    In : node #echo("coucou", 12, node)
]
get_subnode(self, dst, ast, expr)

get the value of subnode

example:

R = [
    __scope__:big  getsomethingbig:>big
    #get(_, big, '.val') // copy big.val into _
]
pred_eq(self, n, val)

Test if a node set with setint or setstr equal a certain value

example:

R = [
    __scope__:n
    ['a' #setint(n, 12) | 'b' #setint(n, 14)]
    C
    [#eq(n, 12) D]
]
pred_false(self)

False in parser. Go to alternative...

example:

R = [
    #false | R2
]
pred_neq(self, n, val)

Test if a node set with setint or setstr not equal a certain value

example:

R = [
    __scope__:n
    ['a' #setint(n, 12) | 'b' #setint(n, 14)]
    C
    [#neq(n, 12) D]
]
pred_true(self)

True in parser. Do nothing

example:

R = [
    R2 | #true
]
read_eof(self) → bool

Returns true if reached end of the stream.

read_one_char(self) → bool

Read one byte in stream

set_node(self, dst, src)

Basically copy one node to another. usefull to transmit a node from a terminal rule as result of the current rule.

example:

R = [
    In : node #set(_, node)
]

here the node return by the rule In is also the node return by the rule R

set_node_as_int(self, dst, src)

Set a int literal to a node

example:

R = [
    In : node #setint(node, 12)
]
set_node_as_str(self, dst, src)

Set a str literal to a node

example:

R = [
    In : node #setstr(node, "toto")
]
vars_nodes(self, rest)

Vars one node instance.

example:

R = [
    In : node #vars(node)
]
class pyrser.parsing.base.Parser(content: str='', stream_name: str=None, raise_diagnostic=True)[source]

Bases: pyrser.parsing.base.BasicParser

An ascii parsing primitive library.

ignore_cxx(self) → bool

Consume comments and whitespace characters.

read_cchar(self) → bool

Read following BNF rule else return False:

"'" -> ['\' #char | ~'\'] "'"
read_cstring(self) → bool

Read following BNF rule else return False:

'"' -> ['\' #char | ~'\'] '"'
read_eol(self) → bool

Return True if the parser can consume an EOL byte sequence.

read_identifier(self) → bool

Read following BNF rule else return False:

readIdentifier = [
    ['a'..'z'|'A'..'Z'|'_']['0'..'9'|'a'..'z'|'A'..'Z'|'_']*
]
read_integer(self) → bool

Read following BNF rule else return False:

readInteger = [
    ['0'..'9']+
]
scope_nodes(self) → bool

Used for create scoped nodes

to_dsl(self)
pyrser.parsing.base.bind(self, dst: str, src: Node) → bool[source]

Allow to alias a node to another name.

Useful to bind a node to _ as return of Rule:

R = [
    __scope__:L [item:I #add_item(L, I]* #bind('_', L)
]

It’s also the default behaviour of ‘:>’

pyrser.parsing.base.read_one_char(self) → bool[source]

Read one byte in stream

pyrser.parsing.base.read_eof(self) → bool[source]

Returns true if reached end of the stream.

pyrser.parsing.base.read_eol(self) → bool[source]

Return True if the parser can consume an EOL byte sequence.

pyrser.parsing.base.read_integer(self) → bool[source]

Read following BNF rule else return False:

readInteger = [
    ['0'..'9']+
]
pyrser.parsing.base.read_identifier(self) → bool[source]

Read following BNF rule else return False:

readIdentifier = [
    ['a'..'z'|'A'..'Z'|'_']['0'..'9'|'a'..'z'|'A'..'Z'|'_']*
]
pyrser.parsing.base.read_cstring(self) → bool[source]

Read following BNF rule else return False:

'"' -> ['\' #char | ~'\'] '"'
pyrser.parsing.base.read_cchar(self) → bool[source]

Read following BNF rule else return False:

"'" -> ['\' #char | ~'\'] "'"
pyrser.parsing.base.scope_nodes(self) → bool[source]

Used for create scoped nodes