status messages + better error messages

This commit is contained in:
ChUrl
2020-12-14 16:04:33 +01:00
parent 1987e6532d
commit 2ef7cefedc
5 changed files with 48 additions and 15 deletions

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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.");
}