ANTLR4:无法匹配 INT 和 BOOLEAN
ANTLR4: Unable to match INT and BOOLEAN
我编写了以下语法来计算 Java 中的逻辑运算符和关系运算符的组合。
在语法中,我只能对 STRING 类型使用等于运算符 (=
) 而不能对 INT 和 BOOLEAN 类型。有人可以帮我找出问题所在吗?
我可以 ("a" == "b")
而不能 ("a" == 567)
。左手操作数是可变的,我将在运行时替换这些值。
grammar testGrammar;
/*
* Parser rules
*/
conditionalExpression: leftOperand=conditionalExpression operator=LOGICAL_OPERATORS rightOperand=conditionalExpression #LogicalOperators
| '(' conditionalExpression ')' #ParenthesisExpression
| leftOperand=STRING operator=BOOLEAN_RELATIONAL_OPERATORS rightOperand=BOOLEAN #RelationalBooleanOperators
| leftOperand=STRING operator=STRING_RELATIONAL_OPERATORS rightOperand=STRING #RelationalStringOperators
| leftOperand=STRING operator=INT_RELATIONAL_OPERATORS rightOperand=INT #RelationalIntOperators
;
/*
* Lexer rules
*/
STRING: '"'CHAR(CHAR)*'"';
INT:DIGIT+;
BOOLEAN: BOOLEAN_TRUE | BOOLEAN_FALSE;
LOGICAL_OPERATORS: LOGICAL_OR | LOGICAL_AND | LOGICAL_NOT;
STRING_RELATIONAL_OPERATORS: RELATIONAL_EQUALS | RELATIONAL_NOT_EQUAL;
INT_RELATIONAL_OPERATORS: RELATIONAL_EQUALS | RELATIONAL_NOT_EQUAL | RELATIONAL_GREATER_THEN
| RELATIONAL_GREATER_THEN_OR_EQUAL | RELATIONAL_LESS_THEN | RELATIONAL_LESS_THEN_OR_EQUAL;
BOOLEAN_RELATIONAL_OPERATORS: RELATIONAL_EQUALS | RELATIONAL_NOT_EQUAL;
fragment RELATIONAL_EQUALS: '==';
fragment RELATIONAL_NOT_EQUAL: '!=';
fragment RELATIONAL_GREATER_THEN: '>';
fragment RELATIONAL_LESS_THEN: '<';
fragment RELATIONAL_GREATER_THEN_OR_EQUAL: '>=';
fragment RELATIONAL_LESS_THEN_OR_EQUAL: '<=';
fragment LOGICAL_AND: '&&';
fragment LOGICAL_OR: '||';
fragment LOGICAL_NOT: '!';
fragment CHAR: [a-zA-Z_];
fragment DIGIT: [0-9];
fragment BOOLEAN_TRUE: 'true';
fragment BOOLEAN_FALSE: 'false';
您有多个词法分析器规则可以匹配输入 ==
或 !=
。 ANTLR(以及大多数词法分析器生成器)通过首先选择产生最长匹配的规则(在这种情况下所有规则将产生长度为 2 的匹配)然后通过选择一个解决关系来解决词法分析器规则中的歧义这在语法中排在第一位。所以当词法分析器看到 ==
或 !=
时,它总是会生成一个 STRING_RELATIONAL_OPERATORS
.
类型的标记
请注意,词法分析器不关心解析器现在需要哪些标记 - 词法分析器独立于解析器运行。它只查看当前输入和定义的词法分析器规则来决定创建哪种令牌。所以相同的字符序列将始终创建相同类型的令牌。
要修正你的语法,你应该定义你的词法分析器规则,这样它们就不会重叠,然后在解析器规则中按照你喜欢的方式对它们进行分组。因此,您可以为每个运算符制定一个词法分析器规则(可能通过在解析器规则中使用字符串文字来隐含),然后只需在解析器中使用 ('==' | '!=' | ...)
。
我还建议只为关系表达式设置一个解析器规则。现在每个类型都有一个不允许比较不同类型的表达式,但这种方法不能扩展(例如,当你引入变量时你打算做什么?)。相反,您应该简单地在解析器中允许错误类型的表达式,然后在您单独编写的类型检查器中拒绝它们。
PS:为了在词法分析器中找到这些类型的问题,它有助于打印为给定输入生成的令牌流。您可以通过在 Java 代码中迭代令牌流或在命令行中通过 运行 grun YourGrammarName tokens -tokens yourInputFile
来实现。
我编写了以下语法来计算 Java 中的逻辑运算符和关系运算符的组合。
在语法中,我只能对 STRING 类型使用等于运算符 (=
) 而不能对 INT 和 BOOLEAN 类型。有人可以帮我找出问题所在吗?
我可以 ("a" == "b")
而不能 ("a" == 567)
。左手操作数是可变的,我将在运行时替换这些值。
grammar testGrammar;
/*
* Parser rules
*/
conditionalExpression: leftOperand=conditionalExpression operator=LOGICAL_OPERATORS rightOperand=conditionalExpression #LogicalOperators
| '(' conditionalExpression ')' #ParenthesisExpression
| leftOperand=STRING operator=BOOLEAN_RELATIONAL_OPERATORS rightOperand=BOOLEAN #RelationalBooleanOperators
| leftOperand=STRING operator=STRING_RELATIONAL_OPERATORS rightOperand=STRING #RelationalStringOperators
| leftOperand=STRING operator=INT_RELATIONAL_OPERATORS rightOperand=INT #RelationalIntOperators
;
/*
* Lexer rules
*/
STRING: '"'CHAR(CHAR)*'"';
INT:DIGIT+;
BOOLEAN: BOOLEAN_TRUE | BOOLEAN_FALSE;
LOGICAL_OPERATORS: LOGICAL_OR | LOGICAL_AND | LOGICAL_NOT;
STRING_RELATIONAL_OPERATORS: RELATIONAL_EQUALS | RELATIONAL_NOT_EQUAL;
INT_RELATIONAL_OPERATORS: RELATIONAL_EQUALS | RELATIONAL_NOT_EQUAL | RELATIONAL_GREATER_THEN
| RELATIONAL_GREATER_THEN_OR_EQUAL | RELATIONAL_LESS_THEN | RELATIONAL_LESS_THEN_OR_EQUAL;
BOOLEAN_RELATIONAL_OPERATORS: RELATIONAL_EQUALS | RELATIONAL_NOT_EQUAL;
fragment RELATIONAL_EQUALS: '==';
fragment RELATIONAL_NOT_EQUAL: '!=';
fragment RELATIONAL_GREATER_THEN: '>';
fragment RELATIONAL_LESS_THEN: '<';
fragment RELATIONAL_GREATER_THEN_OR_EQUAL: '>=';
fragment RELATIONAL_LESS_THEN_OR_EQUAL: '<=';
fragment LOGICAL_AND: '&&';
fragment LOGICAL_OR: '||';
fragment LOGICAL_NOT: '!';
fragment CHAR: [a-zA-Z_];
fragment DIGIT: [0-9];
fragment BOOLEAN_TRUE: 'true';
fragment BOOLEAN_FALSE: 'false';
您有多个词法分析器规则可以匹配输入 ==
或 !=
。 ANTLR(以及大多数词法分析器生成器)通过首先选择产生最长匹配的规则(在这种情况下所有规则将产生长度为 2 的匹配)然后通过选择一个解决关系来解决词法分析器规则中的歧义这在语法中排在第一位。所以当词法分析器看到 ==
或 !=
时,它总是会生成一个 STRING_RELATIONAL_OPERATORS
.
请注意,词法分析器不关心解析器现在需要哪些标记 - 词法分析器独立于解析器运行。它只查看当前输入和定义的词法分析器规则来决定创建哪种令牌。所以相同的字符序列将始终创建相同类型的令牌。
要修正你的语法,你应该定义你的词法分析器规则,这样它们就不会重叠,然后在解析器规则中按照你喜欢的方式对它们进行分组。因此,您可以为每个运算符制定一个词法分析器规则(可能通过在解析器规则中使用字符串文字来隐含),然后只需在解析器中使用 ('==' | '!=' | ...)
。
我还建议只为关系表达式设置一个解析器规则。现在每个类型都有一个不允许比较不同类型的表达式,但这种方法不能扩展(例如,当你引入变量时你打算做什么?)。相反,您应该简单地在解析器中允许错误类型的表达式,然后在您单独编写的类型检查器中拒绝它们。
PS:为了在词法分析器中找到这些类型的问题,它有助于打印为给定输入生成的令牌流。您可以通过在 Java 代码中迭代令牌流或在命令行中通过 运行 grun YourGrammarName tokens -tokens yourInputFile
来实现。