Homework 2
This commit is contained in:
parent
12f678a924
commit
bf60a078d7
64 changed files with 4786 additions and 1185 deletions
|
@ -2,10 +2,9 @@
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="src" path="test"/>
|
<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/junit-4.12.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/hamcrest-core-1.3.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"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
2
.project
2
.project
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<projectDescription>
|
<projectDescription>
|
||||||
<name>Javali-HW1</name>
|
<name>Javali-HW2</name>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
|
|
13
.settings/com.github.jknack.antlr4ide.Antlr4.prefs
Normal file
13
.settings/com.github.jknack.antlr4ide.Antlr4.prefs
Normal 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
|
|
@ -1,12 +1,7 @@
|
||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
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.targetPlatform=1.8
|
||||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
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.assertIdentifier=error
|
||||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
org.eclipse.jdt.core.compiler.source=1.8
|
org.eclipse.jdt.core.compiler.source=1.8
|
||||||
|
|
|
@ -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]
|
38
build.xml
38
build.xml
|
@ -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;
|
<!-- 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
|
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="build.dir" value="${basedir}/bin"/>
|
||||||
<property name="junit.jar" value="${basedir}/lib/junit-4.12.jar"/>
|
<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="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.profile" value="false"/>
|
||||||
<property name="antlr.report" value="false"/>
|
<property name="antlr.report" value="false"/>
|
||||||
<property name="jacocoant.jar" value="${basedir}/lib/jacocoant.jar"/>
|
<property name="jacocoant.jar" value="${basedir}/lib/jacocoant.jar"/>
|
||||||
|
@ -21,16 +21,42 @@
|
||||||
<property name="min.coverage" value="0.5"/>
|
<property name="min.coverage" value="0.5"/>
|
||||||
<property name="coverage.check" value="cd.frontend.*:cd.backend.*"/>
|
<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! -->
|
<!-- Cleans generated code, but NOT the parser source! -->
|
||||||
<target name="clean">
|
<target name="clean">
|
||||||
<delete dir="${build.dir}"/>
|
<delete dir="${build.dir}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<!-- Builds the compiler framework for HW > HW1. -->
|
||||||
<!-- Builds the compiler framework for HW1. -->
|
<target name="compile" depends="generate-parser">
|
||||||
<target name="compile">
|
|
||||||
<mkdir dir="${build.dir}"/>
|
<mkdir dir="${build.dir}"/>
|
||||||
|
|
||||||
<javac debug="true" destdir="${build.dir}" includeantruntime="false">
|
<javac debug="true" destdir="${build.dir}" includeantruntime="false">
|
||||||
|
@ -40,7 +66,6 @@
|
||||||
<pathelement location="${antlr.jar}"/>
|
<pathelement location="${antlr.jar}"/>
|
||||||
<pathelement location="${junit.jar}"/>
|
<pathelement location="${junit.jar}"/>
|
||||||
<pathelement location="${hamcrest.jar}"/>
|
<pathelement location="${hamcrest.jar}"/>
|
||||||
<pathelement location="${parser.jar}"/>
|
|
||||||
</classpath>
|
</classpath>
|
||||||
</javac>
|
</javac>
|
||||||
</target>
|
</target>
|
||||||
|
@ -83,5 +108,4 @@
|
||||||
<fail if="tests-failed" />
|
<fail if="tests-failed" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
18
javali_tests/HW1/Multiplication.javali
Normal file
18
javali_tests/HW1/Multiplication.javali
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
15
javali_tests/HW1/ReadWrite.javali
Normal file
15
javali_tests/HW1/ReadWrite.javali
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
1
javali_tests/HW1/ReadWrite.javali.in
Normal file
1
javali_tests/HW1/ReadWrite.javali.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
22
|
0
javali_tests/HW1_nop90/EightVariablesWrite.javali
Normal file → Executable file
0
javali_tests/HW1_nop90/EightVariablesWrite.javali
Normal file → Executable file
|
@ -14,7 +14,7 @@ class Main {
|
||||||
write(x); writeln();
|
write(x); writeln();
|
||||||
|
|
||||||
/* performe some operation that should generate an int overflow */
|
/* performe some operation that should generate an int overflow */
|
||||||
x = 2147483640;
|
x = 21474836400;
|
||||||
y = 60000;
|
y = 60000;
|
||||||
write( x + y); writeln();
|
write( x + y); writeln();
|
||||||
z = 20000000;
|
z = 20000000;
|
||||||
|
|
10
javali_tests/HW2/ErrWhileMissingBrace.javali
Normal file
10
javali_tests/HW2/ErrWhileMissingBrace.javali
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
12
javali_tests/HW2/OkInheritance.javali
Normal file
12
javali_tests/HW2/OkInheritance.javali
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
class Base {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Extends extends Base {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Main {
|
||||||
|
void main() {
|
||||||
|
write(0);
|
||||||
|
writeln();
|
||||||
|
}
|
||||||
|
}
|
22
javali_tests/HW2/OkSimpleObject.javali
Normal file
22
javali_tests/HW2/OkSimpleObject.javali
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
22
javali_tests/HW2/OkSimpleReturn.javali
Normal file
22
javali_tests/HW2/OkSimpleReturn.javali
Normal 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
javali_tests/HW2/OkSimpleReturnWithExpression.javali
Normal file
27
javali_tests/HW2/OkSimpleReturnWithExpression.javali
Normal 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
24
javali_tests/HW2_nop90/Arrays.javali
Normal file
24
javali_tests/HW2_nop90/Arrays.javali
Normal 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);}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
12
javali_tests/HW2_nop90/Assignments.javali
Normal file
12
javali_tests/HW2_nop90/Assignments.javali
Normal 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];
|
||||||
|
}
|
||||||
|
}
|
16
javali_tests/HW2_nop90/Casts.javali
Executable file
16
javali_tests/HW2_nop90/Casts.javali
Executable 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;
|
||||||
|
}
|
||||||
|
}
|
21
javali_tests/HW2_nop90/Division.javali
Executable file
21
javali_tests/HW2_nop90/Division.javali
Executable 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();
|
||||||
|
}
|
||||||
|
}
|
6
javali_tests/HW2_nop90/DoubleInheritance.javali
Normal file
6
javali_tests/HW2_nop90/DoubleInheritance.javali
Normal 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 {}
|
20
javali_tests/HW2_nop90/EightVariablesWrite.javali
Executable file
20
javali_tests/HW2_nop90/EightVariablesWrite.javali
Executable 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();
|
||||||
|
}
|
||||||
|
}
|
22
javali_tests/HW2_nop90/Expressions.javali
Normal file
22
javali_tests/HW2_nop90/Expressions.javali
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
31
javali_tests/HW2_nop90/Multiplication.javali
Executable file
31
javali_tests/HW2_nop90/Multiplication.javali
Executable 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();
|
||||||
|
}
|
||||||
|
}
|
20
javali_tests/HW2_nop90/NULLTest.javali
Executable file
20
javali_tests/HW2_nop90/NULLTest.javali
Executable 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)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
8
javali_tests/HW2_nop90/OrderOfDeclarations.javali
Normal file
8
javali_tests/HW2_nop90/OrderOfDeclarations.javali
Normal 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) {}
|
||||||
|
}
|
25
javali_tests/HW2_nop90/Overflow.javali
Executable file
25
javali_tests/HW2_nop90/Overflow.javali
Executable 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
1
javali_tests/HW2_nop90/Overflow.javali.in
Executable file
1
javali_tests/HW2_nop90/Overflow.javali.in
Executable file
|
@ -0,0 +1 @@
|
||||||
|
2147483647
|
15
javali_tests/HW2_nop90/ParamLists.javali
Normal file
15
javali_tests/HW2_nop90/ParamLists.javali
Normal 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() {}
|
||||||
|
}
|
26
javali_tests/HW2_nop90/ReadWrite.javali
Executable file
26
javali_tests/HW2_nop90/ReadWrite.javali
Executable 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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
6
javali_tests/HW2_nop90/ReadWrite.javali.in
Executable file
6
javali_tests/HW2_nop90/ReadWrite.javali.in
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
22
|
||||||
|
|
||||||
|
|
||||||
|
1
|
||||||
|
|
||||||
|
-15
|
34
javali_tests/HW2_nop90/Statements.javali
Normal file
34
javali_tests/HW2_nop90/Statements.javali
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
15
javali_tests/HW2_nop90/UnaryOperators.javali
Executable file
15
javali_tests/HW2_nop90/UnaryOperators.javali
Executable 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();
|
||||||
|
}
|
||||||
|
}
|
24
javali_tests/HW2_nop90/conditionExpressions.javali
Executable file
24
javali_tests/HW2_nop90/conditionExpressions.javali
Executable 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;}}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
javali_tests/HW2_nop90/invalidCasts.javali
Executable file
12
javali_tests/HW2_nop90/invalidCasts.javali
Executable 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;
|
||||||
|
}
|
||||||
|
}
|
14
javali_tests/HW2_nop90/newTest.javali
Normal file
14
javali_tests/HW2_nop90/newTest.javali
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
24
javali_tests/HW2_nop90/noParentheses.javali
Executable file
24
javali_tests/HW2_nop90/noParentheses.javali
Executable 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,11 +10,6 @@ public class Config {
|
||||||
MACOSX
|
MACOSX
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* What kind of system we are on
|
|
||||||
*/
|
|
||||||
public static final SystemKind systemKind;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the extension used for assembler files on this platform.
|
* Defines the extension used for assembler files on this platform.
|
||||||
* Currently always {@code .s}.
|
* Currently always {@code .s}.
|
||||||
|
@ -84,11 +79,9 @@ public class Config {
|
||||||
public static final String JAVA_EXE;
|
public static final String JAVA_EXE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
||||||
final String os = System.getProperty("os.name").toLowerCase();
|
final String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
|
||||||
if(os.contains("windows") || os.contains("nt")) {
|
if(os.contains("windows") || os.contains("nt")) {
|
||||||
systemKind = SystemKind.WINDOWS;
|
|
||||||
BINARYEXT = ".exe";
|
BINARYEXT = ".exe";
|
||||||
MAIN = "_main";
|
MAIN = "_main";
|
||||||
PRINTF = "_printf";
|
PRINTF = "_printf";
|
||||||
|
@ -96,7 +89,7 @@ public class Config {
|
||||||
CALLOC = "_calloc";
|
CALLOC = "_calloc";
|
||||||
EXIT = "_exit";
|
EXIT = "_exit";
|
||||||
// These are set up for a Cygwin installation on C:,
|
// 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 = new String[]{"gcc", "-o", "$0", "$1"};
|
||||||
ASM_DIR = new File("C:\\CYGWIN\\BIN");
|
ASM_DIR = new File("C:\\CYGWIN\\BIN");
|
||||||
JAVA_EXE = "javaw.exe";
|
JAVA_EXE = "javaw.exe";
|
||||||
|
@ -108,7 +101,6 @@ public class Config {
|
||||||
COMMENT_SEP = "#";
|
COMMENT_SEP = "#";
|
||||||
}
|
}
|
||||||
else if(os.contains("mac os x") || os.contains("darwin")) {
|
else if(os.contains("mac os x") || os.contains("darwin")) {
|
||||||
systemKind = SystemKind.MACOSX;
|
|
||||||
BINARYEXT = ".bin";
|
BINARYEXT = ".bin";
|
||||||
MAIN = "_main";
|
MAIN = "_main";
|
||||||
PRINTF = "_printf";
|
PRINTF = "_printf";
|
||||||
|
@ -126,7 +118,6 @@ public class Config {
|
||||||
COMMENT_SEP = "#";
|
COMMENT_SEP = "#";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
systemKind = SystemKind.LINUX;
|
|
||||||
BINARYEXT = ".bin";
|
BINARYEXT = ".bin";
|
||||||
MAIN = "main";
|
MAIN = "main";
|
||||||
PRINTF = "printf";
|
PRINTF = "printf";
|
||||||
|
|
|
@ -2,7 +2,6 @@ package cd;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Reader;
|
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.CommonTokenStream;
|
||||||
import org.antlr.v4.runtime.misc.ParseCancellationException;
|
import org.antlr.v4.runtime.misc.ParseCancellationException;
|
||||||
|
|
||||||
import cd.backend.codegen.AstCodeGenerator;
|
|
||||||
import cd.frontend.parser.JavaliAstVisitor;
|
import cd.frontend.parser.JavaliAstVisitor;
|
||||||
import cd.frontend.parser.JavaliLexer;
|
import cd.frontend.parser.JavaliLexer;
|
||||||
import cd.frontend.parser.JavaliParser;
|
import cd.frontend.parser.JavaliParser;
|
||||||
|
@ -36,7 +34,7 @@ public class Main {
|
||||||
// Set to non-null to write debug info out
|
// Set to non-null to write debug info out
|
||||||
public Writer debug = null;
|
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 File cfgdumpbase;
|
||||||
|
|
||||||
public void debug(String format, Object... args) {
|
public void debug(String format, Object... args) {
|
||||||
|
@ -64,15 +62,6 @@ public class Main {
|
||||||
|
|
||||||
// Parse:
|
// Parse:
|
||||||
List<ClassDecl> astRoots = m.parse(fin);
|
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 */
|
/** Dumps the AST to the debug stream */
|
||||||
private void dumpAst(List<ClassDecl> astRoots) throws IOException {
|
private void dumpAst(List<ClassDecl> astRoots) throws IOException {
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
6
src/cd/frontend/parser/.gitignore
vendored
6
src/cd/frontend/parser/.gitignore
vendored
|
@ -1,6 +0,0 @@
|
||||||
/Javali.tokens
|
|
||||||
/JavaliBaseVisitor.java
|
|
||||||
/JavaliLexer.java
|
|
||||||
/JavaliLexer.tokens
|
|
||||||
/JavaliParser.java
|
|
||||||
/JavaliVisitor.java
|
|
203
src/cd/frontend/parser/Javali.g4
Normal file
203
src/cd/frontend/parser/Javali.g4
Normal 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 : . ;
|
127
src/cd/frontend/parser/Javali.interp
Normal file
127
src/cd/frontend/parser/Javali.interp
Normal file
File diff suppressed because one or more lines are too long
85
src/cd/frontend/parser/Javali.tokens
Normal file
85
src/cd/frontend/parser/Javali.tokens
Normal 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
|
329
src/cd/frontend/parser/JavaliAstVisitor.java
Normal file
329
src/cd/frontend/parser/JavaliAstVisitor.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
297
src/cd/frontend/parser/JavaliBaseVisitor.java
Normal file
297
src/cd/frontend/parser/JavaliBaseVisitor.java
Normal 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); }
|
||||||
|
}
|
160
src/cd/frontend/parser/JavaliLexer.interp
Normal file
160
src/cd/frontend/parser/JavaliLexer.interp
Normal file
File diff suppressed because one or more lines are too long
232
src/cd/frontend/parser/JavaliLexer.java
Normal file
232
src/cd/frontend/parser/JavaliLexer.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
src/cd/frontend/parser/JavaliLexer.tokens
Normal file
85
src/cd/frontend/parser/JavaliLexer.tokens
Normal 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
|
2315
src/cd/frontend/parser/JavaliParser.java
Normal file
2315
src/cd/frontend/parser/JavaliParser.java
Normal file
File diff suppressed because it is too large
Load diff
278
src/cd/frontend/parser/JavaliVisitor.java
Normal file
278
src/cd/frontend/parser/JavaliVisitor.java
Normal 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);
|
||||||
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
package cd.ir;
|
package cd.ir;
|
||||||
|
|
||||||
import cd.util.Pair;
|
|
||||||
import cd.util.debug.AstOneLine;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import cd.util.Pair;
|
||||||
|
import cd.util.debug.AstOneLine;
|
||||||
|
|
||||||
public abstract class Ast {
|
public abstract class Ast {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,7 +17,6 @@ public abstract class Ast {
|
||||||
* <p><b>Note:</b> this list may contain null pointers!
|
* <p><b>Note:</b> this list may contain null pointers!
|
||||||
*/
|
*/
|
||||||
public final List<Ast> rwChildren;
|
public final List<Ast> rwChildren;
|
||||||
final String VAR_LABEL_FORMAT = "var_%s";
|
|
||||||
|
|
||||||
protected Ast(int fixedCount) {
|
protected Ast(int fixedCount) {
|
||||||
if (fixedCount == -1)
|
if (fixedCount == -1)
|
||||||
|
@ -70,25 +69,15 @@ public abstract class Ast {
|
||||||
/** Base class for all expressions */
|
/** Base class for all expressions */
|
||||||
public static abstract class Expr extends Ast {
|
public static abstract class Expr extends Ast {
|
||||||
|
|
||||||
int needed = -1;
|
|
||||||
|
|
||||||
protected Expr(int fixedCount) {
|
protected Expr(int fixedCount) {
|
||||||
super(fixedCount);
|
super(fixedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, A> R accept(AstVisitor<R, A> visitor, A arg) {
|
public <R,A> R accept(AstVisitor<R, A> visitor, A arg) {
|
||||||
return this.accept((ExprVisitor<R, A>) visitor, arg);
|
return this.accept((ExprVisitor<R,A>)visitor, arg);
|
||||||
}
|
}
|
||||||
|
public abstract <R,A> R accept(ExprVisitor<R, A> visitor, A 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();
|
|
||||||
|
|
||||||
/** Copies any non-AST fields. */
|
/** Copies any non-AST fields. */
|
||||||
protected <E extends Expr> E postCopy(E item) {
|
protected <E extends Expr> E postCopy(E item) {
|
||||||
|
@ -109,20 +98,6 @@ public abstract class Ast {
|
||||||
setRight(right);
|
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 Expr left() { return (Expr) this.rwChildren.get(0); }
|
||||||
public void setLeft(Expr node) { this.rwChildren.set(0, node); }
|
public void setLeft(Expr node) { this.rwChildren.set(0, node); }
|
||||||
|
|
||||||
|
@ -139,11 +114,6 @@ public abstract class Ast {
|
||||||
setArg(arg);
|
setArg(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int registersNeeded() {
|
|
||||||
return arg().registersNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Expr arg() { return (Expr) this.rwChildren.get(0); }
|
public Expr arg() { return (Expr) this.rwChildren.get(0); }
|
||||||
public void setArg(Expr node) { this.rwChildren.set(0, node); }
|
public void setArg(Expr node) { this.rwChildren.set(0, node); }
|
||||||
|
|
||||||
|
@ -154,11 +124,6 @@ public abstract class Ast {
|
||||||
public LeafExpr() {
|
public LeafExpr() {
|
||||||
super(0);
|
super(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int registersNeeded() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents {@code this}, the current object */
|
/** Represents {@code this}, the current object */
|
||||||
|
@ -382,11 +347,6 @@ public abstract class Ast {
|
||||||
public Var(String name) {
|
public Var(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLabel() {
|
|
||||||
return String.format(VAR_LABEL_FORMAT, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, A> R accept(ExprVisitor<R, A> visitor, A arg) {
|
public <R, A> R accept(ExprVisitor<R, A> visitor, A arg) {
|
||||||
return visitor.var(this, arg);
|
return visitor.var(this, arg);
|
||||||
|
@ -449,11 +409,6 @@ public abstract class Ast {
|
||||||
return visitor.methodCall(this, arg);
|
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;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLabel() {
|
|
||||||
return String.format(VAR_LABEL_FORMAT, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, A> R accept(AstVisitor<R, A> visitor, A arg) {
|
public <R, A> R accept(AstVisitor<R, A> visitor, A arg) {
|
||||||
return visitor.varDecl(this, arg);
|
return visitor.varDecl(this, arg);
|
||||||
|
|
|
@ -16,6 +16,17 @@ public class AstVisitor<R,A> extends ExprVisitor<R,A> {
|
||||||
return ast.accept(this, arg);
|
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},
|
* A handy function which visits the children of {@code ast},
|
||||||
* providing "arg" to each of them. It returns the result of
|
* 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 */
|
* The default action for expressions is to call this */
|
||||||
|
@Override
|
||||||
protected R dfltExpr(Expr ast, A arg) {
|
protected R dfltExpr(Expr ast, A arg) {
|
||||||
return dflt(ast, arg);
|
return dflt(ast, arg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,14 @@ import cd.ir.Ast.Field;
|
||||||
import cd.ir.Ast.IfElse;
|
import cd.ir.Ast.IfElse;
|
||||||
import cd.ir.Ast.Index;
|
import cd.ir.Ast.Index;
|
||||||
import cd.ir.Ast.IntConst;
|
import cd.ir.Ast.IntConst;
|
||||||
|
import cd.ir.Ast.MethodCall;
|
||||||
|
import cd.ir.Ast.MethodCallExpr;
|
||||||
import cd.ir.Ast.MethodDecl;
|
import cd.ir.Ast.MethodDecl;
|
||||||
import cd.ir.Ast.NewArray;
|
import cd.ir.Ast.NewArray;
|
||||||
import cd.ir.Ast.NewObject;
|
import cd.ir.Ast.NewObject;
|
||||||
import cd.ir.Ast.Nop;
|
import cd.ir.Ast.Nop;
|
||||||
import cd.ir.Ast.NullConst;
|
import cd.ir.Ast.NullConst;
|
||||||
|
import cd.ir.Ast.ReturnStmt;
|
||||||
import cd.ir.Ast.Seq;
|
import cd.ir.Ast.Seq;
|
||||||
import cd.ir.Ast.ThisRef;
|
import cd.ir.Ast.ThisRef;
|
||||||
import cd.ir.Ast.UnaryOp;
|
import cd.ir.Ast.UnaryOp;
|
||||||
|
@ -99,6 +102,16 @@ public class AstOneLine {
|
||||||
return Integer.toString(ast.value);
|
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
|
@Override
|
||||||
public String methodDecl(MethodDecl ast, Void arg) {
|
public String methodDecl(MethodDecl ast, Void arg) {
|
||||||
return String.format("%s %s(...) {...}", ast.returnType, ast.name);
|
return String.format("%s %s(...) {...}", ast.returnType, ast.name);
|
||||||
|
@ -134,6 +147,11 @@ public class AstOneLine {
|
||||||
return "this";
|
return "this";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String returnStmt(ReturnStmt ast, Void arg) {
|
||||||
|
return ast.arg() != null ? String.format("return %s", str(ast.arg())) : "return";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String unaryOp(UnaryOp ast, Void arg) {
|
public String unaryOp(UnaryOp ast, Void arg) {
|
||||||
return String.format("%s(%s)", ast.operator.repr, str(ast.arg()));
|
return String.format("%s(%s)", ast.operator.repr, str(ast.arg()));
|
||||||
|
|
34
src/cd/util/debug/DumpUtils.java
Normal file
34
src/cd/util/debug/DumpUtils.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,21 @@
|
||||||
package cd.test;
|
package cd;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
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.frontend.parser.ParseFailure;
|
||||||
import cd.ir.Ast.ClassDecl;
|
import cd.ir.Ast.ClassDecl;
|
||||||
import cd.util.FileUtil;
|
import cd.util.FileUtil;
|
||||||
|
@ -26,13 +27,17 @@ abstract public class AbstractTestAgainstFrozenReference {
|
||||||
public static final String PARSE_FAILURE = "ParseFailure";
|
public static final String PARSE_FAILURE = "ParseFailure";
|
||||||
|
|
||||||
public File file, sfile, binfile, infile;
|
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 File errfile;
|
||||||
public Main main;
|
public Main main;
|
||||||
|
|
||||||
public static int counter = 0;
|
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 {
|
public void test() throws Throwable {
|
||||||
System.err.println("[" + counter++ + " = " + file + "]");
|
System.err.println("[" + counter++ + " = " + file + "]");
|
||||||
|
|
||||||
|
@ -47,9 +52,6 @@ abstract public class AbstractTestAgainstFrozenReference {
|
||||||
|
|
||||||
List<ClassDecl> astRoots = testParser();
|
List<ClassDecl> astRoots = testParser();
|
||||||
if (astRoots != null) {
|
if (astRoots != null) {
|
||||||
{
|
|
||||||
testCodeGenerator(astRoots);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (org.junit.ComparisonFailure cf) {
|
} catch (org.junit.ComparisonFailure cf) {
|
||||||
throw cf;
|
throw cf;
|
||||||
|
@ -78,7 +80,7 @@ abstract public class AbstractTestAgainstFrozenReference {
|
||||||
|
|
||||||
ProcessBuilder pb = new ProcessBuilder(
|
ProcessBuilder pb = new ProcessBuilder(
|
||||||
javaExe, "-Dcd.meta_hidden.Version=" + referenceVersion(),
|
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());
|
"cd.FrozenReferenceMain", file.getAbsolutePath());
|
||||||
|
|
||||||
Process proc = pb.start();
|
Process proc = pb.start();
|
||||||
|
@ -94,13 +96,24 @@ abstract public class AbstractTestAgainstFrozenReference {
|
||||||
|
|
||||||
private static String referenceVersion() {
|
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 */
|
/** Run the parser and compare the output against the reference results */
|
||||||
private List<ClassDecl> testParser() throws Exception {
|
private List<ClassDecl> testParser() throws Exception {
|
||||||
String parserRef = findParserRef();
|
String parserRef = tryReadRefFile(parserreffile);
|
||||||
List<ClassDecl> astRoots = null;
|
List<ClassDecl> astRoots = null;
|
||||||
String parserOut;
|
String parserOut;
|
||||||
|
|
||||||
|
@ -110,8 +123,11 @@ abstract public class AbstractTestAgainstFrozenReference {
|
||||||
parserOut = AstDump.toString(astRoots);
|
parserOut = AstDump.toString(astRoots);
|
||||||
} catch (ParseFailure pf) {
|
} catch (ParseFailure pf) {
|
||||||
{
|
{
|
||||||
// For this assignment, we expect all tests to parse!
|
// Parse errors are ok too.
|
||||||
throw pf;
|
main.debug("");
|
||||||
|
main.debug("");
|
||||||
|
main.debug("%s", pf.toString());
|
||||||
|
parserOut = PARSE_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,64 +137,6 @@ abstract public class AbstractTestAgainstFrozenReference {
|
||||||
return astRoots;
|
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_) {
|
private void assertEquals(String phase, String exp, String act_) {
|
||||||
String act = act_.replace("\r\n", "\n"); // for windows machines
|
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) {
|
private void warnAboutDiff(String phase, String exp, String act) {
|
||||||
try {
|
try {
|
||||||
try (PrintStream err = new PrintStream(errfile)) {
|
try (PrintStream err = new PrintStream(errfile)) {
|
|
@ -1,4 +1,4 @@
|
||||||
package cd.test;
|
package cd;
|
||||||
|
|
||||||
// NOTE: This code was adapted from the code found at
|
// NOTE: This code was adapted from the code found at
|
||||||
// http://www.cs.princeton.edu/introcs/96optimization/Diff.java.html
|
// http://www.cs.princeton.edu/introcs/96optimization/Diff.java.html
|
|
@ -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.File;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
@ -6,14 +11,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
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)
|
@RunWith(Parameterized.class)
|
||||||
public class TestSamplePrograms extends AbstractTestAgainstFrozenReference {
|
public class TestSamplePrograms extends AbstractTestAgainstFrozenReference {
|
||||||
|
|
||||||
|
@ -31,8 +28,8 @@ public class TestSamplePrograms extends AbstractTestAgainstFrozenReference {
|
||||||
* particular directory, use sth. like:
|
* particular directory, use sth. like:
|
||||||
* {@code testDir = new File("javali_tests/HW2/")}.
|
* {@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/HW2_nop90");
|
||||||
public static final File testDir = new File("javali_tests");
|
// public static final File testDir = new File("javali_tests");
|
||||||
|
|
||||||
@Parameters(name="{index}:{0}")
|
@Parameters(name="{index}:{0}")
|
||||||
public static Collection<Object[]> testFiles() {
|
public static Collection<Object[]> testFiles() {
|
||||||
|
@ -64,6 +61,8 @@ public class TestSamplePrograms extends AbstractTestAgainstFrozenReference {
|
||||||
this.semanticreffile = new File(file.getPath() + ".semantic.ref");
|
this.semanticreffile = new File(file.getPath() + ".semantic.ref");
|
||||||
this.execreffile = new File(file.getPath() + ".exec.ref");
|
this.execreffile = new File(file.getPath() + ".exec.ref");
|
||||||
this.cfgreffile = new File(file.getPath() + ".cfg.dot.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.optreffile = new File(file.getPath() + ".opt.ref");
|
||||||
this.errfile = new File(String.format("%s.err", file.getPath()));
|
this.errfile = new File(String.format("%s.err", file.getPath()));
|
||||||
this.main = new Main();
|
this.main = new Main();
|
Loading…
Reference in a new issue