[antlr-interest] antlr should throw NoViableAltException

femto gary femtowin at gmail.com
Sun Apr 15 05:11:39 PDT 2007


also, generating parser will also produce the following warning:
[20:08:36] warning(200): Rubyv3.g:101:32: Decision can match input
such as "SEMI" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input

but for the grammar:
statement
	:	expression (modifier_line)* SEMI? -> ^(STATEMENT expression
(modifier_line)*)
	|       SEMI!
	;
input SEMI shouldn't cause an ambiguity, because expression can't be empty,
so either match the alt1 or alt2, why does it will report that warning.
Anybody has any ideas? Thanks.

On 4/15/07, femto gary <femtowin at gmail.com> wrote:
> Hi all, for following grammar,
>
> grammar Rubyv3;
>
> options {
>         output=AST;
> }
> tokens {
>         // 'imaginary' tokens
>         STATEMENT_LIST;
>         STATEMENT;
>         RPAREN_IN_METHOD_DEFINATION;
>         BODY;
>         CALL;
>         ARG;
>         //COMPSTMT;
>         SYMBOL;
>         BLOCK;
>         MULTIPLE_ASSIGN;
>         MULTIPLE_ASSIGN_WITH_EXTRA_COMMA;
>         BLOCK_ARG;
>         BLOCK_ARG_WITH_EXTRA_COMMA;
>         MRHS;
>         NESTED_LHS;
>         SINGLETON_METHOD;
>         STRING;
> }
>
> /*@rulecatch {
> catch (RecognitionException e) {
> throw e;
> }
> }*/
>
> @header {
> package com.xruby.compiler.parser;
> }
> @lexer::header {
> package com.xruby.compiler.parser;
> }
>
> @members{
>         private int can_be_command_ = 0;
>
>         protected void enterScope()     {assert(false);}
>         protected void enterBlockScope()        {assert(false);}
>         protected void leaveScope()     {assert(false);}
>         protected void addVariable(Token id)    {assert(false);}
>         protected void setIsInNestedMultipleAssign(boolean v)   {assert(false);}
>         protected void
> tellLexerWeHaveFinishedParsingMethodparameters()        {assert(false);}
>         protected void tellLexerWeHaveFinishedParsingSymbol()   {assert(false);}
>         protected void
> tellLexerWeHaveFinishedParsingStringExpressionSubstituation()   {assert(false);}
>         protected void
> tellLexerWeHaveFinishedParsingRegexExpressionSubstituation()    {assert(false);}
>         protected void
> tellLexerWeHaveFinishedParsingHeredocExpressionSubstituation()  {assert(false);}
>
>
> }
>
> @lexer::members
> {
>         //The following methods are to be implemented in the subclass.
>         //In fact they should be 'abstract', but antlr refuses to generate
>         //abstract class. We can either insert 'abstract' keyword manually
>         //after the lexer is generated, or simply use assert() to prevent
>         //these function to run (so you have to overide them). I choosed
>         //the later approach.
>         protected boolean expectOperator(int k) throws
> Exception               {assert(false);return false;}
>         protected boolean expectUnary()  throws
> Exception                       {assert(false);return false;}
>         protected boolean expectHash()                                  {assert(false);return false;}
>         protected boolean expectHeredoc()                               {assert(false);return false;}
>         protected boolean expectLeadingColon2()         {assert(false);return false;}
>         protected boolean expectArrayAccess()                           {assert(false);return false;}
>         protected boolean lastTokenIsDotOrColon2()              {assert(false);return false;}
>         protected boolean lastTokenIsSemi()                             {assert(false);return false;}
>         protected boolean
> lastTokenIsKeywordDefOrColonWithNoFollowingSpace()                      {assert(false);return
> false;}
>         protected boolean
> lastTokenIsColonWithNoFollowingSpace()                  {assert(false);return false;}
>         protected boolean shouldIgnoreLinebreak()                       {assert(false);return false;}
>         protected int trackDelimiterCount(char next_char, char delimeter, int
> delimeter_count)        {assert(false);return 0;}
>         protected boolean isDelimiter(String next_line, String
> delimiter)      {assert(false);return false;}
>         protected boolean isAsciiValueTerminator(char
> value)  {assert(false);return false;}
>         protected boolean justSeenWhitespace()  {assert(false);return false;}
>         protected void setSeenWhitespace()                      {assert(false);}
>         protected boolean expressionSubstitutionIsNext()        throws
> Exception       {assert(false);return false;}
>         protected boolean spaceIsNext() throws Exception        {assert(false);return false;}
>         protected void setCurrentSpecialStringDelimiter(char delimiter, int
> delimiter_count)        {assert(false);}
>         protected void updateCurrentSpecialStringDelimiterCount(int
> delimiter_count)        {assert(false);}
> }
>
> program
>                 :       statement_list
>                 ;
>
> statement_list
>                 :       statement* -> ^(STATEMENT_LIST statement*)
>                         ;
>
> /*terminal
>                 :       SEMI!
>                 |       LINE_BREAK!
>                 ;*/
> statement
>         :       expression (modifier_line)* SEMI? -> ^(STATEMENT expression
> (modifier_line)*)
>         |       SEMI!
>         ;
>
> modifier_line
>         :(IF_MODIFIER|UNLESS_MODIFIER|WHILE_MODIFIER|UNTIL_MODIFIER|RESCUE_MODIFIER)^
> expression
> /*statement
>                 :       body=statementWithoutModifier
>                                                                         (IF_MODIFIER^           if_condition=expression {#statement =
> #(#[LITERAL_if, 'if'], if_condition, #(#[COMPSTMT, 'COMPSTMT'],
> #body));}
>                                                                         |UNLESS_MODIFIER^       unless_condition=expression     {#statement =
> #(#[LITERAL_unless, 'unless'], unless_condition, #(#[COMPSTMT,
> 'COMPSTMT'], #body));}
>                                                                         |WHILE_MODIFIER^        while_condition=expression      {#statement =
> #(#[LITERAL_while, 'while'], while_condition, #(#[COMPSTMT,
> 'COMPSTMT'], #body));}
>                                                                         |UNTIL_MODIFIER^        until_condition=expression      {#statement =
> #(#[LITERAL_until, 'until'], until_condition, #(#[COMPSTMT,
> 'COMPSTMT'], #body));}
>                                                                         |RESCUE_MODIFIER^       rescue_condition=expression     {#statement =
> #(#[LITERAL_rescue, 'rescue'], rescue_condition, #(#[COMPSTMT,
> 'COMPSTMT'], #body));}
>                                                                         )**/
>                 ;
> IF_MODIFIER     :  'if';
> UNLESS_MODIFIER :  'unless';
> WHILE_MODIFIER  :  'while';
> UNTIL_MODIFIER  :  'until';
> RESCUE_MODIFIER :  'resuce';
>
> SEMI    :';'
>         ;
>
> LINE_BREAK
>         :'\r'? '\n'{skip();}
>         ;
> //OMIT_LINE_BREAK
> //      :       LINE_BREAK* {skip();}
> //      ;
> //emptyable_expression
> //      :       expression|;
> expression
>         :       'expression0' | 'expression1' | 'expression2';
>
> WS      :       (' ' | '\t') { skip(); }
>         ;
> ID      :       ('a'..'z' | 'A'..'Z') (('a'..'z' | 'A'..'Z') | ('0'..'9'))*
>         ;
> ----------------------------------------------------------------------------
> ruby should throw NoViableAltException when meeting input
> "if expression1; ",
> this is the test drive:
>
> package com.xruby.compiler.parser;
>
> import org.antlr.runtime.*;
> import org.antlr.runtime.tree.CommonTree;
>
> import java.io.StringReader;
> import java.io.StringBufferInputStream;
> import java.io.IOException;
>
> import junit.framework.TestCase;
>
> /**
>  * Copyright 2005-2007 femto
>  * Distributed under the GNU General Public License 2.0
>  */
> public class Rubyv3Test extends TestCase {
>     public void test_parse() throws Exception {
>         assert_parse("", "STATEMENT_LIST");
>         assert_parse(";", "STATEMENT_LIST");
>         assert_parse("  ", "STATEMENT_LIST");
>         assert_parse(";\n;\n;\n;\n", "STATEMENT_LIST");
>         assert_parse("expression0 \tif expression1 if expression2; ",
> "(STATEMENT_LIST (STATEMENT expression0 (if expression1) (if
> expression2)))");
>         assert_parse("expression0 \tif\nexpression1 if expression2;",
> "(STATEMENT_LIST (STATEMENT expression0 (if expression1) (if
> expression2)))");
>         assert_parse("expression0 \tif\nexpression1 if expression2",
> "(STATEMENT_LIST (STATEMENT expression0 (if expression1) (if
> expression2)))");
>         assert_parse("expression0 \tif expression1 if expression2\n
> expression0", "(STATEMENT_LIST (STATEMENT expression0 (if expression1)
> (if expression2)) (STATEMENT expression0))");
>         assert_parse("expression0 \tif expression1 if expression2;
> expression0", "(STATEMENT_LIST (STATEMENT expression0 (if expression1)
> (if expression2)) (STATEMENT expression0))");
>         assert_parse("expression0 \tif expression1 if expression2;;
> expression0", "(STATEMENT_LIST (STATEMENT expression0 (if expression1)
> (if expression2)) (STATEMENT expression0))");
>         assert_parse("if expression1; ", "");
>     }
>     public void assert_parse(String text, String expectedTree) throws
> IOException
>
>     {
>         ANTLRInputStream input =
>                 new ANTLRInputStream(new StringBufferInputStream(text));
>
>         Rubyv3Lexer lexer = new Rubyv3Lexer(input);
>         CommonTokenStream tokens = new CommonTokenStream(lexer);
>         Rubyv3Parser parser = new Rubyv3Parser(tokens);
>         Rubyv3Parser.program_return result = null;
>         try {
>             result = parser.program();
>         } catch (NoViableAltException e) {
>             e.printStackTrace();
>         }
>         catch (RecognitionException e) {
>             e.printStackTrace();
>         }
>         assertEquals(expectedTree, ((CommonTree)result.tree).toStringTree());
>         //System.out.println("tree:" +
> ((CommonTree)result.tree).toStringTree());
>     }
>
> }
> //besides, in Antlrworks interpreter mode, it will produce NoViableAltException,
> so I think it is a bug in main program.(antlr should throw Exception,
> but instead
> nothing happened).
>


-- 
Best Regards
XRuby http://xruby.com
femto http://hi.baidu.com/femto


More information about the antlr-interest mailing list