Skip to content

Commit b2f7cc5

Browse files
committed
Улучшена обработка ошибок, восстановление
1 parent 5269d02 commit b2f7cc5

File tree

4 files changed

+105
-2
lines changed

4 files changed

+105
-2
lines changed

src/com/annimon/ownlang/Main.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,15 @@ private static void run(String input, boolean showTokens, boolean showAst) {
7070
}
7171
}
7272

73-
final Statement program = new Parser(tokens).parse();
73+
final Parser parser = new Parser(tokens);
74+
final Statement program = parser.parse();
7475
if (showAst) {
7576
System.out.println(program.toString());
7677
}
78+
if (parser.getParseErrors().hasErrors()) {
79+
System.out.println(parser.getParseErrors());
80+
return;
81+
}
7782
program.accept(new FunctionAdder());
7883
// program.accept(new VariablePrinter());
7984
program.accept(new AssignValidator());
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.annimon.ownlang.parser;
2+
3+
public final class ParseError {
4+
5+
private final int line;
6+
private final Exception exception;
7+
8+
public ParseError(int line, Exception exception) {
9+
this.line = line;
10+
this.exception = exception;
11+
}
12+
13+
public int getLine() {
14+
return line;
15+
}
16+
17+
public Exception getException() {
18+
return exception;
19+
}
20+
21+
@Override
22+
public String toString() {
23+
return "ParseError on line " + line + ": " + exception.getMessage();
24+
}
25+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.annimon.ownlang.parser;
2+
3+
import java.util.ArrayList;
4+
import java.util.Iterator;
5+
import java.util.List;
6+
7+
public final class ParseErrors implements Iterable<ParseError> {
8+
9+
private final List<ParseError> errors;
10+
11+
public ParseErrors() {
12+
errors = new ArrayList<>();
13+
}
14+
15+
public void clear() {
16+
errors.clear();
17+
}
18+
19+
public void add(Exception ex, int line) {
20+
errors.add(new ParseError(line, ex));
21+
}
22+
23+
public boolean hasErrors() {
24+
return !errors.isEmpty();
25+
}
26+
27+
@Override
28+
public Iterator<ParseError> iterator() {
29+
return errors.iterator();
30+
}
31+
32+
@Override
33+
public String toString() {
34+
final StringBuilder result = new StringBuilder();
35+
for (ParseError error : errors) {
36+
result.append(error).append(System.lineSeparator());
37+
}
38+
return result.toString();
39+
}
40+
}

src/com/annimon/ownlang/parser/Parser.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,55 @@ public final class Parser {
3838

3939
private final List<Token> tokens;
4040
private final int size;
41+
private final ParseErrors parseErrors;
4142

4243
private int pos;
4344

4445
public Parser(List<Token> tokens) {
4546
this.tokens = tokens;
4647
size = tokens.size();
48+
parseErrors = new ParseErrors();
49+
}
50+
51+
public ParseErrors getParseErrors() {
52+
return parseErrors;
4753
}
4854

4955
public Statement parse() {
56+
parseErrors.clear();
5057
final BlockStatement result = new BlockStatement();
5158
while (!match(TokenType.EOF)) {
52-
result.add(statement());
59+
try {
60+
result.add(statement());
61+
} catch (Exception ex) {
62+
parseErrors.add(ex, getErrorLine());
63+
recover();
64+
}
5365
}
5466
return result;
5567
}
5668

69+
private int getErrorLine() {
70+
if (size == 0) return 0;
71+
if (pos >= size) return tokens.get(size - 1).getRow();
72+
return tokens.get(pos).getRow();
73+
}
74+
75+
private void recover() {
76+
int preRecoverPosition = pos;
77+
for (int i = preRecoverPosition; i < size; i++) {
78+
pos = i;
79+
try {
80+
statement();
81+
// successfully parsed,
82+
pos = i; // restore position
83+
return;
84+
} catch (Exception ex) {
85+
// fail
86+
}
87+
}
88+
}
89+
5790
private Statement block() {
5891
final BlockStatement block = new BlockStatement();
5992
consume(TokenType.LBRACE);

0 commit comments

Comments
 (0)