mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44:20 +03:00
Улучшена обработка ошибок, восстановление
This commit is contained in:
parent
5269d02a66
commit
b2f7cc52ed
@ -70,10 +70,15 @@ public final class Main {
|
||||
}
|
||||
}
|
||||
|
||||
final Statement program = new Parser(tokens).parse();
|
||||
final Parser parser = new Parser(tokens);
|
||||
final Statement program = parser.parse();
|
||||
if (showAst) {
|
||||
System.out.println(program.toString());
|
||||
}
|
||||
if (parser.getParseErrors().hasErrors()) {
|
||||
System.out.println(parser.getParseErrors());
|
||||
return;
|
||||
}
|
||||
program.accept(new FunctionAdder());
|
||||
// program.accept(new VariablePrinter());
|
||||
program.accept(new AssignValidator());
|
||||
|
25
src/com/annimon/ownlang/parser/ParseError.java
Normal file
25
src/com/annimon/ownlang/parser/ParseError.java
Normal file
@ -0,0 +1,25 @@
|
||||
package com.annimon.ownlang.parser;
|
||||
|
||||
public final class ParseError {
|
||||
|
||||
private final int line;
|
||||
private final Exception exception;
|
||||
|
||||
public ParseError(int line, Exception exception) {
|
||||
this.line = line;
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParseError on line " + line + ": " + exception.getMessage();
|
||||
}
|
||||
}
|
40
src/com/annimon/ownlang/parser/ParseErrors.java
Normal file
40
src/com/annimon/ownlang/parser/ParseErrors.java
Normal file
@ -0,0 +1,40 @@
|
||||
package com.annimon.ownlang.parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public final class ParseErrors implements Iterable<ParseError> {
|
||||
|
||||
private final List<ParseError> errors;
|
||||
|
||||
public ParseErrors() {
|
||||
errors = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
errors.clear();
|
||||
}
|
||||
|
||||
public void add(Exception ex, int line) {
|
||||
errors.add(new ParseError(line, ex));
|
||||
}
|
||||
|
||||
public boolean hasErrors() {
|
||||
return !errors.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ParseError> iterator() {
|
||||
return errors.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (ParseError error : errors) {
|
||||
result.append(error).append(System.lineSeparator());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
@ -38,22 +38,55 @@ public final class Parser {
|
||||
|
||||
private final List<Token> tokens;
|
||||
private final int size;
|
||||
private final ParseErrors parseErrors;
|
||||
|
||||
private int pos;
|
||||
|
||||
public Parser(List<Token> tokens) {
|
||||
this.tokens = tokens;
|
||||
size = tokens.size();
|
||||
parseErrors = new ParseErrors();
|
||||
}
|
||||
|
||||
public ParseErrors getParseErrors() {
|
||||
return parseErrors;
|
||||
}
|
||||
|
||||
public Statement parse() {
|
||||
parseErrors.clear();
|
||||
final BlockStatement result = new BlockStatement();
|
||||
while (!match(TokenType.EOF)) {
|
||||
try {
|
||||
result.add(statement());
|
||||
} catch (Exception ex) {
|
||||
parseErrors.add(ex, getErrorLine());
|
||||
recover();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int getErrorLine() {
|
||||
if (size == 0) return 0;
|
||||
if (pos >= size) return tokens.get(size - 1).getRow();
|
||||
return tokens.get(pos).getRow();
|
||||
}
|
||||
|
||||
private void recover() {
|
||||
int preRecoverPosition = pos;
|
||||
for (int i = preRecoverPosition; i < size; i++) {
|
||||
pos = i;
|
||||
try {
|
||||
statement();
|
||||
// successfully parsed,
|
||||
pos = i; // restore position
|
||||
return;
|
||||
} catch (Exception ex) {
|
||||
// fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Statement block() {
|
||||
final BlockStatement block = new BlockStatement();
|
||||
consume(TokenType.LBRACE);
|
||||
|
Loading…
Reference in New Issue
Block a user