slight typchecking, parsing, grammar cleanup

This commit is contained in:
ChUrl
2021-01-31 22:15:20 +01:00
parent a2b35ad4da
commit b76c458498
6 changed files with 61 additions and 26 deletions

View File

@ -10,12 +10,14 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors; 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 { public class ParsingTable {
private static final Pattern X = Pattern.compile("X");
private final Grammar grammar; private final Grammar grammar;
private final Map<Entry<String, String>, String> parsetable; private final Map<Entry<String, String>, String> parsetable;
@ -36,6 +38,9 @@ public class ParsingTable {
return this.grammar.getTerminals(); return this.grammar.getTerminals();
} }
// Printing + Overrides
// TODO: This mess
@Override @Override
public String toString() { public String toString() {
final StringBuilder output = new StringBuilder(); final StringBuilder output = new StringBuilder();
@ -74,7 +79,7 @@ public class ParsingTable {
output.append(" ".repeat(margins.get("NTERM"))) output.append(" ".repeat(margins.get("NTERM")))
.append("| "); .append("| ");
for (String terminal : inputSymbols) { 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"); output.append("|\n");
@ -88,11 +93,11 @@ public class ParsingTable {
.append("\n"); .append("\n");
for (String nonterminal : this.grammar.getNonterminals()) { 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) { for (String terminal : inputSymbols) {
final String prod = this.parsetable.get(new SimpleEntry<>(nonterminal, terminal)); 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"); output.append("|\n");
} }

View File

@ -24,7 +24,7 @@ public class StupsParser {
} }
public static StupsParser fromGrammar(Grammar grammar) { public static StupsParser fromGrammar(Grammar grammar) {
final GrammarAnalyzer analyzer = new GrammarAnalyzer(grammar); final GrammarAnalyzer analyzer = GrammarAnalyzer.fromGrammar(grammar);
return new StupsParser(analyzer.getTable()); return new StupsParser(analyzer.getTable());
} }

View File

@ -16,16 +16,25 @@ import static util.Logger.log;
import static util.Logger.logIfTrue; import static util.Logger.logIfTrue;
import static util.Logger.logNullable; import static util.Logger.logNullable;
public class GrammarAnalyzer { public final class GrammarAnalyzer {
private final Grammar grammar; 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; 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 Map<String, Set<String>> follow;
private final ParsingTable table; private final ParsingTable table;
public GrammarAnalyzer(Grammar grammar) { private GrammarAnalyzer(Grammar grammar) {
this.grammar = grammar; this.grammar = grammar;
log("Analyzing Grammar:\n"); log("Analyzing Grammar:\n");
@ -41,6 +50,10 @@ public class GrammarAnalyzer {
System.out.println("Grammar analysis successful."); System.out.println("Grammar analysis successful.");
} }
public static GrammarAnalyzer fromGrammar(Grammar grammar) {
return new GrammarAnalyzer(grammar);
}
private Map<String, Set<String>> initFirst() { private Map<String, Set<String>> initFirst() {
final Map<String, Set<String>> firstOut = new HashMap<>(); final Map<String, Set<String>> firstOut = new HashMap<>();

View File

@ -2,6 +2,9 @@ package parser.grammar;
import java.util.Objects; import java.util.Objects;
/**
* Repräsentation einer Produktionsregel der Form leftside -> rightside.
*/
public class GrammarRule { public class GrammarRule {
private final String leftside; private final String leftside;
@ -20,18 +23,16 @@ public class GrammarRule {
return this.rightside; return this.rightside;
} }
public String[] getSymbols() {
return this.rightside.split(" ");
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object o) {
if (obj instanceof GrammarRule) { if (this == o) {
return this.leftside.equals(((GrammarRule) obj).leftside) return true;
&& this.rightside.equals(((GrammarRule) obj).rightside);
} }
if (o == null || this.getClass() != o.getClass()) {
return false; return false;
}
final GrammarRule that = (GrammarRule) o;
return this.leftside.equals(that.leftside) && this.rightside.equals(that.rightside);
} }
@Override @Override

View File

@ -18,7 +18,7 @@ public final class TypeChecker {
private TypeChecker() {} private TypeChecker() {}
// TODO: nodeTable? // TODO: merge nodeTable into typetable?
// Wirft exception bei typeerror, return nodeTable? // Wirft exception bei typeerror, return nodeTable?
public static Map<SyntaxTreeNode, String> validate(SyntaxTree tree) { public static Map<SyntaxTreeNode, String> validate(SyntaxTree tree) {
final TypeTable table = TypeTable.fromAST(tree); final TypeTable table = TypeTable.fromAST(tree);

View File

@ -11,13 +11,27 @@ import java.util.Map;
import static util.Logger.log; 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; private final Map<String, String> symbolTable;
/**
* Weist jedem Operator einen Rückgabetyp zu.
*/
private final Map<String, String> methodReturnTable; private final Map<String, String> methodReturnTable;
/**
* Weist jedem Operator die Typen seiner Argumente zu.
*/
private final Map<String, List<String>> methodArgumentTable; private final Map<String, List<String>> methodArgumentTable;
public TypeTable(Map<String, String> symbolTable) { private TypeTable(Map<String, String> symbolTable) {
this.symbolTable = Collections.unmodifiableMap(symbolTable); this.symbolTable = Collections.unmodifiableMap(symbolTable);
// Enthält die Return-Types der Operatoren // Enthält die Return-Types der Operatoren
@ -55,18 +69,18 @@ public class TypeTable {
public static TypeTable fromAST(SyntaxTree tree) { public static TypeTable fromAST(SyntaxTree tree) {
System.out.println(" - Building TypeTable..."); System.out.println(" - Building TypeTable...");
final Map<String, String> tableOut = new HashMap<>(); final Map<String, String> symbolTable = new HashMap<>();
log("Creating TypeTable"); log("Creating TypeTable");
scanTree(tree.getRoot(), tableOut); initSymbolTable(tree.getRoot(), symbolTable);
log("-".repeat(100)); 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()) { for (SyntaxTreeNode child : root.getChildren()) {
scanTree(child, table); initSymbolTable(child, table);
} }
if ("declaration".equals(root.getName())) { if ("declaration".equals(root.getName())) {
@ -82,6 +96,8 @@ public class TypeTable {
} }
} }
// Getters
public String getSymbolType(String sym) { public String getSymbolType(String sym) {
return this.symbolTable.get(sym); return this.symbolTable.get(sym);
} }