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_evaluates_hook_with_weakref_for_node_values(self): node = parsing.Node() parser = mock.Mock(spec=parsing.BasicParser, **{'rule_nodes': { 'hooknode': node }}) hook = parsing.Hook('hook', [('hooknode', parsing.Node)]) hook(parser) parser.eval_hook.assert_called_once_with('hook', [node])
def add_hook(self, sequence, h): """Create a tree.Hook""" sequence.parser_tree = parsing.Hook(h.name, h.listparam) 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_evaluates_hook(self): hookname, params = 'hook', [(1, int), (2, int), (3, int)] parser = mock.Mock(spec=parsing.BasicParser) hook = parsing.Hook(hookname, params) hook(parser) parser.eval_hook.assert_called_once_with(hookname, [1, 2, 3])
def test_it_raises_typeerror_when_param_type_mismatch_value_type(self): with self.assertRaises(TypeError): hook = parsing.Hook('hook', [(1, str)]) hook(None)
def test_it_raises_typeerror_when_param_is_malformed(self): with self.assertRaises(TypeError): parsing.Hook('hook', [(None, None)])
def test_it_evaluates_hook_with_param_values(self): parser = mock.Mock(spec=parsing.BasicParser) hook = parsing.Hook('hook', [(1, int), ('', str), ([], list)]) hook(parser) parser.eval_hook.assert_called_once_with('hook', [1, '', []])
def test_it_is_false_when_the_hook_is_false(self): parser = mock.Mock(spec=parsing.BasicParser, **{'eval_hook.return_value': False}) hook = parsing.Hook('hook', []) self.assertFalse(hook(parser))
def test_topython_generates_code_for_hook(self): hook = parsing.Hook('hookname', tuple()) res = codegen.to_source(passes.rule_topython(hook)) self.assertEqual(res, "self.evalHook('hookname', self.ruleNodes[(-1)])")