开发者

Problem with an antlr grammar

开发者 https://www.devze.com 2023-03-10 17:31 出处:网络
I\'m trying to figure out the grammar for the following syntax. foreach where x = 1 when some_variable = true

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:

Problem with an antlr grammar

larger image


2

Source:

foreach
    where x = 1
        // main block is blank, do nothing
    when none
        print 'none'
endfor

Parse tree:

Problem with an antlr grammar


3

Source:

foreach
    where x = 1 when none = 2
        print 'none'
    // exceptional block is blank
endfor

Parse tree:

Problem with an antlr grammar


0

精彩评论

暂无评论...
验证码 换一张
取 消