[antlr-interest] How to use predicate or workaround the bug ?
Ilia Kantor
ilia at obnovlenie.ru
Wed Jan 3 13:49:32 PST 2007
Thanks for answering, Ter. The book is going to be a must-read for me =).
Still confused, what's up with predicate:
curly_block
:
{true}? LCURL exprs? RCURL -> TEXT[$LCURL] exprs? TEXT[$RCURL] |
LCURL exprs? RCURL -> exprs?
The predicate does not reference anything, it's a plain "true" value.
How should I change it to work ?
The ultimate question is how to make 'input.index()==0' to work, but 'true'
fails to compile also..
> From the book:
>
> Another limitation on semantic predicates is that they should not
> reference local variables, parameters, or anything else that is not
> visible to all rules just in case they are hoisted out of one rule
> into another's prediction DFA. If you are positive that the predicate
> will not be hoisted out of the rule, you can use a parameter, for
> example, to alter prediction in a rule:
>
> method[boolean allowConcrete]
>
> : {allowConcrete}?=> methodHead body
> :
> | methodHead ';'
>
> ;
>
> Workaround is a field or dynamically scope var.
>
> Ter
>
> On Jan 2, 2007, at 6:34 AM, Ilia Kantor wrote:
> > I'm using antlr 3b6 build from Tue Jan 2 14:28:20 UTC 2007. Also
> > tried 3b5.
> >
> > Trying to make use of predicate, but fail.. Is there a workaround ?
> >
> > Here I try to rewrite
> > 'LCURL exprs? RCURL' into 'TEXT exprs? TEXT' in common case and strip
> > LCURL/RCURL if this LCURL/RCURL block is outmost, that is: if LCURL
> > is first
> > token.
> >
> > ==================== rule with predicate=====
> > curly_block
> >
> > {input.index()==0}? LCURL exprs? RCURL -> exprs? |
> > LCURL exprs? RCURL -> TEXT[$LCURL] exprs? TEXT[$RCURL]
> > ===================== error ===========
> >
> >
> > ANTLR Parser Generator Version 3.0b6 (??) 1989-2007
> > Exception in thread "main" java.lang.StackOverflowError
> > at java.util.HashMap$KeyIterator.<init>(HashMap.java:875)
> > at java.util.HashMap$KeyIterator.<init>(HashMap.java:875)
> > at java.util.HashMap.newKeyIterator(HashMap.java:889)
> > at java.util.HashMap$KeySet.iterator(HashMap.java:921)
> > at java.util.HashSet.iterator(HashSet.java:154)
> > at
> > org.antlr.analysis.DFAState.getGatedPredicatesInNFAConfigurations
> > (DFAState.java:695)
> > at
> > org.antlr.codegen.CodeGenerator.canGenerateSwitch
> > (CodeGenerator.java:1119)
> > at
> > org.antlr.codegen.ACyclicDFACodeGenerator.walkFixedDFAGeneratingStateM
> > achine(ACyclicDFACodeGenerator.java:72)
> > at
> > org.antlr.codegen.ACyclicDFACodeGenerator.walkFixedDFAGeneratingStateM
> > achine(ACyclicDFACodeGenerator.java:146)
> > =..................... the latest line repeats many times ..........=
> >
> >
> >
> > ======= Full grammar ===========
> >
> >
> > /* putting this to tokens { .. } causes antlrworks bugs like "...no
> > lexer rule
> > for IF..." */
> > IF : {false}? .;
> > THEN : {false}? .;
> > ELSE : {false}? .;
> > EVAL : {false}? .;
> > TEXT : {false}? .;
> > RULE_PROPERTY : {false}? .;
> > RULE_PART : {false}? .;
> >
> > LCURL : '{';
> > RCURL : '}';
> >
> > RULE_CALL
> >
> > : '#';
> >
> > CONTROL
> >
> > : '~';
> >
> > SEMI: ';';
> >
> > DOT : '.';
> >
> > MINUS
> >
> > : '-';
> >
> > GT : '>';
> >
> > SPECIAL_CHAR
> >
> > : '`' | '!' | '@' | '$' | '%' | '^' | '&' | '*' | '(' | ')' |
> >
> > '+' | '=' | '[' | ']' | ':' | '\'' | '"' | '\\' | '|' | ',' | '<' |
> > '/' | '?';
> >
> >
> >
> > fragment WS_CHAR :
> > (' '|'\r'|'\t'|'\u000C'|'\n' )
> > ;
> >
> > WS : WS_CHAR+;
> >
> > // not SPECIAL_CHAR not WS_CHAR
> > WORD:
> > {
> > // check if previous token was CONTROL
> > Boolean afterControl = input.index()>0 && input.LT(-1)=='~';
> > }
> > (~ ('`' | '!' | '@' | '$' | '%' | '^' | '&' | '*' | '(' | ')' |
> > '+' | '=' | '[' | ']' | ':' | '\'' | '"' | '\\' | '|' | ',' | '<'
> >
> > | '/' | '?'
> > |
> > | '{'
> > | '~'
> > | '}'
> > | '#'
> > | ';'
> > | '.'
> > | '-'
> > | '>'
> > | ' '|'\r'|'\t'|'\u000C'|'\n' ) )+
> >
> > {
> > if (afterControl) {
> > // output WORDs as commands if after control
> > if (getText().equalsIgnoreCase("if")) $type=IF;
> > else if (getText().equalsIgnoreCase("else")) $type=ELSE;
> > else if (getText().equalsIgnoreCase("then")) $type=THEN;
> > }
> > }
> > ;
> >
> >
> >
> > document
> >
> > : exprs;
> >
> > exprs:
> > (expr)+
> > ;
> >
> >
> > expr:
> > (
> > expr_no_semi -> expr_no_semi |
> > SEMI -> TEXT[$SEMI]
> > )
> > ;
> >
> > exprs_no_semi
> >
> > : (expr_no_semi)+
> >
> > ;
> >
> >
> > expr_no_semi
> >
> > (expr_simple) | (curly_block)
> > ;
> >
> >
> >
> > exprs_simple
> >
> > : (expr_simple)+
> >
> > ;
> >
> > /* expression without curl at start and ; */
> > expr_simple
> >
> > command
> >
> > | rule_call
> > | text
> >
> > ;
> >
> >
> > command:
> > command_eval |
> > command_if
> > ;
> >
> >
> > command_if
> >
> > CONTROL IF LCURL exprs? command_if_part_then
> > command_if_part_else?
> > RCURL ->
> > ^(IF exprs? command_if_part_then command_if_part_else?)
> > ;
> >
> >
> > command_if_part_else:
> > CONTROL ELSE exprs? -> ^(ELSE exprs?)
> > ;
> >
> > command_if_part_then
> >
> > : CONTROL THEN exprs? -> ^(THEN exprs?)
> >
> > ;
> >
> >
> >
> > command_eval:
> > CONTROL LCURL exprs? RCURL -> ^(EVAL exprs?)
> > ;
> >
> >
> >
> > rule_call: RULE_CALL WORD -> ^(RULE_CALL WORD) |
> > RULE_CALL LCURL WORD rule_long_def_part* RCURL -> ^(RULE_CALL WORD
> > rule_long_def_part*)
> > ;
> >
> > rule_long_def_part
> >
> > : MINUS GT WORD -> ^(RULE_PROPERTY WORD) |
> >
> > DOT WORD -> ^(RULE_PART WORD)
> > ;
> >
> >
> > curly_block
> >
> > {true}? LCURL exprs? RCURL -> exprs?
> >
> > | LCURL exprs? RCURL -> TEXT[$LCURL] exprs? TEXT[$RCURL]
> >
> > ;
> >
> > text:
> > DOT -> TEXT[$DOT] | MINUS -> TEXT[$MINUS] | WORD -> TEXT[$WORD]
> >
> > | WS -> TEXT[$WS] | GT -> TEXT[$GT] | SPECIAL_CHAR -> TEXT
> >
> > [$SPECIAL_CHAR]
> > ;
More information about the antlr-interest
mailing list