def test_add_incorrect_pratt_parser(): grammar = Grammar() stmt_id = grammar.add_parselet('stmt', kind=ParseletKind.Pratt, result_type=SyntaxToken) expr_id = grammar.add_parselet('expr', kind=ParseletKind.Pratt, result_type=SyntaxToken) integer_id = grammar.add_token('Integer') with pytest.raises(GrammarError): grammar.add_parser(expr_id, make_optional(integer_id)) with pytest.raises(GrammarError): grammar.add_parser(expr_id, make_sequence(stmt_id)) with pytest.raises(GrammarError): grammar.add_parser(expr_id, make_sequence(expr_id, stmt_id)) with pytest.raises(GrammarError): grammar.add_parser(expr_id, make_sequence(expr_id, make_optional(stmt_id))) with pytest.raises(GrammarError): grammar.add_parser(expr_id, make_sequence(expr_id, expr_id))
def test_add_packrat_parser(): grammar = Grammar() stmt_id = grammar.add_parselet('stmt', kind=ParseletKind.Packrat, result_type=SyntaxToken) star_id = grammar.add_implicit('*') assert grammar.add_parser( stmt_id, make_sequence(grammar.add_implicit('('), stmt_id, grammar.add_implicit(')'))) assert grammar.add_parser(stmt_id, make_sequence(grammar.add_implicit('('))) assert grammar.add_parser(stmt_id, star_id) assert grammar.add_parser(stmt_id, stmt_id)
def test_extend_packrat_grammar(): grammar1 = Grammar() grammar1.add_token('Number') grammar1.add_token('String') expr_id = grammar1.add_parselet('expr', result_type=object) grammar1.add_parser(expr_id, 'Number') grammar1.add_parser(expr_id, 'String') grammar2 = Grammar() grammar2.add_token('Number') grammar2.add_token('String') expr_id = grammar2.add_parselet('expr', result_type=object) grammar2.add_parser(expr_id, 'Number') grammar2.add_parser(expr_id, 'String') result = Grammar.merge(grammar1, grammar2) expr_id = result.parselets['expr'] assert expr_id in result.tables assert len(cast(PackratTable, result.tables[expr_id]).parselets) == 4
def test_add_pratt_parser(): grammar = Grammar() expr_id = grammar.add_parselet('expr', kind=ParseletKind.Pratt, result_type=SyntaxToken) integer_id = grammar.add_token('Integer') string_id = grammar.add_token('String') plus_id = grammar.add_implicit('+') star_id = grammar.add_implicit('*') table = cast(PrattTable, grammar.tables[expr_id]) assert table.prefix_tokens == set() assert grammar.add_parser(expr_id, integer_id) assert integer_id in table.prefix_tokens, "Cleanup of pratt table prefix tokens is not worked" assert grammar.add_parser(expr_id, make_named('value', string_id)) assert string_id in table.prefix_tokens, "Cleanup of pratt table prefix tokens is not worked" assert grammar.add_parser(expr_id, make_sequence(expr_id, plus_id, expr_id)) assert grammar.add_parser( expr_id, make_sequence(make_named('lhs', expr_id), make_named('op', star_id), expr_id))
def grammar() -> Grammar: grammar = Grammar() whitespace_id = grammar.add_pattern(grammar.add_token('Whitespace'), r'\s+') grammar.add_trivia(whitespace_id) grammar.add_pattern(grammar.add_token('Name'), r'[a-zA-Z_][a-zA-Z0-9]*') grammar.add_pattern(grammar.add_token('Number'), r'[0-9]+') make_implicit = grammar.add_implicit expr_id = grammar.add_parselet('expr', kind=ParseletKind.Pratt, result_type=object) # expr := value:Number grammar.add_parser(expr_id, "value:Number", make_call(lambda value: value.value, object)) # expr := lhs:expr op:'+' rhs:expr grammar.add_parser(expr_id, 'lhs:expr "**" rhs:expr <899>', make_call(lambda lhs, rhs: (lhs, '**', rhs), object), priority=900) # expr := lhs:expr op:'+' rhs:expr grammar.add_parser(expr_id, 'lhs:expr "+" rhs:expr <600>', make_call(lambda lhs, rhs: (lhs, '+', rhs), object), priority=600) # expr := lhs:expr op:'-' rhs:expr grammar.add_parser(expr_id, 'lhs:expr "-" rhs:expr <600>', make_call(lambda lhs, rhs: (lhs, '-', rhs), object), priority=600) # expr := lhs:expr op:'*' rhs:expr grammar.add_parser(expr_id, 'lhs:expr "*" rhs:expr <700>', make_call(lambda lhs, rhs: (lhs, '*', rhs), object), priority=700) # expr := lhs:expr op:'/' rhs:expr grammar.add_parser(expr_id, 'lhs:expr "/" rhs:expr <700>', make_call(lambda lhs, rhs: (lhs, '/', rhs), object), priority=700) # expr := op:'-' value:expr grammar.add_parser(expr_id, '"-" value:expr <800>', make_call(lambda value: ('-', value), object)) # expr := op:'-' value:expr grammar.add_parser(expr_id, '"+" value:expr <800>', make_call(lambda value: ('+', value), object)) # expr := '(' value:expr ')' grammar.add_parser(expr_id, '"(" value:expr ")"', make_return_variable('value')) return grammar
def create_combinator_grammar() -> Grammar: """ Create grammar for parse combinator definition P.S. This grammar is used for bootstrap process of initial grammar, e.g. definition of combinators in grammar """ grammar = Grammar() grammar.extend(create_core_grammar()) # tokens name_id = grammar.tokens['Name'] string_id = grammar.tokens['String'] number_id = grammar.tokens['Integer'] colon_id = grammar.add_implicit(':') parent_open_id = grammar.tokens['('] parent_close_id = grammar.tokens[')'] square_open_id = grammar.tokens['['] square_close_id = grammar.tokens[']'] curly_open_id = grammar.tokens['{'] curly_close_id = grammar.tokens['}'] less_id = grammar.tokens['<'] great_id = grammar.tokens['>'] # parse combinator definition comb_id = grammar.add_parselet('combinator', result_type=CombinatorNode) seq_id = grammar.add_parselet('combinator_sequence', result_type=SequenceNode) # combinator := name: Name ":" combinator=combinator ; named variable grammar.add_parser( comb_id, make_sequence(make_named('name', name_id), colon_id, make_named('combinator', comb_id)), make_ctor(NamedNode) ) # combinator := name: Name [ '<' priority: Number '>' ] ; reference to parselet or token grammar.add_parser( comb_id, make_sequence(make_named('name', name_id), make_optional(less_id, make_named('priority', number_id), great_id)), make_ctor(ReferenceNode) ) # combinator := value: String ; reference to implicit token grammar.add_parser(comb_id, make_named('value', string_id), make_ctor(ImplicitNode)) # combinator := '[' combinator: combinator_sequence ']' ; optional combinator grammar.add_parser( comb_id, make_sequence(square_open_id, make_named('combinator', seq_id), square_close_id), make_ctor(OptionalNode) ) # combinator := '{' combinator: combinator_sequence '}' ; repeat combinator grammar.add_parser( comb_id, make_sequence(curly_open_id, make_named('combinator', seq_id), curly_close_id), make_ctor(RepeatNode) ) # combinator := '(' combinator: combinator_sequence ')' ; parenthesis combinator grammar.add_parser( comb_id, make_sequence(parent_open_id, make_named('combinator', seq_id), parent_close_id), make_return_variable('combinator') ) # combinator_sequence := combinators:combinator combinators:{ combinator } ; sequence combinator grammar.add_parser( seq_id, make_sequence(make_named('combinators', comb_id), make_named('combinators', make_repeat(comb_id))), make_ctor(SequenceNode) ) return grammar
def test_add_fast_parser(): grammar = Grammar() grammar.add_token('Number') grammar.add_parser('expr', 'Number')