Homework 2

This commit is contained in:
Carlos Galindo 2020-01-15 22:30:09 +01:00
parent 12f678a924
commit bf60a078d7
Signed by: kauron
GPG key ID: 83E68706DEE119A3
64 changed files with 4786 additions and 1185 deletions

View file

@ -2,10 +2,9 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="lib" path="lib/antlr-4.4-complete.jar"/>
<classpathentry kind="lib" path="lib/junit-4.12.jar"/>
<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
<classpathentry kind="lib" path="lib/javaliParserObf.jar"/>
<classpathentry kind="lib" path="lib/antlr-4.7.1-complete.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Javali-HW1</name>
<name>Javali-HW2</name>
<comment></comment>
<projects>
</projects>

View file

@ -0,0 +1,13 @@
antlr4.antlrRegisteredTools=4.4@/tmp/antlr-4.4-complete.jar\:4.7.1@/home/carlos/eth/cd/nop90/HW2/lib/antlr-4.7.1-complete.jar
antlr4.antlrToolPath=/home/carlos/eth/cd/nop90/HW2/lib/antlr-4.7.1-complete.jar
antlr4.encoding=UTF-8
antlr4.listener=true
antlr4.visitor=false
antlr4.vmArgs=
antlr4ide.is_project_specific=true
autobuilding=true
eclipse.preferences.version=1
is_project_specific=
outlet.DEFAULT_OUTPUT.cleanupDerived=true
outlet.DEFAULT_OUTPUT.derived=true
outlet.DEFAULT_OUTPUT.directory=./target/generated-sources/antlr4

View file

@ -1,12 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8

View file

@ -1,5 +1,5 @@
Grade: 24/25
Grade: 29/30
31/31 tests passed [20/20]
251/251 tests passed [25/25]
Submitted test cases [4/5]
Submitted test cases: [4/5]

View file

@ -1,4 +1,4 @@
<project name="compiler-design" default="compile" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
<project name="compiler-design" default="generate-parser" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
<!-- A very simple ant file that primarily exists to run cup and lex;
it also includes targets to build the compiler and run tests for those
@ -13,7 +13,7 @@
<property name="build.dir" value="${basedir}/bin"/>
<property name="junit.jar" value="${basedir}/lib/junit-4.12.jar"/>
<property name="hamcrest.jar" value="${basedir}/lib/hamcrest-core-1.3.jar"/>
<property name="antlr.jar" value="${basedir}/lib/antlr-4.4-complete.jar"/>
<property name="antlr.jar" value="${basedir}/lib/antlr-4.7.1-complete.jar"/>
<property name="antlr.profile" value="false"/>
<property name="antlr.report" value="false"/>
<property name="jacocoant.jar" value="${basedir}/lib/jacocoant.jar"/>
@ -21,16 +21,42 @@
<property name="min.coverage" value="0.5"/>
<property name="coverage.check" value="cd.frontend.*:cd.backend.*"/>
<target name="generate-parser">
<echo message="ANTLR4 ${parser.dir}/Javali.g4" level="info"/>
<echo>${basedir}</echo>
<java classname="org.antlr.v4.Tool" failonerror="true" classpath="${antlr.jar}">
<arg value="${parser.dir}/Javali.g4" />
<arg value="-o" />
<arg value="${parser.dir}" />
<arg value="-no-listener" />
<arg value="-visitor" />
</java>
</target>
<!-- Deletes the generated ANTLR parser files. Don't use in HW1! -->
<target name="clean-parser">
<delete file="${parser.dir}/Javali.tokens"/>
<delete file="${parser.dir}/JavaliLexer.java"/>
<delete file="${parser.dir}/JavaliParser.java"/>
<delete file="${parser.dir}/JavaliWalker.tokens"/>
<delete file="${parser.dir}/JavaliWalker.java"/>
<delete file="${parser.dir}/JavaliBaseListener.java"/>
<delete file="${parser.dir}/JavaliBaseVisitor.java"/>
<delete file="${parser.dir}/JavaliListener.java"/>
<delete file="${parser.dir}/JavaliVisitor.java"/>
<delete file="${parser.dir}/JavaliLexer.tokens"/>
<delete file="${parser.dir}/Javali.interp"/>
<delete file="${parser.dir}/JavaliLexer.interp"/>
</target>
<!-- Cleans generated code, but NOT the parser source! -->
<target name="clean">
<delete dir="${build.dir}"/>
</target>
<!-- Builds the compiler framework for HW1. -->
<target name="compile">
<!-- Builds the compiler framework for HW > HW1. -->
<target name="compile" depends="generate-parser">
<mkdir dir="${build.dir}"/>
<javac debug="true" destdir="${build.dir}" includeantruntime="false">
@ -40,7 +66,6 @@
<pathelement location="${antlr.jar}"/>
<pathelement location="${junit.jar}"/>
<pathelement location="${hamcrest.jar}"/>
<pathelement location="${parser.jar}"/>
</classpath>
</javac>
</target>
@ -83,5 +108,4 @@
<fail if="tests-failed" />
</target>
</project>

View file

@ -0,0 +1,18 @@
class Main {
void main() {
int r1;
int i0, i1;
i0 = 5;
i1 = 2;
r1 = i1 * 3;
write(r1); writeln();
r1 = i0 * i1;
write(r1); writeln();
r1 = r1 * i0 * i1 * 3;
write(r1); writeln();
}
}

View file

@ -0,0 +1,15 @@
/* Test read/write native functions */
class Main {
void main() {
int r1, r2;
int i0, i1, i2;
i0 = 5;
i1 = read();
r1 = i0 + i1;
write(r1); writeln();
write(r1 - 3); writeln();
}
}

View file

@ -0,0 +1 @@
22

0
javali_tests/HW1_nop90/EightVariablesWrite.javali Normal file → Executable file
View file

View file

