Вывод информации о позиции в исходнике, где произошла ошибка

This commit is contained in:
Victor 2015-06-30 16:30:30 +03:00
parent ef175a71af
commit 0883845872
5 changed files with 70 additions and 23 deletions

View File

@ -59,12 +59,14 @@ public final class Lexer {
private final List<Token> tokens;
private int pos;
private int row, col;
public Lexer(String input) {
this.input = input;
length = input.length();
tokens = new ArrayList<>();
row = col = 1;
}
public List<Token> tokenize() {
@ -92,7 +94,7 @@ public final class Lexer {
char current = peek(0);
while (true) {
if (current == '.') {
if (buffer.indexOf(".") != -1) throw new RuntimeException("Invalid float number");
if (buffer.indexOf(".") != -1) throw error("Invalid float number");
} else if (!Character.isDigit(current)) {
break;
}
@ -178,6 +180,7 @@ public final class Lexer {
final StringBuilder buffer = new StringBuilder();
char current = peek(0);
while (true) {
if (current == '\0') throw error("Reached end of file while parsing text string.");
if (current == '\\') {
current = next();
switch (current) {
@ -207,7 +210,7 @@ public final class Lexer {
private void tokenizeMultilineComment() {
char current = peek(0);
while (true) {
if (current == '\0') throw new RuntimeException("Missing close tag");
if (current == '\0') throw error("Reached end of file while parsing multiline comment");
if (current == '*' && peek(1) == '/') break;
current = next();
}
@ -217,7 +220,12 @@ public final class Lexer {
private char next() {
pos++;
return peek(0);
final char result = peek(0);
if (result == '\n') {
row++;
col = 1;
} else col++;
return result;
}
private char peek(int relativePosition) {
@ -231,6 +239,10 @@ public final class Lexer {
}
private void addToken(TokenType type, String text) {
tokens.add(new Token(type, text));
tokens.add(new Token(type, text, row, col));
}
private LexerException error(String text) {
return new LexerException(row, col, text);
}
}

View File

@ -0,0 +1,16 @@
package com.annimon.ownlang.parser;
/**
*
* @author aNNiMON
*/
public final class LexerException extends RuntimeException {
public LexerException(String message) {
super(message);
}
public LexerException(int row, int col, String message) {
super("["+row+":"+col+"] " + message);
}
}

View File

@ -0,0 +1,16 @@
package com.annimon.ownlang.parser;
/**
*
* @author aNNiMON
*/
public final class ParseException extends RuntimeException {
public ParseException() {
super();
}
public ParseException(String string) {
super(string);
}
}

View File

@ -10,7 +10,7 @@ import java.util.List;
*/
public final class Parser {
private static final Token EOF = new Token(TokenType.EOF, "");
private static final Token EOF = new Token(TokenType.EOF, "", -1, -1);
private final List<Token> tokens;
private final int size;
@ -82,7 +82,6 @@ public final class Parser {
}
private Statement assignmentStatement() {
// WORD EQ
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.EQ)) {
final String variable = consume(TokenType.WORD).getText();
consume(TokenType.EQ);
@ -93,7 +92,7 @@ public final class Parser {
consume(TokenType.EQ);
return new ArrayAssignmentStatement(array, expression());
}
throw new RuntimeException("Unknown statement");
throw new ParseException("Unknown statement: " + get(0));
}
private Statement ifElse() {
@ -128,7 +127,7 @@ public final class Parser {
final Expression termination = expression();
consume(TokenType.COMMA);
final Statement increment = assignmentStatement();
match(TokenType.RPAREN);
match(TokenType.RPAREN); // необязательные скобки
final Statement statement = statementOrBlock();
return new ForStatement(initialization, termination, increment, statement);
}
@ -409,12 +408,12 @@ public final class Parser {
match(TokenType.RPAREN);
return result;
}
throw new RuntimeException("Unknown expression");
throw new ParseException("Unknown expression: " + current);
}
private Token consume(TokenType type) {
final Token current = get(0);
if (type != current.getType()) throw new RuntimeException("Token " + current + " doesn't match " + type);
if (type != current.getType()) throw new ParseException("Token " + current + " doesn't match " + type);
pos++;
return current;
}

View File

@ -6,35 +6,39 @@ package com.annimon.ownlang.parser;
*/
public final class Token {
private TokenType type;
private String text;
private final TokenType type;
private final String text;
private final int row, col;
public Token() {
}
public Token(TokenType type, String text) {
public Token(TokenType type, String text, int row, int col) {
this.type = type;
this.text = text;
this.row = row;
this.col = col;
}
public TokenType getType() {
return type;
}
public void setType(TokenType type) {
this.type = type;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public String position() {
return "[" + row + " " + col + "]";
}
@Override
public String toString() {
return type + " " + text;
return type.name() + " " + position() + " " + text;
}
}