在ANTLR词法分析器规则中强制替代

时间:2012-08-07 03:00:09

标签: antlr antlr3 lexer

我尝试使用ANTLR编写一个上下文相关的词法分析器规则但不能让它做我需要的事情。该规则需要根据规则开头的字符匹配2个备选项中的1个。下面是问题的大大简化版本。

这个示例语法:

lexer grammar X;

options
{
  language = C;
}

RULE :
  SimpleIdent {ctx->someFunction($SimpleIdent);}
  (
    {ctx->test != true}?
     //Nothing
  | {ctx->test == true}?
     SLSpace+ OtherText
  )
  ;

fragment SimpleIdent  : ('a'..'z' | 'A'..'Z' | '_')+;
fragment SLSpace    : ' ';
fragment OtherText :  (~'\n')* '\n';

如果 ctx-> test 为false,我希望lexer退出此规则,忽略SimpleIdent之后的任何字符。不幸的是,ANTLR将在测试谓词之前测试SimpleIdent 之后的字符,因此如果那里有空格,它将始终采用第二种选择。这清楚地显示在C代码中:

// X.g:10:3: ({...}?|{...}? ( SLSpace )+ OtherText )
{
    int alt2=2;
    switch ( LA(1) )
    {
    case '\t':
    case ' ':
        {
            alt2=2;
        }
        break;

    default:
        alt2=1;
    }

    switch (alt2)
    {
    case 1:
        // X.g:11:5: {...}?
        {
            if ( !((ctx->test != true)) )
            {
                    //Exception
            }

        }
        break;
    case 2:
        // X.g:13:5: {...}? ( SLSpace )+ OtherText
        {
            if ( !((ctx->test == true)) )
            {
                   //Exception
            }

如何强制ANTLR在运行时在词法分析器中获取特定路径?

1 个答案:

答案 0 :(得分:2)

使用门控语义谓词而不是验证语义谓词 1 。如果表达式验证为false验证谓词将引发异常。让“Nothing alternative”成为最后匹配的。

此外,OtherText也与SLSpace匹配,使SLSpace+ OtherText模糊不清。只需从中移除SLSpace+,或让OtherText' '以外的其他内容开头。

我不熟悉C目标,但是这个Java演示应该适用于C(当然,在翻译Java代码之后):

grammar T;

rules
 : RULE+ EOF
 ;

RULE
 : SimpleIdent {boolean flag = $SimpleIdent.text.startsWith("a");}
   ( {!flag}?=> OtherText
   |            // Nothing
   )
 ;

Spaces 
 : (' ' | '\t' | '\r' | '\n')+ {skip();}
 ;

fragment SimpleIdent : ('a'..'z' | 'A'..'Z' | '_')+;
fragment OtherText   : (~'\n')* '\n';

如果您现在解析输入:

abcd efgh ijkl mnop
bbb aaa ccc ddd

您将获得以下解析:

enter image description here

即。只要RULE以小写"a"开头,它就不会一直匹配到行尾。

1 What is a 'semantic predicate' in ANTLR?