From 21c47e9bf17219def1675aa6fde3652636801c48 Mon Sep 17 00:00:00 2001 From: Mitchell Bosecke Date: Sat, 8 Feb 2014 12:03:06 -0700 Subject: [PATCH] Improved some error reporting --- .../mitchellbosecke/pebble/lexer/Lexer.java | 67 ++++++++++++++++++- .../pebble/lexer/LexerImpl.java | 6 +- .../pebble/lexer/TokenStream.java | 57 ++++++---------- .../pebble/parser/ExpressionParser.java | 2 +- .../pebble/parser/ParserImpl.java | 2 +- 5 files changed, 91 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/mitchellbosecke/pebble/lexer/Lexer.java b/src/main/java/com/mitchellbosecke/pebble/lexer/Lexer.java index 3122f2b1b..b610e3243 100644 --- a/src/main/java/com/mitchellbosecke/pebble/lexer/Lexer.java +++ b/src/main/java/com/mitchellbosecke/pebble/lexer/Lexer.java @@ -11,8 +11,73 @@ import com.mitchellbosecke.pebble.error.ParserException; - public interface Lexer { public TokenStream tokenize(String source, String name) throws ParserException; + + /** + * @return the commentOpenDelimiter + */ + public String getCommentOpenDelimiter(); + + /** + * @param commentOpenDelimiter + * the commentOpenDelimiter to set + */ + public void setCommentOpenDelimiter(String commentOpenDelimiter); + + /** + * @return the commentCloseDelimiter + */ + public String getCommentCloseDelimiter(); + + /** + * @param commentCloseDelimiter + * the commentCloseDelimiter to set + */ + public void setCommentCloseDelimiter(String commentCloseDelimiter); + + /** + * @return the executeOpenDelimiter + */ + public String getExecuteOpenDelimiter(); + + /** + * @param executeOpenDelimiter + * the executeOpenDelimiter to set + */ + public void setExecuteOpenDelimiter(String executeOpenDelimiter); + + /** + * @return the executeCloseDelimiter + */ + public String getExecuteCloseDelimiter(); + + /** + * @param executeCloseDelimiter + * the executeCloseDelimiter to set + */ + public void setExecuteCloseDelimiter(String executeCloseDelimiter); + + /** + * @return the printOpenDelimiter + */ + public String getPrintOpenDelimiter(); + + /** + * @param printOpenDelimiter + * the printOpenDelimiter to set + */ + public void setPrintOpenDelimiter(String printOpenDelimiter); + + /** + * @return the printCloseDelimiter + */ + public String getPrintCloseDelimiter(); + + /** + * @param printCloseDelimiter + * the printCloseDelimiter to set + */ + public void setPrintCloseDelimiter(String printCloseDelimiter); } diff --git a/src/main/java/com/mitchellbosecke/pebble/lexer/LexerImpl.java b/src/main/java/com/mitchellbosecke/pebble/lexer/LexerImpl.java index 19dc6bbe4..359353ff9 100644 --- a/src/main/java/com/mitchellbosecke/pebble/lexer/LexerImpl.java +++ b/src/main/java/com/mitchellbosecke/pebble/lexer/LexerImpl.java @@ -239,7 +239,7 @@ private void lexExecute() throws ParserException { // check if we are at the execute closing delimiter if (brackets.isEmpty() && matcher.lookingAt()) { String token = source.substring(cursor, cursor + matcher.end()); - pushToken(Token.Type.EXECUTE_END); + pushToken(Token.Type.EXECUTE_END, delimiterExecuteClose); moveCursor(token); popState(); } else { @@ -258,7 +258,7 @@ private void lexPrint() throws ParserException { // check if we are at the print closing delimiter if (brackets.isEmpty() && matcher.lookingAt()) { String token = source.substring(cursor, cursor + matcher.end()); - pushToken(Token.Type.PRINT_END); + pushToken(Token.Type.PRINT_END, delimiterPrintClose); moveCursor(token); popState(); } else { @@ -389,7 +389,7 @@ else if (")]}".indexOf(character) >= 0) { } // we should have found something and returned by this point - throw new ParserException(null, String.format("Unexpected character \"%s\"", source.charAt(cursor)), + throw new ParserException(null, String.format("Unexpected character [%s]", source.charAt(cursor)), lineNumber, filename); } diff --git a/src/main/java/com/mitchellbosecke/pebble/lexer/TokenStream.java b/src/main/java/com/mitchellbosecke/pebble/lexer/TokenStream.java index a955e6a67..b580691de 100644 --- a/src/main/java/com/mitchellbosecke/pebble/lexer/TokenStream.java +++ b/src/main/java/com/mitchellbosecke/pebble/lexer/TokenStream.java @@ -50,64 +50,47 @@ public Token next() { /** * Checks the current token to see if it matches the provided type. If it - * doesn't match this will throw a SyntaxException. This will consume - * a token. + * doesn't match this will throw a SyntaxException. This will consume a + * token. * * @param type * The type of token that we expect * @return The current token - * @throws ParserException + * @throws ParserException */ public Token expect(Token.Type type) throws ParserException { - return expect(type, null, null); + return expect(type, null); } - + /** * Checks the current token to see if it matches the provided type. If it - * doesn't match this will throw a SyntaxException. This will consume - * a token. + * doesn't match this will throw a SyntaxException. This will consume a + * token. * * @param type * The type of token that we expect * @return The current token - * @throws ParserException + * @throws ParserException */ public Token expect(Token.Type type, String value) throws ParserException { - return expect(type, value, null); - } - - - /** - * Checks the current token to see if it matches the provided type and - * value. If it doesn't match this will throw a SyntaxException with the - * provided message. This will consume a token. - * - * @param type - * The type of token that we expect - * @param value - * The value of the token that we expect, or null if we only care - * about the type - * @param message - * The message of the exception if the expectation fails - * @return The current token - * @throws ParserException - */ - public Token expect(Token.Type type, String value, String message) throws ParserException { - // TODO: message isn't used Token token = tokens.get(current); + + boolean success = true; + String message = null; if (value == null) { - if (!token.test(type)) { - throw new ParserException(null, "Unexpected token of value [" - + token.getValue() + "] expected token of type " + type - + " ", token.getLineNumber(), filename); + success = token.test(type); + if (!success && message == null) { + message = "Unexpected token of value [" + token.getValue() + "] expected token of type " + type; } } else { - if (!token.test(type, value)) { - throw new ParserException(null, "Unexpected token of value [" - + token.getValue() + "] expected [" + value - + "] ", token.getLineNumber(), filename); + success = token.test(type, value); + if (!success && message == null) { + message = "Unexpected token of value [" + token.getValue() + "] expected [" + value + "] "; } } + if (!success) { + throw new ParserException(null, message, token.getLineNumber(), filename); + } this.next(); return token; } diff --git a/src/main/java/com/mitchellbosecke/pebble/parser/ExpressionParser.java b/src/main/java/com/mitchellbosecke/pebble/parser/ExpressionParser.java index 6edfa3127..a05d4ad31 100644 --- a/src/main/java/com/mitchellbosecke/pebble/parser/ExpressionParser.java +++ b/src/main/java/com/mitchellbosecke/pebble/parser/ExpressionParser.java @@ -114,7 +114,7 @@ private NodeExpression parseExpression(int minPrecedence) throws ParserException stream.next(); expression = parseExpression(); - stream.expect(Token.Type.PUNCTUATION, ")", "An opened parenthesis is not properly closed"); + stream.expect(Token.Type.PUNCTUATION, ")"); expression = parsePostfixExpression(expression); } else { diff --git a/src/main/java/com/mitchellbosecke/pebble/parser/ParserImpl.java b/src/main/java/com/mitchellbosecke/pebble/parser/ParserImpl.java index 1420d5b5f..fd9c0b457 100644 --- a/src/main/java/com/mitchellbosecke/pebble/parser/ParserImpl.java +++ b/src/main/java/com/mitchellbosecke/pebble/parser/ParserImpl.java @@ -196,7 +196,7 @@ public NodeBody subparse(StoppingCondition stopCondition) throws ParserException nodes.add(new NodePrint(expression, token.getLineNumber())); // we expect to see a print closing delimiter - stream.expect(Token.Type.PRINT_END); + stream.expect(Token.Type.PRINT_END, engine.getLexer().getPrintCloseDelimiter()); break;