ANTLR C#4语法 - 优先级

时间:2015-03-27 20:57:02

标签: antlr grammar

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

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

@M =" ABC12345"

但这不是:

@M =" ABC12OR345"

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

无关的输入' OR'期待{'"",LOWCHAR< HIGHCAR,DIGIT}

我不知道如何使优先顺序正确。

由于

            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;

1 个答案:

答案 0 :(得分:1)

你把lexer和parser之间的栏放在错误的位置......

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
        ;

因为它只是使用解析器规则对词法分析器规则进行别名化。