slight typchecking, parsing, grammar cleanup
This commit is contained in:
@ -10,12 +10,14 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Repräsentation einer LL(1)-ParsingTabelle.
|
||||
* Jeder Kombination aus Nichtterminal und Terminal wird ein neues Symbol aus dem Alphabet zugewiesen.
|
||||
*/
|
||||
public class ParsingTable {
|
||||
|
||||
private static final Pattern X = Pattern.compile("X");
|
||||
private final Grammar grammar;
|
||||
private final Map<Entry<String, String>, String> parsetable;
|
||||
|
||||
@ -36,6 +38,9 @@ public class ParsingTable {
|
||||
return this.grammar.getTerminals();
|
||||
}
|
||||
|
||||
// Printing + Overrides
|
||||
|
||||
// TODO: This mess
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder output = new StringBuilder();
|
||||
@ -74,7 +79,7 @@ public class ParsingTable {
|
||||
output.append(" ".repeat(margins.get("NTERM")))
|
||||
.append("| ");
|
||||
for (String terminal : inputSymbols) {
|
||||
format.format(X.matcher("%-Xs ").replaceAll(String.valueOf(margins.get(terminal))), terminal);
|
||||
format.format("%-Xs ".replace("X", String.valueOf(margins.get(terminal))), terminal);
|
||||
}
|
||||
output.append("|\n");
|
||||
|
||||
@ -88,11 +93,11 @@ public class ParsingTable {
|
||||
.append("\n");
|
||||
|
||||
for (String nonterminal : this.grammar.getNonterminals()) {
|
||||
format.format(X.matcher("%-Xs| ").replaceAll(String.valueOf(margins.get("NTERM"))), nonterminal);
|
||||
format.format("%-Xs| ".replace("X", String.valueOf(margins.get("NTERM"))), nonterminal);
|
||||
|
||||
for (String terminal : inputSymbols) {
|
||||
final String prod = this.parsetable.get(new SimpleEntry<>(nonterminal, terminal));
|
||||
format.format(X.matcher("%-Xs ").replaceAll(String.valueOf(margins.get(terminal))), prod == null ? " ".repeat(9) : prod);
|
||||
format.format("%-Xs ".replace("X", String.valueOf(margins.get(terminal))), prod == null ? " ".repeat(9) : prod);
|
||||
}
|
||||
output.append("|\n");
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class StupsParser {
|
||||
}
|
||||
|
||||
public static StupsParser fromGrammar(Grammar grammar) {
|
||||
final GrammarAnalyzer analyzer = new GrammarAnalyzer(grammar);
|
||||
final GrammarAnalyzer analyzer = GrammarAnalyzer.fromGrammar(grammar);
|
||||
return new StupsParser(analyzer.getTable());
|
||||
}
|
||||
|
||||
|
@ -16,16 +16,25 @@ import static util.Logger.log;
|
||||
import static util.Logger.logIfTrue;
|
||||
import static util.Logger.logNullable;
|
||||
|
||||
public class GrammarAnalyzer {
|
||||
public final class GrammarAnalyzer {
|
||||
|
||||
private final Grammar grammar;
|
||||
|
||||
/**
|
||||
* Das first-Set enthält für jedes Nichtterminalsymbol alle Terminalsymbole, die als erstes bei diesen
|
||||
* Nichtterminal auftreten können.
|
||||
*/
|
||||
private final Map<String, Set<String>> first;
|
||||
|
||||
/**
|
||||
* Das follow-Set enhält für jedes Nichtterminalsymbol alle Terminalsymbole, die direkt auf dieses
|
||||
* Nichtterminal folgen können.
|
||||
*/
|
||||
private final Map<String, Set<String>> follow;
|
||||
|
||||
private final ParsingTable table;
|
||||
|
||||
public GrammarAnalyzer(Grammar grammar) {
|
||||
private GrammarAnalyzer(Grammar grammar) {
|
||||
this.grammar = grammar;
|
||||
|
||||
log("Analyzing Grammar:\n");
|
||||
@ -41,6 +50,10 @@ public class GrammarAnalyzer {
|
||||
System.out.println("Grammar analysis successful.");
|
||||
}
|
||||
|
||||
public static GrammarAnalyzer fromGrammar(Grammar grammar) {
|
||||
return new GrammarAnalyzer(grammar);
|
||||
}
|
||||
|
||||
private Map<String, Set<String>> initFirst() {
|
||||
final Map<String, Set<String>> firstOut = new HashMap<>();
|
||||
|
||||
|
@ -2,6 +2,9 @@ package parser.grammar;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Repräsentation einer Produktionsregel der Form leftside -> rightside.
|
||||
*/
|
||||
public class GrammarRule {
|
||||
|
||||
private final String leftside;
|
||||
@ -20,18 +23,16 @@ public class GrammarRule {
|
||||
return this.rightside;
|
||||
}
|
||||
|
||||
public String[] getSymbols() {
|
||||
return this.rightside.split(" ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof GrammarRule) {
|
||||
return this.leftside.equals(((GrammarRule) obj).leftside)
|
||||
&& this.rightside.equals(((GrammarRule) obj).rightside);
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (o == null || this.getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final GrammarRule that = (GrammarRule) o;
|
||||
return this.leftside.equals(that.leftside) && this.rightside.equals(that.rightside);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,7 +18,7 @@ public final class TypeChecker {
|
||||
|
||||
private TypeChecker() {}
|
||||
|
||||
// TODO: nodeTable?
|
||||
// TODO: merge nodeTable into typetable?
|
||||
// Wirft exception bei typeerror, return nodeTable?
|
||||
public static Map<SyntaxTreeNode, String> validate(SyntaxTree tree) {
|
||||
final TypeTable table = TypeTable.fromAST(tree);
|
||||
|
@ -11,13 +11,27 @@ import java.util.Map;
|
||||
|
||||
import static util.Logger.log;
|
||||
|
||||
public class TypeTable {
|
||||
/**
|
||||
* Speichert die Datentypen von Symbolen und Funktionen in einem Programm.
|
||||
*/
|
||||
public final class TypeTable {
|
||||
|
||||
/**
|
||||
* Weist jeder deklarierter Variable ihren Typ zu.
|
||||
*/
|
||||
private final Map<String, String> symbolTable;
|
||||
|
||||
/**
|
||||
* Weist jedem Operator einen Rückgabetyp zu.
|
||||
*/
|
||||
private final Map<String, String> methodReturnTable;
|
||||
|
||||
/**
|
||||
* Weist jedem Operator die Typen seiner Argumente zu.
|
||||
*/
|
||||
private final Map<String, List<String>> methodArgumentTable;
|
||||
|
||||
public TypeTable(Map<String, String> symbolTable) {
|
||||
private TypeTable(Map<String, String> symbolTable) {
|
||||
this.symbolTable = Collections.unmodifiableMap(symbolTable);
|
||||
|
||||
// Enthält die Return-Types der Operatoren
|
||||
@ -55,18 +69,18 @@ public class TypeTable {
|
||||
|
||||
public static TypeTable fromAST(SyntaxTree tree) {
|
||||
System.out.println(" - Building TypeTable...");
|
||||
final Map<String, String> tableOut = new HashMap<>();
|
||||
final Map<String, String> symbolTable = new HashMap<>();
|
||||
|
||||
log("Creating TypeTable");
|
||||
scanTree(tree.getRoot(), tableOut);
|
||||
initSymbolTable(tree.getRoot(), symbolTable);
|
||||
log("-".repeat(100));
|
||||
|
||||
return new TypeTable(tableOut);
|
||||
return new TypeTable(symbolTable);
|
||||
}
|
||||
|
||||
private static void scanTree(SyntaxTreeNode root, Map<? super String, String> table) {
|
||||
private static void initSymbolTable(SyntaxTreeNode root, Map<String, String> table) {
|
||||
for (SyntaxTreeNode child : root.getChildren()) {
|
||||
scanTree(child, table);
|
||||
initSymbolTable(child, table);
|
||||
}
|
||||
|
||||
if ("declaration".equals(root.getName())) {
|
||||
@ -82,6 +96,8 @@ public class TypeTable {
|
||||
}
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
public String getSymbolType(String sym) {
|
||||
return this.symbolTable.get(sym);
|
||||
}
|
||||
|
Reference in New Issue
Block a user