def test_09_RepRules(self): """ Basic test for Rules """ def check_word(parser, test, tutu): test.assertIn(parser.value(tutu), ('asbga', 'njnj')) return True def check_int(parser, test, toto): test.assertIn(parser.value(toto), ('12121', '89898')) return True check_word = mock.Mock(side_effect=check_word) check_int = mock.Mock(side_effect=check_int) parser = parsing.Parser() parser.parsed_stream("asbga 12121 njnj 89898") parser.rule_nodes['test'] = self parser.set_hooks({'checkWord': check_word, 'checkInt': check_int}) parser.set_rules({ 'main': parsing.Seq( parsing.Rep0N( parsing.Alt( parsing.Seq( parsing.Capture('tutu', parsing.Rule('word')), parsing.Hook('checkWord', [("test", parsing.Node), ("tutu", parsing.Node)])), parsing.Rule('int'))), parsing.Rule('Base.eof')), 'word': parsing.Scope( parsing.Call(parsing.Parser.push_ignore, parsing.Parser.ignore_null), parsing.Call(parsing.Parser.pop_ignore), parsing.Rep1N( parsing.Alt( parsing.Call(parsing.Parser.read_range, 'a', 'z'), parsing.Call(parsing.Parser.read_range, 'A', 'Z')))), 'int': parsing.Seq( parsing.Scope( parsing.Call(parsing.Parser.push_ignore, parsing.Parser.ignore_null), parsing.Call(parsing.Parser.pop_ignore), parsing.Capture( 'toto', parsing.Rep1N( parsing.Call(parsing.Parser.read_range, '0', '9')))), parsing.Hook('checkInt', [("test", parsing.Node), ("toto", parsing.Node)])) }) res = parser.eval_rule('main') self.assertTrue(res, "failed to parse") self.assertEqual(2, check_word.call_count) self.assertEqual(2, check_int.call_count)
def test_it_stops_calling_clauses_if_a_clause_is_true(self): parser = mock.Mock(spec=parsing.BasicParser) clauses = mock.Mock(**{ 'clause0.return_value': True, 'clause1.return_value': False }) parsing.Alt(clauses.pt0, clauses.pt1)(parser) self.assertEqual([mock.call.pt0(parser)], clauses.mock_calls)
def test_it_calls_all_clauses_in_order_if_they_all_false(self): parser = mock.Mock(spec=parsing.BasicParser) clauses = mock.Mock(**{ 'pt0.return_value': False, 'pt1.return_value': False }) parsing.Alt(clauses.pt0, clauses.pt1)(parser) self.assertEqual([mock.call.pt0(parser), mock.call.pt1(parser)], clauses.mock_calls)
def test_08_RepAlt(self): """ Basic test for alternatives """ parser = parsing.Parser() parser.parsed_stream("_ad121dwdw ()[]") parseTree = parsing.Seq( parsing.Call(parsing.Parser.begin_tag, 'w1'), parsing.Scope( begin=parsing.Call(parsing.Parser.push_ignore, parsing.Parser.ignore_null), end=parsing.Call(parsing.Parser.pop_ignore), pt=parsing.Seq( parsing.Alt( parsing.Call(parsing.Parser.read_char, '_'), parsing.Call(parsing.Parser.read_range, 'a', 'z'), parsing.Call(parsing.Parser.read_range, 'A', 'Z') ), parsing.Rep0N( parsing.Alt( parsing.Call(parsing.Parser.read_char, '_'), parsing.Call(parsing.Parser.read_range, 'a', 'z'), parsing.Call(parsing.Parser.read_range, 'A', 'Z'), parsing.Call(parsing.Parser.read_range, '0', '9'))))), parsing.Call(parsing.Parser.end_tag, 'w1'), parsing.Capture( 'w2', parsing.Rep1N( parsing.Alt( parsing.Call(parsing.Parser.read_char, '('), parsing.Call(parsing.Parser.read_char, ')'), parsing.Call(parsing.Parser.read_char, '['), parsing.Call(parsing.Parser.read_char, ']'), ) )), parsing.Call(parsing.Parser.read_eof) ) parseTree(parser) # Warning! skip_ignore is called between each parsing.Seq self.assertEqual(str(parser.get_tag("w1")), "_ad121dwdw ", "failed in captured w1") self.assertEqual(str(parser.get_tag("w2")), "()[]", "failed in captured w2")
def test_topython_generates_code_for_complex_alt(self): self.maxDiff = None alt = parsing.Alt( ParseTreeStub('a', False), parsing.Seq( ParseTreeStub('b', False), parsing.Alt(ParseTreeStub('c', False), ParseTreeStub('d', False)))) res = codegen.to_source(ast.Module(passes.rule_topython(alt))) self.assertEqual(res, ("try:\n" " try:\n" " if (not a):\n" " raise AltFalse()\n" " raise AltTrue()\n" " except AltFalse:\n" " pass\n" " try:\n" " if (not b):\n" " raise AltFalse()\n" " try:\n" " try:\n" " if (not c):\n" " raise AltFalse()\n" " raise AltTrue()\n" " except AltFalse:\n" " pass\n" " try:\n" " if (not d):\n" " raise AltFalse()\n" " raise AltTrue()\n" " except AltFalse:\n" " pass\n" " raise AltFalse()\n" " except AltTrue:\n" " pass\n" " raise AltTrue()\n" " except AltFalse:\n" " pass\n" " return False\n" "except AltTrue:\n" " pass"))
def test_it_calls_skipIgnore_before_each_clause(self): parser = mock.Mock(spec=parsing.BasicParser) pt = mock.Mock(return_value=False) parser.pt = pt parsing.Alt(pt, pt)(parser) calls = list( filter( lambda x: x in (mock.call.skip_ignore(), mock.call.pt(parser)), parser.method_calls)) self.assertEqual(calls, [mock.call.skip_ignore(), mock.call.pt(parser)] * 2)
def test_it_save_current_context_before_each_clause(self): parser = mock.Mock(spec=parsing.BasicParser) pt = mock.Mock(return_value=False) parser.pt = pt parsing.Alt(pt, pt)(parser) calls = list( filter( lambda x: x in (mock.call._stream.save_context(), mock.call.pt(parser)), parser.method_calls)) self.assertEqual( calls, [mock.call._stream.save_context(), mock.call.pt(parser)] * 2)
def add_alt(self, alternatives, alt) -> bool: """Create a tree.Alt""" if not hasattr(alternatives, 'parser_tree'): # forward sublevel of alt as is if hasattr(alt, 'parser_tree'): alternatives.parser_tree = alt.parser_tree else: alternatives.parser_tree = alt else: oldnode = alternatives if isinstance(oldnode.parser_tree, parsing.Alt): oldpt = list(oldnode.parser_tree.ptlist) else: oldpt = [oldnode.parser_tree] oldpt.append(alt.parser_tree) alternatives.parser_tree = parsing.Alt(*tuple(oldpt)) return True
def __init__(self, content='', sname=None): """ Define the DSL parser. """ super().__init__(content, sname) self.set_rules({ # # bnf_dsl = [ @ignore("C/C++") bnf_stmts ] # //todo: bnf_dsl = [ @ignore("C/C++") [bnf_stmts] eof ] # 'bnf_dsl': parsing.Seq( # tree is not already construct but Directive need it # forward it thru a lambda parsing.Directive( ignore.Ignore(), [("C/C++", str)], lambda parser: self.__class__._rules['bnf_stmts'] (parser)), ), # # bnf_stmts = [ [rule : r #add_rules(_, r) ]+ Base.eof ] # //todo: bnf_stmts = [ [rule : r #add_rules(_, r) ]+] # 'bnf_stmts': parsing.Seq( parsing.Rep1N( parsing.Seq( parsing.Capture("r", parsing.Rule('rule')), parsing.Hook('add_rules', [("_", parsing.Node), ("r", parsing.Node)]))), parsing.Rule('Base.eof')), # TODO: add directive hooks / change ns_name by def_rule # # rule = [ ns_name : rn '=' '[' alternatives : alts # #add_rule(_, rn, alts) ']' ] # 'rule': parsing.Seq( parsing.Capture("rn", parsing.Rule('ns_name')), parsing.Alt(parsing.Char("="), parsing.Error("Expected '='")), parsing.Alt(parsing.Char("["), parsing.Error("Expected '['")), parsing.Capture("alts", parsing.Rule('alternatives')), parsing.Hook('add_rule', [("_", parsing.Node), ("rn", parsing.Node), ("alts", parsing.Node)]), parsing.Alt( #parsing.Call(parsing.Parser.read_char, ']'), parsing.Char(']'), parsing.Error("Expected ']'"))), # # alternatives = # [ # sequences : alt #add_alt(_, alt) # ['|' sequences : alt #add_alt(_, alt) ]* # ] # 'alternatives': parsing.Seq( parsing.Capture('alt', parsing.Rule('sequences')), parsing.Hook('add_alt', [("_", parsing.Node), ("alt", parsing.Node)]), parsing.Rep0N( parsing.Seq( parsing.Char('|'), parsing.Capture('alt', parsing.Rule('sequences')), parsing.Hook('add_alt', [("_", parsing.Node), ("alt", parsing.Node)])))), # # sequences = [ [ sequence : cla #add_sequences(_, cla) ]+ ] # 'sequences': parsing.Rep1N( parsing.Seq( parsing.Capture('cla', parsing.Rule('sequence')), parsing.Hook('add_sequences', [("_", parsing.Node), ("cla", parsing.Node)]))), # # sequence = [ # [ # [ '~' | "!!" | '!' | "->" ]?: mod # [ ns_name : rid #add_ruleclause_name(_, rid) # | Base.string : txt #add_text(_, txt) # | Base.char : begin ".." Base.char : end # #add_range(_, begin, end) # | Base.char : c #add_char(_, c) # | '[' alternatives : subsequence ']' # #add_subsequence(_, subsequence) # ] #add_mod(_, mod) # [ repeat : rpt #add_rpt(_, mod, rpt) ]? # | hook : h #add_hook(_, h) # | directive2 : d sequences : s #add_directive2(_, d, s) # | directive : d sequences : s #add_directive(_, d, s) # ] # [ # ":>" Base.id : bind #add_bind(_, bind) # | ':' Base.id : cpt #add_capture(_, cpt) # ]? # ] # 'sequence': parsing.Seq( parsing.Alt( parsing.Seq( parsing.Capture( 'mod', parsing.RepOptional( parsing.Alt(parsing.Char('~'), parsing.Text('!!'), parsing.Char('!'), parsing.Text('->')))), parsing.Alt( parsing.Seq( parsing.Capture('rid', parsing.Rule('ns_name')), parsing.Hook('add_ruleclause_name', [("_", parsing.Node), ("rid", parsing.Node)])), parsing.Seq( parsing.Capture('txt', parsing.Rule('Base.string')), parsing.Hook('add_text', [("_", parsing.Node), ("txt", parsing.Node)])), parsing.Seq( parsing.Capture('begin', parsing.Rule('Base.char')), parsing.Text(".."), parsing.Capture('end', parsing.Rule('Base.char')), parsing.Hook('add_range', [("_", parsing.Node), ("begin", parsing.Node), ("end", parsing.Node)])), parsing.Seq( parsing.Capture('c', parsing.Rule('Base.char')), parsing.Hook('add_char', [("_", parsing.Node), ("c", parsing.Node)])), parsing.Seq( parsing.Char('['), parsing.Capture( 'subsequence', parsing.Alt( parsing.Rule('alternatives'), parsing.Error("Expected sequences"))), parsing.Alt(parsing.Char(']'), parsing.Error("Expected ']'")), parsing.Hook('add_subsequence', [("_", parsing.Node), ("subsequence", parsing.Node)]), )), parsing.Hook('add_mod', [("_", parsing.Node), ("mod", parsing.Node)]), parsing.RepOptional( parsing.Seq( parsing.Capture('rpt', parsing.Rule('repeat')), parsing.Hook('add_rpt', [("_", parsing.Node), ("mod", parsing.Node), ("rpt", parsing.Node)]))), ), parsing.Seq( parsing.Capture('h', parsing.Rule('hook')), parsing.Hook('add_hook', [('_', parsing.Node), ('h', parsing.Node)])), parsing.Seq( parsing.Capture('d', parsing.Rule('directive2')), parsing.Capture('s', parsing.Rule('sequences')), parsing.Hook('add_directive2', [('_', parsing.Node), ('d', parsing.Node), ('s', parsing.Node)])), parsing.Seq( parsing.Capture('d', parsing.Rule('directive')), parsing.Capture('s', parsing.Rule('sequences')), parsing.Hook('add_directive', [('_', parsing.Node), ('d', parsing.Node), ('s', parsing.Node)]))), parsing.RepOptional( parsing.Alt( parsing.Seq( parsing.Text(':>'), parsing.Capture('bind', parsing.Rule('Base.id')), parsing.Hook('add_bind', [('_', parsing.Node), ('bind', parsing.Node)])), parsing.Seq( parsing.Char(':'), parsing.Capture('cpt', parsing.Rule('Base.id')), parsing.Hook('add_capture', [('_', parsing.Node), ('cpt', parsing.Node)]))))), # ns_name = [ [@ignore("null") [ Base.id ['.' Base.id]* ]]: rid ] # 'ns_name': parsing.Capture( 'rid', parsing.Scope( parsing.Call(parsing.Parser.push_ignore, parsing.Parser.ignore_null), parsing.Call(parsing.Parser.pop_ignore), parsing.Seq( parsing.Rule('Base.id'), parsing.Rep0N( parsing.Seq( parsing.Char('.'), parsing.Alt( parsing.Rule('Base.id'), parsing.Error( "Expected identifier after '.'"))))))), # # repeat = [ '?' #add_optional(_) # | '*' #add_0N(_) # | '+' #add_1N(_) # ] # 'repeat': parsing.Alt( parsing.Seq( parsing.Char('?'), parsing.Hook('add_optional', [("_", parsing.Node)])), parsing.Seq(parsing.Char('*'), parsing.Hook('add_0N', [("_", parsing.Node)])), parsing.Seq(parsing.Char('+'), parsing.Hook('add_1N', [("_", parsing.Node)])), ), # # hook = [ '#' ns_name : n #hook_name(_, n) # ['(' param : p #hook_param(_, p) # [',' param : p #hook_param(_, p)]* # ')']? # ] # 'hook': parsing.Seq( parsing.Char('#'), parsing.Capture('n', parsing.Rule('ns_name')), parsing.Hook('hook_name', [('_', parsing.Node), ('n', parsing.Node)]), parsing.RepOptional( parsing.Seq( parsing.Char('('), parsing.Capture( 'p', parsing.Alt(parsing.Rule('param'), parsing.Error("Expected parameter"))), parsing.Hook('hook_param', [('_', parsing.Node), ('p', parsing.Node)]), parsing.Rep0N( parsing.Seq( parsing.Char(','), parsing.Capture( 'p', parsing.Alt( parsing.Rule('param'), parsing.Error("Expected parameter"))), parsing.Hook('hook_param', [('_', parsing.Node), ('p', parsing.Node)]))), parsing.Alt(parsing.Char(')'), parsing.Error("Expected ')'")))), ), # # directive2 = [ '$' ns_name : n #hook_name(_, n) # ['(' param : p #hook_param(_, p) # [',' param : p #hook_param(_, p)]* # ')']? # ] 'directive2': parsing.Seq( parsing.Char('$'), parsing.Capture('n', parsing.Rule('ns_name')), parsing.Hook('hook_name', [('_', parsing.Node), ('n', parsing.Node)]), parsing.RepOptional( parsing.Seq( parsing.Char('('), parsing.Capture( 'p', parsing.Alt(parsing.Rule('param'), parsing.Error("Expected parameter"))), parsing.Hook('hook_param', [('_', parsing.Node), ('p', parsing.Node)]), parsing.Rep0N( parsing.Seq( parsing.Char(','), parsing.Capture( 'p', parsing.Alt( parsing.Rule('param'), parsing.Error("Expected parameter"))), parsing.Hook('hook_param', [('_', parsing.Node), ('p', parsing.Node)]), )), parsing.Alt(parsing.Char(')'), parsing.Error("Expected ')'")))), ), # # directive = [ '@' ns_name : n #hook_name(_, n) # ['(' param : p #hook_param(_, p) # [',' param : p #hook_param(_, p)]* # ')']? # ] 'directive': parsing.Seq( parsing.Char('@'), parsing.Capture('n', parsing.Rule('ns_name')), parsing.Hook('hook_name', [('_', parsing.Node), ('n', parsing.Node)]), parsing.RepOptional( parsing.Seq( parsing.Char('('), parsing.Capture( 'p', parsing.Alt(parsing.Rule('param'), parsing.Error("Expected parameter"))), parsing.Hook('hook_param', [('_', parsing.Node), ('p', parsing.Node)]), parsing.Rep0N( parsing.Seq( parsing.Char(','), parsing.Capture( 'p', parsing.Alt( parsing.Rule('param'), parsing.Error("Expected parameter"))), parsing.Hook('hook_param', [('_', parsing.Node), ('p', parsing.Node)]), )), parsing.Alt(parsing.Char(')'), parsing.Error("Expected ')'")))), ), # # param = [ Base.num :n #param_num(_, n) # | Base.string : s #param_str(_, s) # | Base.char : c #param_char(_, c) # | ns_name : i #param_id(_, i) # ] # 'param': parsing.Alt( parsing.Seq( parsing.Capture('n', parsing.Rule('Base.num')), parsing.Hook('param_num', [('_', parsing.Node), ('n', parsing.Node)])), parsing.Seq( parsing.Capture('s', parsing.Rule('Base.string')), parsing.Hook('param_str', [('_', parsing.Node), ('s', parsing.Node)])), parsing.Seq( parsing.Capture('c', parsing.Rule('Base.char')), parsing.Hook('param_char', [('_', parsing.Node), ('c', parsing.Node)])), parsing.Seq( parsing.Capture('i', parsing.Rule('ns_name')), parsing.Hook('param_id', [('_', parsing.Node), ('i', parsing.Node)])), ), })
def test_it_is_false_if_all_clauses_are_false(self): parser = mock.Mock(spec=parsing.BasicParser) clause0 = mock.Mock(return_value=False) clause1 = mock.Mock(return_value=False) alt = parsing.Alt(clause0, clause1) self.assertFalse(alt(parser))
def test_it_is_true_if_a_clause_is_true(self): parser = mock.Mock(spec=parsing.BasicParser) pt = mock.Mock(return_value=True) alt = parsing.Alt(pt) self.assertTrue(alt(parser))
def test_it_restore_saved_context_if_clause_is_false(self): parser = mock.Mock(spec=parsing.BasicParser) pt = mock.Mock(return_value=False) parsing.Alt(pt)(parser) self.assertTrue(parser._stream.restore_context.called)
def test_it_validate_context_if_clause_is_true(self): parser = mock.Mock(spec=parsing.BasicParser) pt = mock.Mock(return_value=True) parsing.Alt(pt)(parser) self.assertTrue(parser._stream.validate_context.called)