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");
         }
     }