Repository: groovy Updated Branches: refs/heads/parrot b9ed6e969 -> 61d7009cd
Refine error messages handling( e.g. missing ')' ) Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/61d7009c Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/61d7009c Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/61d7009c Branch: refs/heads/parrot Commit: 61d7009cdbf24bd5e9b2631631bec02d8c8fa47a Parents: b9ed6e9 Author: Daniel Sun <sun...@apache.org> Authored: Wed Nov 30 23:26:13 2016 +0800 Committer: Daniel Sun <sun...@apache.org> Committed: Wed Nov 30 23:26:13 2016 +0800 ---------------------------------------------------------------------- .../apache/groovy/parser/antlr4/GroovyLexer.g4 | 20 +++++------ .../apache/groovy/parser/antlr4/GroovyParser.g4 | 24 ++++++++++++- .../groovy/parser/antlr4/AbstractLexer.java | 32 +++++++++++++++++ .../groovy/parser/antlr4/AbstractParser.java | 32 +++++++++++++++++ .../apache/groovy/parser/antlr4/AstBuilder.java | 7 +++- .../groovy/parser/antlr4/GroovySyntaxError.java | 18 +++++++++- .../parser/antlr4/SyntaxErrorReportable.java | 38 ++++++++++++++++++++ 7 files changed, 158 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/61d7009c/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyLexer.g4 ---------------------------------------------------------------------- diff --git a/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyLexer.g4 b/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyLexer.g4 index 34999f6..295c7fb 100644 --- a/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyLexer.g4 +++ b/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyLexer.g4 @@ -34,6 +34,10 @@ */ lexer grammar GroovyLexer; +options { + superClass = AbstractLexer; +} + @header { import static org.apache.groovy.parser.antlr4.SemanticPredicates.*; import java.util.Deque; @@ -165,17 +169,13 @@ lexer grammar GroovyLexer; this.setChannel(Token.HIDDEN_CHANNEL); } - private void require(boolean condition, String msg) { - if (condition) { - return; - } - - this.syntaxError(msg); - } - private void syntaxError(String msg) { - throw new GroovySyntaxError(msg + this.genPositionInfo()); + @Override + public int getSyntaxErrorSource() { + return GroovySyntaxError.LEXER; } - private String genPositionInfo() { + + @Override + public String genPositionInfo() { return " @ line " + getLine() + ", column " + (getCharPositionInLine() + 1); } } http://git-wip-us.apache.org/repos/asf/groovy/blob/61d7009c/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4 ---------------------------------------------------------------------- diff --git a/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4 b/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4 index a3c6043..b70736e 100644 --- a/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4 +++ b/subprojects/groovy-antlr4-grammar/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4 @@ -37,6 +37,7 @@ parser grammar GroovyParser; options { tokenVocab = GroovyLexer; contextSuperClass = GroovyParserRuleContext; + superClass = AbstractParser; } @header { @@ -103,6 +104,24 @@ options { return metaDataMap.put(key, value); } } + + @Override + public int getSyntaxErrorSource() { + return GroovySyntaxError.PARSER; + } + + @Override + public String genPositionInfo() { + Token token = _input.LT(-1); + + if (null == token) { + return ""; + } + + return " @ line " + token.getLine() + ", column " + (token.getCharPositionInLine() + 1 + token.getText().length()); + } + + } // starting point for parsing a groovy file @@ -730,7 +749,10 @@ castParExpression ; parExpression - : LPAREN (statementExpression | standardLambda) RPAREN + : LPAREN (statementExpression | standardLambda) + ( RPAREN + | { require(false, "Missing ')'"); } + ) // !!!Error Alternatives!!! //| LPAREN statementExpression RPAREN RPAREN+ { notifyErrorListeners("Too many ')'"); } // the "Too many" case has been handled by the lexer http://git-wip-us.apache.org/repos/asf/groovy/blob/61d7009c/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AbstractLexer.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AbstractLexer.java b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AbstractLexer.java new file mode 100644 index 0000000..b3781b4 --- /dev/null +++ b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AbstractLexer.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.groovy.parser.antlr4; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Lexer; + +/** + * Because antlr4 does not support generating lexer with specified interface, + * we have to create a super class for it and implement the interface. + */ +public abstract class AbstractLexer extends Lexer implements SyntaxErrorReportable { + public AbstractLexer(CharStream input) { + super(input); + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/61d7009c/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AbstractParser.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AbstractParser.java b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AbstractParser.java new file mode 100644 index 0000000..44c51c4 --- /dev/null +++ b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AbstractParser.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.groovy.parser.antlr4; + +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.Parser; + +/** + * Because antlr4 does not support generating parser with specified interface, + * we have to create a super class for it and implement the interface. + */ +public abstract class AbstractParser extends Parser implements SyntaxErrorReportable { + public AbstractParser(TokenStream input) { + super(input); + } +} http://git-wip-us.apache.org/repos/asf/groovy/blob/61d7009c/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java index 23d4fa5..31124d6 100644 --- a/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java +++ b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java @@ -89,7 +89,12 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov AtnManager.RRWL.readLock().lock(); try { result = buildCST(PredictionMode.SLL); - } catch (Exception e) { + } catch (Throwable t) { + // if some syntax error occurred in the lexer, no need to retry the powerful LL mode + if (t instanceof GroovySyntaxError && GroovySyntaxError.LEXER == ((GroovySyntaxError) t).getSource()) { + throw t; + } + result = buildCST(PredictionMode.LL); } finally { AtnManager.RRWL.readLock().unlock(); http://git-wip-us.apache.org/repos/asf/groovy/blob/61d7009c/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/GroovySyntaxError.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/GroovySyntaxError.java b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/GroovySyntaxError.java index fe71cc4..5dc829d 100644 --- a/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/GroovySyntaxError.java +++ b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/GroovySyntaxError.java @@ -18,11 +18,27 @@ */ package org.apache.groovy.parser.antlr4; +import java.util.IllegalFormatCodePointException; + /** * Represents a syntax error of groovy program */ public class GroovySyntaxError extends AssertionError { - public GroovySyntaxError(String message) { + public static final int LEXER = 0; + public static final int PARSER = 1; + private int source; + + public GroovySyntaxError(String message, int source) { super(message, null); + + if (source != LEXER && source != PARSER) { + throw new IllegalArgumentException("Invalid syntax error source: " + source); + } + + this.source = source; + } + + public int getSource() { + return source; } } http://git-wip-us.apache.org/repos/asf/groovy/blob/61d7009c/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/SyntaxErrorReportable.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/SyntaxErrorReportable.java b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/SyntaxErrorReportable.java new file mode 100644 index 0000000..4cfdffe --- /dev/null +++ b/subprojects/groovy-antlr4-grammar/src/main/java/org/apache/groovy/parser/antlr4/SyntaxErrorReportable.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.groovy.parser.antlr4; + +/** + * A SyntaxErrorReportable is a recognizer that can report syntax error + */ +public interface SyntaxErrorReportable { + default void require(boolean condition, String msg) { + if (condition) { + return; + } + + this.throwSyntaxError(msg); + } + default void throwSyntaxError(String msg) { + throw new GroovySyntaxError(msg + this.genPositionInfo(), this.getSyntaxErrorSource()); + } + + int getSyntaxErrorSource(); + String genPositionInfo(); +}