我有下面的语法(简化为演示),我在与逻辑运算符相关的特定情况下遇到问题。
我测试的所有内容都有效,除非逻辑运算符在我引用的标识符中。例如,这有效:
@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;
答案 0 :(得分:1)
你把lexer和parser之间的栏放在错误的位置......
quotedIdentifier
: '"' identifier '"'
;
identifier
: (HIGHCHAR | LOWCHAR | DIGIT)+
;
现在,每个字母都成为一个标记。这样做不会很好,就像你可以看到的那样,因为你得到的错误。
这两个解析器规则实际上应该是词法规则:
QUOTED_IDENTIFIER
: '"' (HIGHCHAR | LOWCHAR | DIGIT)+ '"'
;
IDENTIFIER
: (HIGHCHAR | LOWCHAR | DIGIT)+
;
HIGHCHAR
,LOWCHAR
和DIGIT
应该是片段,以防止在单个字符上获得不同的令牌类型:
fragment LOWCHAR : 'a'..'z';
fragment HIGHCHAR : 'A'..'Z';
fragment DIGIT : '0'..'9';
使用这样的词法分析器,每个标识符将获得一个标记,这对解析来说要好得多。
此外,这些规则几乎没用:
equalityOperator
: EQUAL
;
因为它只是使用解析器规则对词法分析器规则进行别名化。