def testParameterizedProductions(self): passthru = ('Yield', Var('Yield')), name = Nt("name", passthru) stmt = Nt("stmt", passthru) stmts = Nt("stmts", passthru) grammar = Grammar( { 'script': [ ['def'], ['script', 'def'], ], 'def': [ [ 'function', 'IDENT', '(', ')', '{', Nt('stmts', (('Yield', False), )), '}' ], [ 'function', '*', 'IDENT', '(', ')', '{', Nt('stmts', (('Yield', True), )), '}' ], ], 'stmts': NtDef(['Yield'], [ [stmt], [stmts, stmt], ], None), 'stmt': NtDef(['Yield'], [ [name, "(", ")", ";"], [name, "=", name, ";"], Production(["yield", name, ";"], reducer=CallMethod("yield_stmt", [1]), condition=('Yield', True)), ], None), 'name': NtDef( ['Yield'], [ ["IDENT"], # Specifically ask for a method here, because otherwise we # wouldn't get one and then type checking would fail. Production(["yield"], CallMethod("yield_as_name", []), condition=('Yield', False)), ], None), }, variable_terminals=["IDENT"]) self.compile( lexer.LexicalGrammar("( ) { } ; * = function yield", IDENT=r'[A-Za-z]\w*'), grammar) self.assertParse("function* farm() { cow = pig; yield cow; }") self.assertNoParse( "function city() { yield toOncomingTraffic; }", message="expected one of ['(', ';', '='], got 'IDENT'") self.assertNoParse("function* farm() { yield = corn; yield yield; }", message="expected 'IDENT', got '='")
def testConvenienceMethodTypeInference(self): """A method can be called only in an intermediate reduce expression.""" # The action `f(g($0))`. action = CallMethod("f", [CallMethod("g", [0])]) # The grammar `goal ::= NAME => f(g($1))`. grammar = Grammar( { 'goal': [Production(['NAME'], action)], }, variable_terminals=['NAME']) # Since the return value of f() is used as the value of a `goal`, # we infer that f() returns a goal. self.assertEqual( grammar.methods['f'].return_type, jsparagus.types.NtType('goal')) # Since the return value of g() isn't used except as an argument, we # just give it the type `g`. I guess NtType is a bit of a misnomer for # this. self.assertEqual( grammar.methods['g'].return_type, jsparagus.types.NtType('g')) # Since g() is passed to f(), we infer this: self.assertEqual( grammar.methods['f'].argument_types, [jsparagus.types.NtType('g')])
def testMissingParameterError(self): grammar = { 'Foo': [ ['Bar'], ], 'Bar': NtDef(('Arg', ), [ ['NUM'], Production(['STR'], reducer=0, condition=('Arg', True)), ], None), } self.assertRaisesRegex(ValueError, "missing parameters for 'Bar'", lambda: Grammar(grammar))
def prod(body, method_name): return Production(body, CallMethod(method_name, list(range(len(body)))))
def prod(body, method_name): return Production(body, CallMethod(method_name, list(range(len(body))), "AstBuilder", False))