See More

import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.misc.NotNull; import org.antlr.v4.runtime.tree.ErrorNode; import org.antlr.v4.runtime.tree.TerminalNode; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.ParseTreeProperty; import java.util.*; public class AssignmentListener extends MinijavaBaseListener { MinijavaParser parser; final Map klasses; ParseTreeProperty scopes; Scope currentScope = null; boolean isField; boolean isArg; int argCount=-1; public AssignmentListener(final Map klasses, ParseTreeProperty scopes, MinijavaParser parser){ this.scopes=scopes; this.klasses=klasses; this.parser=parser; } void saveScope(ParserRuleContext ctx, Scope s) { scopes.put(ctx, s); } @Override public void enterMainClass(@NotNull MinijavaParser.MainClassContext ctx) { Klass klass = klasses.get(ctx.Identifier(0).getText()); currentScope = klass; saveScope(ctx, currentScope); } @Override public void enterClassDeclaration(@NotNull MinijavaParser.ClassDeclarationContext ctx) { Klass klass = klasses.get(ctx.Identifier(0).getText()); currentScope = klass; saveScope(ctx, currentScope); //scopes.push(currentScope); Klass superKlass; if(ctx.Identifier().size()>1){ superKlass = klasses.get(ctx.Identifier(1).getText()); if(superKlass==null){ ErrorPrinter.printFileNameAndLineNumber(ctx.Identifier(1).getSymbol()); System.err.println("error: cannot find symbol."); ErrorPrinter.underlineError(parser, ctx.Identifier(1).getSymbol()); System.err.println("symbol: class " + ctx.Identifier(1).getText()); } }else{ superKlass=null; } klass.superKlass = superKlass; ErrorPrinter.reportCyclicInheritance(parser, ctx, klass); } @Override public void exitClassDeclaration(@NotNull MinijavaParser.ClassDeclarationContext ctx) { //currentKlass=null; currentScope = currentScope.getEnclosingScope(); } @Override public void enterFieldDeclaration(@NotNull MinijavaParser.FieldDeclarationContext ctx) {isField=true;} @Override public void exitFieldDeclaration(@NotNull MinijavaParser.FieldDeclarationContext ctx) {isField=false;} //@Override public void enterLocalDeclaration(@NotNull MinijavaParser.LocalDeclarationContext ctx) {isField=false;} @Override public void enterVarDeclaration(@NotNull MinijavaParser.VarDeclarationContext ctx) { String typeName = ctx.type().getText(); String varName = ctx.Identifier().getText(); if(currentScope.lookupLocally(varName)!=null){ ErrorPrinter.printSymbolAlreadyDefinedError(parser, ctx.Identifier().getSymbol(), "variable", varName, currentScope.getScopeName()); } currentScope.define(new Symbol(varName, klasses.get(typeName), isField)); } @Override public void enterMethodDeclaration(@NotNull MinijavaParser.MethodDeclarationContext ctx) { Klass returnType = klasses.get(ctx.type().getText()); if(returnType==null){ //The return type of this method is undefined. //error(ctx.Identifier().getSymbol(), "The return type of method: " + currentMethod.name + " is not defined."); //Token t = ctx.Identifier().getSymbol(); //ErrorPrinter.underlineError(parser, t, t.getLine(), t.getCharPositionInLine()); ErrorPrinter.printFullError(parser, ctx.type().Identifier().getSymbol(), "error: cannot find symbol.", "symbol: class " + ctx.type().getText(), "location: class " + currentScope.getScopeName() ); } String methodName = Method.getMethodSignature(ctx); //System.out.println("Current Scope = " + currentScope); //System.out.println("Method Name = " + methodName); if(currentScope.lookupLocally(methodName)!=null){ ErrorPrinter.printSymbolAlreadyDefinedError(parser, ctx.Identifier().getSymbol(), "method", methodName, currentScope.getScopeName()); } Scope owner = currentScope; Method method = new Method(returnType, methodName, owner); currentScope.define(method); currentScope = method; saveScope(ctx, currentScope); //scopes.push(method); //System.out.println("Current Klass: " + currentKlass + " and currentMethod = " + currentMethod); } @Override public void exitMethodDeclaration(@NotNull MinijavaParser.MethodDeclarationContext ctx) { currentScope = currentScope.getEnclosingScope(); } @Override public void enterParameter(@NotNull MinijavaParser.ParameterContext ctx) { Klass parameterType = klasses.get(ctx.type().getText()); Symbol parameter; if(parameterType==null){ //report error. Undefined type. //error(ctx.Identifier().getSymbol(), "Error, undefined type."); ErrorPrinter.printFullError(parser, ctx.type().Identifier().getSymbol(), "error: cannot find symbol.", "symbol: class " + ctx.type().getText(), "location: class " + currentScope.getEnclosingScope().getScopeName() ); } //parameter is not a field parameter = new Symbol(ctx.Identifier().getText(), parameterType, false); ((Method)currentScope).addParameter(parameter); } @Override public void enterNestedStatement(@NotNull MinijavaParser.NestedStatementContext ctx){ enterScope(ctx); } @Override public void exitNestedStatement(@NotNull MinijavaParser.NestedStatementContext ctx){ exitScope(); } @Override public void enterIfBlock(@NotNull MinijavaParser.IfBlockContext ctx){ enterScope(ctx); } @Override public void exitIfBlock(@NotNull MinijavaParser.IfBlockContext ctx){ exitScope(); } @Override public void enterElseBlock(@NotNull MinijavaParser.ElseBlockContext ctx){ enterScope(ctx); } @Override public void exitElseBlock(@NotNull MinijavaParser.ElseBlockContext ctx){ exitScope(); } @Override public void enterWhileStatement(@NotNull MinijavaParser.WhileStatementContext ctx){ enterScope(ctx); } @Override public void exitWhileStatement(@NotNull MinijavaParser.WhileStatementContext ctx){ exitScope(); } public void enterScope(ParserRuleContext ctx){ Block explicitScope = new Block(currentScope); //Do parent scopes need to know about their children? //currentScope.define(explicitScope); currentScope = explicitScope; saveScope(ctx, currentScope); } public void exitScope(){ currentScope = currentScope.getEnclosingScope(); } }