[antlr-interest] antlr should throw NoViableAltException
femto gary
femtowin at gmail.com
Sun Apr 15 03:05:32 PDT 2007
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).
More information about the antlr-interest
mailing list