status messages + better error messages
This commit is contained in:
@ -12,6 +12,7 @@ import java.nio.file.Path;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static util.Logger.log;
|
||||
|
||||
@ -33,7 +34,7 @@ public class StupsParser {
|
||||
}
|
||||
|
||||
public AST parse(List<? extends Token> token, Vocabulary voc) {
|
||||
ASTNode root = new ASTNode(this.parsetable.getStartSymbol());
|
||||
ASTNode root = new ASTNode(this.parsetable.getStartSymbol(), 0);
|
||||
AST tree = new AST(root);
|
||||
Deque<ASTNode> stack = new ArrayDeque<>();
|
||||
stack.push(root);
|
||||
@ -48,6 +49,7 @@ public class StupsParser {
|
||||
final String top = stack.peek().getName();
|
||||
|
||||
final String currentTokenSym;
|
||||
int currentLine = 0;
|
||||
if (inputPosition >= token.size()) {
|
||||
// Wenn auf dem Stack mehr Nichtterminale liegen als Terminale in der Eingabe vorhanden sind
|
||||
// Die Eingabe wurde komplett konsumiert
|
||||
@ -57,6 +59,7 @@ public class StupsParser {
|
||||
// Es sind noch Eingabesymbole vorhanden
|
||||
|
||||
currentTokenSym = voc.getSymbolicName(token.get(inputPosition).getType());
|
||||
currentLine = token.get(inputPosition).getLine();
|
||||
}
|
||||
|
||||
final String prod = this.parsetable.get(top, currentTokenSym);
|
||||
@ -73,13 +76,15 @@ public class StupsParser {
|
||||
} else if (this.parsetable.getTerminals().contains(top)) {
|
||||
// Wenn das Terminal auf dem Stack nicht mit der aktuellen Eingabe übereinstimmt
|
||||
|
||||
System.out.println("Syntaxfehler.");
|
||||
System.out.println("\nLine " + currentLine + " Syntaxerror: Expected " + top + " but found " + currentTokenSym);
|
||||
this.printSourceLine(currentLine, token);
|
||||
|
||||
throw new ParseException("Invalid terminal on stack: " + top, tree);
|
||||
} else if (prod == null) {
|
||||
// Wenn es für das aktuelle Terminal und das Nichtterminal auf dem Stack keine Regel gibt
|
||||
|
||||
System.out.println("Syntaxfehler.");
|
||||
System.out.println("\nLine " + currentLine + " Syntaxerror: Didn't expect " + currentTokenSym);
|
||||
this.printSourceLine(currentLine, token);
|
||||
|
||||
throw new ParseException("No prod. for nonterminal " + top + ", terminal " + currentTokenSym, tree);
|
||||
} else {
|
||||
@ -92,7 +97,7 @@ public class StupsParser {
|
||||
final String[] split = prod.split(" ");
|
||||
|
||||
for (int i = split.length - 1; i >= 0; i--) {
|
||||
ASTNode ASTNode = new ASTNode(split[i]);
|
||||
ASTNode node = new ASTNode(split[i], currentLine);
|
||||
|
||||
if (inputPosition + i < token.size()) {
|
||||
// Die Schleife geht in der Eingabe weiter
|
||||
@ -100,12 +105,12 @@ public class StupsParser {
|
||||
|
||||
// Die Token mit semantischem Inhalt auswählen
|
||||
if ("IDENTIFIER".equals(split[i]) || split[i].endsWith("_LIT")) {
|
||||
ASTNode.setValue(currentTok.getText());
|
||||
node.setValue(currentTok.getText());
|
||||
}
|
||||
}
|
||||
|
||||
stack.push(ASTNode);
|
||||
pop.addChild(ASTNode);
|
||||
stack.push(node);
|
||||
pop.addChild(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,6 +118,17 @@ public class StupsParser {
|
||||
log("\nParsed AST:\n" + tree);
|
||||
log("-".repeat(100) + "\n");
|
||||
|
||||
System.out.println("- Parsing successful.");
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void printSourceLine(int line, List<? extends Token> token) {
|
||||
Optional<String> srcLine = token.stream()
|
||||
.filter(tok -> tok.getLine() == line)
|
||||
.map(Token::getText)
|
||||
.reduce((s1, s2) -> s1 + " " + s2);
|
||||
|
||||
srcLine.ifPresent(s -> System.out.println(" :: " + s));
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ public final class ASTBalancer {
|
||||
|
||||
log(tree.toString());
|
||||
log("-".repeat(100));
|
||||
|
||||
System.out.println("- Tree balancing successful.");
|
||||
}
|
||||
|
||||
// Baum spiegeln, damit höhere Ebenen links sind und EXPR vorwärts laufen
|
||||
@ -106,7 +108,7 @@ public final class ASTBalancer {
|
||||
return false; // Braucht keine weitere Rotation
|
||||
}
|
||||
|
||||
ASTNode insertLeft = new ASTNode(root.getName());
|
||||
ASTNode insertLeft = new ASTNode(root.getName(), root.getLine());
|
||||
insertLeft.setValue(right.getValue()); // Operation wird linksvererbt
|
||||
insertLeft.setChildren(left, right.getChildren().get(0));
|
||||
|
||||
@ -171,7 +173,7 @@ public final class ASTBalancer {
|
||||
|
||||
log("Right-Rotating " + root.getName() + ": " + root.getValue());
|
||||
|
||||
ASTNode insertRight = new ASTNode(root.getName());
|
||||
ASTNode insertRight = new ASTNode(root.getName(), root.getLine());
|
||||
insertRight.setValue(root.getValue());
|
||||
insertRight.setChildren(left.getChildren().get(1), right);
|
||||
|
||||
|
@ -33,6 +33,8 @@ public final class ASTCompacter {
|
||||
log(tree.toString());
|
||||
log("\nCleaned Tree: " + removed + " nodes removed.");
|
||||
log("-".repeat(100));
|
||||
|
||||
System.out.println("- Tree compression successful.");
|
||||
}
|
||||
|
||||
// Entfernt [compact]-able Nodes (Reicht Werte nach oben)
|
||||
|
@ -35,6 +35,8 @@ public class GrammarAnalyzer {
|
||||
this.follow = this.initFollow();
|
||||
|
||||
this.table = this.initParseTable();
|
||||
|
||||
System.out.println("\n- Grammar analysis successful.");
|
||||
}
|
||||
|
||||
private Map<String, Set<String>> initFirst() {
|
||||
@ -280,11 +282,6 @@ public class GrammarAnalyzer {
|
||||
|| this.first.get(sym).contains(this.grammar.getEpsilonSymbol());
|
||||
}
|
||||
|
||||
public boolean allNullable(String rightside) {
|
||||
return rightside.isBlank()
|
||||
|| Arrays.stream(rightside.split(" ")).allMatch(this::nullable);
|
||||
}
|
||||
|
||||
public boolean allNullable(String[] split) {
|
||||
return split.length == 0
|
||||
|| Arrays.stream(split).allMatch(this::nullable);
|
||||
|
@ -25,6 +25,8 @@ public final class TypeChecker {
|
||||
log("Typevalidation:");
|
||||
validate(tree.getRoot(), table, nodeTable);
|
||||
log("-".repeat(100));
|
||||
|
||||
System.out.println("- Typechecking successful.\n");
|
||||
}
|
||||
|
||||
private static void validate(ASTNode root, SymbolTable table, Map<ASTNode, String> nodeTable) {
|
||||
@ -69,6 +71,8 @@ public final class TypeChecker {
|
||||
log("Validating Assignment: " + identifierType + ": " + identifier + " = " + literalType);
|
||||
|
||||
if (!literalType.equals(identifierType)) {
|
||||
System.out.println("Line " + root.getLine() + " Typeerror: Can't assign [" + literalNode.getValue() + "] to [" + identifier + "]: " + identifierType);
|
||||
|
||||
throw new AssignmentTypeMismatchException("Trying to assign " + literalType + " to a " + identifierType + " variable.");
|
||||
}
|
||||
}
|
||||
@ -79,14 +83,24 @@ public final class TypeChecker {
|
||||
|
||||
log("Validating Expression: " + root.getValue());
|
||||
|
||||
if (root.getChildren().size() != 1 && "NOT".equals(op)) {
|
||||
if (!root.hasChildren()) {
|
||||
// Keine Kinder
|
||||
|
||||
System.out.println("Line " + root.getLine() + " Operatorerror: Can't use [" + op + "] without arguments");
|
||||
|
||||
throw new OperatorUsageException("Versuche Operator " + op + " ohne Argumente aufzurufen.");
|
||||
} else if (root.getChildren().size() != 1 && "NOT".equals(op)) {
|
||||
// Unärer Operator mit != 1 Child
|
||||
// SUB, ADD müssen nicht geprüft werden, da diese doppelt belegt sind mit ihrem binären Gegenstück
|
||||
|
||||
System.out.println("Line " + root.getLine() + " Operatorerror: Can't use [" + op + "] with more than 1 argument");
|
||||
|
||||
throw new OperatorUsageException("Versuche unären Operator " + op + " mit mehreren Argument aufzurufen.");
|
||||
} else if (root.getChildren().size() == 1 && !unary.contains(op)) {
|
||||
// Binärer Operator mit 1 Child
|
||||
|
||||
System.out.println("Line " + root.getLine() + " Operatorerror: Can't use [" + op + "] with only 1 argument");
|
||||
|
||||
throw new OperatorUsageException("Versuche binären Operator " + op + " mit einem Argument aufzurufen.");
|
||||
}
|
||||
|
||||
@ -100,6 +114,8 @@ public final class TypeChecker {
|
||||
// Child returned Typ, welcher nicht im SymbolTable als Argumenttyp steht
|
||||
// Der NodeTable enthält auch Literale, diese müssen also nicht einzeln behandelt werden
|
||||
|
||||
System.out.println("Line " + root.getLine() + " Typeerror: Can't use [" + op + "] with argument of type [" + nodeTable.get(child) + "]");
|
||||
|
||||
throw new OperatorTypeMismatchException("Versuche Operator " + op + " mit Argument vom Typ " + nodeTable.get(child) + " aufzurufen.");
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user