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

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 final List<Token> tokens;
private int pos; private int pos;
private int row, col;
public Lexer(String input) { public Lexer(String input) {
this.input = input; this.input = input;
length = input.length(); length = input.length();
tokens = new ArrayList<>(); tokens = new ArrayList<>();
row = col = 1;
} }
public List<Token> tokenize() { public List<Token> tokenize() {
@ -92,7 +94,7 @@ public final class Lexer {
char current = peek(0); char current = peek(0);
while (true) { while (true) {
if (current == '.') { 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)) { } else if (!Character.isDigit(current)) {
break; break;
} }
@ -178,6 +180,7 @@ public final class Lexer {
final StringBuilder buffer = new StringBuilder(); final StringBuilder buffer = new StringBuilder();
char current = peek(0); char current = peek(0);
while (true) { while (true) {
if (current == '\0') throw error("Reached end of file while parsing text string.");
if (current == '\\') { if (current == '\\') {
current = next(); current = next();
switch (current) { switch (current) {
@ -207,7 +210,7 @@ public final class Lexer {
private void tokenizeMultilineComment() { private void tokenizeMultilineComment() {
char current = peek(0); char current = peek(0);
while (true) { 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; if (current == '*' && peek(1) == '/') break;
current = next(); current = next();
} }
@ -217,7 +220,12 @@ public final class Lexer {
private char next() { private char next() {
pos++; pos++;
return peek(0); final char result = peek(0);
if (result == '\n') {
row++;
col = 1;
} else col++;
return result;
} }
private char peek(int relativePosition) { private char peek(int relativePosition) {
@ -231,6 +239,10 @@ public final class Lexer {
} }
private void addToken(TokenType type, String text) { 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 { 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 List<Token> tokens;
private final int size; private final int size;
@ -82,7 +82,6 @@ public final class Parser {
} }
private Statement assignmentStatement() { private Statement assignmentStatement() {
// WORD EQ
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.EQ)) { if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.EQ)) {
final String variable = consume(TokenType.WORD).getText(); final String variable = consume(TokenType.WORD).getText();
consume(TokenType.EQ); consume(TokenType.EQ);
@ -93,7 +92,7 @@ public final class Parser {
consume(TokenType.EQ); consume(TokenType.EQ);
return new ArrayAssignmentStatement(array, expression()); return new ArrayAssignmentStatement(array, expression());
} }
throw new RuntimeException("Unknown statement"); throw new ParseException("Unknown statement: " + get(0));
} }
private Statement ifElse() { private Statement ifElse() {
@ -128,7 +127,7 @@ public final class Parser {
final Expression termination = expression(); final Expression termination = expression();
consume(TokenType.COMMA); consume(TokenType.COMMA);
final Statement increment = assignmentStatement(); final Statement increment = assignmentStatement();
match(TokenType.RPAREN); match(TokenType.RPAREN); // необязательные скобки
final Statement statement = statementOrBlock(); final Statement statement = statementOrBlock();
return new ForStatement(initialization, termination, increment, statement); return new ForStatement(initialization, termination, increment, statement);
} }
@ -409,12 +408,12 @@ public final class Parser {
match(TokenType.RPAREN); match(TokenType.RPAREN);
return result; return result;
} }
throw new RuntimeException("Unknown expression"); throw new ParseException("Unknown expression: " + current);
} }
private Token consume(TokenType type) { private Token consume(TokenType type) {
final Token current = get(0); 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++; pos++;
return current; return current;
} }

View File

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