update grammar to remove more junk + upate tests + codegen

This commit is contained in:
ChUrl
2021-02-05 14:08:08 +01:00
parent d1790e526f
commit 384c318c18
11 changed files with 44 additions and 125 deletions

View File

@ -27,7 +27,11 @@ public final class StackSizeAnalyzer {
final StackModel stack = new StackModel();
runStackModel(tree.getRoot().getChildren().get(3).getChildren().get(11), stack);
if (tree.getRoot().getChildren().size() > 1) {
// Or else main-method would be empty
runStackModel(tree.getRoot().getChildren().get(1), stack);
}
Logger.logDebug("Found required stack-depth", StackSizeAnalyzer.class);
return stack.getMax();
@ -64,7 +68,7 @@ public final class StackSizeAnalyzer {
private static void println(SyntaxTreeNode root, StackModel stack) {
stack.push(root); // Getstatic
runStackModel(root.getChildren().get(1).getChildren().get(1), stack);
runStackModel(root.getChildren().get(0).getChildren().get(0), stack);
stack.pop(); // Objectref
stack.pop(); // Argument

View File

@ -89,7 +89,7 @@ public final class FlowGraphGenerator {
private static FlowGraph initFlowGraph(SyntaxTree tree, Map<String, Integer> varMap, String source) {
final String bytecodeVersion = "49.0";
final String clazz = tree.getRoot().getChildren().get(1).getValue();
final String clazz = tree.getRoot().getChildren().get(0).getValue();
final int stackSize = StackSizeAnalyzer.runStackModel(tree);
final int localCount = varMap.size() + 1;
@ -104,8 +104,14 @@ public final class FlowGraphGenerator {
public FlowGraph generateGraph() {
Logger.logDebug("Beginning generation of source-graph", FlowGraphGenerator.class);
if (this.tree.getRoot().getChildren().size() == 1) {
// Empty main-method
return this.graph;
}
// Skip the first 2 identifiers: ClassName, MainArgs
this.generateNode(this.tree.getRoot().getChildren().get(3).getChildren().get(11));
this.generateNode(this.tree.getRoot().getChildren().get(1));
this.graph.purgeEmptyBlocks();
Logger.logDebug("Source-graph generation complete", FlowGraphGenerator.class);
@ -176,7 +182,7 @@ public final class FlowGraphGenerator {
this.graph.addLabel("LOOPstart" + currentLabel);
// Condition while ( ... ) {
this.generateNode(root.getChildren().get(0).getChildren().get(1));
this.generateNode(root.getChildren().get(0).getChildren().get(0));
// Jump out of loop if condition is false
this.graph.addJump("ifeq", "LOOPend" + currentLabel);
@ -202,7 +208,7 @@ public final class FlowGraphGenerator {
final String inst = switch (type) {
case "INTEGER_TYPE", "BOOLEAN_TYPE" -> "istore";
case "STRING_TYPE" -> "astore";
default -> throw new IllegalStateException("Unexpected value: " + type);
default -> throw new CodeGenerationException("Unexpected value: " + type);
};
Logger.logInfo("assign(): Node \"" + root.getName() + ": " + root.getValue() + "\" => " + inst, FlowGraphGenerator.class);
@ -239,7 +245,7 @@ public final class FlowGraphGenerator {
inst = switch (root.getValue()) {
case "ADD" -> "";
case "SUB" -> "ineg";
default -> throw new IllegalStateException("Unexpected value: " + root.getValue());
default -> throw new CodeGenerationException("Unexpected value: " + root.getValue());
};
} else if (root.getChildren().size() == 2) { //! Stack - 1
// Binary operator
@ -253,7 +259,7 @@ public final class FlowGraphGenerator {
case "MUL" -> "imul";
case "DIV" -> "idiv";
case "MOD" -> "irem"; // Remainder operator
default -> throw new IllegalStateException("Unexpected value: " + root.getValue());
default -> throw new CodeGenerationException("Unexpected value: " + root.getValue());
};
}
@ -276,7 +282,7 @@ public final class FlowGraphGenerator {
if (!"NOT".equals(node.getValue())) {
// Possibility doesn't exist, would be frontend-error
throw new IllegalStateException("Unexpected value: " + node.getValue());
throw new CodeGenerationException("Unexpected value: " + node.getValue());
}
this.generateNode(node.getChildren().get(0));
@ -298,12 +304,12 @@ public final class FlowGraphGenerator {
final String cmpeq = switch (type) {
case "INTEGER_TYPE", "BOOLEAN_TYPE" -> "if_icmpeq";
case "STRING_TYPE" -> "if_accmpeq";
default -> throw new IllegalStateException("Unexpected value: " + type);
default -> throw new CodeGenerationException("Unexpected value: " + type);
};
final String cmpne = switch (type) {
case "INTEGER_TYPE", "BOOLEAN_TYPE" -> "if_icmpne";
case "STRING_TYPE" -> "if_accmpne";
default -> throw new IllegalStateException("Unexpected value: " + type);
default -> throw new CodeGenerationException("Unexpected value: " + type);
};
// The comparison operations need to jump
@ -316,7 +322,7 @@ public final class FlowGraphGenerator {
case "LESS_EQUAL" -> this.genComparisonInst("if_icmple", "LE", currentLabel);
case "GREATER" -> this.genComparisonInst("if_icmpgt", "GT", currentLabel);
case "GREATER_EQUAL" -> this.genComparisonInst("if_icmpge", "GE", currentLabel);
default -> throw new IllegalStateException("Unexpected value: " + node.getValue());
default -> throw new CodeGenerationException("Unexpected value: " + node.getValue());
}
}
}
@ -359,7 +365,7 @@ public final class FlowGraphGenerator {
final String inst = switch (type) {
case "INTEGER_TYPE", "BOOLEAN_TYPE" -> "iload";
case "STRING_TYPE" -> "aload";
default -> throw new IllegalStateException("Unexpected value: " + type);
default -> throw new CodeGenerationException("Unexpected value: " + type);
};
Logger.logInfo("identifier(): Node \"" + node.getName() + ": " + node.getValue() + "\" => " + inst, FlowGraphGenerator.class);
@ -370,12 +376,12 @@ public final class FlowGraphGenerator {
private void printlnNode(SyntaxTreeNode node) { //! Stack + 1
this.graph.addInstruction("getstatic", "java/lang/System/out", "Ljava/io/PrintStream;");
final SyntaxTreeNode expr = node.getChildren().get(1).getChildren().get(1);
final SyntaxTreeNode expr = node.getChildren().get(0).getChildren().get(0);
final String type = switch (this.nodeTypeMap.get(expr)) {
case "BOOLEAN_TYPE" -> "Z";
case "INTEGER_TYPE" -> "I";
case "STRING_TYPE" -> "Ljava/lang/String;";
default -> throw new IllegalStateException("Unexpected value: " + this.nodeTypeMap.get(expr));
default -> throw new CodeGenerationException("Unexpected value: " + this.nodeTypeMap.get(expr));
};
this.generateNode(expr);

View File

@ -59,7 +59,7 @@ public final class TypeChecker {
} else if ("par_expr".equals(root.getName())) {
// Nodetable Eintrag für Klammern
final SyntaxTreeNode centerChild = root.getChildren().get(1);
final SyntaxTreeNode centerChild = root.getChildren().get(0);
nodeTable.put(root, nodeTable.get(centerChild));
} else if ("IDENTIFIER".equals(root.getName())) {

View File

@ -36,7 +36,7 @@ class FlowGraphGeneratorTest {
@BeforeAll
static void init() throws IOException, URISyntaxException {
final Path path = Paths.get(FlowGraphGeneratorTest.class.getClassLoader().getResource("exampleGrammars/Grammar.grammar").toURI());
final Path path = Paths.get(System.getProperty("user.dir") + "/stups.grammar");
final Grammar grammar = Grammar.fromFile(path);
parser = StupsParser.fromGrammar(grammar);
stupsGrammar = grammar;

View File

@ -34,7 +34,7 @@ class LivenessAnalysisTest {
@BeforeAll
static void init() throws IOException, URISyntaxException {
final Path path = Paths.get(LivenessAnalysisTest.class.getClassLoader().getResource("exampleGrammars/Grammar.grammar").toURI());
final Path path = Paths.get(System.getProperty("user.dir") + "/stups.grammar");
final Grammar grammar = Grammar.fromFile(path);
parser = StupsParser.fromGrammar(grammar);
stupsGrammar = grammar;

View File

@ -24,7 +24,7 @@ class LexerGrammarParserTest {
@BeforeAll
static void init() throws IOException, URISyntaxException {
final Path path = Paths.get(LexerGrammarParserTest.class.getClassLoader().getResource("exampleGrammars/Grammar.grammar").toURI());
final Path path = Paths.get(System.getProperty("user.dir") + "/stups.grammar");
final Grammar grammar = Grammar.fromFile(path);
parser = StupsParser.fromGrammar(grammar);
}

View File

@ -24,7 +24,7 @@ class ParseTreeCleanerTest {
@BeforeAll
static void init() throws IOException, URISyntaxException {
final Path path = Paths.get(ParseTreeCleanerTest.class.getClassLoader().getResource("exampleGrammars/Grammar.grammar").toURI());
final Path path = Paths.get(System.getProperty("user.dir") + "/stups.grammar");
grammar = Grammar.fromFile(path);
parser = StupsParser.fromGrammar(grammar);
}
@ -49,7 +49,7 @@ class ParseTreeCleanerTest {
ParseTreeCleaner.deleteChildren(tree, grammar);
assertThat(before - tree.size()).isEqualTo(3);
assertThat(before - tree.size()).isEqualTo(19);
}
@Test
@ -79,6 +79,6 @@ class ParseTreeCleanerTest {
ParseTreeCleaner.clean(tree, grammar);
assertThat(tree.size()).isEqualTo(28);
assertThat(tree.size()).isEqualTo(10);
}
}

View File

@ -23,7 +23,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
class TypeCheckerTest {
private final Path path = Paths.get(this.getClass().getClassLoader().getResource("exampleGrammars/Grammar.grammar").toURI());
private final Path path = Paths.get(System.getProperty("user.dir") + "/stups.grammar");
private final Grammar grammar = Grammar.fromFile(this.path);
private final StupsParser stupsParser = StupsParser.fromGrammar(this.grammar);
@ -39,9 +39,8 @@ class TypeCheckerTest {
private SyntaxTree getTree(String expr) {
final Lexer lex = new StupsLexer(CharStreams.fromString(exprToProg(expr)));
final SyntaxTree tree = this.stupsParser.parse(lex.getAllTokens(), lex.getVocabulary());
final SyntaxTree ast = SyntaxTree.toAbstractSyntaxTree(tree, this.grammar);
return ast;
return SyntaxTree.toAbstractSyntaxTree(tree, this.grammar);
}
@ParameterizedTest

View File

@ -28,7 +28,7 @@ class TypeTableTest {
@BeforeAll
static void init() throws IOException, URISyntaxException {
final Path path = Paths.get(TypeTableTest.class.getClassLoader().getResource("exampleGrammars/Grammar.grammar").toURI());
final Path path = Paths.get(System.getProperty("user.dir") + "/stups.grammar");
grammar = Grammar.fromFile(path);
parser = StupsParser.fromGrammar(grammar);
}

View File

@ -1,93 +0,0 @@
// NTERM, TERM are reserved
// Some Grammar-Symbols have to be named this way:
// assignment, declaration (for TypeTable creation)
// IDENTIFIER, NOT, ADD, SUB (for TypeChecking)
// expr, par_expr, assignment (for TypeChecking)
// Nonterminals:
NTERM: val type
NTERM: op unary arith_op logic_op compare_op
NTERM: S class_cnt block_cnt
NTERM: statement stmt print
NTERM: declaration assignment
NTERM: par_expr expr expr_2 expr_f
NTERM: loop cond cond_else single_or_braced
// Token:
TERM: CLASS PUBLIC STATIC
TERM: STRING_TYPE INTEGER_TYPE BOOLEAN_TYPE VOID_TYPE
TERM: WHILE IF ELSE
TERM: PRINTLN
TERM: ADD MUL SUB DIV MOD
TERM: AND OR NOT
TERM: LESS LESS_EQUAL GREATER GREATER_EQUAL EQUAL NOT_EQUAL
TERM: ASSIGN
TERM: L_BRACE R_BRACE L_BRACKET R_BRACKET L_PAREN R_PAREN SEMICOLON COMMA DOT
TERM: INTEGER_LIT STRING_LIT BOOLEAN_LIT
TERM: IDENTIFIER IDENTIFIER_MAIN
// Actions: promote - Information "hochreichen": Ersetzt Node mit Child, wenn es nur ein Child gibt
// - val[promote] :: --val--INTEGER_LIT: 5 => --INTEGER_LIT: 5
// delifempty - Kann Node löschen, wenn dieser keinen Inhalt hat, normalerweise bei eps
// - block_cnt[delifempty] :: --block_cnt => --
// delchild= - Entfernt bestimmte Child-Nodes eines Parents
// - cond[delchild=IF] :: --cond--IF => --cond
// - assignment[delchild=ASSIGN] :: --assignment--ASSIGN => --assignment
// valtoval= - Verschiebt eine Child-Value in die Parent-Value und entfernt das Child
// - assignment[valtoval=IDENTIFIER] :: --assignment--IDENTIFIER: a => --assignment: a
// nametoval= - Verschiebt einen Child-Name in die Parent-Value und entfernt das Child
// - expr_2[nametoval=ADD] :: --expr_2--ADD => --expr_2: ADD
// renameto= - Führt Umbenennung eines Nodes durch
// - expr_2[renameto=expr] :: --expr_2: ADD => --expr: ADD
// General -----------------------------------------------------------------------------------------
val[promote] -> INTEGER_LIT | STRING_LIT | BOOLEAN_LIT | IDENTIFIER
type[promote] -> INTEGER_TYPE | STRING_TYPE | BOOLEAN_TYPE
// OP-List: ADD,SUB,MUL,DIV,MOD,AND,OR,NOT,LESS,LESS_EQUAL,GREATER,GREATER_EQUAL,EQUAL,NOT_EQUAL
op[promote] -> arith_op | logic_op | compare_op
unary[promote] -> ADD | SUB | NOT
arith_op[promote] -> ADD | SUB | MUL | DIV | MOD
logic_op[promote] -> AND | OR | NOT
compare_op[promote] -> LESS | LESS_EQUAL | GREATER | GREATER_EQUAL | EQUAL | NOT_EQUAL
// -------------------------------------------------------------------------------------------------
// START -> class IDENTIFIER { class_cnt }
S[promote] -> CLASS IDENTIFIER L_BRACE class_cnt R_BRACE | eps
// class_cnt -> public static void main(String[] args) { block_cnt }
class_cnt[promote delifempty] -> PUBLIC STATIC VOID_TYPE IDENTIFIER_MAIN L_PAREN STRING_TYPE L_BRACKET R_BRACKET IDENTIFIER R_PAREN L_BRACE block_cnt R_BRACE | eps
// block_ccnt -> stuff in {} | list of statements
block_cnt[promote delifempty] -> statement block_cnt | L_BRACE block_cnt R_BRACE | eps
// statement -> stuff ending with ; | loop | condition
statement[promote] -> stmt SEMICOLON | loop | cond
stmt[promote] -> print | declaration | assignment
print -> PRINTLN par_expr
// declaration -> type IDENTIFIER = expr;
declaration[nametoval=INTEGER_TYPE,BOOLEAN_TYPE,STRING_TYPE] -> type assignment
assignment[delchild=ASSIGN valtoval=IDENTIFIER] -> IDENTIFIER ASSIGN expr
// par_expr -> ( expr )
par_expr -> L_PAREN expr R_PAREN
// expr -> expression that returns something | literal
expr[promote nametoval=ADD,SUB,MUL,DIV,MOD,AND,OR,NOT,LESS,LESS_EQUAL,GREATER,GREATER_EQUAL,EQUAL,NOT_EQUAL] -> expr_f expr_2
expr_2[promote delifempty renameto=expr] -> op expr_f expr_2 | eps
expr_f[promote renameto=expr] -> unary expr_f | par_expr | val
// Control-Flow
loop[delchild=WHILE] -> WHILE par_expr single_or_braced
cond[delchild=IF] -> IF par_expr single_or_braced cond_else
cond_else[delifempty delchild=ELSE] -> ELSE single_or_braced | eps
single_or_braced -> L_BRACE block_cnt R_BRACE | stmt SEMICOLON

View File

@ -61,25 +61,27 @@ compare_op[promote] -> LESS | LESS_EQUAL | GREATER | GREATER_EQUAL | EQUAL | NOT
// -------------------------------------------------------------------------------------------------
// START -> class IDENTIFIER { class_cnt }
S[promote] -> CLASS IDENTIFIER L_BRACE class_cnt R_BRACE | eps
S[renameto=CLASS delchild=CLASS,R_BRACE,L_BRACE] -> CLASS IDENTIFIER L_BRACE class_cnt R_BRACE | eps
// class_cnt -> public static void main(String[] args) { block_cnt }
class_cnt[promote delifempty] -> PUBLIC STATIC VOID_TYPE IDENTIFIER_MAIN L_PAREN STRING_TYPE L_BRACKET R_BRACKET IDENTIFIER R_PAREN L_BRACE block_cnt R_BRACE | eps
// remove all the stuff that is irrelevant to this simple case
class_cnt[promote delifempty delchild=L_BRACE,R_BRACE,L_PAREN,R_PAREN,L_BRACKET,R_BRACKET,IDENTIFIER,IDENTIFIER_MAIN,STRING_TYPE,VOID_TYPE,STATIC,PUBLIC] -> PUBLIC STATIC VOID_TYPE IDENTIFIER_MAIN L_PAREN STRING_TYPE L_BRACKET R_BRACKET IDENTIFIER R_PAREN L_BRACE block_cnt R_BRACE | eps
// block_ccnt -> stuff in {} | list of statements
block_cnt[promote delifempty] -> statement block_cnt | L_BRACE block_cnt R_BRACE | eps
// statement -> stuff ending with ; | loop | condition
statement[promote] -> stmt SEMICOLON | loop | cond
statement[promote delchild=SEMICOLON] -> stmt SEMICOLON | loop | cond
stmt[promote] -> print | declaration | assignment
print -> PRINTLN par_expr
print[nametoval=PRINTLN] -> PRINTLN par_expr
// declaration -> type IDENTIFIER = expr;
declaration[nametoval=INTEGER_TYPE,BOOLEAN_TYPE,STRING_TYPE] -> type assignment
assignment[delchild=ASSIGN valtoval=IDENTIFIER] -> IDENTIFIER ASSIGN expr
// par_expr -> ( expr )
par_expr -> L_PAREN expr R_PAREN
// dont [promote] par_expr to make parenthesis-precedence easier
par_expr[delchild=L_PAREN,R_PAREN] -> L_PAREN expr R_PAREN
// expr -> expression that returns something | literal
expr[promote nametoval=ADD,SUB,MUL,DIV,MOD,AND,OR,NOT,LESS,LESS_EQUAL,GREATER,GREATER_EQUAL,EQUAL,NOT_EQUAL] -> expr_f expr_2
@ -87,7 +89,8 @@ expr_2[promote delifempty renameto=expr] -> op expr_f expr_2 | eps
expr_f[promote renameto=expr] -> unary expr_f | par_expr | val
// Control-Flow
// Don't [delifempty] single_or_braced to make it easier to get the expression
loop[delchild=WHILE] -> WHILE par_expr single_or_braced
cond[delchild=IF] -> IF par_expr single_or_braced cond_else
cond_else[delifempty delchild=ELSE] -> ELSE single_or_braced | eps
single_or_braced -> L_BRACE block_cnt R_BRACE | stmt SEMICOLON
single_or_braced[promote delchild=L_BRACE,R_BRACE] -> L_BRACE block_cnt R_BRACE | stmt SEMICOLON