[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