I'm trying to figure out the grammar for the following syntax.
foreach
where x = 1 when some_variable = true
where x = 2 when some_variable = false
where y = 0
print z // Main block
when none // optional
print 'not found' // Exception block
endfor
My grammar looks like:
foreach_stmt : 'for' 'each' where_opt* blockstmt* whennone_opt? 'endfor'
;
where_opt : 'where' cond_clause
;
cond开发者_开发百科_clause : test when_opt*
;
when_opt : 'when' test
;
whennone_opt : 'when' 'none' blockstmt*
;
test : or_test
;
// further rules omitted
But when the main block is blank, for example
foreach
where x = 1
// main block is blank, do nothing
when none
print 'none'
endfor
In this case my grammar considers "when none" is a cond_clause to "where x = 1" which is not what I'm expecting.
Also consider the following case:
foreach
where x = 1 when none = 2
print 'none'
// exceptional block is blank
endfor
Where the "none" can be a variable, and "none = 2" should match the "test" rule so it's part of "where...when...".
However when "none" is not in an expression statement, I want "when none" match the "foreach" rather than the previous "where". How can I modify my grammar to do this?
Sorry this title sucks but I don't know how to describe the problem in a few words. Any help would be greatly appreciated.
The parser generated from the following ANTLR grammar:
grammar Genexus;
parse
: foreach_stmt* EOF
;
foreach_stmt
: 'foreach' where_opt* blockstmt* whennone_opt? 'endfor'
;
where_opt
: 'where' cond_clause
;
cond_clause
: test when_opt*
;
when_opt
: 'when' test
;
whennone_opt
: 'when' 'none' blockstmt*
;
test
: identifier '=' atom
;
identifier
: 'none'
| Identifier
;
blockstmt
: 'print' atom
;
atom
: Boolean
| Number
| StringLiteral
| Identifier
;
Number
: '0'..'9'+
;
Boolean
: 'true'
| 'false'
;
Identifier
: ('a'..'z' | 'A'..'Z' | '_')+
;
StringLiteral
: '\'' ~'\''* '\''
;
Ignore
: (' ' | '\t' | '\r' | '\n') {skip();}
| '//' ~('\r' | '\n')* {skip();}
| '/*' .* '*/' {skip();}
;
Produces the following 3 parse-trees from your examples:
1
Source:
foreach
where x = 1 when some_variable = true
where x = 2 when some_variable = false
where y = 0
print z // Main block
when none // optional
print 'not found' // Exception block
endfor
Parse tree:
larger image
2
Source:
foreach
where x = 1
// main block is blank, do nothing
when none
print 'none'
endfor
Parse tree:
3
Source:
foreach
where x = 1 when none = 2
print 'none'
// exceptional block is blank
endfor
Parse tree:
精彩评论