From c00decd11bbc44af25730c9bb549da4f6aa4561f Mon Sep 17 00:00:00 2001 From: Thibaud Date: Thu, 5 Apr 2018 20:03:37 +0200 Subject: [PATCH] Add java code and test cases --- compiler/pom.xml | 23 + .../letsbuildacompiler/compiler/DataType.java | 15 + .../compiler/FunctionDefinitionFinder.java | 31 + .../compiler/FunctionList.java | 36 + .../compiler/JasminVisitor.java | 304 ++++ .../letsbuildacompiler/compiler/JvmStack.java | 18 + .../de/letsbuildacompiler/compiler/Main.java | 33 + .../compiler/exceptions/CompileException.java | 13 + .../FunctionAlreadyDefinedException.java | 18 + .../UndeclaredVariableException.java | 20 + .../UndefinedFunctionException.java | 18 + .../VariableAlreadyDefinedException.java | 18 + .../compiler/CompilerTest.java | 173 +++ .../examples/branch/if_int_false | 5 + .../examples/branch/if_int_true | 5 + .../examples/functions/int_parameters | 5 + .../test-resources/examples/functions/scopes | 9 + .../examples/functions/simple_function | 5 + .../examples/operators/and-skip-right | 6 + .../examples/operators/or-skip-right | 6 + .../test-classes/examples/branch/if_int_false | 5 + .../test-classes/examples/branch/if_int_true | 5 + .../examples/functions/int_parameters | 5 + .../test-classes/examples/functions/scopes | 9 + .../examples/functions/simple_function | 5 + .../examples/operators/and-skip-right | 6 + .../examples/operators/or-skip-right | 6 + parser/pom.xml | 15 + .../de/letsbuildacompiler/parser/Demo.interp | 52 + .../de/letsbuildacompiler/parser/Demo.tokens | 50 + .../parser/DemoBaseVisitor.java | 196 +++ .../parser/DemoLexer.interp | 65 + .../letsbuildacompiler/parser/DemoLexer.java | 160 ++ .../parser/DemoLexer.tokens | 50 + .../letsbuildacompiler/parser/DemoParser.java | 1317 +++++++++++++++++ .../parser/DemoVisitor.java | 182 +++ 36 files changed, 2889 insertions(+) create mode 100644 compiler/pom.xml create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/DataType.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/FunctionDefinitionFinder.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/FunctionList.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/JasminVisitor.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/JvmStack.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/Main.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/CompileException.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/FunctionAlreadyDefinedException.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/UndeclaredVariableException.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/UndefinedFunctionException.java create mode 100644 compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/VariableAlreadyDefinedException.java create mode 100644 compiler/src/test/java/de/letsbuildacompiler/compiler/CompilerTest.java create mode 100644 compiler/src/test/test-resources/examples/branch/if_int_false create mode 100644 compiler/src/test/test-resources/examples/branch/if_int_true create mode 100644 compiler/src/test/test-resources/examples/functions/int_parameters create mode 100644 compiler/src/test/test-resources/examples/functions/scopes create mode 100644 compiler/src/test/test-resources/examples/functions/simple_function create mode 100644 compiler/src/test/test-resources/examples/operators/and-skip-right create mode 100644 compiler/src/test/test-resources/examples/operators/or-skip-right create mode 100644 compiler/target/test-classes/examples/branch/if_int_false create mode 100644 compiler/target/test-classes/examples/branch/if_int_true create mode 100644 compiler/target/test-classes/examples/functions/int_parameters create mode 100644 compiler/target/test-classes/examples/functions/scopes create mode 100644 compiler/target/test-classes/examples/functions/simple_function create mode 100644 compiler/target/test-classes/examples/operators/and-skip-right create mode 100644 compiler/target/test-classes/examples/operators/or-skip-right create mode 100644 parser/pom.xml create mode 100644 parser/src/main/java/de/letsbuildacompiler/parser/Demo.interp create mode 100644 parser/src/main/java/de/letsbuildacompiler/parser/Demo.tokens create mode 100644 parser/src/main/java/de/letsbuildacompiler/parser/DemoBaseVisitor.java create mode 100644 parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.interp create mode 100644 parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.java create mode 100644 parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.tokens create mode 100644 parser/src/main/java/de/letsbuildacompiler/parser/DemoParser.java create mode 100644 parser/src/main/java/de/letsbuildacompiler/parser/DemoVisitor.java diff --git a/compiler/pom.xml b/compiler/pom.xml new file mode 100644 index 0000000..0e1b82e --- /dev/null +++ b/compiler/pom.xml @@ -0,0 +1,23 @@ + + + + antlr-compiler + org.example + 1.0-SNAPSHOT + + 4.0.0 + + compiler + + + + org.example + parser + 1.0-SNAPSHOT + + + + + \ No newline at end of file diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/DataType.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/DataType.java new file mode 100644 index 0000000..cdb3249 --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/DataType.java @@ -0,0 +1,15 @@ +package de.letsbuildacompiler.compiler; + +public enum DataType { + INT("I"), STRING("Ljava/lang/String;"); + + public final String jvmType; + + DataType(String jvmType) { + this.jvmType = jvmType; + } + + public String getJvmType() { + return jvmType; + } +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/FunctionDefinitionFinder.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/FunctionDefinitionFinder.java new file mode 100644 index 0000000..92ae18f --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/FunctionDefinitionFinder.java @@ -0,0 +1,31 @@ +package de.letsbuildacompiler.compiler; + +import de.letsbuildacompiler.compiler.exceptions.FunctionAlreadyDefinedException; +import de.letsbuildacompiler.parser.DemoBaseVisitor; +import de.letsbuildacompiler.parser.DemoParser; +import org.antlr.v4.runtime.tree.ParseTree; + +import java.util.HashSet; +import java.util.Set; + +public class FunctionDefinitionFinder { + + public static FunctionList findFunctions(ParseTree tree) { + final FunctionList definedFunctions = new FunctionList(); + + new DemoBaseVisitor() { + @Override + public Void visitFunctionDefinition(DemoParser.FunctionDefinitionContext ctx) { + String functionName = ctx.funcName.getText(); + int numberOfArguments = ctx.params.declarations.size(); + if (definedFunctions.contains(functionName, numberOfArguments)) { + throw new FunctionAlreadyDefinedException(ctx.funcName); + } + definedFunctions.add(functionName, numberOfArguments); + return null; + } + }.visit(tree); + + return definedFunctions; + } +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/FunctionList.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/FunctionList.java new file mode 100644 index 0000000..d62542c --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/FunctionList.java @@ -0,0 +1,36 @@ +package de.letsbuildacompiler.compiler; + +import java.util.ArrayList; +import java.util.Collection; + +public class FunctionList { + + private Collection definitions; + + FunctionList() { + this.definitions = new ArrayList<>(); + } + + public boolean contains(String functionName, int parameterCount) { + for (FunctionDefinition definition : definitions) { + if (definition.functionName.equals(functionName) && definition.parameterCount == parameterCount) { + return true; + } + } + return false; + } + + public void add (String functionName, int parameterCount) { + definitions.add(new FunctionDefinition(functionName, parameterCount)); + } + + private static final class FunctionDefinition { + private final String functionName; + private final int parameterCount; + + private FunctionDefinition(String functionName, int parameterCount) { + this.functionName = functionName; + this.parameterCount = parameterCount; + } + } +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/JasminVisitor.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/JasminVisitor.java new file mode 100644 index 0000000..aeb8a3c --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/JasminVisitor.java @@ -0,0 +1,304 @@ +package de.letsbuildacompiler.compiler; + +import de.letsbuildacompiler.compiler.exceptions.UndeclaredVariableException; +import de.letsbuildacompiler.compiler.exceptions.UndefinedFunctionException; +import de.letsbuildacompiler.compiler.exceptions.VariableAlreadyDefinedException; +import de.letsbuildacompiler.parser.DemoBaseVisitor; +import de.letsbuildacompiler.parser.DemoParser; +import de.letsbuildacompiler.parser.DemoParser.MainStatementContext; +import de.letsbuildacompiler.parser.DemoParser.NumberContext; +import de.letsbuildacompiler.parser.DemoParser.PlusContext; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.tree.ParseTree; + +import java.util.HashMap; +import java.util.Map; + +public class JasminVisitor extends DemoBaseVisitor { + + // Symbol table + private Map variables = new HashMap<>(); + private JvmStack jvmStack = new JvmStack(); + private final FunctionList definedFunctions; + private int branchCounter = 0; + private int compareCount = 0; + private int andCounter = 0; + private int orCounter = 0; + + JasminVisitor(FunctionList definedFunctions) { + if (definedFunctions == null) { + throw new NullPointerException("definedFunctions"); + } + this.definedFunctions = definedFunctions; + } + + @Override + public String visitNumber(NumberContext ctx) { + jvmStack.push(DataType.INT); + return "ldc " + ctx.number.getText(); + } + + @Override + public String visitString(DemoParser.StringContext ctx) { + jvmStack.push(DataType.STRING); + return "ldc " + ctx.txt.getText(); + } + + private String visitBinaryOperation(String name, DemoParser.ExpressionContext ctx) { + String instructions = visitChildren(ctx) + "\n" + name; + jvmStack.pop(); + jvmStack.pop(); + jvmStack.push(DataType.INT); + return instructions; + } + + @Override + public String visitPlus(PlusContext ctx) { + return visitBinaryOperation("iadd", ctx); + } + + @Override + public String visitMinus(DemoParser.MinusContext ctx) { + return visitBinaryOperation("isub", ctx); + } + + @Override + public String visitDiv(DemoParser.DivContext ctx) { + return visitBinaryOperation("idiv", ctx); + } + + @Override + public String visitMult(DemoParser.MultContext ctx) { + return visitBinaryOperation("imul", ctx); + } + + @Override + public String visitRelational(DemoParser.RelationalContext ctx) { + int compareNum = compareCount++; + String jumpInstruction; + + switch (ctx.operator.getText()) { + case "<": + jumpInstruction = "if_icmplt"; + break; + case "<=": + jumpInstruction = "if_icmple"; + break; + case ">": + jumpInstruction = "if_icmpgt"; + break; + case ">=": + jumpInstruction = "if_icmpge"; + break; + default: + throw new IllegalArgumentException("Unknown operator : <" + ctx.operator.getText() + ">"); + } + + final String instructions = visitChildren(ctx) + "\n" + + jumpInstruction + " onTrue" + compareNum + "\n" + + "ldc 0\n" + + "goto onFalse" + compareNum + "\n" + + "onTrue" + compareNum + ":\n" + + "ldc 1\n" + + "onFalse" + compareNum + ":"; + jvmStack.pop(); + jvmStack.pop(); + jvmStack.push(DataType.INT); + return instructions; + } + + @Override + public String visitAnd(DemoParser.AndContext ctx) { + String left = visit(ctx.left); + String right = visit(ctx.right); + int andNum = andCounter++; + jvmStack.pop(); + jvmStack.pop(); + jvmStack.push(DataType.INT); + + return left + "\n" + + "ifeq onAndFalse" + andNum + "\n" + + right + "\n" + + "ifeq onAndFalse" + andNum + "\n" + + "ldc 1\n" + + "goto andEnd" + andNum + "\n" + + "onAndFalse" + andNum + ":\n" + + "ldc 0\n" + + "andEnd" + andNum + ":"; + } + + @Override + public String visitOr(DemoParser.OrContext ctx) { + String left = visit(ctx.left); + String right = visit(ctx.right); + int orNum = orCounter++; + jvmStack.pop(); + jvmStack.pop(); + jvmStack.push(DataType.INT); + + return left + "\n" + + "ifne onOrTrue" + orNum + "\n" + + right + "\n" + + "ifne onOrTrue" + orNum + "\n" + + "ldc 0\n" + + "goto orEnd" + orNum + "\n" + + "onOrTrue" + orNum + ":\n" + + "ldc 1\n" + + "orEnd" + orNum + ":"; + } + + @Override + public String visitPrintln(DemoParser.PrintlnContext ctx) { + String arg = visit(ctx.argument); + DataType type = jvmStack.pop(); + return "getstatic java/lang/System/out Ljava/io/PrintStream;\n" + + arg + "\n" + + "invokevirtual java/io/PrintStream/println(" + type.getJvmType() + ")V\n"; + } + + @Override + public String visitPrint(DemoParser.PrintContext ctx) { + String arg = visit(ctx.argument); + DataType type = jvmStack.pop(); + return "getstatic java/lang/System/out Ljava/io/PrintStream;\n" + + arg + "\n" + + "invokevirtual java/io/PrintStream/print(" + type.getJvmType() + ")V\n"; + } + + @Override + public String visitVariable(DemoParser.VariableContext ctx) { + jvmStack.push(DataType.INT); + return "iload " + requireVariableIndex(ctx.varName); + } + + private int requireVariableIndex(Token varName) { + Integer varIndex = variables.get(varName.getText()); + if (varIndex == null) { + throw new UndeclaredVariableException(varName); + } + return varIndex; + } + + @Override + public String visitVarDeclaration(DemoParser.VarDeclarationContext ctx) { + String key = ctx.varName.getText(); + if (variables.containsKey(key)) { + throw new VariableAlreadyDefinedException(ctx.varName); + } + variables.put(key, variables.size()); + return ""; + } + + @Override + public String visitBranch(DemoParser.BranchContext ctx) { + String condition = visit(ctx.condition); + jvmStack.pop(); + String onTrue = visit(ctx.onTrue); + String onFalse = visit(ctx.onFalse); + int branchNum = branchCounter++; + + return condition + "\n" + + "ifne ifTrue" + branchNum + "\n" + + onFalse + "\n" + + "goto endIf" + branchNum + "\n" + + "ifTrue" + branchNum + ":\n" + + onTrue + "\n" + + "endIf" + branchNum + ":\n"; + } + + @Override + public String visitAssignment(DemoParser.AssignmentContext ctx) { + final String instructions = visit(ctx.expr) + "\n" + + "istore " + requireVariableIndex(ctx.varName) + "\n"; + jvmStack.pop(); + return instructions; + } + + @Override + public String visitFunctionDefinition(DemoParser.FunctionDefinitionContext ctx) { + Map oldVars = this.variables; + JvmStack oldJvmStack = jvmStack; + jvmStack = new JvmStack(); + variables = new HashMap<>(); + visit(ctx.params); + String statements = visit(ctx.statements); + String instructions = ".method public static " + ctx.funcName.getText() + "("; + int numberOfParams = ctx.params.declarations.size(); + instructions += stringRepeat("I", numberOfParams); + instructions += ")I\n" + + ".limit locals 100\n" + + ".limit stack 100\n" + + (statements == null ? "" : statements + "\n") + + visit(ctx.retValue) + "\n" + + "ireturn\n" + + ".end method\n"; + jvmStack.pop(); + variables = oldVars; + jvmStack = oldJvmStack; + return instructions; + } + + private String stringRepeat(String string, int numberOfParams) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < numberOfParams; i++) { + result.append(string); + } + return result.toString(); + } + + @Override + public String visitFunctionCall(DemoParser.FunctionCallContext ctx) { + if (!definedFunctions.contains(ctx.funcName.getText(), ctx.args.expressions.size() )) { + throw new UndefinedFunctionException(ctx.funcName); + } + + String instructions = ""; + String args = visit(ctx.args); + if (args != null) { + instructions += args + "\n"; + } + instructions += "invokestatic HelloWorld/" + ctx.funcName.getText() + "("; + int numberOfParams = ctx.args.expressions.size(); + instructions += stringRepeat("I", numberOfParams); + instructions +=")I\n"; + for (int i = 0; i < numberOfParams; i++) { + jvmStack.pop(); + } + jvmStack.push(DataType.INT); + return instructions; + } + + @Override + public String visitProgram(DemoParser.ProgramContext ctx) { + StringBuilder mainCode = new StringBuilder(); + StringBuilder functions = new StringBuilder(); + + for (ParseTree child : ctx.children) { + final String instructions = visit(child); + if (child instanceof MainStatementContext) { + mainCode.append(instructions); + } else { + functions.append(instructions); + } + } + final String instructions = ".method public static main([Ljava/lang/String;)V\n" + + ".limit stack 100\n" + + ".limit locals 100\n" + + mainCode + "\n" + + "return\n" + + ".end method\n"; + + return functions.append(instructions).toString(); + } + + @Override + protected String aggregateResult(String aggregate, String nextResult) { + if (aggregate == null) { + return nextResult; + } + if (nextResult == null) { + return aggregate; + } + return aggregate + "\n" + nextResult; + } +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/JvmStack.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/JvmStack.java new file mode 100644 index 0000000..bde22ab --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/JvmStack.java @@ -0,0 +1,18 @@ +package de.letsbuildacompiler.compiler; + +import java.util.Deque; +import java.util.LinkedList; + +public class JvmStack { + + private Deque typesOnStack = new LinkedList<>(); + + public void push(DataType type) { + typesOnStack.push(type); + } + + public DataType pop() { + return typesOnStack.pop(); + } + +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/Main.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/Main.java new file mode 100644 index 0000000..591f7b8 --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/Main.java @@ -0,0 +1,33 @@ +package de.letsbuildacompiler.compiler; + +import de.letsbuildacompiler.parser.DemoLexer; +import de.letsbuildacompiler.parser.DemoParser; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CodePointCharStream; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; + +public class Main { + public static void main(String[] args) { + CodePointCharStream input = CharStreams.fromString("print(2 < 2);"); + System.out.println(compile(input)); + } + + public static String compile(CharStream input) { + DemoLexer lexer = new DemoLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + DemoParser parser = new DemoParser(tokens); + + ParseTree tree = parser.program(); + FunctionList definedFunctions = FunctionDefinitionFinder.findFunctions(tree); + return createJasminFile(new JasminVisitor(definedFunctions).visit(tree)); + } + + private static String createJasminFile(String instructions) { + return ".class public HelloWorld\n" + + ".super java/lang/Object\n" + + "\n" + + instructions; + } +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/CompileException.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/CompileException.java new file mode 100644 index 0000000..e0b29de --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/CompileException.java @@ -0,0 +1,13 @@ +package de.letsbuildacompiler.compiler.exceptions; + +import org.antlr.v4.runtime.Token; + +class CompileException extends RuntimeException { + int line; + int col; + + CompileException(Token token) { + line = token.getLine(); + col = token.getCharPositionInLine(); + } +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/FunctionAlreadyDefinedException.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/FunctionAlreadyDefinedException.java new file mode 100644 index 0000000..3ad4b5e --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/FunctionAlreadyDefinedException.java @@ -0,0 +1,18 @@ +package de.letsbuildacompiler.compiler.exceptions; + +import org.antlr.v4.runtime.Token; + +public class FunctionAlreadyDefinedException extends CompileException{ + + private String funcName; + + public FunctionAlreadyDefinedException(Token token) { + super(token); + funcName = token.getText(); + } + + @Override + public String getMessage() { + return line + ":" + col + " function already defined : <" + funcName + ">"; + } +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/UndeclaredVariableException.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/UndeclaredVariableException.java new file mode 100644 index 0000000..2f11f1a --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/UndeclaredVariableException.java @@ -0,0 +1,20 @@ +package de.letsbuildacompiler.compiler.exceptions; + + +import org.antlr.v4.runtime.Token; + +public class UndeclaredVariableException extends CompileException { + + private final String varName; + + public UndeclaredVariableException(Token token) { + super(token); + varName = token.getText(); + } + + @Override + public String getMessage() { + return line + ":" + col + " undeclared variable <" + varName + ">"; + } + +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/UndefinedFunctionException.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/UndefinedFunctionException.java new file mode 100644 index 0000000..f23496e --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/UndefinedFunctionException.java @@ -0,0 +1,18 @@ +package de.letsbuildacompiler.compiler.exceptions; + +import org.antlr.v4.runtime.Token; + +public class UndefinedFunctionException extends CompileException { + + private String funcName; + + public UndefinedFunctionException(Token token) { + super(token); + funcName = token.getText(); + } + + @Override + public String getMessage() { + return line + ":" + col + " call to undefined function : <" + funcName + ">"; + } +} diff --git a/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/VariableAlreadyDefinedException.java b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/VariableAlreadyDefinedException.java new file mode 100644 index 0000000..ceec844 --- /dev/null +++ b/compiler/src/main/java/de/letsbuildacompiler/compiler/exceptions/VariableAlreadyDefinedException.java @@ -0,0 +1,18 @@ +package de.letsbuildacompiler.compiler.exceptions; + +import org.antlr.v4.runtime.Token; + +public class VariableAlreadyDefinedException extends CompileException { + + private String varName; + + public VariableAlreadyDefinedException(Token token) { + super(token); + varName = token.getText(); + } + + @Override + public String getMessage() { + return line + ":" + col + " variable <" + varName + "> already defined"; + } +} diff --git a/compiler/src/test/java/de/letsbuildacompiler/compiler/CompilerTest.java b/compiler/src/test/java/de/letsbuildacompiler/compiler/CompilerTest.java new file mode 100644 index 0000000..8a8d03c --- /dev/null +++ b/compiler/src/test/java/de/letsbuildacompiler/compiler/CompilerTest.java @@ -0,0 +1,173 @@ +package de.letsbuildacompiler.compiler; + +import de.letsbuildacompiler.compiler.exceptions.FunctionAlreadyDefinedException; +import de.letsbuildacompiler.compiler.exceptions.UndeclaredVariableException; +import de.letsbuildacompiler.compiler.exceptions.UndefinedFunctionException; +import de.letsbuildacompiler.compiler.exceptions.VariableAlreadyDefinedException; +import jasmin.ClassFile; +import org.antlr.v4.runtime.CharStreams; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Objects; +import java.util.Scanner; + +import static org.testng.AssertJUnit.assertEquals; + +public class CompilerTest { + + private Path tempDir; + + @BeforeMethod + public void createTempDir() throws IOException { + tempDir = Files.createTempDirectory("compilerTest"); + } + + @AfterMethod + public void deleteTempDir() { + deleteRecursive(tempDir.toFile()); + } + + private void deleteRecursive(File file) { + if (file.isDirectory()) { + for (File f : Objects.requireNonNull(file.listFiles())) { + deleteRecursive(f); + } + } + + if (!file.delete()) { + throw new Error("Could not delete file <" + file + ">"); + } + } + + @Test(dataProvider = "provider") + @SuppressWarnings("unused") + public void runningCode_outputsExpectedText(String description, String code, String expectedText) throws Exception { + String actual = compileAndRun(code); + assertEquals(expectedText, actual); + } + + @DataProvider(name = "provider") + public Object[][] provide_code_expectedText() { + return new Object[][] { + {"plus", "println(1+2);", "3" + System.lineSeparator()}, + {"chained plus", "println(1+4+42);", "47" + System.lineSeparator()}, + {"multiple statements", "println(1); println(2);", "1" + System.lineSeparator() + "2" + System.lineSeparator()}, + {"minus", "println(3-2);", "1" + System.lineSeparator()}, + {"times", "println(3*3);", "9" + System.lineSeparator()}, + {"division", "println(6/3);", "2" + System.lineSeparator()}, + {"truncated division", "println(7/2);", "3" + System.lineSeparator()}, + {"operator precedence times and divide", "println(8/2*4);", "16" + System.lineSeparator()}, + {"operator precedence times and plus", "println(2+3*3);", "11" + System.lineSeparator()}, + {"operator precedence times and minus", "println(9-2*3);", "3" + System.lineSeparator()}, + {"operator precedence minus and plus", "println(8-2+5);", "11" + System.lineSeparator()}, + {"int variable", "int foo; foo = 42; println(foo);", "42" + System.lineSeparator()}, + {"add variable and constant parameters", + "int foo; foo = 42; println(foo+2);", "44" + System.lineSeparator()}, + {"add two variables parameters", + "int foo; int bar; foo = 42; bar = 43; println(foo+bar);", "85" + System.lineSeparator()}, + + example("functions/simple_function", "4" + System.lineSeparator()), + example("functions/scopes", "4" + System.lineSeparator() + "42" + System.lineSeparator()), + example("functions/int_parameters", "13" + System.lineSeparator()), + example("branch/if_int_false", "42" + System.lineSeparator()), + example("branch/if_int_true", "81" + System.lineSeparator()), + + {"lower than true", "println(1 < 2);", "1" + System.lineSeparator()}, + {"lower than false", "println(2 < 2);", "0" + System.lineSeparator()}, + {"lower or equal true", "println(1 <= 1);", "1" + System.lineSeparator()}, + {"lower or equal false", "println(3 <= 2);", "0" + System.lineSeparator()}, + + {"greater than true", "println(3 > 2);", "1" + System.lineSeparator()}, + {"greater than false", "println(3 > 3);", "0" + System.lineSeparator()}, + {"greater or equal true", "println(3 >= 3);", "1" + System.lineSeparator()}, + {"greater or equal false", "println(2 >= 3);", "0" + System.lineSeparator()}, + + {"and true", "println(1 && 1);", "1" + System.lineSeparator()}, + {"and left false", "println(0 && 1);", "0" + System.lineSeparator()}, + {"and right false", "println(1 && 0);", "0" + System.lineSeparator()}, + example("operators/and-skip-right", "0" + System.lineSeparator() + "0" + System.lineSeparator()), + + {"or false", "println(0 || 0);", "0" + System.lineSeparator()}, + {"or left true", "println(1 || 0);", "1" + System.lineSeparator()}, + {"or right true", "println(0 || 1);", "1" + System.lineSeparator()}, + example("operators/or-skip-right", "1" + System.lineSeparator() + "1" + System.lineSeparator()), + + {"print", "print(42);", "42"}, + {"print string litteral", "print(\"Hello world\");", "Hello world"}, + }; + } + + @Test(expectedExceptions = UndeclaredVariableException.class, + expectedExceptionsMessageRegExp = "1:8 undeclared variable ") + public void compilingCode_throwsUndeclaredVariableException_ifReadingUndefinedVariable() throws Exception { + compileAndRun("println(x);"); + // evaluation performed by expected exception. + } + + @Test(expectedExceptions = UndeclaredVariableException.class, + expectedExceptionsMessageRegExp = "1:0 undeclared variable ") + public void compilingCode_throwsUndeclaredVariableException_ifWritingUndefinedVariable() throws Exception { + compileAndRun("x = 5;"); + // evaluation performed by expected exception. + } + + @Test(expectedExceptions = VariableAlreadyDefinedException.class, + expectedExceptionsMessageRegExp = "2:4 variable already defined") + public void compilingCode_throwsAlreadyDefinedException_whenDefiningAlreadyDefinedVariable() throws Exception { + compileAndRun("int x;" + System.lineSeparator() + + "int x;"); + // evaluation performed by expected exception. + } + + @Test(expectedExceptions = UndefinedFunctionException.class, + expectedExceptionsMessageRegExp = "1:8 call to undefined function : ") + public void compilingCode_throwsUndefinedFunctionException_whenCallingUndefinedFunction() throws Exception { + compileAndRun("println(undefinedFunction());"); + // evaluation performed by expected exception. + } + + @Test(expectedExceptions = FunctionAlreadyDefinedException.class, + expectedExceptionsMessageRegExp = "2:4 function already defined : ") + public void compilingCode_throwsAlreadyDefinedFunctionException_whenDefiningFunctionTwice() throws Exception { + compileAndRun("int x() { return 42; }\n" + + "int x() { return 45; }"); + // evaluation performed by expected exception. + } + + private String compileAndRun(String code) throws Exception { + code = Main.compile(CharStreams.fromString(code)); + ClassFile classFile = new ClassFile(); + classFile.readJasmin(new StringReader(code), "", false); + Path outputPath = tempDir.resolve(classFile.getClassName() + ".class"); + try (OutputStream outputStream = Files.newOutputStream(outputPath)) { + classFile.write(outputStream); + } + return runJavaClass(tempDir, classFile.getClassName()); + } + + private String runJavaClass(Path dir, String className) throws IOException { + Process process = Runtime.getRuntime().exec(new String[]{"java", "-cp", dir.toString(), className}); + try (InputStream in = process.getInputStream()) { + return new Scanner(in).useDelimiter("\\A").next(); + } + } + + private String[] example(String name, String expectedResult) throws IllegalArgumentException { + try (InputStream in = CompilerTest.class.getClassLoader().getResourceAsStream("examples/" + name)) { + if (in == null) { + throw new IllegalArgumentException("No such example " + name); + } + String code = new Scanner(in, "UTF-8").useDelimiter("\\A").next(); + + return new String[] {name, code, expectedResult}; + } catch (IOException e) { + throw new IllegalArgumentException("No such example " + name); + } + } +} \ No newline at end of file diff --git a/compiler/src/test/test-resources/examples/branch/if_int_false b/compiler/src/test/test-resources/examples/branch/if_int_false new file mode 100644 index 0000000..763f1e5 --- /dev/null +++ b/compiler/src/test/test-resources/examples/branch/if_int_false @@ -0,0 +1,5 @@ +if (0) { + println(81); +} else { + println(42); +} \ No newline at end of file diff --git a/compiler/src/test/test-resources/examples/branch/if_int_true b/compiler/src/test/test-resources/examples/branch/if_int_true new file mode 100644 index 0000000..456cbc3 --- /dev/null +++ b/compiler/src/test/test-resources/examples/branch/if_int_true @@ -0,0 +1,5 @@ +if(1){ + println(81); +} else{ + println(42); +} \ No newline at end of file diff --git a/compiler/src/test/test-resources/examples/functions/int_parameters b/compiler/src/test/test-resources/examples/functions/int_parameters new file mode 100644 index 0000000..d35553d --- /dev/null +++ b/compiler/src/test/test-resources/examples/functions/int_parameters @@ -0,0 +1,5 @@ +int add(int a, int b) { + return a + b; +} + +println(add(5, 8)); \ No newline at end of file diff --git a/compiler/src/test/test-resources/examples/functions/scopes b/compiler/src/test/test-resources/examples/functions/scopes new file mode 100644 index 0000000..f680f90 --- /dev/null +++ b/compiler/src/test/test-resources/examples/functions/scopes @@ -0,0 +1,9 @@ +int i; +i = 42; +int randomNumber() { + int i; + i = 4; + return i; +} +println(randomNumber()); +println(i); \ No newline at end of file diff --git a/compiler/src/test/test-resources/examples/functions/simple_function b/compiler/src/test/test-resources/examples/functions/simple_function new file mode 100644 index 0000000..cbfc0b2 --- /dev/null +++ b/compiler/src/test/test-resources/examples/functions/simple_function @@ -0,0 +1,5 @@ +int number() { + return 4; +} + +println(number()); \ No newline at end of file diff --git a/compiler/src/test/test-resources/examples/operators/and-skip-right b/compiler/src/test/test-resources/examples/operators/and-skip-right new file mode 100644 index 0000000..fb7be68 --- /dev/null +++ b/compiler/src/test/test-resources/examples/operators/and-skip-right @@ -0,0 +1,6 @@ +int x(int i) { + println(i); + return i; +} + +println(x(0) && x(1)); \ No newline at end of file diff --git a/compiler/src/test/test-resources/examples/operators/or-skip-right b/compiler/src/test/test-resources/examples/operators/or-skip-right new file mode 100644 index 0000000..f53e56a --- /dev/null +++ b/compiler/src/test/test-resources/examples/operators/or-skip-right @@ -0,0 +1,6 @@ +int x(int i) { + println(i); + return i; +} + +println(x(1) || x(0)); \ No newline at end of file diff --git a/compiler/target/test-classes/examples/branch/if_int_false b/compiler/target/test-classes/examples/branch/if_int_false new file mode 100644 index 0000000..763f1e5 --- /dev/null +++ b/compiler/target/test-classes/examples/branch/if_int_false @@ -0,0 +1,5 @@ +if (0) { + println(81); +} else { + println(42); +} \ No newline at end of file diff --git a/compiler/target/test-classes/examples/branch/if_int_true b/compiler/target/test-classes/examples/branch/if_int_true new file mode 100644 index 0000000..456cbc3 --- /dev/null +++ b/compiler/target/test-classes/examples/branch/if_int_true @@ -0,0 +1,5 @@ +if(1){ + println(81); +} else{ + println(42); +} \ No newline at end of file diff --git a/compiler/target/test-classes/examples/functions/int_parameters b/compiler/target/test-classes/examples/functions/int_parameters new file mode 100644 index 0000000..d35553d --- /dev/null +++ b/compiler/target/test-classes/examples/functions/int_parameters @@ -0,0 +1,5 @@ +int add(int a, int b) { + return a + b; +} + +println(add(5, 8)); \ No newline at end of file diff --git a/compiler/target/test-classes/examples/functions/scopes b/compiler/target/test-classes/examples/functions/scopes new file mode 100644 index 0000000..f680f90 --- /dev/null +++ b/compiler/target/test-classes/examples/functions/scopes @@ -0,0 +1,9 @@ +int i; +i = 42; +int randomNumber() { + int i; + i = 4; + return i; +} +println(randomNumber()); +println(i); \ No newline at end of file diff --git a/compiler/target/test-classes/examples/functions/simple_function b/compiler/target/test-classes/examples/functions/simple_function new file mode 100644 index 0000000..cbfc0b2 --- /dev/null +++ b/compiler/target/test-classes/examples/functions/simple_function @@ -0,0 +1,5 @@ +int number() { + return 4; +} + +println(number()); \ No newline at end of file diff --git a/compiler/target/test-classes/examples/operators/and-skip-right b/compiler/target/test-classes/examples/operators/and-skip-right new file mode 100644 index 0000000..fb7be68 --- /dev/null +++ b/compiler/target/test-classes/examples/operators/and-skip-right @@ -0,0 +1,6 @@ +int x(int i) { + println(i); + return i; +} + +println(x(0) && x(1)); \ No newline at end of file diff --git a/compiler/target/test-classes/examples/operators/or-skip-right b/compiler/target/test-classes/examples/operators/or-skip-right new file mode 100644 index 0000000..f53e56a --- /dev/null +++ b/compiler/target/test-classes/examples/operators/or-skip-right @@ -0,0 +1,6 @@ +int x(int i) { + println(i); + return i; +} + +println(x(1) || x(0)); \ No newline at end of file diff --git a/parser/pom.xml b/parser/pom.xml new file mode 100644 index 0000000..16d5de0 --- /dev/null +++ b/parser/pom.xml @@ -0,0 +1,15 @@ + + + + compiler + org.example + 1.0-SNAPSHOT + + 4.0.0 + + parser + + + \ No newline at end of file diff --git a/parser/src/main/java/de/letsbuildacompiler/parser/Demo.interp b/parser/src/main/java/de/letsbuildacompiler/parser/Demo.interp new file mode 100644 index 0000000..c45b1a7 --- /dev/null +++ b/parser/src/main/java/de/letsbuildacompiler/parser/Demo.interp @@ -0,0 +1,52 @@ +token literal names: +null +';' +'/' +'*' +'-' +'+' +'int' +'=' +'print(' +')' +'(' +'{' +'return' +'}' +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +null +null +null +IDENTIFIER +NUMBER +WHITESPACE + +rule names: +program +programPart +statement +expression +varDeclaration +assignment +print +functionDefinition +functionCall + + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 18, 85, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 3, 2, 6, 2, 22, 10, 2, 13, 2, 14, 2, 23, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 30, 10, 3, 3, 4, 3, 4, 3, 4, 5, 4, 35, 10, 4, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 41, 10, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 7, 5, 55, 10, 5, 12, 5, 14, 5, 58, 11, 5, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 2, 3, 8, 11, 2, 4, 6, 8, 10, 12, 14, 16, 18, 2, 2, 2, 85, 2, 21, 3, 2, 2, 2, 4, 29, 3, 2, 2, 2, 6, 34, 3, 2, 2, 2, 8, 40, 3, 2, 2, 2, 10, 59, 3, 2, 2, 2, 12, 62, 3, 2, 2, 2, 14, 66, 3, 2, 2, 2, 16, 70, 3, 2, 2, 2, 18, 80, 3, 2, 2, 2, 20, 22, 5, 4, 3, 2, 21, 20, 3, 2, 2, 2, 22, 23, 3, 2, 2, 2, 23, 21, 3, 2, 2, 2, 23, 24, 3, 2, 2, 2, 24, 3, 3, 2, 2, 2, 25, 26, 5, 6, 4, 2, 26, 27, 7, 3, 2, 2, 27, 30, 3, 2, 2, 2, 28, 30, 5, 16, 9, 2, 29, 25, 3, 2, 2, 2, 29, 28, 3, 2, 2, 2, 30, 5, 3, 2, 2, 2, 31, 35, 5, 14, 8, 2, 32, 35, 5, 10, 6, 2, 33, 35, 5, 12, 7, 2, 34, 31, 3, 2, 2, 2, 34, 32, 3, 2, 2, 2, 34, 33, 3, 2, 2, 2, 35, 7, 3, 2, 2, 2, 36, 37, 8, 5, 1, 2, 37, 41, 7, 17, 2, 2, 38, 41, 7, 16, 2, 2, 39, 41, 5, 18, 10, 2, 40, 36, 3, 2, 2, 2, 40, 38, 3, 2, 2, 2, 40, 39, 3, 2, 2, 2, 41, 56, 3, 2, 2, 2, 42, 43, 12, 9, 2, 2, 43, 44, 7, 4, 2, 2, 44, 55, 5, 8, 5, 10, 45, 46, 12, 8, 2, 2, 46, 47, 7, 5, 2, 2, 47, 55, 5, 8, 5, 9, 48, 49, 12, 7, 2, 2, 49, 50, 7, 6, 2, 2, 50, 55, 5, 8, 5, 8, 51, 52, 12, 6, 2, 2, 52, 53, 7, 7, 2, 2, 53, 55, 5, 8, 5, 7, 54, 42, 3, 2, 2, 2, 54, 45, 3, 2, 2, 2, 54, 48, 3, 2, 2, 2, 54, 51, 3, 2, 2, 2, 55, 58, 3, 2, 2, 2, 56, 54, 3, 2, 2, 2, 56, 57, 3, 2, 2, 2, 57, 9, 3, 2, 2, 2, 58, 56, 3, 2, 2, 2, 59, 60, 7, 8, 2, 2, 60, 61, 7, 16, 2, 2, 61, 11, 3, 2, 2, 2, 62, 63, 7, 16, 2, 2, 63, 64, 7, 9, 2, 2, 64, 65, 5, 8, 5, 2, 65, 13, 3, 2, 2, 2, 66, 67, 7, 10, 2, 2, 67, 68, 5, 8, 5, 2, 68, 69, 7, 11, 2, 2, 69, 15, 3, 2, 2, 2, 70, 71, 7, 8, 2, 2, 71, 72, 7, 16, 2, 2, 72, 73, 7, 12, 2, 2, 73, 74, 7, 11, 2, 2, 74, 75, 7, 13, 2, 2, 75, 76, 7, 14, 2, 2, 76, 77, 5, 8, 5, 2, 77, 78, 7, 3, 2, 2, 78, 79, 7, 15, 2, 2, 79, 17, 3, 2, 2, 2, 80, 81, 7, 16, 2, 2, 81, 82, 7, 12, 2, 2, 82, 83, 7, 11, 2, 2, 83, 19, 3, 2, 2, 2, 8, 23, 29, 34, 40, 54, 56] \ No newline at end of file diff --git a/parser/src/main/java/de/letsbuildacompiler/parser/Demo.tokens b/parser/src/main/java/de/letsbuildacompiler/parser/Demo.tokens new file mode 100644 index 0000000..899fb50 --- /dev/null +++ b/parser/src/main/java/de/letsbuildacompiler/parser/Demo.tokens @@ -0,0 +1,50 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +IDENTIFIER=24 +NUMBER=25 +WHITESPACE=26 +STRING=27 +';'=1 +'if'=2 +'('=3 +')'=4 +'else'=5 +'{'=6 +'}'=7 +'/'=8 +'*'=9 +'-'=10 +'+'=11 +'<'=12 +'<='=13 +'>'=14 +'>='=15 +'&&'=16 +'||'=17 +'int'=18 +'='=19 +'println('=20 +'print('=21 +'return'=22 +','=23 diff --git a/parser/src/main/java/de/letsbuildacompiler/parser/DemoBaseVisitor.java b/parser/src/main/java/de/letsbuildacompiler/parser/DemoBaseVisitor.java new file mode 100644 index 0000000..78662c3 --- /dev/null +++ b/parser/src/main/java/de/letsbuildacompiler/parser/DemoBaseVisitor.java @@ -0,0 +1,196 @@ +// Generated from /home/thibaud/Programmation/Java/antlr-compiler/Demo.g4 by ANTLR 4.7 +package de.letsbuildacompiler.parser; +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link DemoVisitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class DemoBaseVisitor extends AbstractParseTreeVisitor implements DemoVisitor { + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitProgram(DemoParser.ProgramContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMainStatement(DemoParser.MainStatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitProgPartFunctionDefinition(DemoParser.ProgPartFunctionDefinitionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitStatement(DemoParser.StatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBranch(DemoParser.BranchContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitBlock(DemoParser.BlockContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitDiv(DemoParser.DivContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitVariable(DemoParser.VariableContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFuncCallExpression(DemoParser.FuncCallExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitOr(DemoParser.OrContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitNumber(DemoParser.NumberContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMult(DemoParser.MultContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitAnd(DemoParser.AndContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitRelational(DemoParser.RelationalContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitString(DemoParser.StringContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPlus(DemoParser.PlusContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitMinus(DemoParser.MinusContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitVarDeclaration(DemoParser.VarDeclarationContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitAssignment(DemoParser.AssignmentContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPrintln(DemoParser.PrintlnContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitPrint(DemoParser.PrintContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFunctionDefinition(DemoParser.FunctionDefinitionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitStatementList(DemoParser.StatementListContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitParameters(DemoParser.ParametersContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFunctionCall(DemoParser.FunctionCallContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitExpressionList(DemoParser.ExpressionListContext ctx) { return visitChildren(ctx); } +} \ No newline at end of file diff --git a/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.interp b/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.interp new file mode 100644 index 0000000..20b9e01 --- /dev/null +++ b/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.interp @@ -0,0 +1,65 @@ +token literal names: +null +';' +'/' +'*' +'-' +'+' +'int' +'=' +'print(' +')' +'(' +'{' +'return' +'}' +null +null +null + +token symbolic names: +null +null +null +null +null +null +null +null +null +null +null +null +null +null +IDENTIFIER +NUMBER +WHITESPACE + +rule names: +T__0 +T__1 +T__2 +T__3 +T__4 +T__5 +T__6 +T__7 +T__8 +T__9 +T__10 +T__11 +T__12 +IDENTIFIER +NUMBER +WHITESPACE + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 18, 92, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 7, 15, 76, 10, 15, 12, 15, 14, 15, 79, 11, 15, 3, 16, 6, 16, 82, 10, 16, 13, 16, 14, 16, 83, 3, 17, 6, 17, 87, 10, 17, 13, 17, 14, 17, 88, 3, 17, 3, 17, 2, 2, 18, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 3, 2, 6, 4, 2, 67, 92, 99, 124, 5, 2, 50, 59, 67, 92, 99, 124, 3, 2, 50, 59, 5, 2, 11, 12, 15, 15, 34, 34, 2, 94, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 3, 35, 3, 2, 2, 2, 5, 37, 3, 2, 2, 2, 7, 39, 3, 2, 2, 2, 9, 41, 3, 2, 2, 2, 11, 43, 3, 2, 2, 2, 13, 45, 3, 2, 2, 2, 15, 49, 3, 2, 2, 2, 17, 51, 3, 2, 2, 2, 19, 58, 3, 2, 2, 2, 21, 60, 3, 2, 2, 2, 23, 62, 3, 2, 2, 2, 25, 64, 3, 2, 2, 2, 27, 71, 3, 2, 2, 2, 29, 73, 3, 2, 2, 2, 31, 81, 3, 2, 2, 2, 33, 86, 3, 2, 2, 2, 35, 36, 7, 61, 2, 2, 36, 4, 3, 2, 2, 2, 37, 38, 7, 49, 2, 2, 38, 6, 3, 2, 2, 2, 39, 40, 7, 44, 2, 2, 40, 8, 3, 2, 2, 2, 41, 42, 7, 47, 2, 2, 42, 10, 3, 2, 2, 2, 43, 44, 7, 45, 2, 2, 44, 12, 3, 2, 2, 2, 45, 46, 7, 107, 2, 2, 46, 47, 7, 112, 2, 2, 47, 48, 7, 118, 2, 2, 48, 14, 3, 2, 2, 2, 49, 50, 7, 63, 2, 2, 50, 16, 3, 2, 2, 2, 51, 52, 7, 114, 2, 2, 52, 53, 7, 116, 2, 2, 53, 54, 7, 107, 2, 2, 54, 55, 7, 112, 2, 2, 55, 56, 7, 118, 2, 2, 56, 57, 7, 42, 2, 2, 57, 18, 3, 2, 2, 2, 58, 59, 7, 43, 2, 2, 59, 20, 3, 2, 2, 2, 60, 61, 7, 42, 2, 2, 61, 22, 3, 2, 2, 2, 62, 63, 7, 125, 2, 2, 63, 24, 3, 2, 2, 2, 64, 65, 7, 116, 2, 2, 65, 66, 7, 103, 2, 2, 66, 67, 7, 118, 2, 2, 67, 68, 7, 119, 2, 2, 68, 69, 7, 116, 2, 2, 69, 70, 7, 112, 2, 2, 70, 26, 3, 2, 2, 2, 71, 72, 7, 127, 2, 2, 72, 28, 3, 2, 2, 2, 73, 77, 9, 2, 2, 2, 74, 76, 9, 3, 2, 2, 75, 74, 3, 2, 2, 2, 76, 79, 3, 2, 2, 2, 77, 75, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 30, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 80, 82, 9, 4, 2, 2, 81, 80, 3, 2, 2, 2, 82, 83, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 32, 3, 2, 2, 2, 85, 87, 9, 5, 2, 2, 86, 85, 3, 2, 2, 2, 87, 88, 3, 2, 2, 2, 88, 86, 3, 2, 2, 2, 88, 89, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 91, 8, 17, 2, 2, 91, 34, 3, 2, 2, 2, 6, 2, 77, 83, 88, 3, 8, 2, 2] \ No newline at end of file diff --git a/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.java b/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.java new file mode 100644 index 0000000..63ebbf8 --- /dev/null +++ b/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.java @@ -0,0 +1,160 @@ +// Generated from /home/thibaud/Programmation/Java/antlr-compiler/Demo.g4 by ANTLR 4.7 +package de.letsbuildacompiler.parser; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class DemoLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, IDENTIFIER=24, + NUMBER=25, WHITESPACE=26, STRING=27; + public static String[] channelNames = { + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + }; + + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + public static final String[] ruleNames = { + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "IDENTIFIER", "NUMBER", + "WHITESPACE", "STRING" + }; + + private static final String[] _LITERAL_NAMES = { + null, "';'", "'if'", "'('", "')'", "'else'", "'{'", "'}'", "'/'", "'*'", + "'-'", "'+'", "'<'", "'<='", "'>'", "'>='", "'&&'", "'||'", "'int'", "'='", + "'println('", "'print('", "'return'", "','" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + "IDENTIFIER", "NUMBER", "WHITESPACE", "STRING" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public DemoLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "Demo.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getChannelNames() { return channelNames; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\35\u009e\b\1\4\2"+ + "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+ + "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ + "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+ + "\t\31\4\32\t\32\4\33\t\33\4\34\t\34\3\2\3\2\3\3\3\3\3\3\3\4\3\4\3\5\3"+ + "\5\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3"+ + "\f\3\r\3\r\3\16\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\21\3\21\3\21\3\22"+ + "\3\22\3\22\3\23\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25"+ + "\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27"+ + "\3\27\3\27\3\27\3\30\3\30\3\31\3\31\7\31\u0085\n\31\f\31\16\31\u0088\13"+ + "\31\3\32\6\32\u008b\n\32\r\32\16\32\u008c\3\33\6\33\u0090\n\33\r\33\16"+ + "\33\u0091\3\33\3\33\3\34\3\34\7\34\u0098\n\34\f\34\16\34\u009b\13\34\3"+ + "\34\3\34\3\u0099\2\35\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27"+ + "\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33"+ + "\65\34\67\35\3\2\6\4\2C\\c|\5\2\62;C\\c|\3\2\62;\5\2\13\f\17\17\"\"\2"+ + "\u00a1\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2"+ + "\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3"+ + "\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2"+ + "\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2"+ + "/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\39\3\2\2"+ + "\2\5;\3\2\2\2\7>\3\2\2\2\t@\3\2\2\2\13B\3\2\2\2\rG\3\2\2\2\17I\3\2\2\2"+ + "\21K\3\2\2\2\23M\3\2\2\2\25O\3\2\2\2\27Q\3\2\2\2\31S\3\2\2\2\33U\3\2\2"+ + "\2\35X\3\2\2\2\37Z\3\2\2\2!]\3\2\2\2#`\3\2\2\2%c\3\2\2\2\'g\3\2\2\2)i"+ + "\3\2\2\2+r\3\2\2\2-y\3\2\2\2/\u0080\3\2\2\2\61\u0082\3\2\2\2\63\u008a"+ + "\3\2\2\2\65\u008f\3\2\2\2\67\u0095\3\2\2\29:\7=\2\2:\4\3\2\2\2;<\7k\2"+ + "\2<=\7h\2\2=\6\3\2\2\2>?\7*\2\2?\b\3\2\2\2@A\7+\2\2A\n\3\2\2\2BC\7g\2"+ + "\2CD\7n\2\2DE\7u\2\2EF\7g\2\2F\f\3\2\2\2GH\7}\2\2H\16\3\2\2\2IJ\7\177"+ + "\2\2J\20\3\2\2\2KL\7\61\2\2L\22\3\2\2\2MN\7,\2\2N\24\3\2\2\2OP\7/\2\2"+ + "P\26\3\2\2\2QR\7-\2\2R\30\3\2\2\2ST\7>\2\2T\32\3\2\2\2UV\7>\2\2VW\7?\2"+ + "\2W\34\3\2\2\2XY\7@\2\2Y\36\3\2\2\2Z[\7@\2\2[\\\7?\2\2\\ \3\2\2\2]^\7"+ + "(\2\2^_\7(\2\2_\"\3\2\2\2`a\7~\2\2ab\7~\2\2b$\3\2\2\2cd\7k\2\2de\7p\2"+ + "\2ef\7v\2\2f&\3\2\2\2gh\7?\2\2h(\3\2\2\2ij\7r\2\2jk\7t\2\2kl\7k\2\2lm"+ + "\7p\2\2mn\7v\2\2no\7n\2\2op\7p\2\2pq\7*\2\2q*\3\2\2\2rs\7r\2\2st\7t\2"+ + "\2tu\7k\2\2uv\7p\2\2vw\7v\2\2wx\7*\2\2x,\3\2\2\2yz\7t\2\2z{\7g\2\2{|\7"+ + "v\2\2|}\7w\2\2}~\7t\2\2~\177\7p\2\2\177.\3\2\2\2\u0080\u0081\7.\2\2\u0081"+ + "\60\3\2\2\2\u0082\u0086\t\2\2\2\u0083\u0085\t\3\2\2\u0084\u0083\3\2\2"+ + "\2\u0085\u0088\3\2\2\2\u0086\u0084\3\2\2\2\u0086\u0087\3\2\2\2\u0087\62"+ + "\3\2\2\2\u0088\u0086\3\2\2\2\u0089\u008b\t\4\2\2\u008a\u0089\3\2\2\2\u008b"+ + "\u008c\3\2\2\2\u008c\u008a\3\2\2\2\u008c\u008d\3\2\2\2\u008d\64\3\2\2"+ + "\2\u008e\u0090\t\5\2\2\u008f\u008e\3\2\2\2\u0090\u0091\3\2\2\2\u0091\u008f"+ + "\3\2\2\2\u0091\u0092\3\2\2\2\u0092\u0093\3\2\2\2\u0093\u0094\b\33\2\2"+ + "\u0094\66\3\2\2\2\u0095\u0099\7$\2\2\u0096\u0098\13\2\2\2\u0097\u0096"+ + "\3\2\2\2\u0098\u009b\3\2\2\2\u0099\u009a\3\2\2\2\u0099\u0097\3\2\2\2\u009a"+ + "\u009c\3\2\2\2\u009b\u0099\3\2\2\2\u009c\u009d\7$\2\2\u009d8\3\2\2\2\7"+ + "\2\u0086\u008c\u0091\u0099\3\b\2\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.tokens b/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.tokens new file mode 100644 index 0000000..899fb50 --- /dev/null +++ b/parser/src/main/java/de/letsbuildacompiler/parser/DemoLexer.tokens @@ -0,0 +1,50 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +T__16=17 +T__17=18 +T__18=19 +T__19=20 +T__20=21 +T__21=22 +T__22=23 +IDENTIFIER=24 +NUMBER=25 +WHITESPACE=26 +STRING=27 +';'=1 +'if'=2 +'('=3 +')'=4 +'else'=5 +'{'=6 +'}'=7 +'/'=8 +'*'=9 +'-'=10 +'+'=11 +'<'=12 +'<='=13 +'>'=14 +'>='=15 +'&&'=16 +'||'=17 +'int'=18 +'='=19 +'println('=20 +'print('=21 +'return'=22 +','=23 diff --git a/parser/src/main/java/de/letsbuildacompiler/parser/DemoParser.java b/parser/src/main/java/de/letsbuildacompiler/parser/DemoParser.java new file mode 100644 index 0000000..9c94054 --- /dev/null +++ b/parser/src/main/java/de/letsbuildacompiler/parser/DemoParser.java @@ -0,0 +1,1317 @@ +// Generated from /home/thibaud/Programmation/Java/antlr-compiler/Demo.g4 by ANTLR 4.7 +package de.letsbuildacompiler.parser; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class DemoParser extends Parser { + static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, IDENTIFIER=24, + NUMBER=25, WHITESPACE=26, STRING=27; + public static final int + RULE_program = 0, RULE_programPart = 1, RULE_statement = 2, RULE_branch = 3, + RULE_block = 4, RULE_expression = 5, RULE_varDeclaration = 6, RULE_assignment = 7, + RULE_println = 8, RULE_print = 9, RULE_functionDefinition = 10, RULE_statementList = 11, + RULE_parameters = 12, RULE_functionCall = 13, RULE_expressionList = 14; + public static final String[] ruleNames = { + "program", "programPart", "statement", "branch", "block", "expression", + "varDeclaration", "assignment", "println", "print", "functionDefinition", + "statementList", "parameters", "functionCall", "expressionList" + }; + + private static final String[] _LITERAL_NAMES = { + null, "';'", "'if'", "'('", "')'", "'else'", "'{'", "'}'", "'/'", "'*'", + "'-'", "'+'", "'<'", "'<='", "'>'", "'>='", "'&&'", "'||'", "'int'", "'='", + "'println('", "'print('", "'return'", "','" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + "IDENTIFIER", "NUMBER", "WHITESPACE", "STRING" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "Demo.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + public DemoParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + public static class ProgramContext extends ParserRuleContext { + public List programPart() { + return getRuleContexts(ProgramPartContext.class); + } + public ProgramPartContext programPart(int i) { + return getRuleContext(ProgramPartContext.class,i); + } + public ProgramContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_program; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitProgram(this); + else return visitor.visitChildren(this); + } + } + + public final ProgramContext program() throws RecognitionException { + ProgramContext _localctx = new ProgramContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_program); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(31); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(30); + programPart(); + } + } + setState(33); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__1) | (1L << T__17) | (1L << T__19) | (1L << T__20) | (1L << IDENTIFIER))) != 0) ); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ProgramPartContext extends ParserRuleContext { + public ProgramPartContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_programPart; } + + public ProgramPartContext() { } + public void copyFrom(ProgramPartContext ctx) { + super.copyFrom(ctx); + } + } + public static class MainStatementContext extends ProgramPartContext { + public StatementContext statement() { + return getRuleContext(StatementContext.class,0); + } + public MainStatementContext(ProgramPartContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitMainStatement(this); + else return visitor.visitChildren(this); + } + } + public static class ProgPartFunctionDefinitionContext extends ProgramPartContext { + public FunctionDefinitionContext functionDefinition() { + return getRuleContext(FunctionDefinitionContext.class,0); + } + public ProgPartFunctionDefinitionContext(ProgramPartContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitProgPartFunctionDefinition(this); + else return visitor.visitChildren(this); + } + } + + public final ProgramPartContext programPart() throws RecognitionException { + ProgramPartContext _localctx = new ProgramPartContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_programPart); + try { + setState(37); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,1,_ctx) ) { + case 1: + _localctx = new MainStatementContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(35); + statement(); + } + break; + case 2: + _localctx = new ProgPartFunctionDefinitionContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(36); + functionDefinition(); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class StatementContext extends ParserRuleContext { + public PrintlnContext println() { + return getRuleContext(PrintlnContext.class,0); + } + public PrintContext print() { + return getRuleContext(PrintContext.class,0); + } + public VarDeclarationContext varDeclaration() { + return getRuleContext(VarDeclarationContext.class,0); + } + public AssignmentContext assignment() { + return getRuleContext(AssignmentContext.class,0); + } + public BranchContext branch() { + return getRuleContext(BranchContext.class,0); + } + public StatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_statement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitStatement(this); + else return visitor.visitChildren(this); + } + } + + public final StatementContext statement() throws RecognitionException { + StatementContext _localctx = new StatementContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_statement); + try { + setState(52); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__19: + enterOuterAlt(_localctx, 1); + { + setState(39); + println(); + setState(40); + match(T__0); + } + break; + case T__20: + enterOuterAlt(_localctx, 2); + { + setState(42); + print(); + setState(43); + match(T__0); + } + break; + case T__17: + enterOuterAlt(_localctx, 3); + { + setState(45); + varDeclaration(); + setState(46); + match(T__0); + } + break; + case IDENTIFIER: + enterOuterAlt(_localctx, 4); + { + setState(48); + assignment(); + setState(49); + match(T__0); + } + break; + case T__1: + enterOuterAlt(_localctx, 5); + { + setState(51); + branch(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class BranchContext extends ParserRuleContext { + public ExpressionContext condition; + public BlockContext onTrue; + public BlockContext onFalse; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List block() { + return getRuleContexts(BlockContext.class); + } + public BlockContext block(int i) { + return getRuleContext(BlockContext.class,i); + } + public BranchContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_branch; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitBranch(this); + else return visitor.visitChildren(this); + } + } + + public final BranchContext branch() throws RecognitionException { + BranchContext _localctx = new BranchContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_branch); + try { + enterOuterAlt(_localctx, 1); + { + setState(54); + match(T__1); + setState(55); + match(T__2); + setState(56); + ((BranchContext)_localctx).condition = expression(0); + setState(57); + match(T__3); + setState(58); + ((BranchContext)_localctx).onTrue = block(); + setState(59); + match(T__4); + setState(60); + ((BranchContext)_localctx).onFalse = block(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class BlockContext extends ParserRuleContext { + public StatementListContext statementList() { + return getRuleContext(StatementListContext.class,0); + } + public BlockContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_block; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitBlock(this); + else return visitor.visitChildren(this); + } + } + + public final BlockContext block() throws RecognitionException { + BlockContext _localctx = new BlockContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_block); + try { + enterOuterAlt(_localctx, 1); + { + setState(62); + match(T__5); + setState(63); + statementList(); + setState(64); + match(T__6); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ExpressionContext extends ParserRuleContext { + public ExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_expression; } + + public ExpressionContext() { } + public void copyFrom(ExpressionContext ctx) { + super.copyFrom(ctx); + } + } + public static class DivContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public DivContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitDiv(this); + else return visitor.visitChildren(this); + } + } + public static class VariableContext extends ExpressionContext { + public Token varName; + public TerminalNode IDENTIFIER() { return getToken(DemoParser.IDENTIFIER, 0); } + public VariableContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitVariable(this); + else return visitor.visitChildren(this); + } + } + public static class FuncCallExpressionContext extends ExpressionContext { + public FunctionCallContext functionCall() { + return getRuleContext(FunctionCallContext.class,0); + } + public FuncCallExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitFuncCallExpression(this); + else return visitor.visitChildren(this); + } + } + public static class OrContext extends ExpressionContext { + public ExpressionContext left; + public Token operator; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public OrContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitOr(this); + else return visitor.visitChildren(this); + } + } + public static class NumberContext extends ExpressionContext { + public Token number; + public TerminalNode NUMBER() { return getToken(DemoParser.NUMBER, 0); } + public NumberContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitNumber(this); + else return visitor.visitChildren(this); + } + } + public static class MultContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public MultContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitMult(this); + else return visitor.visitChildren(this); + } + } + public static class AndContext extends ExpressionContext { + public ExpressionContext left; + public Token operator; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public AndContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitAnd(this); + else return visitor.visitChildren(this); + } + } + public static class RelationalContext extends ExpressionContext { + public ExpressionContext left; + public Token operator; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public RelationalContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitRelational(this); + else return visitor.visitChildren(this); + } + } + public static class StringContext extends ExpressionContext { + public Token txt; + public TerminalNode STRING() { return getToken(DemoParser.STRING, 0); } + public StringContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitString(this); + else return visitor.visitChildren(this); + } + } + public static class PlusContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public PlusContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitPlus(this); + else return visitor.visitChildren(this); + } + } + public static class MinusContext extends ExpressionContext { + public ExpressionContext left; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public MinusContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitMinus(this); + else return visitor.visitChildren(this); + } + } + + public final ExpressionContext expression() throws RecognitionException { + return expression(0); + } + + private ExpressionContext expression(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState); + ExpressionContext _prevctx = _localctx; + int _startState = 10; + enterRecursionRule(_localctx, 10, RULE_expression, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(71); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) { + case 1: + { + _localctx = new NumberContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(67); + ((NumberContext)_localctx).number = match(NUMBER); + } + break; + case 2: + { + _localctx = new StringContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(68); + ((StringContext)_localctx).txt = match(STRING); + } + break; + case 3: + { + _localctx = new VariableContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(69); + ((VariableContext)_localctx).varName = match(IDENTIFIER); + } + break; + case 4: + { + _localctx = new FuncCallExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(70); + functionCall(); + } + break; + } + _ctx.stop = _input.LT(-1); + setState(96); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,5,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(94); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) { + case 1: + { + _localctx = new DivContext(new ExpressionContext(_parentctx, _parentState)); + ((DivContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(73); + if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); + setState(74); + match(T__7); + setState(75); + ((DivContext)_localctx).right = expression(12); + } + break; + case 2: + { + _localctx = new MultContext(new ExpressionContext(_parentctx, _parentState)); + ((MultContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(76); + if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); + setState(77); + match(T__8); + setState(78); + ((MultContext)_localctx).right = expression(11); + } + break; + case 3: + { + _localctx = new MinusContext(new ExpressionContext(_parentctx, _parentState)); + ((MinusContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(79); + if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); + setState(80); + match(T__9); + setState(81); + ((MinusContext)_localctx).right = expression(10); + } + break; + case 4: + { + _localctx = new PlusContext(new ExpressionContext(_parentctx, _parentState)); + ((PlusContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(82); + if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); + setState(83); + match(T__10); + setState(84); + ((PlusContext)_localctx).right = expression(9); + } + break; + case 5: + { + _localctx = new RelationalContext(new ExpressionContext(_parentctx, _parentState)); + ((RelationalContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(85); + if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); + setState(86); + ((RelationalContext)_localctx).operator = _input.LT(1); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14))) != 0)) ) { + ((RelationalContext)_localctx).operator = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(87); + ((RelationalContext)_localctx).right = expression(8); + } + break; + case 6: + { + _localctx = new AndContext(new ExpressionContext(_parentctx, _parentState)); + ((AndContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(88); + if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); + setState(89); + ((AndContext)_localctx).operator = match(T__15); + setState(90); + ((AndContext)_localctx).right = expression(7); + } + break; + case 7: + { + _localctx = new OrContext(new ExpressionContext(_parentctx, _parentState)); + ((OrContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(91); + if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); + setState(92); + ((OrContext)_localctx).operator = match(T__16); + setState(93); + ((OrContext)_localctx).right = expression(6); + } + break; + } + } + } + setState(98); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,5,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public static class VarDeclarationContext extends ParserRuleContext { + public Token varName; + public TerminalNode IDENTIFIER() { return getToken(DemoParser.IDENTIFIER, 0); } + public VarDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_varDeclaration; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitVarDeclaration(this); + else return visitor.visitChildren(this); + } + } + + public final VarDeclarationContext varDeclaration() throws RecognitionException { + VarDeclarationContext _localctx = new VarDeclarationContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_varDeclaration); + try { + enterOuterAlt(_localctx, 1); + { + setState(99); + match(T__17); + setState(100); + ((VarDeclarationContext)_localctx).varName = match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class AssignmentContext extends ParserRuleContext { + public Token varName; + public ExpressionContext expr; + public TerminalNode IDENTIFIER() { return getToken(DemoParser.IDENTIFIER, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public AssignmentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_assignment; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitAssignment(this); + else return visitor.visitChildren(this); + } + } + + public final AssignmentContext assignment() throws RecognitionException { + AssignmentContext _localctx = new AssignmentContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_assignment); + try { + enterOuterAlt(_localctx, 1); + { + setState(102); + ((AssignmentContext)_localctx).varName = match(IDENTIFIER); + setState(103); + match(T__18); + setState(104); + ((AssignmentContext)_localctx).expr = expression(0); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PrintlnContext extends ParserRuleContext { + public ExpressionContext argument; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public PrintlnContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_println; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitPrintln(this); + else return visitor.visitChildren(this); + } + } + + public final PrintlnContext println() throws RecognitionException { + PrintlnContext _localctx = new PrintlnContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_println); + try { + enterOuterAlt(_localctx, 1); + { + setState(106); + match(T__19); + setState(107); + ((PrintlnContext)_localctx).argument = expression(0); + setState(108); + match(T__3); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PrintContext extends ParserRuleContext { + public ExpressionContext argument; + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public PrintContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_print; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitPrint(this); + else return visitor.visitChildren(this); + } + } + + public final PrintContext print() throws RecognitionException { + PrintContext _localctx = new PrintContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_print); + try { + enterOuterAlt(_localctx, 1); + { + setState(110); + match(T__20); + setState(111); + ((PrintContext)_localctx).argument = expression(0); + setState(112); + match(T__3); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class FunctionDefinitionContext extends ParserRuleContext { + public Token funcName; + public ParametersContext params; + public StatementListContext statements; + public ExpressionContext retValue; + public TerminalNode IDENTIFIER() { return getToken(DemoParser.IDENTIFIER, 0); } + public ParametersContext parameters() { + return getRuleContext(ParametersContext.class,0); + } + public StatementListContext statementList() { + return getRuleContext(StatementListContext.class,0); + } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public FunctionDefinitionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_functionDefinition; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitFunctionDefinition(this); + else return visitor.visitChildren(this); + } + } + + public final FunctionDefinitionContext functionDefinition() throws RecognitionException { + FunctionDefinitionContext _localctx = new FunctionDefinitionContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_functionDefinition); + try { + enterOuterAlt(_localctx, 1); + { + setState(114); + match(T__17); + setState(115); + ((FunctionDefinitionContext)_localctx).funcName = match(IDENTIFIER); + setState(116); + match(T__2); + setState(117); + ((FunctionDefinitionContext)_localctx).params = parameters(); + setState(118); + match(T__3); + setState(119); + match(T__5); + setState(120); + ((FunctionDefinitionContext)_localctx).statements = statementList(); + setState(121); + match(T__21); + setState(122); + ((FunctionDefinitionContext)_localctx).retValue = expression(0); + setState(123); + match(T__0); + setState(124); + match(T__6); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class StatementListContext extends ParserRuleContext { + public List statement() { + return getRuleContexts(StatementContext.class); + } + public StatementContext statement(int i) { + return getRuleContext(StatementContext.class,i); + } + public StatementListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_statementList; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitStatementList(this); + else return visitor.visitChildren(this); + } + } + + public final StatementListContext statementList() throws RecognitionException { + StatementListContext _localctx = new StatementListContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_statementList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(129); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__1) | (1L << T__17) | (1L << T__19) | (1L << T__20) | (1L << IDENTIFIER))) != 0)) { + { + { + setState(126); + statement(); + } + } + setState(131); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ParametersContext extends ParserRuleContext { + public VarDeclarationContext varDeclaration; + public List declarations = new ArrayList(); + public List varDeclaration() { + return getRuleContexts(VarDeclarationContext.class); + } + public VarDeclarationContext varDeclaration(int i) { + return getRuleContext(VarDeclarationContext.class,i); + } + public ParametersContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_parameters; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitParameters(this); + else return visitor.visitChildren(this); + } + } + + public final ParametersContext parameters() throws RecognitionException { + ParametersContext _localctx = new ParametersContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_parameters); + int _la; + try { + setState(141); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__3: + enterOuterAlt(_localctx, 1); + { + } + break; + case T__17: + enterOuterAlt(_localctx, 2); + { + setState(133); + ((ParametersContext)_localctx).varDeclaration = varDeclaration(); + ((ParametersContext)_localctx).declarations.add(((ParametersContext)_localctx).varDeclaration); + setState(138); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__22) { + { + { + setState(134); + match(T__22); + setState(135); + ((ParametersContext)_localctx).varDeclaration = varDeclaration(); + ((ParametersContext)_localctx).declarations.add(((ParametersContext)_localctx).varDeclaration); + } + } + setState(140); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class FunctionCallContext extends ParserRuleContext { + public Token funcName; + public ExpressionListContext args; + public TerminalNode IDENTIFIER() { return getToken(DemoParser.IDENTIFIER, 0); } + public ExpressionListContext expressionList() { + return getRuleContext(ExpressionListContext.class,0); + } + public FunctionCallContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_functionCall; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitFunctionCall(this); + else return visitor.visitChildren(this); + } + } + + public final FunctionCallContext functionCall() throws RecognitionException { + FunctionCallContext _localctx = new FunctionCallContext(_ctx, getState()); + enterRule(_localctx, 26, RULE_functionCall); + try { + enterOuterAlt(_localctx, 1); + { + setState(143); + ((FunctionCallContext)_localctx).funcName = match(IDENTIFIER); + setState(144); + match(T__2); + setState(145); + ((FunctionCallContext)_localctx).args = expressionList(); + setState(146); + match(T__3); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ExpressionListContext extends ParserRuleContext { + public ExpressionContext expression; + public List expressions = new ArrayList(); + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public ExpressionListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_expressionList; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof DemoVisitor ) return ((DemoVisitor)visitor).visitExpressionList(this); + else return visitor.visitChildren(this); + } + } + + public final ExpressionListContext expressionList() throws RecognitionException { + ExpressionListContext _localctx = new ExpressionListContext(_ctx, getState()); + enterRule(_localctx, 28, RULE_expressionList); + int _la; + try { + setState(157); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__3: + enterOuterAlt(_localctx, 1); + { + } + break; + case IDENTIFIER: + case NUMBER: + case STRING: + enterOuterAlt(_localctx, 2); + { + setState(149); + ((ExpressionListContext)_localctx).expression = expression(0); + ((ExpressionListContext)_localctx).expressions.add(((ExpressionListContext)_localctx).expression); + setState(154); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__22) { + { + { + setState(150); + match(T__22); + setState(151); + ((ExpressionListContext)_localctx).expression = expression(0); + ((ExpressionListContext)_localctx).expressions.add(((ExpressionListContext)_localctx).expression); + } + } + setState(156); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 5: + return expression_sempred((ExpressionContext)_localctx, predIndex); + } + return true; + } + private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return precpred(_ctx, 11); + case 1: + return precpred(_ctx, 10); + case 2: + return precpred(_ctx, 9); + case 3: + return precpred(_ctx, 8); + case 4: + return precpred(_ctx, 7); + case 5: + return precpred(_ctx, 6); + case 6: + return precpred(_ctx, 5); + } + return true; + } + + public static final String _serializedATN = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\35\u00a2\4\2\t\2"+ + "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\3\2\6\2\"\n\2\r\2"+ + "\16\2#\3\3\3\3\5\3(\n\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3"+ + "\4\3\4\5\4\67\n\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\7"+ + "\3\7\3\7\3\7\3\7\5\7J\n\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7"+ + "\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\7\7a\n\7\f\7\16\7d\13\7\3\b\3"+ + "\b\3\b\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\f\3\f\3\f"+ + "\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\7\r\u0082\n\r\f\r\16\r\u0085"+ + "\13\r\3\16\3\16\3\16\3\16\7\16\u008b\n\16\f\16\16\16\u008e\13\16\5\16"+ + "\u0090\n\16\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\7\20\u009b\n"+ + "\20\f\20\16\20\u009e\13\20\5\20\u00a0\n\20\3\20\2\3\f\21\2\4\6\b\n\f\16"+ + "\20\22\24\26\30\32\34\36\2\3\3\2\16\21\2\u00a7\2!\3\2\2\2\4\'\3\2\2\2"+ + "\6\66\3\2\2\2\b8\3\2\2\2\n@\3\2\2\2\fI\3\2\2\2\16e\3\2\2\2\20h\3\2\2\2"+ + "\22l\3\2\2\2\24p\3\2\2\2\26t\3\2\2\2\30\u0083\3\2\2\2\32\u008f\3\2\2\2"+ + "\34\u0091\3\2\2\2\36\u009f\3\2\2\2 \"\5\4\3\2! \3\2\2\2\"#\3\2\2\2#!\3"+ + "\2\2\2#$\3\2\2\2$\3\3\2\2\2%(\5\6\4\2&(\5\26\f\2\'%\3\2\2\2\'&\3\2\2\2"+ + "(\5\3\2\2\2)*\5\22\n\2*+\7\3\2\2+\67\3\2\2\2,-\5\24\13\2-.\7\3\2\2.\67"+ + "\3\2\2\2/\60\5\16\b\2\60\61\7\3\2\2\61\67\3\2\2\2\62\63\5\20\t\2\63\64"+ + "\7\3\2\2\64\67\3\2\2\2\65\67\5\b\5\2\66)\3\2\2\2\66,\3\2\2\2\66/\3\2\2"+ + "\2\66\62\3\2\2\2\66\65\3\2\2\2\67\7\3\2\2\289\7\4\2\29:\7\5\2\2:;\5\f"+ + "\7\2;<\7\6\2\2<=\5\n\6\2=>\7\7\2\2>?\5\n\6\2?\t\3\2\2\2@A\7\b\2\2AB\5"+ + "\30\r\2BC\7\t\2\2C\13\3\2\2\2DE\b\7\1\2EJ\7\33\2\2FJ\7\35\2\2GJ\7\32\2"+ + "\2HJ\5\34\17\2ID\3\2\2\2IF\3\2\2\2IG\3\2\2\2IH\3\2\2\2Jb\3\2\2\2KL\f\r"+ + "\2\2LM\7\n\2\2Ma\5\f\7\16NO\f\f\2\2OP\7\13\2\2Pa\5\f\7\rQR\f\13\2\2RS"+ + "\7\f\2\2Sa\5\f\7\fTU\f\n\2\2UV\7\r\2\2Va\5\f\7\13WX\f\t\2\2XY\t\2\2\2"+ + "Ya\5\f\7\nZ[\f\b\2\2[\\\7\22\2\2\\a\5\f\7\t]^\f\7\2\2^_\7\23\2\2_a\5\f"+ + "\7\b`K\3\2\2\2`N\3\2\2\2`Q\3\2\2\2`T\3\2\2\2`W\3\2\2\2`Z\3\2\2\2`]\3\2"+ + "\2\2ad\3\2\2\2b`\3\2\2\2bc\3\2\2\2c\r\3\2\2\2db\3\2\2\2ef\7\24\2\2fg\7"+ + "\32\2\2g\17\3\2\2\2hi\7\32\2\2ij\7\25\2\2jk\5\f\7\2k\21\3\2\2\2lm\7\26"+ + "\2\2mn\5\f\7\2no\7\6\2\2o\23\3\2\2\2pq\7\27\2\2qr\5\f\7\2rs\7\6\2\2s\25"+ + "\3\2\2\2tu\7\24\2\2uv\7\32\2\2vw\7\5\2\2wx\5\32\16\2xy\7\6\2\2yz\7\b\2"+ + "\2z{\5\30\r\2{|\7\30\2\2|}\5\f\7\2}~\7\3\2\2~\177\7\t\2\2\177\27\3\2\2"+ + "\2\u0080\u0082\5\6\4\2\u0081\u0080\3\2\2\2\u0082\u0085\3\2\2\2\u0083\u0081"+ + "\3\2\2\2\u0083\u0084\3\2\2\2\u0084\31\3\2\2\2\u0085\u0083\3\2\2\2\u0086"+ + "\u0090\3\2\2\2\u0087\u008c\5\16\b\2\u0088\u0089\7\31\2\2\u0089\u008b\5"+ + "\16\b\2\u008a\u0088\3\2\2\2\u008b\u008e\3\2\2\2\u008c\u008a\3\2\2\2\u008c"+ + "\u008d\3\2\2\2\u008d\u0090\3\2\2\2\u008e\u008c\3\2\2\2\u008f\u0086\3\2"+ + "\2\2\u008f\u0087\3\2\2\2\u0090\33\3\2\2\2\u0091\u0092\7\32\2\2\u0092\u0093"+ + "\7\5\2\2\u0093\u0094\5\36\20\2\u0094\u0095\7\6\2\2\u0095\35\3\2\2\2\u0096"+ + "\u00a0\3\2\2\2\u0097\u009c\5\f\7\2\u0098\u0099\7\31\2\2\u0099\u009b\5"+ + "\f\7\2\u009a\u0098\3\2\2\2\u009b\u009e\3\2\2\2\u009c\u009a\3\2\2\2\u009c"+ + "\u009d\3\2\2\2\u009d\u00a0\3\2\2\2\u009e\u009c\3\2\2\2\u009f\u0096\3\2"+ + "\2\2\u009f\u0097\3\2\2\2\u00a0\37\3\2\2\2\r#\'\66I`b\u0083\u008c\u008f"+ + "\u009c\u009f"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/parser/src/main/java/de/letsbuildacompiler/parser/DemoVisitor.java b/parser/src/main/java/de/letsbuildacompiler/parser/DemoVisitor.java new file mode 100644 index 0000000..b7ab066 --- /dev/null +++ b/parser/src/main/java/de/letsbuildacompiler/parser/DemoVisitor.java @@ -0,0 +1,182 @@ +// Generated from /home/thibaud/Programmation/Java/antlr-compiler/Demo.g4 by ANTLR 4.7 +package de.letsbuildacompiler.parser; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link DemoParser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface DemoVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by {@link DemoParser#program}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitProgram(DemoParser.ProgramContext ctx); + /** + * Visit a parse tree produced by the {@code MainStatement} + * labeled alternative in {@link DemoParser#programPart}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMainStatement(DemoParser.MainStatementContext ctx); + /** + * Visit a parse tree produced by the {@code ProgPartFunctionDefinition} + * labeled alternative in {@link DemoParser#programPart}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitProgPartFunctionDefinition(DemoParser.ProgPartFunctionDefinitionContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#statement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStatement(DemoParser.StatementContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#branch}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBranch(DemoParser.BranchContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#block}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBlock(DemoParser.BlockContext ctx); + /** + * Visit a parse tree produced by the {@code Div} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDiv(DemoParser.DivContext ctx); + /** + * Visit a parse tree produced by the {@code Variable} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitVariable(DemoParser.VariableContext ctx); + /** + * Visit a parse tree produced by the {@code FuncCallExpression} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFuncCallExpression(DemoParser.FuncCallExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code Or} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitOr(DemoParser.OrContext ctx); + /** + * Visit a parse tree produced by the {@code Number} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNumber(DemoParser.NumberContext ctx); + /** + * Visit a parse tree produced by the {@code Mult} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMult(DemoParser.MultContext ctx); + /** + * Visit a parse tree produced by the {@code And} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAnd(DemoParser.AndContext ctx); + /** + * Visit a parse tree produced by the {@code Relational} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitRelational(DemoParser.RelationalContext ctx); + /** + * Visit a parse tree produced by the {@code String} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitString(DemoParser.StringContext ctx); + /** + * Visit a parse tree produced by the {@code Plus} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPlus(DemoParser.PlusContext ctx); + /** + * Visit a parse tree produced by the {@code Minus} + * labeled alternative in {@link DemoParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMinus(DemoParser.MinusContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#varDeclaration}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitVarDeclaration(DemoParser.VarDeclarationContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#assignment}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAssignment(DemoParser.AssignmentContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#println}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPrintln(DemoParser.PrintlnContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#print}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPrint(DemoParser.PrintContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#functionDefinition}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFunctionDefinition(DemoParser.FunctionDefinitionContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#statementList}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStatementList(DemoParser.StatementListContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#parameters}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitParameters(DemoParser.ParametersContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#functionCall}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFunctionCall(DemoParser.FunctionCallContext ctx); + /** + * Visit a parse tree produced by {@link DemoParser#expressionList}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitExpressionList(DemoParser.ExpressionListContext ctx); +} \ No newline at end of file