finished exercise
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="lib2" level="project" />
|
||||
<orderEntry type="library" name="lib" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -9,8 +9,7 @@ import ssw.mj.scanner.Token;
|
||||
import javax.xml.stream.FactoryConfigurationError;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import static ssw.mj.Errors.Message.TOKEN_EXPECTED;
|
||||
import static ssw.mj.Errors.Message.UNDEFINED_ESCAPE;
|
||||
import static ssw.mj.Errors.Message.*;
|
||||
import static ssw.mj.scanner.Token.Kind.*;
|
||||
|
||||
public final class Parser {
|
||||
@@ -60,6 +59,10 @@ public final class Parser {
|
||||
*/
|
||||
public final Tab tab;
|
||||
|
||||
private static int MIN_ERROR_DIST = 3;
|
||||
|
||||
private int errorDist = MIN_ERROR_DIST;
|
||||
|
||||
public Parser(Scanner scanner) {
|
||||
this.scanner = scanner;
|
||||
tab = new Tab(this);
|
||||
@@ -76,6 +79,7 @@ public final class Parser {
|
||||
t = la;
|
||||
la = scanner.next();
|
||||
sym = la.kind;
|
||||
errorDist++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,8 +99,12 @@ public final class Parser {
|
||||
public void error(Message msg, Object... msgParams) {
|
||||
// TODO Exercise UE-P-3: Replace panic mode with error recovery (i.e., keep track of error distance)
|
||||
// TODO Exercise UE-P-3: Hint: Replacing panic mode also affects scan() method
|
||||
scanner.errors.error(la.line, la.col, msg, msgParams);
|
||||
throw new Errors.PanicMode();
|
||||
|
||||
if (errorDist >= MIN_ERROR_DIST) {
|
||||
scanner.errors.error(la.line, la.col, msg, msgParams);
|
||||
}
|
||||
|
||||
errorDist = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,10 +132,15 @@ public final class Parser {
|
||||
static final EnumSet<Token.Kind> firstConstDecl = EnumSet.of(Token.Kind.final_);
|
||||
static final EnumSet<Token.Kind> firstVarDecl = EnumSet.of(Token.Kind.ident);
|
||||
static final EnumSet<Token.Kind> firstClassDecl = EnumSet.of(Token.Kind.class_);
|
||||
static final EnumSet<Token.Kind> breakDecl = EnumSet.of(lbrace, eof);
|
||||
static final EnumSet<Token.Kind> firstStatement = EnumSet.of(ident, if_, while_, break_, return_, read, print, lbrace, semicolon);
|
||||
static final EnumSet<Token.Kind> breakStatement = EnumSet.of(rbrace, else_, eof);
|
||||
static final EnumSet<Token.Kind> firstAsignop = EnumSet.of(assign, plusas, minusas, timesas, slashas, remas);
|
||||
static final EnumSet<Token.Kind> firstFactor = EnumSet.of(ident, number, charConst, new_, lpar);
|
||||
static final EnumSet<Token.Kind> firstMulop = EnumSet.of(times, slash, rem);
|
||||
static final EnumSet<Token.Kind> firstMethodDecl = EnumSet.of(ident, void_);
|
||||
static final EnumSet<Token.Kind> breakMethodDecl = EnumSet.of(rbrace, eof);
|
||||
|
||||
|
||||
static <T extends Enum<T>> EnumSet<T> enumUnion(EnumSet<T> first, EnumSet<T> ...sets) {
|
||||
final var copy = EnumSet.copyOf(first);
|
||||
@@ -154,22 +167,26 @@ public final class Parser {
|
||||
check(Token.Kind.program);
|
||||
check(Token.Kind.ident);
|
||||
|
||||
final var firstDeclarationUnion = enumUnion(firstConstDecl, firstVarDecl, firstClassDecl);
|
||||
|
||||
while (firstDeclarationUnion.contains(sym)) {
|
||||
while (!breakDecl.contains(sym)) {
|
||||
if (firstVarDecl.contains(sym)) {
|
||||
VarDecl();
|
||||
} else if (firstClassDecl.contains(sym)) {
|
||||
ClassDecl();
|
||||
} else {
|
||||
} else if (firstConstDecl.contains(sym)){
|
||||
ConstDecl();
|
||||
} else {
|
||||
recoverDecl();
|
||||
}
|
||||
}
|
||||
|
||||
check(lbrace);
|
||||
|
||||
while (sym == ident || sym == void_) {
|
||||
MethodDecl();
|
||||
while (!breakMethodDecl.contains(sym)) {
|
||||
if (firstMethodDecl.contains(sym)) {
|
||||
MethodDecl();
|
||||
} else {
|
||||
recoverMethodDecl();
|
||||
}
|
||||
}
|
||||
|
||||
check(rbrace);
|
||||
@@ -266,7 +283,7 @@ public final class Parser {
|
||||
}
|
||||
|
||||
private void Statement() {
|
||||
while (firstStatement.contains(sym)) {
|
||||
while (!breakStatement.contains(sym)) {
|
||||
switch (sym) {
|
||||
case ident -> {
|
||||
Designator();
|
||||
@@ -340,6 +357,7 @@ public final class Parser {
|
||||
}
|
||||
case lbrace -> Block();
|
||||
case semicolon -> scan();
|
||||
default -> recoverStatement();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -504,6 +522,40 @@ public final class Parser {
|
||||
|
||||
// TODO Exercise UE-P-3: Error recovery methods: recoverDecl, recoverMethodDecl and recoverStat (+ TODO Exercise UE-P-5: Check idents for Type kind)
|
||||
|
||||
private void recoverDecl() {
|
||||
final var firstDeclarationUnion = enumUnion(firstConstDecl, firstVarDecl, firstClassDecl);
|
||||
final var recoverDeclSet = enumUnion(breakDecl, firstDeclarationUnion);
|
||||
error(DECLARATION_RECOVERY);
|
||||
|
||||
do {
|
||||
scan();
|
||||
} while (!recoverDeclSet.contains(sym));
|
||||
errorDist = 0;
|
||||
}
|
||||
|
||||
private void recoverMethodDecl() {
|
||||
error(METHOD_DECL_RECOVERY);
|
||||
|
||||
final var recoveryMethoDeclSet = enumUnion(breakMethodDecl, firstMethodDecl);
|
||||
do {
|
||||
scan();
|
||||
} while (!recoveryMethoDeclSet.contains(sym));
|
||||
errorDist = 0;
|
||||
}
|
||||
|
||||
private void recoverStatement() {
|
||||
error(STATEMENT_RECOVERY);
|
||||
|
||||
var recoveryStatementSet = enumUnion(breakStatement, firstStatement);
|
||||
recoveryStatementSet.remove(ident);
|
||||
recoveryStatementSet.remove(lbrace);
|
||||
|
||||
do {
|
||||
scan();
|
||||
} while (!recoveryStatementSet.contains(sym));
|
||||
errorDist = 0;
|
||||
}
|
||||
|
||||
// ====================================
|
||||
// ====================================
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user