def __init__(self): self.grammarParser = GrammarParser() self.loader = Loader() self.lexer = Lexer() self.parser = Parser() self.checker = Checker() self.genFactory = GenFactory() # compile grammar rules self.grammarParser.compileGrammar() self.compiledModules = {}
class Compiler(object): def __init__(self): self.grammarParser = GrammarParser() self.loader = Loader() self.lexer = Lexer() self.parser = Parser() self.checker = Checker() self.genFactory = GenFactory() # compile grammar rules self.grammarParser.compileGrammar() self.compiledModules = {} def compile(self, srcPaths, moduleName): """ Create mutant lang source code tree. Load module and all referenced modules. Tokenize and parse source code. Always cache modules by moduleName (import name). output: module - common.Module instance. """ # check if moduleName already compiled if moduleName in self.compiledModules: return self.compiledModules[moduleName] self.loader.setPaths(srcPaths) # loader, lexer and parser all change module object mainModule = self.loader.loadModule(moduleName) # parse each module in lexer.modules cache for name, module in self.loader.modules.items(): # check cache if name in self.compiledModules: continue self.lexer.parse(module) self.parser.parse(module) # check and set functioncall as constructor for name, module in self.loader.modules.items(): self.markConstructors(module) # check and add module to cache for name, module in self.loader.modules.items(): self.checker.check(module) self.compiledModules[name] = module return mainModule def mutate(self, module, destPath, genName): """ Translate module and referenced modules to genName language modules. Create generated module sources formatted. Save generated sources to disk. """ gen = self.genFactory.createGen(genName) def save(self, filename, lines): with open(filename, 'w') as f: f.writelines(lines) def markConstructors(self, module): """ Find and mark constructor among functioncall nodes """ # find in variables body for name, va in module.variables.items(): self.markConstructorInVariable(module, va) # find in functions for name, fn in module.functions.items(): self.markConstructorInNodes(module, fn.bodyNodes) for cn, cl in module.classes.items(): # find in class variables body for name, va in cl.variables.items(): self.markConstructorInVariable(module, va) # find in class functions variables body for name, fn in cl.functions.items(): self.markConstructorInNodes(module, fn.bodyNodes) def markConstructorInVariable(self, module, va): if va.body and (va.body.nodetype == 'functioncall'): self.markConstructorFunctioncall(module, va.body) def markConstructorFunctioncall(self, module, fc): if common.isClassName(module, fc.name): fc.isConstructorCall = True # mark constructor in params for node in fc.params: if node.nodetype == 'functioncall': self.markConstructorFunctioncall(module, node) def markConstructorInNodes(self, module, nodes): for node in nodes: if (node.nodetype == 'variable') and node.body: if node.body.nodetype == 'functioncall': self.markConstructorFunctioncall(module, node.body) elif (node.nodetype == 'value') and node.body and (node.body.nodetype == 'functioncall'): self.markConstructorFunctioncall(module, node.body) elif node.nodetype == 'return': if node.body.nodetype == 'functioncall': self.markConstructorFunctioncall(module, node.body) elif node.nodetype == 'if': if node.body: self.markConstructorInNodes(module, node.body) if node.elseBody: self.markConstructorInNodes(module, node.elseBody)
def setUp(self): self.parser = GrammarParser() self.parser.compileGrammar()
class GrammarParserTest(unittest.TestCase): def setUp(self): self.parser = GrammarParser() self.parser.compileGrammar() def equalNodes(self, left, right): if len(left) != len(right): return False return True def testImport(self): importNode = mt.ValueNode('import') paramNode = mt.ParamNode('module') paramNode.childs = [mt.NamedNode('namespace_name')] asNode = mt.ValueNode('as') aliasNode = mt.ParamNode('alias') aliasNode.childs = [mt.ValueNode('name')] endNode = mt.ValueNode(';') expected = [importNode, paramNode, asNode, aliasNode, endNode] actual = grammar.compiled['import'] self.assertEquals(True, self.equalNodes(actual, expected)) self.assertEquals(0, len(actual[0].childs)) self.assertEquals(1, len(actual[1].childs)) self.assertEquals('as', actual[2].value) def testVariable(self): actual = grammar.getRule('variable') self.assertIsNotNone(actual) self.assertEqual(len(actual), 3) typeNode = actual[0] nameNode = actual[1] handleNode = actual[2] self.assertEqual(typeNode.name, 'type') self.assertEqual(len(typeNode.childs), 1) altNode = typeNode.childs[0] self.assertEqual(len(altNode.childs), 2) self.assertEqual(altNode.childs[0].value, 'var') self.assertEqual(altNode.childs[1].name, 'type') # self.assertEqual(nameNode.name, 'name') # self.assertEqual(len(nameNode.childs), 1) # self.assertEqual(nameNode.childs[0].value, 'name') def testType(self): expected = mt.ParamNode('type') altNode = mt.AltNode() altNode.childs.append(mt.NamedNode('array_type')) altNode.childs.append(mt.NamedNode('simple_type')) expected.childs.append(altNode) actual = grammar.getRule('type') self.assertIsNotNone(actual) self.assertEqual(len(actual), 1) typeNode = actual[0] self.assertEqual(len(typeNode.childs), 3) self.assertEqual(typeNode.childs[0].name, 'dict_type') self.assertEqual(typeNode.childs[1].name, 'array_type') self.assertEqual(typeNode.childs[2].name, 'simple_type')