antlr语法的问题

antlr语法的问题,antlr,antlr3,Antlr,Antlr3,我试图找出以下语法的语法 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 b

我试图找出以下语法的语法

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
我的语法看起来像:

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
但是当主块为空时,例如

foreach
    where x = 1
        // main block is blank, do nothing
    when none
        print 'none'
endfor
在这种情况下,我的语法认为“when none”是“where x=1”的第二个从句,这不是我所期望的

也考虑以下情况:

foreach
    where x = 1 when none = 2
        print 'none'
    // exceptional block is blank
endfor
其中“none”可以是一个变量,“none=2”应该匹配“test”规则,因此它是“Where…when…”的一部分

但是,当表达式语句中没有“none”时,我希望“when none”与“foreach”匹配,而不是前面的“where”。我如何修改语法才能做到这一点


对不起,这个标题很烂,但我不知道如何用几句话来描述这个问题。任何帮助都将不胜感激。

解析器由以下ANTLR语法生成:

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();}
  ;
根据示例生成以下3个解析树:


1. 资料来源:

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
foreach
    where x = 1
        // main block is blank, do nothing
    when none
        print 'none'
endfor
foreach
    where x = 1 when none = 2
        print 'none'
    // exceptional block is blank
endfor
解析树:


2. 资料来源:

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
foreach
    where x = 1
        // main block is blank, do nothing
    when none
        print 'none'
endfor
foreach
    where x = 1 when none = 2
        print 'none'
    // exceptional block is blank
endfor
解析树:


3. 资料来源:

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
foreach
    where x = 1
        // main block is blank, do nothing
    when none
        print 'none'
endfor
foreach
    where x = 1 when none = 2
        print 'none'
    // exceptional block is blank
endfor
解析树:



为什么允许
none
同时作为关键字和标识符?你让自己很难解析这些源。我还想知道blockstmt可能是什么:你能发布你的全部语法吗?@Bart我没有设计那种语言(实际上它是genexus的脚本语言,一种神秘的工具),所以我不得不接受其中所有棘手的部分。虽然理论上,
none
是一个有效的变量名,但我认为忽略这个情况也是可以接受的,因为我想人们几乎不会做这样疯狂的事情。。。整个语法有点大,大多数规则与此问题无关。“我会尽量写一个简单的语法。”肖恩,啊,我明白了。您是自己提取这些规则的,还是根据genexus制造商的正式(BNF)规范创建的?如果是后者,你能发布一个到规范的链接吗?谢谢@巴特:有一个维基,在那里可以找到大多数BNF。基本上,我是根据这些信息提取规则的。但它们并不完整,还有一些未记录的语法,这是我在解析几个实际项目时遇到的。单击该链接时,我没有看到BNF规范。在我看来,你发布的更多的是函数/方法列表。更像是一个API。通过使用搜索,我遇到了一个没有答案的问题,所以我猜这种语言是专有的,如果不熟悉这种语言,就很难为它编写正确的语法。因为我对此一无所知,我想我帮不了什么忙。非常感谢。我意识到问题可能在于blockstmt部分,我正试图弄清楚这一部分,但有许多复杂的规则使得它很难在AntlWorks中顺利运行。语法在很大程度上依赖于回溯,我也在尝试删除回溯。我会做一个更清晰的版本,然后编辑这个问题。很抱歉,我的回复太晚了,被其他作品抓住了。@Shaung,当你的语法中只有一个谓词时,不要依赖ANTLRWorks的解释器。您可能看到的解析树很可能不是由语法生成的解析器导致的正确树。