@ -14,7 +14,7 @@ class Main {
write(x); writeln();
/* performe some operation that should generate an int overflow */
x = 2147483640;
x = 21474836400;
y = 60000;
write( x + y); writeln();
z = 20000000;

View file

@ -0,0 +1,10 @@
class Main {
void main() {
int i;
// Note: In Javali, while() loops must have braces ({}) after them,
// so this is an expected syntax error.
while(true)
i = 1;
}
}

View file

@ -0,0 +1,12 @@
class Base {
}
class Extends extends Base {
}
class Main {
void main() {
write(0);
writeln();
}
}

View file

@ -0,0 +1,22 @@
class Main {
int field;
void method() {
write(this.field);
writeln();
}
void method(int withArg) {
write(withArg);
writeln();
}
void main() {
this.field = 3;
method(field);
method(3);
method(this.field);
method();
}
}

View file

@ -0,0 +1,22 @@
class Main {
int m() {
return 0;
}
void main() {
int res;
res = -1;
res = m();
write(res);
writeln();
res = this.m();
write(res);
writeln();
}
}

View file

@ -0,0 +1,27 @@
class Main {
int m(int a, int b) {
return a + b + 1;
}
void main() {
int res;
res = -1;
res = m(1, 2);
write(res);
writeln();
res = this.m(1, 2);
write(res);
writeln();
write(m(1, 2));
writeln();
write(this.m(1, 2));
writeln();
}
}

View file

@ -0,0 +1,24 @@
/* testing arrays with primitive types as well as new objects
the if/else statements shows that the array is boolean array is initialized with false
*/
class Main {
void main() {
int [] testArray;
boolean [] boolarray;
boolarray = new boolean [3];
testArray = new int [10];
testArray[5] = 3;
boolarray[1] = true;
if (boolarray[0]){
write(1);}
else{
write(5);}
writeln();
if (boolarray[1]){
write(1);}
}
}

View file

@ -0,0 +1,12 @@
/* testing assign statements*/
class Main {
void main() {
a = read();
b = methodCall();
c = methodCall(param1, param2);
d = object.access;
e = new Ast();
d = new int[size];
f = new Object[size];
}
}

View file

@ -0,0 +1,16 @@
/* testing casting as well as creating new Objects*/
class Main
{
void main()
{
int a;
int b;
Object c;
Object d;
c = null;
d = new Object();
a = 10;
c = (Object) d;
}
}

View file

@ -0,0 +1,21 @@
class Main {
void main() {
int a, b, c, d, e;
a = 10;
b = -1;
c = 0;
d = 100;
e = 2;
write(a / b); writeln();
write(d / e); writeln();
write(c / d); writeln();
write(b / a + c); writeln();
write(d / e * a / b * c); writeln();
write(d / e * a / b); writeln();
write(d / e + a / b); writeln();
write(d / e * a * b * c); writeln();
write(d / e * a - b + c); writeln();
}
}

View file

@ -0,0 +1,6 @@
/* testing basic inheritance*/
class C1 {}
class C2 extends C1 {}
class C3 extends C2 {}
class C4 extends C2 {}
class C5 extends C3 {}

View file

@ -0,0 +1,20 @@
/* Test expression evaluation with 8 variables */
class Main {
void main() {
int r1, r2, r3;
int i0, i1, i2, i3, i4, i5, i6, i7;
i0 = 0;
i1 = 1;
i2 = 2;
i3 = 3;
i4 = 4;
i5 = 5;
i6 = 6;
i7 = 7;
write(i0 + (i1 + ( i2 + ( i3 + ( i4 + (i5 + (i6 + i7))))))); writeln();
write(((((((i0 + i1) + i2) + i3) + i4) + i5) + i6) + i7); writeln();
write(((i0 + i1) + (i2 + i3)) + ((i4 + i5) + (i6 + i7))); writeln();
}
}

View file

@ -0,0 +1,22 @@
/* testing different expressions
compiler should recognize Type error: Return statement of method with void return type should not have arguments
*/
class Main {
void main() {
return;
return true;
return false;
return 0x10;
return 10;
return variable;
return array[index];
return methodAccess();
return object.field;
return object.call();
return op + op2;
return op / asd * asd && a == true;
return this.run();
return this;
return this.field;
}
}

View file

@ -0,0 +1,31 @@
class Main {
void main() {
int r1;
int i0, i1;
int x,y,z;
i0 = 5;
i1 = 2;
r1 = i1 * 3;
write(r1); writeln();
r1 = i0 * i1;
write(r1); writeln();
r1 = r1 * i0 * i1 * 3;
write(r1); writeln();
y = 5;
z = 10;
x = (-y * z);
write(x); writeln();
y = 0;
z = - 10;
x = (y * z);
write(x); writeln();
write(y * z); writeln();
write(0 * -10); writeln();
}
}

View file

@ -0,0 +1,20 @@
/* testing null references:
assigning null to an int or a boolean results in an error
write(null) results in a parser failure
*/
class Main {
void main() {
int a;
boolean b;
Object c;
a = null;
b = null;
c = null;
write(a);
writeln();
//write(null)
}
}

View file

@ -0,0 +1,8 @@
/*Check the order of the declarations in the generated parser
* Do the variables come always first or in their place? */
class ClassName {
void a() {}
int a;
void a() {}
void tests(boolean d, nulle a) {}
}

View file

@ -0,0 +1,25 @@
/* Test what happens for Integers that are to big for 32bits
2147483647 (=0x7FFFFFFF) is the biggest integer in 32bits (IntMAX)
*/
class Main {
void main() {
int x,y,z;
x = 2147483647;
write( x ); writeln();
/* add 1 to IntMax and output it */
write( x + 1); writeln();
/* read an int bigger than IntMAX */
x = read();
write(x); writeln();
/* performe some operation that should generate an int overflow */
x = 21474836400;
y = 60000;
write( x + y); writeln();
z = 20000000;
write( y * z); writeln();
write( (y * z) ); writeln();
}
}

View file

@ -0,0 +1 @@
2147483647

View file

@ -0,0 +1,15 @@
/*Testing all related to methods (declaration and execution)*/
class Main {
void main() {
callWithParams(a, b, c, 0, false);
object.call(a, b, d);
}
int method(int a, String b, int[] c) {
}
int[] method2() {}
Object method3() {}
Model[] method4() {}
}

View file

@ -0,0 +1,26 @@
/* Test read/write native functions */
class Main {
void main() {
int r1, r2, readvar, a1;
r1 = 6;
/* r2 = 22 */
r2 = read();
write(r1); writeln(); // 6
/* test expressions inside write() */
write(r1 - 3); writeln(); // 3
write(r1 - 6); writeln(); // 0
write(r1 - 7); writeln(); // -1
/* should output 111 */
readvar = read(); // 1
write( (r1 + (r2 * 5)) + readvar); // 117
write(- r1); // -6
writeln();
/* should output 15 */
a1 = read(); // -15
write(- a1); // 15
}
}

View file

@ -0,0 +1,6 @@
22
1
-15

View file

@ -0,0 +1,34 @@
/* testing different statements
'condition' is not initialized
*/
class Main {
void main() {
if (condition) {
instructions();
asd.b = c;
if (cond2) {
} else {
nonEmptyBlock = a;
}
} else {
}
// Whiles
while (condition) {
while (anotherLoop == false) {
nestedLoops();
}
}
while (false) {} // emptyloop
// Returns
return; // empty
return expr; // with expressions (expressions already tested)
return array[index];
// Writes
write(a);
write(9 + 10);
writeln();
write(call());
}
}

View file

@ -0,0 +1,15 @@
class Main {
void main() {
int a, b;
a = 1;
b = 2;
write(+a); writeln();
write(-a); writeln();
write(+a --b); writeln();
write(-a--b); writeln();
write(-----a-----5--b); writeln();
write(-----a*---------b);writeln();
}
}

View file

@ -0,0 +1,24 @@
/* testing conditions*/
class Main {
void main() {
boolean a;
int b,c, d, e;
b = 10;
c = 3;
d = 40;
e = 1;
while ( b > c ) {
write(b);
b = b-1;
}
a = c < (b+4-5/2);
if (a){
write(13);}
if (100/2>d*e){
while(e<d){
d = d/2;}}
}
}

View file

@ -0,0 +1,12 @@
/* testing invalid casts */
class Main
{
void main()
{
int a;
Object d;
d = new Object();
a = (Object) d;
a = (boolean[]) a;
}
}

View file

@ -0,0 +1,14 @@
class Main {
void main() {
boolean b;
int a,c,n;
a = 10;
//b = true;
while ( a>0 ) {
a = a-1;
}
}

View file

@ -0,0 +1,24 @@
/* test what happens if there are no parentheses */
class Main {
void main() {
int x;
int y;
int z;
x = 5;
y = 10;
z = 100;
write( x + y + z); writeln();
/* */
write( - x + y - z); writeln();
/* should output 205 */
write( x + 2 * z); writeln();
write( x + 2 * z / x + 1); writeln();
write(+x); writeln();
}
}

View file

@ -10,11 +10,6 @@ public class Config {
MACOSX
}
/**
* What kind of system we are on
*/
public static final SystemKind systemKind;
/**
* Defines the extension used for assembler files on this platform.
* Currently always {@code .s}.
@ -84,11 +79,9 @@ public class Config {
public static final String JAVA_EXE;
static {
final String os = System.getProperty("os.name").toLowerCase();
if(os.contains("windows") || os.contains("nt")) {
systemKind = SystemKind.WINDOWS;
BINARYEXT = ".exe";
MAIN = "_main";
PRINTF = "_printf";
@ -96,7 +89,7 @@ public class Config {
CALLOC = "_calloc";
EXIT = "_exit";
// These are set up for a Cygwin installation on C:,
// you can change as registersNeeded.
// you can change as needed.
ASM = new String[]{"gcc", "-o", "$0", "$1"};
ASM_DIR = new File("C:\\CYGWIN\\BIN");
JAVA_EXE = "javaw.exe";
@ -108,7 +101,6 @@ public class Config {
COMMENT_SEP = "#";
}
else if(os.contains("mac os x") || os.contains("darwin")) {
systemKind = SystemKind.MACOSX;
BINARYEXT = ".bin";
MAIN = "_main";
PRINTF = "_printf";
@ -126,7 +118,6 @@ public class Config {
COMMENT_SEP = "#";
}
else {
systemKind = SystemKind.LINUX;
BINARYEXT = ".bin";
MAIN = "main";
PRINTF = "printf";

View file

@ -2,7 +2,6 @@ package cd;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Reader;
@ -15,7 +14,6 @@ import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import cd.backend.codegen.AstCodeGenerator;
import cd.frontend.parser.JavaliAstVisitor;
import cd.frontend.parser.JavaliLexer;
import cd.frontend.parser.JavaliParser;
@ -36,7 +34,7 @@ public class Main {
// Set to non-null to write debug info out
public Writer debug = null;
// Set to non-null to write dump of control flow graph (Advanced Compiler Design)
// Set to non-null to write dump of control flow graph
public File cfgdumpbase;
public void debug(String format, Object... args) {
@ -64,15 +62,6 @@ public class Main {
// Parse:
List<ClassDecl> astRoots = m.parse(fin);
// Run the semantic check:
m.semanticCheck(astRoots);
// Generate code:
String sFile = arg + Config.ASMEXT;
try (FileWriter fout = new FileWriter(sFile)) {
m.generateCode(astRoots, fout);
}
}
}
}
@ -105,18 +94,7 @@ public class Main {
}
public void semanticCheck(List<ClassDecl> astRoots) {
{
// Not registersNeeded until later. Ignore.
}
}
public void generateCode(List<ClassDecl> astRoots, Writer out) {
{
AstCodeGenerator cg = AstCodeGenerator.createCodeGenerator(this, out);
cg.go(astRoots);
}
}
/** Dumps the AST to the debug stream */
private void dumpAst(List<ClassDecl> astRoots) throws IOException {

View file

@ -1,164 +0,0 @@
package cd.backend.codegen;
import java.io.IOException;
import java.io.Writer;
import cd.Config;
import cd.backend.codegen.RegisterManager.Register;
public class AssemblyEmitter {
public Writer out;
public StringBuilder indent = new StringBuilder();
public int counter = 0;
public AssemblyEmitter(Writer out) {
this.out = out;
}
/** Creates an constant operand. */
static String constant(int i) {
return "$" + i;
}
/** Creates an constant operand with the address of a label. */
static String labelAddress(String lbl) {
return "$" + lbl;
}
/** Creates an operand relative to another operand. */
static String registerOffset(int offset, Register reg) {
return String.format("%d(%s)", offset, reg);
}
/** Creates an operand addressing an item in an array */
static String arrayAddress(Register arrReg, Register idxReg) {
final int offset = Config.SIZEOF_PTR * 2; // one word each in front for
// vptr and length
final int mul = Config.SIZEOF_PTR; // assume all arrays of 4-byte elem
return String.format("%d(%s,%s,%d)", offset, arrReg, idxReg, mul);
}
void increaseIndent(String comment) {
indent.append(" ");
if (comment != null)
emitComment(comment);
}
void decreaseIndent() {
indent.setLength(indent.length() - 2);
}
void emitCommentSection(String name) {
int indentLen = indent.length();
int breakLen = 68 - indentLen - name.length();
StringBuffer sb = new StringBuffer();
sb.append(Config.COMMENT_SEP).append(" ");
for (int i = 0; i < indentLen; i++)
sb.append("_");
sb.append(name);
for (int i = 0; i < breakLen; i++)
sb.append("_");
try {
out.write(sb.toString());
out.write("\n");
} catch (IOException e) {
}
}
void emitComment(String comment) {
emitRaw(Config.COMMENT_SEP + " " + comment);
}
void emit(String op, Register src, String dest) {
emit(op, src.repr, dest);
}
void emit(String op, String src, Register dest) {
emit(op, src, dest.repr);
}
void emit(String op, Register src, Register dest) {
emit(op, src.repr, dest.repr);
}
void emit(String op, String src, String dest) {
emitRaw(String.format("%s %s, %s", op, src, dest));
}
void emit(String op, int src, Register dest) {
emit(op, constant(src), dest);
}
void emit(String op, String dest) {
emitRaw(op + " " + dest);
}
void emit(String op) {
emitRaw(op);
}
void emit(String op, Register reg) {
emit(op, reg.repr);
}
void emit(String op, int dest) {
emit(op, constant(dest));
}
void emitMove(Register src, String dest) {
emitMove(src.repr, dest);
}
void emitMove(Register src, Register dest) {
emitMove(src.repr, dest.repr);
}
void emitMove(String src, Register dest) {
emitMove(src, dest.repr);
}
void emitMove(String src, String dest) {
if (!src.equals(dest))
emit("movl", src, dest);
}
void emitLoad(int srcOffset, Register src, Register dest) {
emitMove(registerOffset(srcOffset, src), dest.repr);
}
void emitStore(Register src, int destOffset, Register dest) {
emitStore(src.repr, destOffset, dest);
}
void emitStore(String src, int destOffset, Register dest) {
emitMove(src, registerOffset(destOffset, dest));
}
void emitConstantData(String data) {
emitRaw(String.format("%s %s", Config.DOT_INT, data));
}
String uniqueLabel() {
String labelName = "label" + counter++;
return labelName;
}
void emitLabel(String label) {
try {
out.write(label + ":" + "\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void emitRaw(String op) {
try {
out.write(indent.toString());
out.write(op);
out.write("\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -1,14 +0,0 @@
package cd.backend.codegen;
public class AssemblyFailedException extends RuntimeException {
private static final long serialVersionUID = -5658502514441032016L;
public final String assemblerOutput;
public AssemblyFailedException(
String assemblerOutput) {
super("Executing assembler failed.\n"
+ "Output:\n"
+ assemblerOutput);
this.assemblerOutput = assemblerOutput;
}
}

View file

@ -1,58 +0,0 @@
package cd.backend.codegen;
import cd.Main;
import cd.ir.Ast.ClassDecl;
import java.io.Writer;
import java.util.List;
public class AstCodeGenerator {
protected ExprGenerator eg;
protected StmtGenerator sg;
protected final Main main;
protected final AssemblyEmitter emit;
protected final RegisterManager rm = new RegisterManager();
AstCodeGenerator(Main main, Writer out) {
this.emit = new AssemblyEmitter(out);
this.main = main;
this.eg = new ExprGenerator(this);
this.sg = new StmtGenerator(this);
}
protected void debug(String format, Object... args) {
this.main.debug(format, args);
}
public static AstCodeGenerator createCodeGenerator(Main main, Writer out) {
return new AstCodeGenerator(main, out);
}
/**
* Main method. Causes us to emit x86 assembly corresponding to {@code ast}
* into {@code file}. Throws a {@link RuntimeException} should any I/O error
* occur.
*
* <p>
* The generated file will be divided into two sections:
* <ol>
* <li>Prologue: Generated by {@link #emitPrefix()}. This contains any
* introductory declarations and the like.
* <li>Body: Generated by {@link ExprGenerator}. This contains the main
* method definitions.
* </ol>
*/
public void go(List<? extends ClassDecl> astRoots) {
for (ClassDecl ast : astRoots) {
sg.gen(ast);
}
}
protected void initMethodData() {
}
}

View file

@ -1,307 +0,0 @@
package cd.backend.codegen;
import cd.backend.codegen.RegisterManager.Register;
import cd.ir.Ast.*;
import cd.ir.Ast.BinaryOp.BOp;
import cd.ir.ExprVisitor;
import cd.util.debug.AstOneLine;
/**
* Generates code to evaluate expressions. After emitting the code, returns a
* String which indicates the register where the result can be found.
*/
class ExprGenerator extends ExprVisitor<Register, Void> {
protected final AstCodeGenerator cg;
ExprGenerator(AstCodeGenerator astCodeGenerator) {
cg = astCodeGenerator;
}
public Register gen(Expr ast) {
return visit(ast, null);
}
@Override
public Register visit(Expr ast, Void arg) {
try {
cg.emit.increaseIndent("Emitting " + AstOneLine.toString(ast));
return super.visit(ast, null);
} finally {
cg.emit.decreaseIndent();
}
}
@Override
public Register binaryOp(BinaryOp ast, Void arg) {
String op;
if (ast.operator == BOp.B_TIMES)
op = "imul";
else if (ast.operator == BOp.B_PLUS)
op = "add";
else if (ast.operator == BOp.B_MINUS)
op = "sub";
else if (ast.operator == BOp.B_DIV)
op = "div";
else
throw new RuntimeException("Not required (optional)");
op += "l"; // long = 4B = 32b
Register left, right;
int leftNeeded = ast.left().registersNeeded();
int rightNeeded = ast.right().registersNeeded();
if (leftNeeded > rightNeeded) {
left = cg.eg.visit(ast.left(), arg);
right = cg.eg.visit(ast.right(), arg);
} else {
right = cg.eg.visit(ast.right(), arg);
left = cg.eg.visit(ast.left(), arg);
}
if (ast.operator == BOp.B_DIV) {
// The dividend (left) will be replaced with the quotient
// So free the divisor register (right) and return the quotient (left)
division(left, right);
cg.rm.releaseRegister(right);
return left;
} else {
// All operators take the form OP A, B --> B = B OP A --> B is left, A is right
// Therefore the result is stored in B (left) and A (right) can be freed
cg.emit.emit(op, right, left);
cg.rm.releaseRegister(right);
return left;
}
}
/**
* Division with divide by zero check incorporated
*/
private void division(Register dividend, Register divisor) {
division(dividend, divisor, true);
}
/**
* Special implementation for divisions, as it requires specific registers to be used
* @param dividend Maximum 32bit (even though the division is implemented as 64bit)
* @param divisor Maximum 32bit
* @param checkZero Whether to generate code that checks for division by zero or not
* @return The quotient will be in place of the dividend and the remainder in the divisor
*/
protected void division(Register dividend, Register divisor, boolean checkZero) {
if (checkZero) {
String beginDivision = cg.emit.uniqueLabel();
cg.emit.emit("cmp", 0, divisor);
cg.emit.emit("jne", beginDivision);
// Exit with error code in case of div/0
Interrupts.exit(cg, Interrupts.EXIT_DIV_0);
cg.emit.emitLabel(beginDivision);
}
// D = d * q + r (dividend, divisor, quotient, remainder)
// EDX:EAX = d * EAX + EDX (before and after the div operation)
// Take care of register use: move EAX to memory if necessary
// The stack is not needed because the division operator is not recursive
// After the division is performed, move the data back to dividend and divisor
Register d, D = Register.EAX;
if (divisor.equals(D)) {
d = cg.rm.getRegister();
cg.emit.emitMove(divisor, d);
cg.emit.emitMove(dividend, Register.EAX);
} else {
if (!dividend.equals(D) && cg.rm.isInUse(D))
cg.emit.emitMove(D, "(" + Interrupts.Mem.EAX.pos + ")");
cg.emit.emitMove(dividend, D);
if (divisor.equals(Register.EDX)) {
d = cg.rm.getRegister();
cg.emit.emitMove(divisor, d);
}
}
// Division
cg.emit.emit("cdq");
cg.emit.emit("idiv", divisor);
cg.emit.emitMove(Register.EAX, dividend);
cg.emit.emitMove(Register.EDX, divisor);
Register q = Register.EAX, r = Register.EDX;
if (divisor.equals(D)) {
cg.emit.emitMove(q, dividend);
cg.emit.emitMove(r, divisor);
} else {
if (!dividend.equals(D) && cg.rm.isInUse(D))
cg.emit.emitMove(Interrupts.Mem.EAX.pos, D);
cg.emit.emitMove(dividend, D);
if (!divisor.equals(r)) {
cg.emit.emitMove(r, divisor);
}
}
}
@Override
public Register booleanConst(BooleanConst ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register builtInRead(BuiltInRead ast, Void arg) {
// Holds the first digit and then is used to accumulate the total value
Register value = cg.rm.getRegister();
// Used to mark for positive (0) or negative (1) value
Register negative = cg.rm.getRegister();
// Holds the next digit read, once the first has been read
Register nextDigit = cg.rm.getRegister();
// Labels for the read structure
String removeWhitespace = cg.emit.uniqueLabel();
String negativeFirstDigit = cg.emit.uniqueLabel();
String inputError = cg.emit.uniqueLabel();
String moreDigits = cg.emit.uniqueLabel();
String endRead = cg.emit.uniqueLabel();
String checkSign = cg.emit.uniqueLabel();
// By default, variable is positive (negative == 0)
cg.emit.emitMove(AssemblyEmitter.constant(0), negative);
// Skip whitespace ( \t\n\r) at the beginning
cg.emit.emitLabel(removeWhitespace);
Interrupts.readChar(cg, value);
cg.emit.emit("cmp", '\n', value);
cg.emit.emit("je", removeWhitespace);
cg.emit.emit("cmp", ' ', value);
cg.emit.emit("je", removeWhitespace);
cg.emit.emit("cmp", '\t', value);
cg.emit.emit("je", removeWhitespace);
cg.emit.emit("cmp", '\r', value);
cg.emit.emit("je", removeWhitespace);
// Recognize first digit, if negative read another digit to place at value
cg.emit.emit("cmp", '-', value);
cg.emit.emit("je", negativeFirstDigit);
charToIntOrJump(value, inputError);
cg.emit.emit("jmp", moreDigits);
// Negative first digit
cg.emit.emitLabel(negativeFirstDigit);
Interrupts.readChar(cg, value);
cg.emit.emitMove(AssemblyEmitter.constant(1), negative);
charToIntOrJump(value, inputError);
// All other digits:
// while ( (nextDigit = read()).isDigit())
// value = value * 10 + nextDigit
cg.emit.emitLabel(moreDigits);
Interrupts.readChar(cg, nextDigit);
charToIntOrJump(nextDigit, checkSign);
cg.emit.emit("imul", 10, value);
cg.emit.emit("add", nextDigit, value);
cg.emit.emit("jmp", moreDigits);
// No number can be read (non-digit first or following the '-')
cg.emit.emitLabel(inputError);
Interrupts.exit(cg, Interrupts.EXIT_INPUT_MISMATCH);
// Sign check and end
cg.emit.emitLabel(checkSign);
cg.emit.emit("cmp", 0, negative);
cg.emit.emit("je", endRead);
cg.emit.emit("negl", value);
cg.emit.emitLabel(endRead);
// Register bookkeeping and return read value
cg.rm.releaseRegister(negative);
cg.rm.releaseRegister(nextDigit);
return value;
}
private void charToIntOrJump(Register reg, String jumpLabel) {
cg.emit.emit("cmp", '0', reg);
cg.emit.emit("jl", jumpLabel);
cg.emit.emit("cmp", '9', reg);
cg.emit.emit("jg", jumpLabel);
cg.emit.emit("sub", '0', reg);
}
@Override
public Register cast(Cast ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register index(Index ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register intConst(IntConst ast, Void arg) {
Register r = cg.rm.getRegister();
cg.emit.emitMove(AssemblyEmitter.constant(ast.value), r);
return r;
}
@Override
public Register field(Field ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register newArray(NewArray ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register newObject(NewObject ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register nullConst(NullConst ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register thisRef(ThisRef ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register unaryOp(UnaryOp ast, Void arg) {
Register aux = cg.eg.visit(ast.arg(), arg);
switch (ast.operator) {
case U_PLUS:
return aux;
case U_MINUS:
cg.emit.emit("negl", aux);
return aux;
case U_BOOL_NOT:
cg.emit.emit("notl", aux);
return aux;
default:
throw new RuntimeException("Not implemented");
}
}
@Override
public Register var(Var ast, Void arg) {
Register r = cg.rm.getRegister();
cg.emit.emitMove(ast.getLabel(), r);
return r;
}
}

View file

@ -1,97 +0,0 @@
package cd.backend.codegen;
import cd.backend.codegen.RegisterManager.Register;
import static cd.backend.codegen.Interrupts.Mem.BUFFER;
public class Interrupts {
protected static final int EXIT_OK = 0, EXIT_DIV_0 = 7, EXIT_INPUT_MISMATCH = 8;
protected static final int STDIN = 0, STDOUT = 1, STDERR = 2;
protected static final int I_EXIT = 1, I_READ = 3, I_WRITE = 4;
protected enum Mem {
BUFFER("io_buffer"), EAX("eax");
String pos;
Mem(String pos) {
this.pos = pos;
}
@Override
public String toString() {
return pos;
}
}
/**
* Write auxiliary data variables needed for I/O and division
* @param cg AstCodeGenerator to print instructions
*/
protected static void reserveMemory(AstCodeGenerator cg) {
for (Mem m : Mem.values()) {
cg.emit.emitLabel(m.pos);
cg.emit.emitConstantData("0");
}
}
/**
* Writes a single character passed as parameter
* @param cg AstCodeGenerator to print instructions
* @param i Character code in ASCII (or single casted character)
*/
protected static void printChar(AstCodeGenerator cg, int i) {
cg.emit.emitMove(AssemblyEmitter.constant(i), BUFFER.pos);
printChar(cg);
}
/**
* Writes a single character from the BUFFER memory pos to stdout
* @param cg AstCodeGenerator to print instructions
*/
protected static void printChar(AstCodeGenerator cg) {
Register[] needed = {Register.EAX, Register.EBX, Register.ECX, Register.EDX};
for (int i = 0; i < needed.length; i++)
if (cg.rm.isInUse(needed[i]))
cg.emit.emit("push", needed[i]);
cg.emit.emitMove(AssemblyEmitter.constant(I_WRITE), Register.EAX);
cg.emit.emitMove(AssemblyEmitter.constant(STDOUT), Register.EBX);
cg.emit.emitMove("$" + BUFFER.pos, Register.ECX);
cg.emit.emitMove(AssemblyEmitter.constant(1), Register.EDX);
cg.emit.emit("int", 0x80);
for (int i = needed.length - 1; i >= 0; i--)
if (cg.rm.isInUse(needed[i]))
cg.emit.emit("pop", needed[i]);
}
/**
* Reads a single character from stdin and places it in the
* memory pos BUFFER
*/
protected static void readChar(AstCodeGenerator cg, Register destination) {
Register[] needed = {Register.EAX, Register.EBX, Register.ECX, Register.EDX};
for (int i = 0; i < needed.length; i++)
if (cg.rm.isInUse(needed[i]))
cg.emit.emit("push", needed[i]);
cg.emit.emitMove(AssemblyEmitter.constant(I_READ), Register.EAX);
cg.emit.emitMove(AssemblyEmitter.constant(STDIN), Register.EBX);
cg.emit.emitMove("$" + BUFFER.pos, Register.ECX);
cg.emit.emitMove(AssemblyEmitter.constant(1), Register.EDX);
cg.emit.emit("int", 0x80);
for (int i = needed.length - 1; i >= 0; i--)
if (cg.rm.isInUse(needed[i]))
cg.emit.emit("pop", needed[i]);
cg.emit.emitMove(BUFFER.pos, destination);
}
/**
* Generates a exit interrupt with the code provided
* @param cg AstCodeGenerator to print instructions
* @param exitCode Number to use as exit code (can use constants in this class)
*/
protected static void exit(AstCodeGenerator cg, int exitCode) {
cg.emit.emitMove(AssemblyEmitter.constant(I_EXIT), Register.EAX);
cg.emit.emitMove(AssemblyEmitter.constant(exitCode), Register.EBX);
cg.emit.emit("int", 0x80);
}
}

View file

@ -1,123 +0,0 @@
package cd.backend.codegen;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Simple class that manages the set of currently used
* and unused registers
*/
public class RegisterManager {
private List<Register> registers = new ArrayList<Register>();
// lists of register to save by the callee and the caller
public static final Register CALLEE_SAVE[] = new Register[]{Register.ESI,
Register.EDI, Register.EBX};
public static final Register CALLER_SAVE[] = new Register[]{Register.EAX,
Register.ECX, Register.EDX};
// list of general purpose registers
public static final Register GPR[] = new Register[]{Register.EAX, Register.EBX,
Register.ECX, Register.EDX, Register.ESI, Register.EDI};
// special purpose registers
public static final Register BASE_REG = Register.EBP;
public static final Register STACK_REG = Register.ESP;
public static final int SIZEOF_REG = 4;
public enum Register {
EAX("%eax", ByteRegister.EAX), EBX("%ebx", ByteRegister.EBX), ECX(
"%ecx", ByteRegister.ECX), EDX("%edx", ByteRegister.EDX), ESI(
"%esi", null), EDI("%edi", null), EBP("%ebp", null), ESP(
"%esp", null);
public final String repr;
private final ByteRegister lowByteVersion;
private Register(String repr, ByteRegister bv) {
this.repr = repr;
this.lowByteVersion = bv;
}
@Override
public String toString() {
return repr;
}
/**
* determines if this register has an 8bit version
*/
public boolean hasLowByteVersion() {
return lowByteVersion != null;
}
/**
* Given a register like {@code %eax} returns {@code %al}, but doesn't
* work for {@code %esi} and {@code %edi}!
*/
public ByteRegister lowByteVersion() {
assert hasLowByteVersion();
return lowByteVersion;
}
}
public enum ByteRegister {
EAX("%al"), EBX("%bl"), ECX("%cl"), EDX("%dl");
public final String repr;
private ByteRegister(String repr) {
this.repr = repr;
}
@Override
public String toString() {
return repr;
}
}
/**
* Reset all general purpose registers to free
*/
public void initRegisters() {
registers.clear();
registers.addAll(Arrays.asList(GPR));
}
/**
* returns a free register and marks it as used
*/
public Register getRegister() {
int last = registers.size() - 1;
if (last < 0)
throw new AssemblyFailedException(
"Program requires too many registers");
return registers.remove(last);
}
/**
* marks a currently used register as free
*/
public void releaseRegister(Register reg) {
assert !registers.contains(reg);
registers.add(reg);
}
/**
* Returns whether the register is currently non-free
*/
public boolean isInUse(Register reg) {
return !registers.contains(reg);
}
/**
* returns the number of free registers
*/
public int availableRegisters() {
return registers.size();
}
}

View file

@ -1,206 +0,0 @@
package cd.backend.codegen;
import cd.backend.codegen.RegisterManager.Register;
import cd.ir.Ast;
import cd.ir.Ast.*;
import cd.ir.AstVisitor;
import cd.util.debug.AstOneLine;
import java.util.*;
/**
* Generates code to process statements and declarations.
*/
class StmtGenerator extends AstVisitor<Register, Void> {
protected final AstCodeGenerator cg;
StmtGenerator(AstCodeGenerator astCodeGenerator) {
cg = astCodeGenerator;
}
public void gen(Ast ast) {
visit(ast, null);
}
@Override
public Register visit(Ast ast, Void arg) {
try {
cg.emit.increaseIndent("Emitting " + AstOneLine.toString(ast));
return super.visit(ast, arg);
} finally {
cg.emit.decreaseIndent();
}
}
/**
* Declares a variable in the data segment. This method was implemented because it was necessary
* to create the data segment
* @param ast Variable declaration node
* @param arg Extra arguments
* @return null
*/
@Override
public Register varDecl(Ast.VarDecl ast, Void arg) {
cg.emit.emitLabel(ast.getLabel());
cg.emit.emitConstantData("0");
return null;
}
@Override
public Register methodCall(MethodCall ast, Void dummy) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register methodDecl(MethodDecl ast, Void arg) {
// Prologue: in future version a more complex prologue that
// takes care of parameters and return values is necessary
// Method code
cg.rm.initRegisters();
cg.emit.emitRaw(".section .data");
Interrupts.reserveMemory(cg);
// Variables
cg.sg.visit(ast.decls(), arg);
cg.emit.emitRaw(".section .text");
cg.emit.emitRaw(".globl " + ast.name);
cg.emit.emitLabel(ast.name);
Register result = cg.sg.visit(ast.body(), arg);
// Epilogue: not needed in the simple HW1
return null;
}
@Override
public Register ifElse(IfElse ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register whileLoop(WhileLoop ast, Void arg) {
{
throw new RuntimeException("Not required");
}
}
@Override
public Register assign(Assign ast, Void arg) {
// Because we only handle very simple programs in HW1,
// you can just emit the prologue here!
Register value = cg.eg.visit(ast.right(), arg);
Ast.Var variable = (Var) ast.left();
cg.emit.emitMove(value, variable.getLabel());
cg.rm.releaseRegister(value);
return null;
}
@Override
public Register builtInWrite(BuiltInWrite ast, Void arg) {
String printNonZero = cg.emit.uniqueLabel();
String end = cg.emit.uniqueLabel();
String printPositive = cg.emit.uniqueLabel();
String stackLoop = cg.emit.uniqueLabel();
String printLoop = cg.emit.uniqueLabel();
Register value = cg.eg.visit(ast.arg(), arg);
// Begin: decide if print 0 or print number
cg.emit.emit("cmp", 0, value);
cg.emit.emit("jne", printNonZero); // value != 0
// Print 0
Interrupts.printChar(cg, '0'); // print 0
cg.emit.emit("jmp", end);
// Not 0: positive or negative?
cg.emit.emitLabel(printNonZero);
cg.emit.emit("jg", printPositive); // value > 0
// Number is negative, print '-' then number (with sign changed)
Interrupts.printChar(cg, '-');
cg.emit.emit("negl", value);
// Print number: extract and print all digits of number
cg.emit.emitLabel(printPositive);
// In order to avoid using EAX and EDX, we are going to guarantee
// that there will be at least 2 other registers available
List<Register> auxRegs = Arrays.asList(Register.EDI, Register.ESI);
List<Register> divRegs = Arrays.asList(Register.EAX, Register.EDX);
Map<Register, Boolean> isPushed = new HashMap<>();
boolean usingAuxRegs = cg.rm.availableRegisters() < 4;
if (usingAuxRegs)
for (int i = 0; i < auxRegs.size(); i++)
isPushed.put(auxRegs.get(i), cg.rm.isInUse(auxRegs.get(i)));
// Free EAX and EDX for div operand use
isPushed.put(Register.EAX, cg.rm.isInUse(Register.EAX) && !value.equals(Register.EAX));
isPushed.put(Register.EDX, cg.rm.isInUse(Register.EDX));
// Push all elements
for (Register r : isPushed.keySet())
if (isPushed.get(r))
cg.emit.emit("push", r);
// Force counter and divisor to not be EDX/EAX, as they need to coexist
Register counter = cg.rm.getRegister();
Register divisor = cg.rm.getRegister();
while (divRegs.contains(counter)) {
Register aux = cg.rm.getRegister();
cg.rm.releaseRegister(counter);
counter = aux;
}
while (divRegs.contains(divisor)) {
Register aux = cg.rm.getRegister();
cg.rm.releaseRegister(divisor);
divisor = aux;
}
// Divide by 10 to extract the remainders and push them to the stack
// Registers used: EAX is the remaining digits (initially the value)
// in div it is used for the lower half of the dividend and for quotient
// divisor
// EDX is used as the high half of the dividend and as remainder
cg.emit.emitMove(value, Register.EAX);
cg.rm.releaseRegister(value);
cg.emit.emitMove(AssemblyEmitter.constant(0), counter);
cg.emit.emitLabel(stackLoop);
cg.emit.emitMove(AssemblyEmitter.constant(0), Register.EDX);
cg.emit.emitMove(AssemblyEmitter.constant(10), divisor);
cg.emit.emit("div", divisor);
cg.emit.emit("add", '0', Register.EDX);
cg.emit.emit("push", Register.EDX);
cg.emit.emit("inc", counter);
cg.emit.emit("cmp", 0, Register.EAX);
cg.emit.emit("je", printLoop);
cg.emit.emit("jmp", stackLoop);
// Release divisor register
cg.rm.releaseRegister(divisor);
// Print digits from the stack
cg.emit.emitLabel(printLoop);
cg.emit.emit("cmp", 0, counter);
cg.emit.emit("jz", end);
cg.emit.emit("dec", counter);
cg.emit.emit("pop", Interrupts.Mem.BUFFER.pos);
Interrupts.printChar(cg);
cg.emit.emit("jmp", printLoop);
cg.emit.emitLabel(end);
cg.rm.releaseRegister(counter);
// Restore original registers
for (Register r : isPushed.keySet())
if (isPushed.get(r))
cg.emit.emit("pop", r);
return null;
}
@Override
public Register builtInWriteln(BuiltInWriteln ast, Void arg) {
Interrupts.printChar(cg, '\n');
return null;
}
}

View file

@ -1,6 +0,0 @@
/Javali.tokens
/JavaliBaseVisitor.java
/JavaliLexer.java
/JavaliLexer.tokens
/JavaliParser.java
/JavaliVisitor.java

View file

@ -0,0 +1,203 @@
grammar Javali; // parser grammar, parses streams of tokens
@header {
// Java header
package cd.frontend.parser;
}
// PARSER RULES
literal
: 'null' # NullLiteral
| Boolean # BoolLiteral
| Integer # IntLiteral
;
// Types
type
: primitiveType
| referenceType
;
referenceType
: Ident
| arrayType
;
arrayType
: Ident '[' ']'
| primitiveType '[' ']'
;
primitiveType
: 'boolean'
| 'int'
;
// Program structure
unit
: classDecl+ EOF
;
classDecl
: 'class' Ident ('extends' Ident)? '{' memberList '}'
;
memberList
: (varDecl | methodDecl)*
;
varDecl
: type Ident (',' Ident)* ';'
;
methodDecl
: (type | 'void') Ident '(' formalParamList? ')' '{' varDecl* stmt* '}'
;
formalParamList
: type Ident (',' type Ident)*
;
// Statements
stmt
: assignmentStmt
| methodCallStmt
| ifStmt
| whileStmt
| returnStmt
| writeStmt
;
stmtBlock
: '{' stmt* '}'
;
methodCallStmt
: Ident '(' actualParamList? ')' ';' # LocalMethodCallStmt
| identAccess '.' Ident '(' actualParamList? ')' ';' # ObjectMethodCallStmt
;
assignmentStmt
: identAccess '=' (expr | newExpr | readExpr) ';'
;
writeStmt
: 'write' '(' expr ')' ';' # Write
| 'writeln' '(' ')' ';' # WriteLn
;
ifStmt
: 'if' '(' expr ')' stmtBlock ('else' stmtBlock)?
;
whileStmt
: 'while' '(' expr ')' stmtBlock
;
returnStmt
: 'return' expr? ';'
;
// Expressions
newExpr
: 'new' Ident '(' ')' # NewObject
| 'new' Ident '[' expr ']' # NewObjectArray
| 'new' primitiveType '[' expr ']' # NewPrimitiveArray
;
readExpr
: 'read' '(' ')'
;
actualParamList
: expr (',' expr)*
;
identAccess
: Ident # AccessLocalField
| 'this' # AccessThis
| identAccess '.' Ident # AccessObjectField
| identAccess '[' expr ']' # AccessArray
| Ident '(' actualParamList? ')' # AccessLocalMethod
| identAccess '.' Ident '(' actualParamList? ')'# AccessObjectMethod
;
expr
: literal # ExprConstant
| identAccess # ExprIdentAccess
| '(' expr ')' # ExprParentheses
| ('+'|'-'|'!') expr # ExprUnary
| '(' referenceType ')' expr # ExprCast
| expr ('*'|'/'|'%') expr # ExprBinary
| expr ('+'|'-') expr # ExprBinary
| expr ('<'|'>'|'<='|'>=') expr # ExprBinary
| expr ('=='|'!=') expr # ExprBinary
| expr '&&' expr # ExprBinary
| expr '||' expr # ExprBinary
;
// LEXER RULES
fragment
Letter
: 'A'..'Z'
| 'a'..'z'
;
fragment
Digit
: '0'..'9'
;
fragment
HexDigit
: Digit
| 'a'..'f'
| 'A'..'F'
;
fragment
Decimal
: '0'
| '1'..'9' Digit*
;
fragment
Hexadecimal
: ('0x'|'0X') HexDigit+
;
Integer
: Decimal
| Hexadecimal
;
Boolean
: 'false'
| 'true'
;
Ident
: Letter (Letter|Digit)*
;
// comments and white space does not produce tokens:
COMMENT
: '/*' .*? '*/' -> skip
;
LINE_COMMENT
: '//' ~('\n'|'\r')* -> skip
;
WS
: (' '|'\r'|'\t'|'\n') -> skip
;
// handle characters which failed to match any other token
ErrorCharacter : . ;

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,85 @@
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
T__23=24
T__24=25
T__25=26
T__26=27
T__27=28
T__28=29
T__29=30
T__30=31
T__31=32
T__32=33
T__33=34
T__34=35
T__35=36
T__36=37
T__37=38
T__38=39
Integer=40
Boolean=41
Ident=42
COMMENT=43
LINE_COMMENT=44
WS=45
ErrorCharacter=46
'null'=1
'['=2
']'=3
'boolean'=4
'int'=5
'class'=6
'extends'=7
'{'=8
'}'=9
','=10
';'=11
'void'=12
'('=13
')'=14
'.'=15
'='=16
'write'=17
'writeln'=18
'if'=19
'else'=20
'while'=21
'return'=22
'new'=23
'read'=24
'this'=25
'+'=26
'-'=27
'!'=28
'*'=29
'/'=30
'%'=31
'<'=32
'>'=33
'<='=34
'>='=35
'=='=36
'!='=37
'&&'=38
'||'=39

View file

@ -0,0 +1,329 @@
package cd.frontend.parser;
import cd.frontend.parser.JavaliParser.*;
import cd.ir.Ast;
import cd.ir.Ast.*;
import cd.ir.Ast.BinaryOp.BOp;
import cd.ir.Ast.UnaryOp.UOp;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;
import java.util.ArrayList;
import java.util.List;
public final class JavaliAstVisitor extends JavaliBaseVisitor<Ast> {
public List<ClassDecl> classDecls = new ArrayList<>();
@Override
public Ast visitUnit(UnitContext ctx) {
for (ClassDeclContext classDeclContext : ctx.classDecl())
classDecls.add((ClassDecl) visit(classDeclContext));
return new Seq(new ArrayList<>(classDecls));
}
@Override
public Ast visitClassDecl(ClassDeclContext ctx) {
String name = ctx.Ident(0).getText();
String superClass = "Object"; // Common superclass
if (ctx.Ident().size() == 2)
superClass = ctx.Ident(1).getText();
Seq members = (Seq) visit(ctx.memberList());
return new ClassDecl(name, superClass, members.children());
}
@Override
public Ast visitMemberList(MemberListContext ctx) {
if (ctx.children == null) {
return new Seq(new ArrayList<>());
}
List<Ast> list = new ArrayList<>(ctx.children.size());
for (ParseTree parseTree : ctx.children) {
if (parseTree instanceof VarDeclContext) {
Seq seqVars = (Seq) visit(parseTree);
list.addAll(seqVars.children());
} else {
assert parseTree instanceof MethodDeclContext;
list.add(visit(parseTree));
}
}
return new Seq(list);
}
@Override
public Ast visitVarDecl(VarDeclContext ctx) {
List<Ast> list = new ArrayList<>(ctx.Ident().size());
String type = ctx.type().getText();
for (TerminalNode n : ctx.Ident())
list.add(new VarDecl(type, n.getText()));
return new Seq(list);
}
@Override
public Ast visitMethodDecl(MethodDeclContext ctx) {
List<String> argumentTypes = new ArrayList<>();
List<String> argumentNames = new ArrayList<>();
if (ctx.formalParamList() != null) {
Seq paramList = (Seq) visit(ctx.formalParamList());
for (Ast ast : paramList.children()) {
VarDecl var = (VarDecl) ast;
argumentNames.add(var.name);
argumentTypes.add(var.type);
}
}
List<Ast> decls = new ArrayList<>(ctx.varDecl().size());
for (VarDeclContext varDecl : ctx.varDecl()) {
Seq declarationSeq = (Seq) visit(varDecl);
decls.addAll(declarationSeq.children());
}
List<Ast> stmts = new ArrayList<>(ctx.stmt().size());
for (StmtContext s : ctx.stmt())
stmts.add(visit(s));
return new MethodDecl(
ctx.type() == null ? "void" : ctx.type().getText(),
ctx.Ident().getText(),
argumentTypes,
argumentNames,
new Seq(decls),
new Seq(stmts)
);
}
@Override
public Ast visitFormalParamList(FormalParamListContext ctx) {
List<Ast> list = new ArrayList<>(ctx.type().size());
for (int i = 0; i < ctx.type().size(); i++) {
String type = ctx.type(i).getText();
String name = ctx.Ident(i).getText();
list.add(new VarDecl(type, name));
}
return new Seq(list);
}
@Override
public Ast visitStmt(StmtContext ctx) {
return visit(ctx.children.get(0));
}
@Override
public Ast visitStmtBlock(StmtBlockContext ctx) {
List<Ast> list = new ArrayList<>(ctx.stmt().size());
for (StmtContext stmtContext : ctx.stmt())
list.add(visit(stmtContext));
return new Seq(list);
}
@Override
public Ast visitLocalMethodCallStmt(LocalMethodCallStmtContext ctx) {
return new MethodCall(new MethodCallExpr(
new ThisRef(),
ctx.Ident().getText(),
getParams(ctx.actualParamList())
));
}
@Override
public Ast visitObjectMethodCallStmt(ObjectMethodCallStmtContext ctx) {
return new MethodCall(new MethodCallExpr(
(Expr) visit(ctx.identAccess()),
ctx.Ident().getText(),
getParams(ctx.actualParamList())
));
}
@Override
public Ast visitAssignmentStmt(AssignmentStmtContext ctx) {
Expr left = (Expr) visit(ctx.children.get(0));
Expr right = (Expr) visit(ctx.children.get(2));
return new Assign(left, right);
}
@Override
public Ast visitWrite(WriteContext ctx) {
return new BuiltInWrite((Expr) visit(ctx.expr()));
}
@Override
public Ast visitWriteLn(WriteLnContext ctx) {
return new BuiltInWriteln();
}
@Override
public Ast visitIfStmt(IfStmtContext ctx) {
Expr condition = (Expr) visit(ctx.expr());
Ast then = visit(ctx.stmtBlock(0));
Ast otherwise = new Nop();
if (ctx.stmtBlock().size() == 2)
otherwise = visit(ctx.stmtBlock(1));
return new IfElse(condition, then, otherwise);
}
@Override
public Ast visitWhileStmt(WhileStmtContext ctx) {
Expr condition = (Expr) visit(ctx.expr());
Ast body = visit(ctx.stmtBlock());
return new WhileLoop(condition, body);
}
@Override
public Ast visitReturnStmt(ReturnStmtContext ctx) {
if (ctx.expr() != null)
return new ReturnStmt((Expr) visit(ctx.expr()));
else
return new ReturnStmt(null);
}
@Override
public Ast visitNewObject(NewObjectContext ctx) {
return new NewObject(ctx.Ident().getText());
}
@Override
public Ast visitNewObjectArray(NewObjectArrayContext ctx) {
String type = ctx.Ident().getText();
Expr size = (Expr) visit(ctx.expr());
return new NewArray(type + "[]", size);
}
@Override
public Ast visitNewPrimitiveArray(NewPrimitiveArrayContext ctx) {
String type = ctx.primitiveType().getText();
Expr size = (Expr) visit(ctx.expr());
return new NewArray(type + "[]", size);
}
@Override
public Ast visitReadExpr(ReadExprContext ctx) {
return new BuiltInRead();
}
@Override
public Ast visitActualParamList(ActualParamListContext ctx) {
List<Ast> list = new ArrayList<>(ctx.expr().size());
for (ExprContext exprContext : ctx.expr())
list.add(visit(exprContext));
return new Seq(list);
}
@Override
public Ast visitAccessThis(AccessThisContext ctx) {
return new ThisRef();
}
@Override
public Ast visitAccessLocalField(AccessLocalFieldContext ctx) {
return new Var(ctx.Ident().getText());
}
@Override
public Ast visitAccessObjectField(AccessObjectFieldContext ctx) {
Expr arg = (Expr) visit(ctx.identAccess());
String fieldName = ctx.Ident().getText();
return new Field(arg, fieldName);
}
@Override
public Ast visitAccessLocalMethod(AccessLocalMethodContext ctx) {
return new MethodCallExpr(
new ThisRef(),
ctx.Ident().getText(),
getParams(ctx.actualParamList())
);
}
@Override
public Ast visitAccessArray(AccessArrayContext ctx) {
Expr array = (Expr) visit(ctx.identAccess());
Expr index = (Expr) visit(ctx.expr());
return new Index(array, index);
}
@Override
public Ast visitAccessObjectMethod(AccessObjectMethodContext ctx) {
return new MethodCallExpr(
(Expr) visit(ctx.identAccess()),
ctx.Ident().getText(),
getParams(ctx.actualParamList())
);
}
@Override
public Ast visitExprBinary(ExprBinaryContext ctx) {
Expr left = (Expr) visit(ctx.expr(0));
Expr right = (Expr) visit(ctx.expr(1));
String op = ctx.getChild(1).getText();
for (BOp bop : BOp.values())
if (bop.repr.equals(op))
return new BinaryOp(left, bop, right);
throw new RuntimeException("BOp enum is inconsistent with grammar");
}
@Override
public Ast visitExprCast(ExprCastContext ctx) {
Expr arg = (Expr) visit(ctx.expr());
String typeName = ctx.referenceType().getText();
return new Cast(arg, typeName);
}
@Override
public Ast visitExprParentheses(ExprParenthesesContext ctx) {
return visit(ctx.expr());
}
@Override
public Ast visitExprUnary(ExprUnaryContext ctx) {
Expr expr = (Expr) visit(ctx.expr());
String op = ctx.getChild(0).getText();
for (UOp uop : UOp.values())
if (uop.repr.equals(op))
return new UnaryOp(uop, expr);
throw new RuntimeException("UOp enum is inconsistent with grammar");
}
@Override
public Ast visitExprConstant(ExprConstantContext ctx) {
return visit(ctx.literal());
}
@Override
public Ast visitNullLiteral(NullLiteralContext ctx) {
return new NullConst();
}
@Override
public Ast visitBoolLiteral(BoolLiteralContext ctx) {
return new BooleanConst(ctx.Boolean().getText().equals("true"));
}
@Override
public Ast visitIntLiteral(IntLiteralContext ctx) {
try {
return new IntConst(Integer.decode(ctx.Integer().getText()));
} catch (NumberFormatException exception) {
throw new ParseFailure(ctx.start.getLine(), "Value not in 32bit signed int range");
}
}
@Override
public Ast visitExprIdentAccess(ExprIdentAccessContext ctx) {
return visit(ctx.identAccess());
}
/**
* Obtain the parameters for a method call
* @param paramListContext Formal parameter list from the ANTRL tree
* @return List of parameters for the method call
*/
private List<Expr> getParams(ActualParamListContext paramListContext) {
List<Expr> paramList = new ArrayList<>();
if (paramListContext != null) {
Seq paramSeq = (Seq) visit(paramListContext);
for (Ast ast : paramSeq.children())
paramList.add((Expr) ast);
}
return paramList;
}
}

View file

@ -0,0 +1,297 @@
// Generated from /home/carlos/eth/cd/nop90/HW2/src/cd/frontend/parser/Javali.g4 by ANTLR 4.7.1
// Java header
package cd.frontend.parser;
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
/**
* This class provides an empty implementation of {@link JavaliVisitor},
* which can be extended to create a visitor which only needs to handle a subset
* of the available methods.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public class JavaliBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements JavaliVisitor<T> {
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNullLiteral(JavaliParser.NullLiteralContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitBoolLiteral(JavaliParser.BoolLiteralContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIntLiteral(JavaliParser.IntLiteralContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitType(JavaliParser.TypeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitReferenceType(JavaliParser.ReferenceTypeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitArrayType(JavaliParser.ArrayTypeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitPrimitiveType(JavaliParser.PrimitiveTypeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitUnit(JavaliParser.UnitContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitClassDecl(JavaliParser.ClassDeclContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitMemberList(JavaliParser.MemberListContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitVarDecl(JavaliParser.VarDeclContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitMethodDecl(JavaliParser.MethodDeclContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFormalParamList(JavaliParser.FormalParamListContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitStmt(JavaliParser.StmtContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitStmtBlock(JavaliParser.StmtBlockContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLocalMethodCallStmt(JavaliParser.LocalMethodCallStmtContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitObjectMethodCallStmt(JavaliParser.ObjectMethodCallStmtContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAssignmentStmt(JavaliParser.AssignmentStmtContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitWrite(JavaliParser.WriteContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitWriteLn(JavaliParser.WriteLnContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIfStmt(JavaliParser.IfStmtContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitWhileStmt(JavaliParser.WhileStmtContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitReturnStmt(JavaliParser.ReturnStmtContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNewObject(JavaliParser.NewObjectContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNewObjectArray(JavaliParser.NewObjectArrayContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNewPrimitiveArray(JavaliParser.NewPrimitiveArrayContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitReadExpr(JavaliParser.ReadExprContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitActualParamList(JavaliParser.ActualParamListContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAccessThis(JavaliParser.AccessThisContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAccessLocalField(JavaliParser.AccessLocalFieldContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAccessObjectField(JavaliParser.AccessObjectFieldContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAccessLocalMethod(JavaliParser.AccessLocalMethodContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAccessArray(JavaliParser.AccessArrayContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAccessObjectMethod(JavaliParser.AccessObjectMethodContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprBinary(JavaliParser.ExprBinaryContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprCast(JavaliParser.ExprCastContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprParentheses(JavaliParser.ExprParenthesesContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprUnary(JavaliParser.ExprUnaryContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprConstant(JavaliParser.ExprConstantContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprIdentAccess(JavaliParser.ExprIdentAccessContext ctx) { return visitChildren(ctx); }
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,232 @@
// Generated from /home/carlos/eth/cd/nop90/HW2/src/cd/frontend/parser/Javali.g4 by ANTLR 4.7.1
// Java header
package cd.frontend.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 JavaliLexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.7.1", 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, T__23=24,
T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31,
T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38,
T__38=39, Integer=40, Boolean=41, Ident=42, COMMENT=43, LINE_COMMENT=44,
WS=45, ErrorCharacter=46;
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", "T__23", "T__24",
"T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32",
"T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "Letter", "Digit",
"HexDigit", "Decimal", "Hexadecimal", "Integer", "Boolean", "Ident", "COMMENT",
"LINE_COMMENT", "WS", "ErrorCharacter"
};
private static final String[] _LITERAL_NAMES = {
null, "'null'", "'['", "']'", "'boolean'", "'int'", "'class'", "'extends'",
"'{'", "'}'", "','", "';'", "'void'", "'('", "')'", "'.'", "'='", "'write'",
"'writeln'", "'if'", "'else'", "'while'", "'return'", "'new'", "'read'",
"'this'", "'+'", "'-'", "'!'", "'*'", "'/'", "'%'", "'<'", "'>'", "'<='",
"'>='", "'=='", "'!='", "'&&'", "'||'"
};
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,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, "Integer", "Boolean", "Ident", "COMMENT", "LINE_COMMENT",
"WS", "ErrorCharacter"
};
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] = "<INVALID>";
}
}
}
@Override
@Deprecated
public String[] getTokenNames() {
return tokenNames;
}
@Override
public Vocabulary getVocabulary() {
return VOCABULARY;
}
public JavaliLexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "Javali.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\60\u0147\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\4\35\t\35\4\36\t\36\4\37\t\37\4 \t"+
" \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t"+
"+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+
"\t\64\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\4\3\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\3\7\3\b\3\b\3\b\3\b\3\b\3\b\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\r\3\r\3\r\3\16\3\16"+
"\3\17\3\17\3\20\3\20\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23"+
"\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25"+
"\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\30\3\30\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\33"+
"\3\33\3\34\3\34\3\35\3\35\3\36\3\36\3\37\3\37\3 \3 \3!\3!\3\"\3\"\3#\3"+
"#\3#\3$\3$\3$\3%\3%\3%\3&\3&\3&\3\'\3\'\3\'\3(\3(\3(\3)\3)\3*\3*\3+\3"+
"+\5+\u00fb\n+\3,\3,\3,\7,\u0100\n,\f,\16,\u0103\13,\5,\u0105\n,\3-\3-"+
"\3-\3-\5-\u010b\n-\3-\6-\u010e\n-\r-\16-\u010f\3.\3.\5.\u0114\n.\3/\3"+
"/\3/\3/\3/\3/\3/\3/\3/\5/\u011f\n/\3\60\3\60\3\60\7\60\u0124\n\60\f\60"+
"\16\60\u0127\13\60\3\61\3\61\3\61\3\61\7\61\u012d\n\61\f\61\16\61\u0130"+
"\13\61\3\61\3\61\3\61\3\61\3\61\3\62\3\62\3\62\3\62\7\62\u013b\n\62\f"+
"\62\16\62\u013e\13\62\3\62\3\62\3\63\3\63\3\63\3\63\3\64\3\64\3\u012e"+
"\2\65\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\359\36"+
";\37= ?!A\"C#E$G%I&K\'M(O)Q\2S\2U\2W\2Y\2[*]+_,a-c.e/g\60\3\2\6\4\2C\\"+
"c|\4\2CHch\4\2\f\f\17\17\5\2\13\f\17\17\"\"\2\u014c\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\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2"+
"?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3"+
"\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2"+
"\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\3i\3\2\2\2\5n\3\2\2\2\7p\3\2\2\2\t"+
"r\3\2\2\2\13z\3\2\2\2\r~\3\2\2\2\17\u0084\3\2\2\2\21\u008c\3\2\2\2\23"+
"\u008e\3\2\2\2\25\u0090\3\2\2\2\27\u0092\3\2\2\2\31\u0094\3\2\2\2\33\u0099"+
"\3\2\2\2\35\u009b\3\2\2\2\37\u009d\3\2\2\2!\u009f\3\2\2\2#\u00a1\3\2\2"+
"\2%\u00a7\3\2\2\2\'\u00af\3\2\2\2)\u00b2\3\2\2\2+\u00b7\3\2\2\2-\u00bd"+
"\3\2\2\2/\u00c4\3\2\2\2\61\u00c8\3\2\2\2\63\u00cd\3\2\2\2\65\u00d2\3\2"+
"\2\2\67\u00d4\3\2\2\29\u00d6\3\2\2\2;\u00d8\3\2\2\2=\u00da\3\2\2\2?\u00dc"+
"\3\2\2\2A\u00de\3\2\2\2C\u00e0\3\2\2\2E\u00e2\3\2\2\2G\u00e5\3\2\2\2I"+
"\u00e8\3\2\2\2K\u00eb\3\2\2\2M\u00ee\3\2\2\2O\u00f1\3\2\2\2Q\u00f4\3\2"+
"\2\2S\u00f6\3\2\2\2U\u00fa\3\2\2\2W\u0104\3\2\2\2Y\u010a\3\2\2\2[\u0113"+
"\3\2\2\2]\u011e\3\2\2\2_\u0120\3\2\2\2a\u0128\3\2\2\2c\u0136\3\2\2\2e"+
"\u0141\3\2\2\2g\u0145\3\2\2\2ij\7p\2\2jk\7w\2\2kl\7n\2\2lm\7n\2\2m\4\3"+
"\2\2\2no\7]\2\2o\6\3\2\2\2pq\7_\2\2q\b\3\2\2\2rs\7d\2\2st\7q\2\2tu\7q"+
"\2\2uv\7n\2\2vw\7g\2\2wx\7c\2\2xy\7p\2\2y\n\3\2\2\2z{\7k\2\2{|\7p\2\2"+
"|}\7v\2\2}\f\3\2\2\2~\177\7e\2\2\177\u0080\7n\2\2\u0080\u0081\7c\2\2\u0081"+
"\u0082\7u\2\2\u0082\u0083\7u\2\2\u0083\16\3\2\2\2\u0084\u0085\7g\2\2\u0085"+
"\u0086\7z\2\2\u0086\u0087\7v\2\2\u0087\u0088\7g\2\2\u0088\u0089\7p\2\2"+
"\u0089\u008a\7f\2\2\u008a\u008b\7u\2\2\u008b\20\3\2\2\2\u008c\u008d\7"+
"}\2\2\u008d\22\3\2\2\2\u008e\u008f\7\177\2\2\u008f\24\3\2\2\2\u0090\u0091"+
"\7.\2\2\u0091\26\3\2\2\2\u0092\u0093\7=\2\2\u0093\30\3\2\2\2\u0094\u0095"+
"\7x\2\2\u0095\u0096\7q\2\2\u0096\u0097\7k\2\2\u0097\u0098\7f\2\2\u0098"+
"\32\3\2\2\2\u0099\u009a\7*\2\2\u009a\34\3\2\2\2\u009b\u009c\7+\2\2\u009c"+
"\36\3\2\2\2\u009d\u009e\7\60\2\2\u009e \3\2\2\2\u009f\u00a0\7?\2\2\u00a0"+
"\"\3\2\2\2\u00a1\u00a2\7y\2\2\u00a2\u00a3\7t\2\2\u00a3\u00a4\7k\2\2\u00a4"+
"\u00a5\7v\2\2\u00a5\u00a6\7g\2\2\u00a6$\3\2\2\2\u00a7\u00a8\7y\2\2\u00a8"+
"\u00a9\7t\2\2\u00a9\u00aa\7k\2\2\u00aa\u00ab\7v\2\2\u00ab\u00ac\7g\2\2"+
"\u00ac\u00ad\7n\2\2\u00ad\u00ae\7p\2\2\u00ae&\3\2\2\2\u00af\u00b0\7k\2"+
"\2\u00b0\u00b1\7h\2\2\u00b1(\3\2\2\2\u00b2\u00b3\7g\2\2\u00b3\u00b4\7"+
"n\2\2\u00b4\u00b5\7u\2\2\u00b5\u00b6\7g\2\2\u00b6*\3\2\2\2\u00b7\u00b8"+
"\7y\2\2\u00b8\u00b9\7j\2\2\u00b9\u00ba\7k\2\2\u00ba\u00bb\7n\2\2\u00bb"+
"\u00bc\7g\2\2\u00bc,\3\2\2\2\u00bd\u00be\7t\2\2\u00be\u00bf\7g\2\2\u00bf"+
"\u00c0\7v\2\2\u00c0\u00c1\7w\2\2\u00c1\u00c2\7t\2\2\u00c2\u00c3\7p\2\2"+
"\u00c3.\3\2\2\2\u00c4\u00c5\7p\2\2\u00c5\u00c6\7g\2\2\u00c6\u00c7\7y\2"+
"\2\u00c7\60\3\2\2\2\u00c8\u00c9\7t\2\2\u00c9\u00ca\7g\2\2\u00ca\u00cb"+
"\7c\2\2\u00cb\u00cc\7f\2\2\u00cc\62\3\2\2\2\u00cd\u00ce\7v\2\2\u00ce\u00cf"+
"\7j\2\2\u00cf\u00d0\7k\2\2\u00d0\u00d1\7u\2\2\u00d1\64\3\2\2\2\u00d2\u00d3"+
"\7-\2\2\u00d3\66\3\2\2\2\u00d4\u00d5\7/\2\2\u00d58\3\2\2\2\u00d6\u00d7"+
"\7#\2\2\u00d7:\3\2\2\2\u00d8\u00d9\7,\2\2\u00d9<\3\2\2\2\u00da\u00db\7"+
"\61\2\2\u00db>\3\2\2\2\u00dc\u00dd\7\'\2\2\u00dd@\3\2\2\2\u00de\u00df"+
"\7>\2\2\u00dfB\3\2\2\2\u00e0\u00e1\7@\2\2\u00e1D\3\2\2\2\u00e2\u00e3\7"+
">\2\2\u00e3\u00e4\7?\2\2\u00e4F\3\2\2\2\u00e5\u00e6\7@\2\2\u00e6\u00e7"+
"\7?\2\2\u00e7H\3\2\2\2\u00e8\u00e9\7?\2\2\u00e9\u00ea\7?\2\2\u00eaJ\3"+
"\2\2\2\u00eb\u00ec\7#\2\2\u00ec\u00ed\7?\2\2\u00edL\3\2\2\2\u00ee\u00ef"+
"\7(\2\2\u00ef\u00f0\7(\2\2\u00f0N\3\2\2\2\u00f1\u00f2\7~\2\2\u00f2\u00f3"+
"\7~\2\2\u00f3P\3\2\2\2\u00f4\u00f5\t\2\2\2\u00f5R\3\2\2\2\u00f6\u00f7"+
"\4\62;\2\u00f7T\3\2\2\2\u00f8\u00fb\5S*\2\u00f9\u00fb\t\3\2\2\u00fa\u00f8"+
"\3\2\2\2\u00fa\u00f9\3\2\2\2\u00fbV\3\2\2\2\u00fc\u0105\7\62\2\2\u00fd"+
"\u0101\4\63;\2\u00fe\u0100\5S*\2\u00ff\u00fe\3\2\2\2\u0100\u0103\3\2\2"+
"\2\u0101\u00ff\3\2\2\2\u0101\u0102\3\2\2\2\u0102\u0105\3\2\2\2\u0103\u0101"+
"\3\2\2\2\u0104\u00fc\3\2\2\2\u0104\u00fd\3\2\2\2\u0105X\3\2\2\2\u0106"+
"\u0107\7\62\2\2\u0107\u010b\7z\2\2\u0108\u0109\7\62\2\2\u0109\u010b\7"+
"Z\2\2\u010a\u0106\3\2\2\2\u010a\u0108\3\2\2\2\u010b\u010d\3\2\2\2\u010c"+
"\u010e\5U+\2\u010d\u010c\3\2\2\2\u010e\u010f\3\2\2\2\u010f\u010d\3\2\2"+
"\2\u010f\u0110\3\2\2\2\u0110Z\3\2\2\2\u0111\u0114\5W,\2\u0112\u0114\5"+
"Y-\2\u0113\u0111\3\2\2\2\u0113\u0112\3\2\2\2\u0114\\\3\2\2\2\u0115\u0116"+
"\7h\2\2\u0116\u0117\7c\2\2\u0117\u0118\7n\2\2\u0118\u0119\7u\2\2\u0119"+
"\u011f\7g\2\2\u011a\u011b\7v\2\2\u011b\u011c\7t\2\2\u011c\u011d\7w\2\2"+
"\u011d\u011f\7g\2\2\u011e\u0115\3\2\2\2\u011e\u011a\3\2\2\2\u011f^\3\2"+
"\2\2\u0120\u0125\5Q)\2\u0121\u0124\5Q)\2\u0122\u0124\5S*\2\u0123\u0121"+
"\3\2\2\2\u0123\u0122\3\2\2\2\u0124\u0127\3\2\2\2\u0125\u0123\3\2\2\2\u0125"+
"\u0126\3\2\2\2\u0126`\3\2\2\2\u0127\u0125\3\2\2\2\u0128\u0129\7\61\2\2"+
"\u0129\u012a\7,\2\2\u012a\u012e\3\2\2\2\u012b\u012d\13\2\2\2\u012c\u012b"+
"\3\2\2\2\u012d\u0130\3\2\2\2\u012e\u012f\3\2\2\2\u012e\u012c\3\2\2\2\u012f"+
"\u0131\3\2\2\2\u0130\u012e\3\2\2\2\u0131\u0132\7,\2\2\u0132\u0133\7\61"+
"\2\2\u0133\u0134\3\2\2\2\u0134\u0135\b\61\2\2\u0135b\3\2\2\2\u0136\u0137"+
"\7\61\2\2\u0137\u0138\7\61\2\2\u0138\u013c\3\2\2\2\u0139\u013b\n\4\2\2"+
"\u013a\u0139\3\2\2\2\u013b\u013e\3\2\2\2\u013c\u013a\3\2\2\2\u013c\u013d"+
"\3\2\2\2\u013d\u013f\3\2\2\2\u013e\u013c\3\2\2\2\u013f\u0140\b\62\2\2"+
"\u0140d\3\2\2\2\u0141\u0142\t\5\2\2\u0142\u0143\3\2\2\2\u0143\u0144\b"+
"\63\2\2\u0144f\3\2\2\2\u0145\u0146\13\2\2\2\u0146h\3\2\2\2\16\2\u00fa"+
"\u0101\u0104\u010a\u010f\u0113\u011e\u0123\u0125\u012e\u013c\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);
}
}
}

View file

@ -0,0 +1,85 @@
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
T__23=24
T__24=25
T__25=26
T__26=27
T__27=28
T__28=29
T__29=30
T__30=31
T__31=32
T__32=33
T__33=34
T__34=35
T__35=36
T__36=37
T__37=38
T__38=39
Integer=40
Boolean=41
Ident=42
COMMENT=43
LINE_COMMENT=44
WS=45
ErrorCharacter=46
'null'=1
'['=2
']'=3
'boolean'=4
'int'=5
'class'=6
'extends'=7
'{'=8
'}'=9
','=10
';'=11
'void'=12
'('=13
')'=14
'.'=15
'='=16
'write'=17
'writeln'=18
'if'=19
'else'=20
'while'=21
'return'=22
'new'=23
'read'=24
'this'=25
'+'=26
'-'=27
'!'=28
'*'=29
'/'=30
'%'=31
'<'=32
'>'=33
'<='=34
'>='=35
'=='=36
'!='=37
'&&'=38
'||'=39

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,278 @@
// Generated from /home/carlos/eth/cd/nop90/HW2/src/cd/frontend/parser/Javali.g4 by ANTLR 4.7.1
// Java header
package cd.frontend.parser;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
/**
* This interface defines a complete generic visitor for a parse tree produced
* by {@link JavaliParser}.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public interface JavaliVisitor<T> extends ParseTreeVisitor<T> {
/**
* Visit a parse tree produced by the {@code NullLiteral}
* labeled alternative in {@link JavaliParser#literal}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNullLiteral(JavaliParser.NullLiteralContext ctx);
/**
* Visit a parse tree produced by the {@code BoolLiteral}
* labeled alternative in {@link JavaliParser#literal}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitBoolLiteral(JavaliParser.BoolLiteralContext ctx);
/**
* Visit a parse tree produced by the {@code IntLiteral}
* labeled alternative in {@link JavaliParser#literal}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitIntLiteral(JavaliParser.IntLiteralContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#type}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitType(JavaliParser.TypeContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#referenceType}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitReferenceType(JavaliParser.ReferenceTypeContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#arrayType}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitArrayType(JavaliParser.ArrayTypeContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#primitiveType}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitPrimitiveType(JavaliParser.PrimitiveTypeContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#unit}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitUnit(JavaliParser.UnitContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#classDecl}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitClassDecl(JavaliParser.ClassDeclContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#memberList}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitMemberList(JavaliParser.MemberListContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#varDecl}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitVarDecl(JavaliParser.VarDeclContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#methodDecl}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitMethodDecl(JavaliParser.MethodDeclContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#formalParamList}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitFormalParamList(JavaliParser.FormalParamListContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#stmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitStmt(JavaliParser.StmtContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#stmtBlock}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitStmtBlock(JavaliParser.StmtBlockContext ctx);
/**
* Visit a parse tree produced by the {@code LocalMethodCallStmt}
* labeled alternative in {@link JavaliParser#methodCallStmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLocalMethodCallStmt(JavaliParser.LocalMethodCallStmtContext ctx);
/**
* Visit a parse tree produced by the {@code ObjectMethodCallStmt}
* labeled alternative in {@link JavaliParser#methodCallStmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitObjectMethodCallStmt(JavaliParser.ObjectMethodCallStmtContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#assignmentStmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAssignmentStmt(JavaliParser.AssignmentStmtContext ctx);
/**
* Visit a parse tree produced by the {@code Write}
* labeled alternative in {@link JavaliParser#writeStmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitWrite(JavaliParser.WriteContext ctx);
/**
* Visit a parse tree produced by the {@code WriteLn}
* labeled alternative in {@link JavaliParser#writeStmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitWriteLn(JavaliParser.WriteLnContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#ifStmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitIfStmt(JavaliParser.IfStmtContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#whileStmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitWhileStmt(JavaliParser.WhileStmtContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#returnStmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitReturnStmt(JavaliParser.ReturnStmtContext ctx);
/**
* Visit a parse tree produced by the {@code NewObject}
* labeled alternative in {@link JavaliParser#newExpr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNewObject(JavaliParser.NewObjectContext ctx);
/**
* Visit a parse tree produced by the {@code NewObjectArray}
* labeled alternative in {@link JavaliParser#newExpr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNewObjectArray(JavaliParser.NewObjectArrayContext ctx);
/**
* Visit a parse tree produced by the {@code NewPrimitiveArray}
* labeled alternative in {@link JavaliParser#newExpr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNewPrimitiveArray(JavaliParser.NewPrimitiveArrayContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#readExpr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitReadExpr(JavaliParser.ReadExprContext ctx);
/**
* Visit a parse tree produced by {@link JavaliParser#actualParamList}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitActualParamList(JavaliParser.ActualParamListContext ctx);
/**
* Visit a parse tree produced by the {@code AccessThis}
* labeled alternative in {@link JavaliParser#identAccess}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAccessThis(JavaliParser.AccessThisContext ctx);
/**
* Visit a parse tree produced by the {@code AccessLocalField}
* labeled alternative in {@link JavaliParser#identAccess}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAccessLocalField(JavaliParser.AccessLocalFieldContext ctx);
/**
* Visit a parse tree produced by the {@code AccessObjectField}
* labeled alternative in {@link JavaliParser#identAccess}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAccessObjectField(JavaliParser.AccessObjectFieldContext ctx);
/**
* Visit a parse tree produced by the {@code AccessLocalMethod}
* labeled alternative in {@link JavaliParser#identAccess}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAccessLocalMethod(JavaliParser.AccessLocalMethodContext ctx);
/**
* Visit a parse tree produced by the {@code AccessArray}
* labeled alternative in {@link JavaliParser#identAccess}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAccessArray(JavaliParser.AccessArrayContext ctx);
/**
* Visit a parse tree produced by the {@code AccessObjectMethod}
* labeled alternative in {@link JavaliParser#identAccess}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAccessObjectMethod(JavaliParser.AccessObjectMethodContext ctx);
/**
* Visit a parse tree produced by the {@code ExprBinary}
* labeled alternative in {@link JavaliParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprBinary(JavaliParser.ExprBinaryContext ctx);
/**
* Visit a parse tree produced by the {@code ExprCast}
* labeled alternative in {@link JavaliParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprCast(JavaliParser.ExprCastContext ctx);
/**
* Visit a parse tree produced by the {@code ExprParentheses}
* labeled alternative in {@link JavaliParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprParentheses(JavaliParser.ExprParenthesesContext ctx);
/**
* Visit a parse tree produced by the {@code ExprUnary}
* labeled alternative in {@link JavaliParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprUnary(JavaliParser.ExprUnaryContext ctx);
/**
* Visit a parse tree produced by the {@code ExprConstant}
* labeled alternative in {@link JavaliParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprConstant(JavaliParser.ExprConstantContext ctx);
/**
* Visit a parse tree produced by the {@code ExprIdentAccess}
* labeled alternative in {@link JavaliParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprIdentAccess(JavaliParser.ExprIdentAccessContext ctx);
}

View file

@ -1,13 +1,13 @@
package cd.ir;
import cd.util.Pair;
import cd.util.debug.AstOneLine;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import cd.util.Pair;
import cd.util.debug.AstOneLine;
public abstract class Ast {
/**
@ -17,7 +17,6 @@ public abstract class Ast {
* <p><b>Note:</b> this list may contain null pointers!
*/
public final List<Ast> rwChildren;
final String VAR_LABEL_FORMAT = "var_%s";
protected Ast(int fixedCount) {
if (fixedCount == -1)
@ -70,25 +69,15 @@ public abstract class Ast {
/** Base class for all expressions */
public static abstract class Expr extends Ast {
int needed = -1;
protected Expr(int fixedCount) {
super(fixedCount);
}
@Override
public <R, A> R accept(AstVisitor<R, A> visitor, A arg) {
return this.accept((ExprVisitor<R, A>) visitor, arg);
public <R,A> R accept(AstVisitor<R, A> visitor, A arg) {
return this.accept((ExprVisitor<R,A>)visitor, arg);
}
public abstract <R, A> R accept(ExprVisitor<R, A> visitor, A arg);
/**
* Registers needed to perform the operation represented by this Expr node
* If not already run, the cost is visiting all subnodes, else the cost is constant
* @return Minimum number of registers needed
*/
public abstract int registersNeeded();
public abstract <R,A> R accept(ExprVisitor<R, A> visitor, A arg);
/** Copies any non-AST fields. */
protected <E extends Expr> E postCopy(E item) {
@ -109,20 +98,6 @@ public abstract class Ast {
setRight(right);
}
@Override
public int registersNeeded() {
if (needed != -1)
return needed;
int leftNeed = left().registersNeeded();
int rightNeed = right().registersNeeded();
if (leftNeed > rightNeed)
return needed = leftNeed;
else if (leftNeed < rightNeed)
return needed = rightNeed;
else
return needed = ++rightNeed;
}
public Expr left() { return (Expr) this.rwChildren.get(0); }
public void setLeft(Expr node) { this.rwChildren.set(0, node); }
@ -139,11 +114,6 @@ public abstract class Ast {
setArg(arg);
}
@Override
public int registersNeeded() {
return arg().registersNeeded();
}
public Expr arg() { return (Expr) this.rwChildren.get(0); }
public void setArg(Expr node) { this.rwChildren.set(0, node); }
@ -154,11 +124,6 @@ public abstract class Ast {
public LeafExpr() {
super(0);
}
@Override
public int registersNeeded() {
return 1;
}
}
/** Represents {@code this}, the current object */
@ -382,11 +347,6 @@ public abstract class Ast {
public Var(String name) {
this.name = name;
}
public String getLabel() {
return String.format(VAR_LABEL_FORMAT, name);
}
@Override
public <R, A> R accept(ExprVisitor<R, A> visitor, A arg) {
return visitor.var(this, arg);
@ -449,11 +409,6 @@ public abstract class Ast {
return visitor.methodCall(this, arg);
}
@Override
public int registersNeeded() {
throw new RuntimeException("Not implemented");
}
}
// _________________________________________________________________
@ -643,10 +598,6 @@ public abstract class Ast {
this.name = name;
}
public String getLabel() {
return String.format(VAR_LABEL_FORMAT, name);
}
@Override
public <R, A> R accept(AstVisitor<R, A> visitor, A arg) {
return visitor.varDecl(this, arg);

View file

@ -16,6 +16,17 @@ public class AstVisitor<R,A> extends ExprVisitor<R,A> {
return ast.accept(this, arg);
}
/**
* Overrides {@link ExprVisitor#visitChildren(Expr, Object)} and
* delegates to the more general {@link #visitChildren(Ast, Object)}
* with {@link Ast} parameter. This method is final to prevent
* overriding only one of the two versions.
*/
@Override
public final R visitChildren(Expr ast, A arg) {
return visitChildren((Ast) ast, arg);
}
/**
* A handy function which visits the children of {@code ast},
* providing "arg" to each of them. It returns the result of
@ -45,6 +56,7 @@ public class AstVisitor<R,A> extends ExprVisitor<R,A> {
/**
* The default action for expressions is to call this */
@Override
protected R dfltExpr(Expr ast, A arg) {
return dflt(ast, arg);
}

View file

@ -13,11 +13,14 @@ import cd.ir.Ast.Field;
import cd.ir.Ast.IfElse;
import cd.ir.Ast.Index;
import cd.ir.Ast.IntConst;
import cd.ir.Ast.MethodCall;
import cd.ir.Ast.MethodCallExpr;
import cd.ir.Ast.MethodDecl;
import cd.ir.Ast.NewArray;
import cd.ir.Ast.NewObject;
import cd.ir.Ast.Nop;
import cd.ir.Ast.NullConst;
import cd.ir.Ast.ReturnStmt;
import cd.ir.Ast.Seq;
import cd.ir.Ast.ThisRef;
import cd.ir.Ast.UnaryOp;
@ -99,6 +102,16 @@ public class AstOneLine {
return Integer.toString(ast.value);
}
@Override
public String methodCall(MethodCall ast, Void arg) {
return str(ast.getMethodCallExpr());
}
@Override
public String methodCall(MethodCallExpr ast, Void arg) {
return String.format("%s.%s(...)", str(ast.receiver()), ast.methodName);
}
@Override
public String methodDecl(MethodDecl ast, Void arg) {
return String.format("%s %s(...) {...}", ast.returnType, ast.name);
@ -134,6 +147,11 @@ public class AstOneLine {
return "this";
}
@Override
public String returnStmt(ReturnStmt ast, Void arg) {
return ast.arg() != null ? String.format("return %s", str(ast.arg())) : "return";
}
@Override
public String unaryOp(UnaryOp ast, Void arg) {
return String.format("%s(%s)", ast.operator.repr, str(ast.arg()));

View file

@ -0,0 +1,34 @@
package cd.util.debug;
import static java.util.Collections.sort;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import cd.ir.Ast.ClassDecl;
import cd.ir.Ast.MethodDecl;
class DumpUtils {
static final Comparator<ClassDecl> classComparator = new Comparator<ClassDecl>() {
public int compare(ClassDecl left, ClassDecl right) {
return left.name.compareTo(right.name);
}
};
static final Comparator<MethodDecl> methodComparator = new Comparator<MethodDecl>() {
public int compare(MethodDecl left, MethodDecl right) {
return left.name.compareTo(right.name);
}
};
static List<String> sortedStrings(Set<?> set) {
List<String> strings = new ArrayList<String>();
for(Object element : set)
strings.add(element.toString());
sort(strings);
return strings;
}
}

View file

@ -1,20 +1,21 @@
package cd.test;
package cd;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
import cd.Config;
import cd.Main;
import cd.backend.codegen.AssemblyFailedException;
import cd.frontend.parser.ParseFailure;
import cd.ir.Ast.ClassDecl;
import cd.util.FileUtil;
@ -26,13 +27,17 @@ abstract public class AbstractTestAgainstFrozenReference {
public static final String PARSE_FAILURE = "ParseFailure";
public File file, sfile, binfile, infile;
public File parserreffile, semanticreffile, execreffile, cfgreffile, optreffile;
public File parserreffile, semanticreffile, execreffile, cfgreffile, rdreffile,
nnreffile, optreffile;
public File errfile;
public Main main;
public static int counter = 0;
@Test(timeout=10000)
@Rule
public TestRule timeout = new DisableOnDebug(new Timeout(15, TimeUnit.SECONDS));
@Test
public void test() throws Throwable {
System.err.println("[" + counter++ + " = " + file + "]");
@ -47,9 +52,6 @@ abstract public class AbstractTestAgainstFrozenReference {
List<ClassDecl> astRoots = testParser();
if (astRoots != null) {
{
testCodeGenerator(astRoots);
}
}
} catch (org.junit.ComparisonFailure cf) {
throw cf;
@ -78,7 +80,7 @@ abstract public class AbstractTestAgainstFrozenReference {
ProcessBuilder pb = new ProcessBuilder(
javaExe, "-Dcd.meta_hidden.Version=" + referenceVersion(),
"-cp", "lib/frozenReferenceObf.jar" + colon + " lib/junit-4.12.jar" + colon + "lib/antlr-4.4-complete.jar",
"-cp", "lib/frozenReferenceObf.jar" + colon + " lib/junit-4.12.jar" + colon + "lib/antlr-4.7.1-complete.jar",
"cd.FrozenReferenceMain", file.getAbsolutePath());
Process proc = pb.start();
@ -94,13 +96,24 @@ abstract public class AbstractTestAgainstFrozenReference {
private static String referenceVersion() {
{
return "CD_HW_CODEGEN_SIMPLE_SOL";
return "CD_HW_PARSER_SOL";
}
}
private String tryReadRefFile(File fileToFind) {
if (fileToFind.exists() && fileToFind.lastModified() >= file.lastModified()) {
try {
return FileUtil.read(fileToFind);
} catch (IOException e) {
throw new RuntimeException("ERROR: could not read file " + fileToFind.getPath());
}
}
throw new RuntimeException("ERROR: could not find file " + fileToFind.getPath());
}
/** Run the parser and compare the output against the reference results */
private List<ClassDecl> testParser() throws Exception {
String parserRef = findParserRef();
String parserRef = tryReadRefFile(parserreffile);
List<ClassDecl> astRoots = null;
String parserOut;
@ -110,8 +123,11 @@ abstract public class AbstractTestAgainstFrozenReference {
parserOut = AstDump.toString(astRoots);
} catch (ParseFailure pf) {
{
// For this assignment, we expect all tests to parse!
throw pf;
// Parse errors are ok too.
main.debug("");
main.debug("");
main.debug("%s", pf.toString());
parserOut = PARSE_FAILURE;
}
}
@ -121,64 +137,6 @@ abstract public class AbstractTestAgainstFrozenReference {
return astRoots;
}
private String findParserRef() throws IOException {
// Check for a .ref file
if (parserreffile.exists() && parserreffile.lastModified() >= file.lastModified()) {
return FileUtil.read(parserreffile);
}
throw new RuntimeException("ERROR: could not find parser .ref");
}
/**
* Run the code generator, assemble the resulting .s file, and (if the output
* is well-defined) compare against the expected output.
*/
private void testCodeGenerator(List<ClassDecl> astRoots)
throws IOException {
// Determine the input and expected output.
String inFile = (infile.exists() ? FileUtil.read(infile) : "");
String execRef = findExecRef();
// Run the code generator:
try (FileWriter fw = new FileWriter(this.sfile)) {
main.generateCode(astRoots, fw);
}
// At this point, we have generated a .s file and we have to compile
// it to a binary file. We need to call out to GCC or something
// to do this.
String asmOutput = FileUtil.runCommand(
Config.ASM_DIR,
Config.ASM,
new String[] { binfile.getAbsolutePath(),
sfile.getAbsolutePath() }, null, false);
// To check if gcc succeeded, check if the binary file exists.
// We could use the return code instead, but this seems more
// portable to other compilers / make systems.
if (!binfile.exists())
throw new AssemblyFailedException(asmOutput);
// Execute the binary file, providing input if relevant, and
// capturing the output. Check the error code so see if the
// code signaled dynamic errors.
String execOut = FileUtil.runCommand(new File("."),
new String[] { binfile.getAbsolutePath() }, new String[] {},
inFile, true);
// Compute the output to what we expected to see.
if (!execRef.equals(execOut))
assertEqualOutput("exec", execRef, execOut);
}
private String findExecRef() throws IOException {
// Check for a .ref file
if (execreffile.exists() && execreffile.lastModified() > file.lastModified()) {
return FileUtil.read(execreffile);
}
throw new RuntimeException("ERROR: could not find execution .ref");
}
private void assertEquals(String phase, String exp, String act_) {
String act = act_.replace("\r\n", "\n"); // for windows machines
@ -187,16 +145,6 @@ abstract public class AbstractTestAgainstFrozenReference {
}
}
/**
* Compare the output of two executions
*/
private void assertEqualOutput(String phase, String exp, String act_) {
String act = act_.replace("\r\n", "\n"); // for windows machines
if (!exp.equals(act)) {
warnAboutDiff(phase, exp, act);
}
}
private void warnAboutDiff(String phase, String exp, String act) {
try {
try (PrintStream err = new PrintStream(errfile)) {

View file

@ -1,4 +1,4 @@
package cd.test;
package cd;
// NOTE: This code was adapted from the code found at
// http://www.cs.princeton.edu/introcs/96optimization/Diff.java.html

View file

@ -1,4 +1,9 @@
package cd.test;
package cd;
import cd.util.FileUtil;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.io.File;
import java.io.StringWriter;
@ -6,14 +11,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import cd.Config;
import cd.Main;
import cd.util.FileUtil;
@RunWith(Parameterized.class)
public class TestSamplePrograms extends AbstractTestAgainstFrozenReference {
@ -31,8 +28,8 @@ public class TestSamplePrograms extends AbstractTestAgainstFrozenReference {
* particular directory, use sth. like:
* {@code testDir = new File("javali_tests/HW2/")}.
*/
// public static final File testDir = new File("javali_tests/HW1");
public static final File testDir = new File("javali_tests");
public static final File testDir = new File("javali_tests/HW2_nop90");
// public static final File testDir = new File("javali_tests");
@Parameters(name="{index}:{0}")
public static Collection<Object[]> testFiles() {
@ -64,6 +61,8 @@ public class TestSamplePrograms extends AbstractTestAgainstFrozenReference {
this.semanticreffile = new File(file.getPath() + ".semantic.ref");
this.execreffile = new File(file.getPath() + ".exec.ref");
this.cfgreffile = new File(file.getPath() + ".cfg.dot.ref");
this.rdreffile = new File(file.getPath() + ".rd.ref");
this.nnreffile = new File(file.getPath() + ".nn.ref");
this.optreffile = new File(file.getPath() + ".opt.ref");
this.errfile = new File(String.format("%s.err", file.getPath()));
this.main = new Main();