我正在尝试创建自己的分析器/解析器。
我有一个问题,我理解为什么它不起作用,但我不确定如何解决它。
这是我的解析器的问题部分的代码。
void Expression() : {}{
Term() ((<PLUS> | <MINUS>) Term())*
}
void Term() : {}{
Factor()((<MULTIPLY> | <DIVIDE>) Factor())*
}
void Factor() : {}{
(<ID> | <NUMBER> | ((<PLUS> | <MINUS>)?<OPEN_PARENTHESIS> Expression() <CLOSE_PARENTHESIS>))
}
void Condition() : {}{
(
(<NOT> Condition()) |
(<OPEN_PARENTHESIS> Condition() (<AND> | <OR>) Condition() <CLOSE_PARENTHESIS>) |
(Expression() (<EQUAL_CHECK> | <NOT_EQUAL> | <LESS> | <LESS_EQUAL> | <GREATER> | <GREATER_EQUAL>) Expression())
)
}
正如您所看到的,问题出现在OR部分三个选项中最后两个选项的Condition()方法中。这是因为Expression()最终可能会变成"(Expression()[/em>)",因此第三个和第二个选项都可以以左括号标记开头。
然而,我不确定该如何解决这个问题。我之前在解析器中解决了一个类似的问题,但我不能在这里使用相同的逻辑,因为Expression()-->Term(。
如有任何建议,我们将不胜感激。
谢谢,
托马斯。
编辑:
有关更多信息,我将向代码提供应该使用此解析器但由于上面解释的错误而无法使用的示例。
fun succesful_method()
start
var i = 1;
if(i > 0 and i < 2)
do
i = 2;
stop
stop
start
successful_method()
stop
上面的方法将成功运行,因为它使用了Condition()方法的第二个替代方法。
fun succesful_method()
start
var i = 1;
if(i > 0)
do
i = 2;
stop
stop
start
successful_method()
stop
上面的方法会失败,因为它需要使用第三个备选方案,但是由于"("导致解析器调用第二个备选方案而无法访问。
您可以通过语法前瞻来解决此问题。
void CompOp() : {} { <EQUAL_CHECK> | <NOT_EQUAL> | <LESS> | <LESS_EQUAL> | <GREATER> | <GREATER_EQUAL> }
void Condition() : {}{
<NOT> Condition()
|
LOOKAHEAD(Expression() CompOp())
Expression()
CompOp()
Expression()
|
<OPEN_PARENTHESIS>
Condition()
(<AND> | <OR>)
Condition()
<CLOSE_PARENTHESIS>
}
只有在存在(
时才向前看,效率稍高。
void Condition() : {}{
<NOT> Condition()
| LOOKAHEAD( <OPEN_PARENTHESIS> )
(
LOOKAHEAD(Expression() CompOp())
Expression()
CompOp()
Expression()
|
<OPEN_PARENTHESIS>
Condition()
(<AND> | <OR>)
Condition()
<CLOSE_PARENTHESIS>
)
|
Expression()
CompOp()
Expression()
}
为所有表达式使用单一语法并为所有运算符定义优先级应该可以解决您的问题,而不需要为表达式类型添加语义检查。
Expr -> AndExpr (<OR> AndExpr)*
AndExpr -> NotExpr (<AND> NotExpr)*
NotExpr -> <NOT>* RelExpr
RelExpr -> NumExpr () (<RELOP> NumExpr)?
NumExpr -> Term ((<PLUS>|<MINUS>) Term)*
Term -> Factor ((<MULTIPLY>|<DIVIDE>) Factor)*
Factor -> (<PLUS>|<MINUS>)* Atom
Atom -> <ID> | <NUMBER> | <OPEN_PARENTHESIS> Expr <CLOSE_PARENTHESIS>
令牌<RELOP>
表示您的关系运算符。
请注意,该语法允许您混合布尔表达式和数字表达式,因此您应该检查错误。
例如,对于Expr -> AndExpr
,返回的类型将是AndExpr的类型。但是对于AndExpr <OR> AndExpr
,您应该检查两个AndExpr都是布尔表达式,并且Expr返回的类型将是布尔类型。