【问题标题】:ANTLR C# 4 Grammar - PrecedenceANTLR C# 4 语法 - 优先级
【发布时间】:2015-06-01 08:03:10
【问题描述】:

我有下面的语法(为演示而简化),但在与逻辑运算符相关的特定情况下我遇到了问题。

除了逻辑运算符在我引用的标识符内的情况外,我测试的所有内容都有效。例如这有效:

@M = "ABC12345"

但这不是:

@M = "ABC12OR345"

字符串中的 OR 会导致以下错误

外部输入 'OR' 期望 {'"", LOWCHAR

我不知道如何获得正确的优先级。

谢谢

            grammar PRDL;

            options
            {
                    language=CSharp;
            }

            statement
                : expression ( logicalOperator expression )*
                ;

            logicalOperator
                : logicalOR | logicalAND
                ;

            logicalOR
                : OR
                ;

            logicalAND
                : AND
                ;

            expression
                : mVar
                | nVar
                | parenStatement
                | notExpression
                ;

            parenStatement
                : LPAREN statement RPAREN
                ;

            notExpression
                : NOT expression
                ;

            mVar
                : M equalityOperator quotedIdentifier
                ;

            nVar
                : N equalityOperator quotedIdentifier
                ;

            equalityOperator
                    : EQUAL
                    ;

            quotedIdentifier
                : '"' identifier '"'
                ;

            identifier
                : (HIGHCHAR | LOWCHAR | DIGIT)+
                ;


            // ============  Lexer Defintions  ========================

            // OPERATORS

            NOT_ALLOWED : '*' | '/' | '+' | '-' | '#' | '$' | '%' | '^';

            EQUAL       : '=';

            COMMA       : ',';

            LPAREN      : '(';

            RPAREN      : ')';

            LPARENSQ    : '[';

            RPARENSQ    : ']';

            OR          : ('OR' | 'or' | '||');

            AND         : ('AND' | 'and' | '&&');

            NOT         : ('NOT' | 'not' | '!') ;

            M               : '@M';

            N               : '@N';

            LOWCHAR     : 'a'..'z';

            HIGHCHAR    : 'A'..'Z';

            DIGIT       : '0'..'9';


            // Whitespace -- ignored
            WS          : [ \n\t\r\f]+ -> skip;

【问题讨论】:

    标签: antlr grammar


    【解决方案1】:

    你把词法分析器和解析器之间的栏放在错误的地方......

    quotedIdentifier
        : '"' identifier '"'
        ;
    
    identifier
        : (HIGHCHAR | LOWCHAR | DIGIT)+
        ;
    

    现在,每一个字母都变成了一个标记。这不会很好地工作,就像你看到的那样,因为你得到的错误。

    这两个解析器规则实际上应该是词法分析器规则:

    QUOTED_IDENTIFIER
        : '"' (HIGHCHAR | LOWCHAR | DIGIT)+ '"'
        ;
    
    IDENTIFIER
        : (HIGHCHAR | LOWCHAR | DIGIT)+
        ;
    

    并且HIGHCHARLOWCHARDIGIT 应该是片段,以防止在单个字符上获得不同的令牌类型:

    fragment LOWCHAR     : 'a'..'z';
    fragment HIGHCHAR    : 'A'..'Z';
    fragment DIGIT       : '0'..'9';
    

    使用这样的词法分析器,每个标识符都会得到一个标记,这对于解析来说要好得多。

    而且,像这样的规则几乎没用:

    equalityOperator
            : EQUAL
            ;
    

    因为它只是用解析器规则为词法分析器规则别名。

    【讨论】:

    • 嗨卢卡斯,感谢您的回复。根据您的信息,我尝试了几种变体,但仍然存在问题。
    • 抱歉,按回车键没有及时返回。我没有提到的一件事是我正在使用侦听器,因此我在解析器中有更多规则(例如 public override void ExitQuotedIdentifier ...)。在解析时,我正在构建一个内部列表,稍后我可以将实际值应用于变量并评估真/假条件。看来我需要做更多的阅读才能更好地理解使用这个版本的 antlr - 与我 8 或 10 年前使用的版本有些不同。
    • 好的,我明白了。通过更改:标识符:(HIGHCHAR | LOWCHAR | DIGIT)+;为此:标识符:IDENTIFIER+;然后将 IDENTIFIER 放在词法分析器中,如下所示: IDENTIFIER : (HIGHCHAR | LOWCHAR | DIGIT)+;我能够让事情正常进行。谢谢,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-12
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多