package nebula.vm; /*** * Excerpted from "The Definitive ANTLR Reference", * published by The Pragmatic Bookshelf. * Copyrights apply to this code. It may not be used to create training material, * courses, books, articles, and the like. Contact us if you are in doubt. * We make no guarantees that this code is fit for any purpose. * Visit http://www.pragmaticprogrammer.com/titles/tpantlr for more book information. ***/ import junit.framework.TestCase; import org.antlr.runtime.ANTLRFileStream; import org.antlr.runtime.ANTLRStringStream; import org.antlr.runtime.CharStream; import org.antlr.runtime.CommonTokenStream; public class TestNebulaParser extends TestCase { final StringBuilder sb = new StringBuilder(); private NebulaRegisterParser loadFromString(String code) throws Exception { return parse(new ANTLRStringStream(code)); } private NebulaRegisterParser loadFromFile(String filename) throws Exception { return parse(new ANTLRFileStream(filename)); } private NebulaRegisterParser parse(CharStream stream) throws Exception { NebulaRegisterLexer assemblerLexer = new NebulaRegisterLexer(stream); CommonTokenStream tokens = new CommonTokenStream(assemblerLexer); sb.setLength(0); NebulaRegisterParser parser = new NebulaRegisterParser(tokens) { protected void info(String str) { if (str.charAt(str.length() - 1) == '\n') { String txtTemps = ""; for (TempVar v : tmps) { txtTemps += "" + (v.applied ? " " : v.reg) + " "; } str = String.format("|%1$-10s| %2$s", txtTemps, str); } sb.append(str); }; }; return parser; } public void testClassDefineFile() throws Exception { String filename = "ClsDefineOnly.n"; NebulaRegisterParser parser = loadFromFile(filename); ClassSymbol clz = parser.classDefinition(); assertTrue(parser.getNumberOfSyntaxErrors() == 0); System.out.println(sb.toString()); assertEquals("ClsDefineOnly", clz.name); } public void testClsFieldGet() throws Exception { NebulaRegisterParser result = loadFromFile("ClsFieldGet.n"); System.out.println(result); String filename = "ClsFieldGet.n"; NebulaRegisterParser parser = loadFromFile(filename); ClassSymbol clz = parser.classDefinition(); assertTrue(parser.getNumberOfSyntaxErrors() == 0); System.out.println(sb.toString()); assertEquals("ClsFieldGet", clz.name); } public void test_classDefinition() throws Exception { //@formatter:off String text = "" + "class Test { " + " int i;" + "}"; //@formatter:on NebulaRegisterParser parser = loadFromString(text); ClassSymbol clz = parser.classDefinition(); assertTrue(parser.getNumberOfSyntaxErrors() == 0); assertEquals("Test", clz.name); String actual = sb.toString(); System.out.println(actual); //@formatter:off String expected = "" + "| | FIELD : i\n"; //@formatter:on assertEquals(expected, actual); } public void test_methodDefinition_define_i() throws Exception { //@formatter:off String text = "" + "void funcSayHello(){" + " int i = 9;" + "}"; //@formatter:on NebulaRegisterParser parser = loadFromString(text); ClassSymbol clz = parser.enterClass("Test",null); MethodSymbol method = parser.methodDeclaration(clz); clz = parser.exitClass(clz); assertTrue(parser.getNumberOfSyntaxErrors() == 0); assertEquals("funcSayHello", method.name); assertEquals("V",method.returnType.getName()); String actual = sb.toString(); System.out.println(actual); //@formatter:off String expected = "" + "| | FUNC : funcSayHello() {\n" + "|1 | ICONST: tmp1#I = 9;\n" + "|1 | HIDE : i#I = tmp1#I;\n" + "| | }\n"; //@formatter:on assertEquals(expected, actual); } public void test_methodDefinition_add_1_2() throws Exception { //@formatter:off String text = "" + "void funcSayHello(){" + " int i = 1+2;" + "}"; //@formatter:on NebulaRegisterParser parser = loadFromString(text); ClassSymbol clz = parser.enterClass("test",null); MethodSymbol method = parser.methodDeclaration(clz); clz = parser.exitClass(clz); assertTrue(parser.getNumberOfSyntaxErrors() == 0); assertEquals("funcSayHello", method.name); assertEquals("V",method.returnType.getName()); String actual = sb.toString(); System.out.println(actual); //@formatter:off String expected = "" + "| | FUNC : funcSayHello() {\n" + "|1 | ICONST: tmp1#I = 1;\n" + "|1 2 | ICONST: tmp2#I = 2;\n" + "|1 | IADD : tmp1#I = tmp1#I + tmp2#I;\n" + "|1 | HIDE : i#I = tmp1#I;\n" + "| | }\n"; //@formatter:on assertEquals(expected, actual); } public void test_methodDefinition_invoke() throws Exception { //@formatter:off String text = "" + "void funcSayHello(){" + " int i = this.test();" + "}"; //@formatter:on NebulaRegisterParser parser = loadFromString(text); ClassSymbol clz = parser.enterClass("Test",null); MethodSymbol method = parser.methodDeclaration(clz); clz = parser.exitClass(clz); assertTrue(parser.getNumberOfSyntaxErrors() == 0); assertEquals("funcSayHello", method.name); String actual = sb.toString(); System.out.println(actual); //@formatter:off String expected = "" + "| | FUNC : funcSayHello() {\n" + "|1 | CALL : tmp1#* = this#Test.Test_test();\n" + "|1 | HIDE : i#I = tmp1#*;\n" + "| | }\n"; //@formatter:on assertEquals(expected, actual); } public void test_methodDefinition_invoke_1() throws Exception { //@formatter:off String text = "" + "void funcSayHello(){" + " int we = this.test(2);" + "}"; //@formatter:on NebulaRegisterParser parser = loadFromString(text); ClassSymbol clz = parser.enterClass("Test",null); MethodSymbol method = parser.methodDeclaration(clz); clz = parser.exitClass(clz); assertTrue(parser.getNumberOfSyntaxErrors() == 0); assertEquals("funcSayHello", method.name); String actual = sb.toString(); System.out.println(actual); //@formatter:off String expected = "" + "| | FUNC : funcSayHello() {\n" + "|1 | ICONST: tmp1#I = 2;\n" + "| | CALL : tmp1#* = this#Test.Test_test(tmp1#I );\n" + "| | HIDE : we#I = tmp1#*;\n" + "| | }\n"; //@formatter:on assertEquals(expected, actual); } public void test_methodDefinition_invoke_1_a() throws Exception { //@formatter:off String text = "" + "void funcSayHello2a(){" + " int a = 10;" + " int i = this.test(2,a+9);" + "}"; //@formatter:on NebulaRegisterParser parser = loadFromString(text); ClassSymbol clz = parser.enterClass("Test",null); MethodSymbol method = parser.methodDeclaration(clz); clz = parser.exitClass(clz); assertTrue(parser.getNumberOfSyntaxErrors() == 0); assertEquals("funcSayHello2a", method.name); String actual = sb.toString(); System.out.println(actual); //@formatter:off String expected = "" + "| | FUNC : funcSayHello2a() {\n" + "|1 | ICONST: tmp1#I = 10;\n" + "|1 | HIDE : a#I = tmp1#I;\n" + "|2 | ICONST: tmp2#I = 2;\n" + "|2 3 | ICONST: tmp3#I = 9;\n" + "|2 3 | IADD : tmp3#I = a#I + tmp3#I;\n" + "| | CALL : tmp2#* = this#Test.Test_test(tmp2#I tmp3#I );\n" + "| | HIDE : i#I = tmp2#*;\n" + "| | }\n"; //@formatter:on assertEquals(expected, actual); } public void test_method_complex_compute() throws Exception { //@formatter:off String text = "" + "class Test {" + " void funcSayHello2a(){\n" + " int a = 10;\n" + " Person p = new Person();\n" + " p.age = a; \n" + " int d = this.test(p.age+1,10);\n" + " return a;\n" + " }" + " int test(int a,int b ){" + " return a + b + b;" + " }" + "}"; //@formatter:on NebulaRegisterParser parser = loadFromString(text); ClassSymbol clz = parser.classDefinition(); assertTrue(parser.getNumberOfSyntaxErrors() == 0); assertEquals("funcSayHello2a", clz.methods[0].name); String actual = sb.toString(); System.out.println(actual); //@formatter:off String expectedMain = "" + "| | FUNC : funcSayHello2a() {\n" + "|1 | ICONST: tmp1#I = 10;\n" + "|1 | HIDE : a#I = tmp1#I;\n" + "|2 | STRUCT: tmp2#Person = new Person;\n" + "|2 | HIDE : p#Person = tmp2#Person;\n" + "| | FSTORE: p#Person.age = a#I\n" + "|3 | FLOAD : tmp3#* = p#Person.age\n" + "|3 4 | ICONST: tmp4#I = 1;\n" + "|3 | IADD : tmp3#* = tmp3#* + tmp4#I;\n" + "|3 4 | ICONST: tmp4#I = 10;\n" + "| | CALL : tmp3#* = this#Test.Test_test(tmp3#* tmp4#I );\n" + "| | HIDE : d#I = tmp3#*;\n" + "| | RET : ;\n" + "| | }\n" + "| | FUNC : test() {\n" + "|5 | IADD : tmp5#I = a#I + b#I;\n" + "|5 | IADD : tmp5#I = tmp5#I + b#I;\n" + "|5 | RET : ;\n" + "| | }\n"; //@formatter:on assertEquals(expectedMain, actual); } public void test_methodDefinition_params() throws Exception { //@formatter:off String text = "" + "void funcSayHello(int a, int b){" + " int c = a + b;" + "}"; //@formatter:on NebulaRegisterParser parser = loadFromString(text); ClassSymbol clz = parser.enterClass("test",null); MethodSymbol method = parser.methodDeclaration(clz); clz = parser.exitClass(clz); assertTrue(parser.getNumberOfSyntaxErrors() == 0); assertEquals("funcSayHello", method.name); String actual = sb.toString(); System.out.println(actual); //@formatter:off String expected = "" + "| | FUNC : funcSayHello() {\n" + "|3 | IADD : tmp3#I = a#I + b#I;\n" + "|3 | HIDE : c#I = tmp3#I;\n" + "| | }\n"; //@formatter:on assertEquals(expected, actual); } }