public void ShouldConflictWithMainClassTest() { var mainMethod = MethodDeclaration.CreateMainMethodDeclaration(new List<IStatement>(), 0, 0); var mainClass = ClassDeclaration.CreateMainClassDeclaration("Foo", mainMethod, 0, 0); var otherClass = new ClassDeclaration("Foo", null, new List<Declaration>(), 2, 0); var program = new Program(mainClass, new List<ClassDeclaration>( new ClassDeclaration[] { otherClass })); var errorReporter = new ErrorLogger(); var builder = new SymbolTableBuilder(program, errorReporter); Assert.AreEqual(SymbolTableBuilder.ExitCode.FatalError, builder.BuildSymbolTable()); var errors = errorReporter.Errors; Assert.AreEqual(errors.Count, 1); Assert.AreEqual("Conflicting definitions for Foo.", errors[0].Content); Assert.AreEqual(errors[0].Row, 2); }
public static SemanticsChecker SetUpTypeAndReferenceChecker(string program, out IErrorReporter errorLog) { var reader = new StringReader(program); var scanner = new MiniJavaScanner(reader); var errors = new ErrorLogger(); var parser = new Parser(scanner, errors, true); Program syntaxTree; parser.TryParse(out syntaxTree); reader.Close(); Assert.That(errors.Errors, Is.Empty); var symbolTableBuilder = new SymbolTableBuilder(syntaxTree, errors); Assert.That(errors.Errors, Is.Empty); Assert.DoesNotThrow(() => symbolTableBuilder.BuildSymbolTable()); errorLog = new ErrorLogger(); return new SemanticsChecker(syntaxTree, errorLog); }
public void ShouldConflictWithPredefinedTypesTest() { var mainMethod = MethodDeclaration.CreateMainMethodDeclaration(new List<IStatement>(), 0, 0); var mainClass = ClassDeclaration.CreateMainClassDeclaration("int", mainMethod, 1, 0); var secondClass = new ClassDeclaration("boolean", null, new List<Declaration>(), 2, 0); var thirdClass = new ClassDeclaration("int", null, new List<Declaration>(), 3, 0); var program = new Program(mainClass, new List<ClassDeclaration> ( new [] { secondClass, thirdClass })); var errorReporter = new ErrorLogger(); var builder = new SymbolTableBuilder(program, errorReporter); Assert.AreEqual(SymbolTableBuilder.ExitCode.FatalError, builder.BuildSymbolTable()); var errors = errorReporter.Errors; Assert.AreEqual(3, errors.Count); Assert.AreEqual("Conflicting definitions for int.", errors[0].Content); Assert.AreEqual(1, errors[0].Row); Assert.AreEqual("Conflicting definitions for boolean.", errors[1].Content); Assert.AreEqual(2, errors[1].Row); Assert.AreEqual("Conflicting definitions for int.", errors[2].Content); Assert.AreEqual(3, errors[2].Row); }
/* Performs semantic analysis on the program. Returns null if any of the phases * fails. If a fatal error is encountered in one phase, analysis will not continue, * but internal recovery is attempted within each phase of analysis. * * The phases are: * 1. Building a symbol table. This checks that there are no name clashes in * type declarations or cyclic dependencies. Cyclic dependencies are treated * as fatal errors and will lead to type and reference checks not being run. * If name clashes are found, the compiler will not even proceed to check * cyclic dependencies. This is also treated as a fatal error. * 2. Semantic checks. This phase checks first the validity of name references * and then performs type checks on all expressions. References to possibly * uninitialized variables are also detected. * * All errors are logged in the error log. */ private bool ConstructSymbolTableAndCheckProgram(Program abstractSyntaxTree) { var symbolTableSuccess = new SymbolTableBuilder(abstractSyntaxTree, _errorLog).BuildSymbolTable(); bool semanticCheckSuccess = true; if (symbolTableSuccess != SymbolTableBuilder.ExitCode.FatalError) { semanticCheckSuccess = new SemanticsChecker(abstractSyntaxTree, _errorLog).RunCheck(); } return (symbolTableSuccess == SymbolTableBuilder.ExitCode.Success) && semanticCheckSuccess; }
public void ValidTypeDefinitionsTest() { var mainMethod = MethodDeclaration.CreateMainMethodDeclaration(new List<IStatement>(), 0, 0); var mainClass = ClassDeclaration.CreateMainClassDeclaration("Foo", mainMethod, 0, 0); var secondClass = new ClassDeclaration("Bar", null, new List<Declaration>(), 2, 0); var thirdClass = new ClassDeclaration("Baz", null, new List<Declaration>(), 3, 0); var program = new Program(mainClass, new List<ClassDeclaration>( new [] { secondClass, thirdClass })); var errorReporter = new ErrorLogger(); var builder = new SymbolTableBuilder(program, errorReporter); builder.BuildSymbolTable(); var types = (program.Scope as GlobalScope).UserDefinedTypeNames.ToList(); Assert.Contains("Foo", types); Assert.Contains("Bar", types); Assert.Contains("Baz", types); Assert.That(types, Is.Not.Contains("int")); Assert.That(types, Is.Not.Contains("boolean")); Assert.That(types.Count, Is.EqualTo(3)); }
private SymbolTableBuilder.ExitCode BuildSymbolTableFor(string program, out GlobalScope symbolTable) { var reader = new StringReader(program); var scanner = new MiniJavaScanner(reader); _errors = new ErrorLogger(); var parser = new Parser(scanner, _errors, true); Program syntaxTree; parser.TryParse(out syntaxTree); reader.Close(); Assert.That(_errors.Errors, Is.Empty); var symbolTableBuilder = new SymbolTableBuilder(syntaxTree, _errors); Assert.That(_errors.Errors, Is.Empty); var success = symbolTableBuilder.BuildSymbolTable(); symbolTable = syntaxTree.Scope as GlobalScope; return success; }