def main(filename): # get the root of the parse tree of the input file parseTreeRoot = parseFile(filename) # the errorHandler which will group all of the errors errorHandler = ErrorHandler(filename) try: # create an AST an attach it to a listener so the listener can fill in the tree abstractSyntaxTree = buildAST(parseTreeRoot) firstPassDecoration(abstractSyntaxTree) # create a symbol table and symbol table filler, fill in the table and check if everything is declared before it is used in the c file symbolTable = SymbolTable() scopeCheck(abstractSyntaxTree, errorHandler, symbolTable) # do the type checking typeCheck(abstractSyntaxTree, errorHandler) output(str(abstractSyntaxTree)) output(str(symbolTable)) # generate code if not errorHandler.errorCount(): generateCode(abstractSyntaxTree, symbolTable) except Exception as e: ex_type, ex, tb = sys.exc_info() traceback.print_exception(ex_type, ex, tb) if errorHandler.errorCount() or errorHandler.warningCount(): print(str(errorHandler.errorCount()) + " error" + ("s" if errorHandler.errorCount() != 1 else "")) print(str(errorHandler.warningCount()) + " warning" + ("s" if errorHandler.warningCount() != 1 else "")) errorHandler.printErrors()
class ASTTest(): def setUp(self): self.errorHandler = None def parseFile(self, filename): input_file = FileStream(filename) lexer = CLexer(input_file) stream = CommonTokenStream(lexer) parser = CParser(stream) programContext = parser.program() if parser._syntaxErrors > 0: raise Exception("error parsing file " + filename) walker = ParseTreeWalker() abstractSyntaxTree = AbstractSyntaxTree(); self.errorHandler = ErrorHandler(filename) listener = Listener(abstractSyntaxTree) walker.walk(listener, programContext) decorator = VisitorDecorator() decorator.visitProgramNode(abstractSyntaxTree.root) symbolTable = SymbolTable() functionFiller = VisitorSymbolTableFiller(symbolTable, self.errorHandler) functionFiller.visitProgramNode(abstractSyntaxTree.root) tableFiller = VisitorDeclarationProcessor(symbolTable, self.errorHandler) tableFiller.visitProgramNode(abstractSyntaxTree.root) typeCheck = VisitorTypeChecker(self.errorHandler) typeCheck.visitProgramNode(abstractSyntaxTree.root) if self.errorHandler.errorCount() == 0: pFilename = os.path.splitext(filename)[0] + ".p" codeGenerator = VisitorCodeGenerator(symbolTable, pFilename) codeGenerator.visitProgramNode(abstractSyntaxTree.root) def generateErrorsAndCompare(self, filename): self.parseFile(filename + ".c") self.assertTrue(self.errorHandler.errorCount() or self.errorHandler.warningCount()) # if there is error output generated, compare with txt file try: with open(filename + ".txt", "r") as myfile: correctOutputOriginal = myfile.read() except: with open(filename + ".txt", "w") as myfile: correctOutputOriginal = "" errorMessage = self.errorHandler.errorsToString() errorMessageWithWhitespace = copy.copy(errorMessage) # remove all whitespace errorMessage = re.sub("[ \t\n\r]", "", errorMessage) correctOutput = re.sub("[ \t\n\r]", "", correctOutputOriginal) # expectedOutputFound = errorMessage.find(correctOutput) != -1 expectedOutputFound = errorMessage == correctOutput if setTxtFiles and not expectedOutputFound: f = open(filename + ".txt", "w") f.write(errorMessageWithWhitespace) f.close() if not expectedOutputFound: print("\nEXPECTED:\n" + correctOutputOriginal + "\nGOT:\n" + errorMessageWithWhitespace + "\n\n\n\n") self.assertTrue(expectedOutputFound) def generateNoError(self, filename): self.parseFile(filename + ".c") self.assertTrue(self.errorHandler.errorCount() == 0) # open the newly generated p code file try: with open(filename + ".p", "r") as myfile: pCodeGeneratedOriginal = myfile.read() except: with open(filename + ".p", "w") as myfile: pCodeGeneratedOriginal = "" # open the file with the correct p code try: with open(filename + ".p_correct", "r") as myfile: pCodeCorrectOriginal = myfile.read() except: with open(filename + ".p_correct", "w") as myfile: pCodeCorrectOriginal = "" # remove all whitespace pCodeGenerated = re.sub("[ \t\n\r]", "", pCodeGeneratedOriginal) pCodeCorrect = re.sub("[ \t\n\r]", "", pCodeCorrectOriginal) # expectedOutputFound = errorMessage.find(correctOutput) != -1 expectedCodeFound = pCodeGenerated == pCodeCorrect if setPCode and not expectedCodeFound: f = open(filename + ".p_correct", "w") f.write(pCodeGeneratedOriginal) f.close() if not expectedCodeFound: print("\nEXPECTED:\n" + pCodeGeneratedOriginal + "\nGOT:\n" + pCodeCorrectOriginal + "\n\n\n\n") # os.system("gcc -std=c99 " + filename + ".c -w -o " + filename + ".testbin") self.assertTrue(expectedCodeFound)