You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by mr...@apache.org on 2009/01/21 02:31:34 UTC
svn commit: r736186 - in /ode/sandbox/simpel/src:
main/antlr/org/apache/ode/simpel/antlr/ main/java/org/apache/ode/simpel/
main/java/org/apache/ode/simpel/util/ test/java/org/apache/ode/simpel/
Author: mriou
Date: Tue Jan 20 17:31:33 2009
New Revision: 736186
URL: http://svn.apache.org/viewvc?rev=736186&view=rev
Log:
Improved parser error messages.
Added:
ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/ErrorMessageBuilder.java
Modified:
ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPEL.g
ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPELWalker.g
ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/ErrorListener.java
ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/DefaultErrorListener.java
ode/sandbox/simpel/src/test/java/org/apache/ode/simpel/SimPELCompilerTest.java
Modified: ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPEL.g
URL: http://svn.apache.org/viewvc/ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPEL.g?rev=736186&r1=736185&r2=736186&view=diff
==============================================================================
--- ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPEL.g (original)
+++ ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPEL.g Tue Jan 20 17:31:33 2009
@@ -14,6 +14,13 @@
SIGNAL; JOIN; WITH; MAP;
EXPR; EXT_EXPR; XML_LITERAL; CALL; NAMESPACE; NS; PATH;
}
+
+@lexer::header {
+package org.apache.ode.simpel.antlr;
+import org.apache.ode.simpel.ErrorListener;
+import org.apache.ode.simpel.util.ErrorMessageBuilder;
+}
+
@parser::header {
package org.apache.ode.simpel.antlr;
@@ -21,12 +28,9 @@
import uk.co.badgersinfoil.e4x.antlr.LinkedListTree;
import uk.co.badgersinfoil.e4x.E4XHelper;
import org.apache.ode.simpel.ErrorListener;
+import org.apache.ode.simpel.util.ErrorMessageBuilder;
import org.apache.ode.simpel.util.JSHelper;
}
-@lexer::header {
-package org.apache.ode.simpel.antlr;
-import org.apache.ode.simpel.ErrorListener;
-}
@lexer::members {
private ErrorListener el;
@@ -35,7 +39,12 @@
this.el = el;
}
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
- el.reportRecognitionError(tokenNames, e.line, getErrorMessage(e, tokenNames), e);
+ el.reportRecognitionError(e.line, e.charPositionInLine, getErrorMessage(e, tokenNames), e);
+ }
+ public String getErrorMessage(RecognitionException e, String[] tokenNames) {
+ String msg = ErrorMessageBuilder.msg(e, tokenNames, null);
+ if (msg == null) msg = super.getErrorMessage(e, tokenNames);
+ return msg;
}
}
@@ -45,6 +54,7 @@
private SimPELLexer lexer;
private CharStream cs;
private ErrorListener el;
+ private Stack paraphrases = new Stack();
public void setInput(SimPELLexer lexer, CharStream cs) {
this.lexer = lexer;
@@ -64,20 +74,14 @@
}
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
- el.reportRecognitionError(tokenNames, e.line, getErrorMessage(e, tokenNames), e);
+ el.reportRecognitionError(e.line, e.charPositionInLine, getErrorMessage(e, tokenNames), e);
}
public String getErrorMessage(RecognitionException e, String[] tokenNames) {
- List stack = getRuleInvocationStack(e, this.getClass().getName());
- String msg = null;
- if ( e instanceof NoViableAltException ) {
- NoViableAltException nvae = (NoViableAltException)e;
- msg = " no viable alt; token="+e.token+" (decision="+nvae.decisionNumber+" state "+nvae.stateNumber+")"+
- " decision=<<"+nvae.grammarDecisionDescription+">>";
- } else {
- msg = super.getErrorMessage(e, tokenNames);
- }
- return stack+" "+msg;
+// List stack = getRuleInvocationStack(e, this.getClass().getName());
+ String msg = ErrorMessageBuilder.msg(e, tokenNames, (String) paraphrases.peek());
+ if (msg == null) msg = super.getErrorMessage(e, tokenNames);
+ return msg;
}
public String getTokenErrorDisplay(Token t) {
@@ -95,102 +99,193 @@
process : 'process' ns_id body -> ^(PROCESS ns_id body);
proc_stmt
+@init { paraphrases.push("in a process"); }
+@after { paraphrases.pop(); }
: pick | flow | if_ex | while_ex | until_ex | foreach | forall | try_ex | scope_ex | with_ex
| receive | request | invoke | ((reply | assign | throw_ex | wait_ex | exit | signal | join
| variables | partner_link) SEMI!);
-block : '{' proc_stmt+ '}' -> ^(SEQUENCE proc_stmt+);
+block
+@init { paraphrases.push("in a block of statements"); }
+@after { paraphrases.pop(); }
+ : '{' proc_stmt+ '}' -> ^(SEQUENCE proc_stmt+);
+
param_block
+@init { paraphrases.push("in a parameterized block of statements"); }
+@after { paraphrases.pop(); }
: '{' ('|' in+=ID (',' in+=ID)* '|')? proc_stmt+ '}' -> ^(SEQUENCE $in* proc_stmt+);
+
body : block | proc_stmt;
// Structured activities
-pick : 'pick' '{' receive* timeout* '}' -> ^(PICK receive* timeout*);
-timeout : 'timeout' '(' expr ')' block -> ^(TIMEOUT expr block);
-
-flow : 'parallel' b+=body ('and' b+=body)* -> ^(FLOW $b*);
+pick
+@init { paraphrases.push("in a pick"); }
+@after { paraphrases.pop(); }
+ : 'pick' '{' receive* timeout* '}' -> ^(PICK receive* timeout*);
+
+timeout
+@init { paraphrases.push("in a timeout"); }
+@after { paraphrases.pop(); }
+ : 'timeout' '(' expr ')' block -> ^(TIMEOUT expr block);
+
+flow
+@init { paraphrases.push("in a flow"); }
+@after { paraphrases.pop(); }
+ : 'parallel' b+=body ('and' b+=body)* -> ^(FLOW $b*);
signal : 'signal' '('ID (',' expr)? ')' -> ^(SIGNAL ID expr?);
join : 'join' '(' k+=ID (',' k+=ID)* (',' expr)? ')' -> ^(JOIN $k+ expr?);
-if_ex : 'if' '(' expr ')' ifb=body ('else' eb=body)? -> ^(IF expr $ifb (^(ELSE $eb))?);
-
-while_ex: 'while' '(' expr ')' body -> ^(WHILE expr body);
-
-until_ex: 'do' body 'until' '(' expr ')' -> ^(UNTIL expr body);
-
-foreach : 'for' '(' ID '=' init=expr ';' cond=expr ';' assign ')' body -> ^(FOREACH ID $init $cond assign body);
-forall : 'forall' '(' ID '=' from=expr 'to' to=expr ')' body -> ^(FORALL ID $from $to body);
-
-try_ex : 'try' body catch_ex* -> ^(TRY body catch_ex*);
-catch_ex: 'catch' '(' ns_id ')' param_block -> ^(CATCH ns_id param_block);
-
-scope_ex: 'scope' ('(' ID ')')? body scope_stmt* -> ^(SCOPE ID? body scope_stmt*);
+if_ex
+@init { paraphrases.push("in a if expression"); }
+@after { paraphrases.pop(); }
+ : 'if' '(' expr ')' ifb=body ('else' eb=body)? -> ^(IF expr $ifb (^(ELSE $eb))?);
+
+while_ex
+@init { paraphrases.push("in a while"); }
+@after { paraphrases.pop(); }
+ : 'while' '(' expr ')' body -> ^(WHILE expr body);
+
+until_ex
+@init { paraphrases.push("in an until"); }
+@after { paraphrases.pop(); }
+ : 'do' body 'until' '(' expr ')' -> ^(UNTIL expr body);
+
+foreach
+@init { paraphrases.push("in a foreach loop"); }
+@after { paraphrases.pop(); }
+ : 'for' '(' ID '=' init=expr ';' cond=expr ';' assign ')' body -> ^(FOREACH ID $init $cond assign body);
+forall
+@init { paraphrases.push("in a forall loop"); }
+@after { paraphrases.pop(); }
+ : 'forall' '(' ID '=' from=expr 'to' to=expr ')' body -> ^(FORALL ID $from $to body);
+
+try_ex
+@init { paraphrases.push("in a try block"); }
+@after { paraphrases.pop(); }
+ : 'try' body catch_ex* -> ^(TRY body catch_ex*);
+catch_ex
+@init { paraphrases.push("in a catch block"); }
+@after { paraphrases.pop(); }
+ : 'catch' '(' ns_id ')' param_block -> ^(CATCH ns_id param_block);
+
+scope_ex
+@init { paraphrases.push("in a scope declaration"); }
+@after { paraphrases.pop(); }
+ : 'scope' ('(' ID ')')? body scope_stmt* -> ^(SCOPE ID? body scope_stmt*);
scope_stmt
- : onevent | onalarm | compensation | onquery | onrec | onupd;
+ : onevent | onalarm | compensation | onquery | onrec | onupd;
+
+onevent
+@init { paraphrases.push("in an onEvent"); }
+@after { paraphrases.pop(); }
+ : 'onEvent' '(' p=ID ',' o=ID ')' param_block -> ^(ONEVENT $p $o param_block);
+onalarm
+@init { paraphrases.push("in an onAlarm"); }
+@after { paraphrases.pop(); }
+ : 'onAlarm' '(' expr ')' body -> ^(ONALARM expr body);
+onquery
+@init { paraphrases.push("in an onQuery"); }
+@after { paraphrases.pop(); }
+ : 'onQuery' '(' r=ID ')' body -> ^(ONQUERY $r body);
+onrec
+@init { paraphrases.push("in an onReceive"); }
+@after { paraphrases.pop(); }
+ : 'onReceive' '(' r=ID ')' body -> ^(ONRECEIVE $r body);
+onupd
+@init { paraphrases.push("in an onUpdate"); }
+@after { paraphrases.pop(); }
+ : 'onUpdate' '(' r=ID ')' body -> ^(ONUPDATE $r body);
-onevent : 'onEvent' '(' p=ID ',' o=ID ')' param_block -> ^(ONEVENT $p $o param_block);
-onalarm : 'onAlarm' '(' expr ')' body -> ^(ONALARM expr body);
-onquery : 'onQuery' '(' r=ID ')' body -> ^(ONQUERY $r body);
-onrec : 'onReceive' '(' r=ID ')' body -> ^(ONRECEIVE $r body);
-onupd : 'onUpdate' '(' r=ID ')' body -> ^(ONUPDATE $r body);
compensation
+@init { paraphrases.push("in an compensation"); }
+@after { paraphrases.pop(); }
: 'compensation' body -> ^(COMPENSATION body);
-with_ex :
- 'with' '(' wm+=with_map (',' wm+=with_map)* ')' body -> ^(WITH $wm+ body);
+with_ex
+@init { paraphrases.push("in a with expression"); }
+@after { paraphrases.pop(); }
+ : 'with' '(' wm+=with_map (',' wm+=with_map)* ')' body -> ^(WITH $wm+ body);
with_map: ID ':' path_expr -> ^(MAP ID path_expr);
// Simple activities
-invoke
- : invoke_base param_block -> ^(INVOKE invoke_base) param_block
+invoke : invoke_base param_block -> ^(INVOKE invoke_base) param_block
| invoke_base SEMI -> ^(INVOKE invoke_base);
invoke_base
+@init { paraphrases.push("in an invoke"); }
+@after { paraphrases.pop(); }
: 'invoke' '(' p=ID ',' o=ID (',' in=ID)? ')' -> ^($p $o $in?);
-receive
- : receive_base param_block -> ^(RECEIVE receive_base) param_block
+receive : receive_base param_block -> ^(RECEIVE receive_base) param_block
| receive_base SEMI -> ^(RECEIVE receive_base);
receive_base
- : 'receive' '(' p=ID (',' o=ID (',' correlation)? )? ')' -> ^($p $o? correlation?);
+@init { paraphrases.push("in a receive"); }
+@after { paraphrases.pop(); }
+ : 'receive' '(' p=ID (',' o=ID (',' correlation)? )? ')' -> ^($p $o? correlation?);
request
options {backtrack=true;}
: request_base param_block -> ^(REQUEST request_base) param_block
| request_base SEMI -> ^(REQUEST request_base);
+
request_base
+@init { paraphrases.push("in a request"); }
+@after { paraphrases.pop(); }
: 'request' '(' expr (',' meth=STRING (',' msg=ID)?)? ')' -> ^(REQ_BASE expr $meth? $msg?);
-reply : 'reply' '(' ID (',' ID (',' ID)?)? ')' -> ^(REPLY ID (ID ID?)?);
-
-assign : path_expr '=' rvalue -> ^(ASSIGN path_expr rvalue);
+reply
+@init { paraphrases.push("in a reply"); }
+@after { paraphrases.pop(); }
+ : 'reply' '(' ID (',' ID (',' ID)?)? ')' -> ^(REPLY ID (ID ID?)?);
+
+assign
+@init { paraphrases.push("in an assignment"); }
+@after { paraphrases.pop(); }
+ : path_expr '=' rvalue -> ^(ASSIGN path_expr rvalue);
rvalue
- : receive_base -> ^(RECEIVE receive_base)
- | invoke_base -> ^(INVOKE invoke_base)
- | request_base -> ^(REQUEST request_base)
- | resource | expr | xml_literal;
+@init { paraphrases.push("in an assignment right value"); }
+@after { paraphrases.pop(); }
+ : receive_base -> ^(RECEIVE receive_base)
+ | invoke_base -> ^(INVOKE invoke_base)
+ | request_base -> ^(REQUEST request_base)
+ | resource | expr | xml_literal;
-throw_ex: 'throw' '('? ns_id ')'? -> ^(THROW ns_id);
+throw_ex
+@init { paraphrases.push("in a throw"); }
+@after { paraphrases.pop(); }
+ : 'throw' '('? ns_id ')'? -> ^(THROW ns_id);
+
+wait_ex
+@init { paraphrases.push("in a wait"); }
+@after { paraphrases.pop(); }
-wait_ex : 'wait' '('expr')' -> ^(WAIT expr);
+ : 'wait' '('expr')' -> ^(WAIT expr);
compensate
- : 'compensate' ('(' ID ')')? -> ^(COMPENSATE ID?);
+@init { paraphrases.push("in a compensate"); }
+@after { paraphrases.pop(); }
+ : 'compensate' ('(' ID ')')? -> ^(COMPENSATE ID?);
exit : 'exit' -> ^(EXIT);
// Others
namespace
- : 'namespace' ID '=' STRING SEMI -> ^(NAMESPACE ID STRING);
+ : 'namespace' ID '=' STRING SEMI -> ^(NAMESPACE ID STRING);
resource
- : 'resource' '(' expr? (',' ID)? ')' -> ^(RESOURCE expr? ID?);
+@init { paraphrases.push("in a resource declaration"); }
+@after { paraphrases.pop(); }
+ : 'resource' '(' expr? (',' ID)? ')' -> ^(RESOURCE expr? ID?);
variables
- : 'var'! v+=variable (','! v+=variable)*;
+@init { paraphrases.push("in variable declaration"); }
+@after { paraphrases.pop(); }
+ : 'var'! v+=variable (','! v+=variable)*;
variable: ID VAR_MODS* -> ^(VARIABLE ID VAR_MODS*);
partner_link
+@init { paraphrases.push("in a partner link declaration"); }
+@after { paraphrases.pop(); }
: 'partnerLink' pl+=ID (',' pl+=ID)* -> ^(PARTNERLINK $pl+);
correlation
Modified: ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPELWalker.g
URL: http://svn.apache.org/viewvc/ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPELWalker.g?rev=736186&r1=736185&r2=736186&view=diff
==============================================================================
--- ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPELWalker.g (original)
+++ ode/sandbox/simpel/src/main/antlr/org/apache/ode/simpel/antlr/SimPELWalker.g Tue Jan 20 17:31:33 2009
@@ -31,7 +31,7 @@
this.el = el;
}
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
- el.reportRecognitionError(tokenNames, e.line, getErrorMessage(e, tokenNames), e);
+ el.reportRecognitionError(e.line, e.charPositionInLine, getErrorMessage(e, tokenNames), e);
}
public String getErrorMessage(RecognitionException e, String[] tokenNames) {
Modified: ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/ErrorListener.java
URL: http://svn.apache.org/viewvc/ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/ErrorListener.java?rev=736186&r1=736185&r2=736186&view=diff
==============================================================================
--- ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/ErrorListener.java (original)
+++ ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/ErrorListener.java Tue Jan 20 17:31:33 2009
@@ -7,5 +7,5 @@
*/
public interface ErrorListener {
- public void reportRecognitionError(String[] tokens, int line, String message, RecognitionException e);
+ public void reportRecognitionError(int line, int column, String message, RecognitionException e);
}
Modified: ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/DefaultErrorListener.java
URL: http://svn.apache.org/viewvc/ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/DefaultErrorListener.java?rev=736186&r1=736185&r2=736186&view=diff
==============================================================================
--- ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/DefaultErrorListener.java (original)
+++ ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/DefaultErrorListener.java Tue Jan 20 17:31:33 2009
@@ -17,20 +17,20 @@
return _errors;
}
- public void reportRecognitionError(String[] tokens, int line, String message, RecognitionException e) {
- _errors.add(new Error(tokens, line, message, e));
- System.err.println("line " + line + ": " + message);
+ public void reportRecognitionError(int line, int column, String message, RecognitionException e) {
+ _errors.add(new Error(line, column, message, e));
+ System.err.println(line + ":" + column + " " + message);
}
public class Error {
- public String tokens[];
public int line;
+ public int column;
public String message;
public RecognitionException e;
- public Error(String[] tokens, int line, String message, RecognitionException e) {
- this.tokens = tokens;
+ public Error(int line, int column, String message, RecognitionException e) {
this.line = line;
+ this.column = column;
this.message = message;
this.e = e;
}
Added: ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/ErrorMessageBuilder.java
URL: http://svn.apache.org/viewvc/ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/ErrorMessageBuilder.java?rev=736186&view=auto
==============================================================================
--- ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/ErrorMessageBuilder.java (added)
+++ ode/sandbox/simpel/src/main/java/org/apache/ode/simpel/util/ErrorMessageBuilder.java Tue Jan 20 17:31:33 2009
@@ -0,0 +1,27 @@
+package org.apache.ode.simpel.util;
+
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.NoViableAltException;
+import org.antlr.runtime.MismatchedTokenException;
+import org.antlr.runtime.EarlyExitException;
+
+/**
+ * ANTLR-specific error message builder. Analyzes parser exceptions raised by ANTLR and
+ * produces a user-friendly error message for SimPEL.
+ */
+public class ErrorMessageBuilder {
+
+ public static String msg(RecognitionException e, String[] tokenNames, String paraphrase) {
+ String msg = null;
+ if (e instanceof NoViableAltException) {
+ msg = "Syntax error, unexpected token " + tokenNames[e.token.getType()];
+ } else if (e instanceof MismatchedTokenException) {
+ MismatchedTokenException mte = (MismatchedTokenException) e;
+ msg = "Syntax error, unexpected token " + tokenNames[e.token.getType()] + ", expecting " + tokenNames[mte.expecting];
+ } else if (e instanceof EarlyExitException) {
+ msg = "At least one element is required at " + tokenNames[e.token.getType()];
+ }
+ if (msg != null && paraphrase != null) msg = msg + " " + paraphrase;
+ return msg;
+ }
+}
Modified: ode/sandbox/simpel/src/test/java/org/apache/ode/simpel/SimPELCompilerTest.java
URL: http://svn.apache.org/viewvc/ode/sandbox/simpel/src/test/java/org/apache/ode/simpel/SimPELCompilerTest.java?rev=736186&r1=736185&r2=736186&view=diff
==============================================================================
--- ode/sandbox/simpel/src/test/java/org/apache/ode/simpel/SimPELCompilerTest.java (original)
+++ ode/sandbox/simpel/src/test/java/org/apache/ode/simpel/SimPELCompilerTest.java Tue Jan 20 17:31:33 2009
@@ -137,7 +137,7 @@
private static class TestErrorListener implements ErrorListener {
public StringBuffer messages = new StringBuffer();
- public void reportRecognitionError(String[] tokens, int line, String message, RecognitionException e) {
+ public void reportRecognitionError(int line, int column, String message, RecognitionException e) {
messages.append(" - line ").append(line).append(": ").append(message).append("\n");
}
}