[antlr-interest] ANTLR bug??? ReportError not called on "NonViableAltException"

Frank Smith fasmith718 at gmail.com
Tue Aug 7 20:34:03 PDT 2007


Hi all.  I recently uncovered a problem with my parser where i'm doing
something illegal and ReportError is never called.  ANTLRworks' interpreter
window shows that there is a Nonviable alt, but the breakpoint i put in
RecognitionError is never reached on code execution.

This is a big problem because I am trying to make my language fail
immediately on parse errors, but I can't do this if they are never thrown by
the generated antlr code!

Here is the sample program - you should not be able to put a statement
outside of a function :
fun wave main()
    print "main";
end fun
x = 1;

yet this compiles without reporting an error.  However, putting it in
ANTLRWorks' interpreter shows it to be wrong (which is what i want, darn
it!)

Here is my entire .g file.  If someone could just past it into their
antrlworks and explain this discrepancy i would be highly highly
appreciative.  This is for a project and I need to know if I should pass
this off as a bug in ANTRL generated code... :-/

Thanks a million times in advance!!!
     Frank

grammar ASML;

options{output = AST;
 ASTLabelType=CommonTree;}

tokens{ //tokens to act as artificial roots for structures wo/keywords or
operators
    DECLRT;
    PARAMRT;
    CALLRT;
    BLOCKRT;
}
@header {package asml;}
@members{
    public boolean hasError = false;

    public void setHasError(boolean aHasError){
        hasError = aHasError;
    }

@Override
    public void reportError(RecognitionException e){
        super.reportError(e);
        hasError = true;
    }

    @Override
    protected void mismatch(IntStream input, int ttype, BitSet follow)
        throws RecognitionException{
        throw new MismatchedTokenException(ttype, input);
    }

    @Override
    public void recoverFromMismatchedSet(IntStream input,
        RecognitionException e, BitSet follow) throws RecognitionException{
        throw e;
    }
}

@rulecatch {
    catch (RecognitionException e) {
        reportError(e);
        throw e;
    }
}

@lexer::header {package asml;}
@lexer::members{
    public String stripEscapeChars(String in){
        String newStr = in.replaceAll("\\\\\"", "\"");

            char[] formSlashes = new char[newStr.length()];
            int charsAdded = 0;
            for(int i=0; i<newStr.length(); i++){
                if((newStr.charAt(i) == '\\') &&
                        (newStr.charAt(i+1) == '\\')){
                    formSlashes[charsAdded++] = newStr.charAt(++i);

                }//end if
                else{
                    formSlashes[charsAdded++] = newStr.charAt(i);

                }//end else
            }//end for
            newStr = new String(formSlashes);
            newStr = newStr.substring(0, charsAdded);

            return newStr;
    }
}

program    :    (include_stmt)*(fun_decl)+;

include_stmt
    :     INCLUDE^ STRING SEMI!;
fun_decl:    FUN TYPE ID LPARENS params? RPARENS block FUN -> ^(FUN TYPE ID
params? block);

block    :    stmt* END     -> ^(BLOCKRT stmt*);

//stmts     :    (stmt stmts)?;
stmt    :    decl SEMI!
    |    expr SEMI!
    |    if_stmt
    |    while_stmt
    |    for_stmt
    |    print_stmt
    |    return_stmt;

if_stmt    :    IF^ LPARENS! expr RPARENS! block (ELSE! block)? IF!;

for_stmt:    FOR^ LPARENS! expr SEMI! expr SEMI! expr RPARENS! block FOR!;
while_stmt
    :    WHILE^ LPARENS! expr RPARENS! block WHILE!;
return_stmt
    :    RETURN^ expr SEMI!;
print_stmt:    PRINT^ expr SEMI!;


params    :    param (COMMA! params)?;
param    :    TYPE ID        -> ^(PARAMRT TYPE ID);
decl    :
    TYPE ID (ASSIGN expr)?    -> ^(DECLRT TYPE ID expr?);

expr_list
    :    expr (COMMA! expr_list)?;
expr    :    log_expr (ASSIGN^ expr)?;
log_expr:    rel_expr (LOG_OP^ rel_expr)*;
rel_expr:    add_expr (REL_OP^ add_expr)*;
add_expr:    mult_expr ((ADD_OP^ | SUB_OP^) mult_expr)*;
mult_expr
    :    unary_expr ((MULT_OP^ | DIV_OP^ | MOD_OP^) unary_expr )*;
unary_expr
    :    ('!'^ | '-'^ | AMPLOF^)? at_expr;
at_expr    :    fun_call (AT^ fun_call (TO! fun_call)?)*;

fun_call:    ID LPARENS expr_list? RPARENS     -> ^(CALLRT ID expr_list?)
        | top_expr            -> top_expr;

top_expr:    LPARENS! expr RPARENS! | NUMBER | STRING | ID;



COMMENT    :    '/*' (options{greedy = false;}: .)* '*/'{skip();};

ADD_OP    :    '+';
SUB_OP    :    '-';
MULT_OP    :     '*';
DIV_OP    :    '/';
MOD_OP    :    '%';
ASSIGN    :    '=';

REL_OP    :    '<' | '>' | '<=' | '>=' | '==' | '!=';
LOG_OP    :    '||' | '&&';



LPARENS    :     '(';
RPARENS    :    ')';
COMMA    :    ',';
SEMI    :    ';';

fragment LETTER
    :    ('a'..'z')|('A'..'Z');
fragment DIGIT
    :    ('0'..'9');
fragment INTEGER
    :    (DIGIT)+;
fragment FRAC
    :    '.'(INTEGER);

/*CONSTANT:    NUMBER;*/

NUMBER     :    INTEGER /*set type to int*/
        ('Hz'/*set type to freq*/
        |'ms'/*set type to time*/)?
    | INTEGER? FRAC /*set type to float*/
        ('a' /*set type to ampl*/
        |'Hz'/*set type to freq*/
        |'ms'/*set type to time*/)?;


TYPE    :    'ampl'|'float'|'freq'|'int'|'time'|'wave';

/*fragment STR_QUOTE
    :    '\\' '"' { setText("\"");};
fragment STR_BACKSLASH
    :    '\\' '\\' { setText("\\");};*/
fragment STR_CONTENT
    :    (('\\''"') | ('\\''\\') | ~('"'|'\\'))*;
STRING    :    '"' t = STR_CONTENT '"'
{setText(stripEscapeChars($STR_CONTENT.text));};

WS    :    (' ' | '\t' | '\n' | '\r')+ {skip();};


AMPLOF    :    'amplof';
AT    :    'at';
ELSE    :     'else';
END    :    'end';
FOR    :    'for';
FUN    :    'fun';
IF    :    'if';
INCLUDE    :    'include';
PRINT    :    'print';
RETURN    :    'return';
TO    :    'to';
WHILE     :    'while';

ID    :     (LETTER|'_')(LETTER|'_'|DIGIT)*;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org/pipermail/antlr-interest/attachments/20070807/8eb0f023/attachment.html 


More information about the antlr-interest mailing list