【发布时间】:2019-02-06 18:49:43
【问题描述】:
我一直在为自己的语言编写词法分析器/解析器/解释器,到目前为止一切正常。我一直在关注Ruslan Spivak's blog 上的示例(Github 每篇文章的链接)。
我想将我的语言语法扩展到文章中所写的内容,以包括更多运算符,如比较(<、>= 等)和指数(** 或 ^ 在我的语言中) .我有这个语法:
expression : exponent ((ADD | SUB) exponent)*
exponent : term ((POWER) term)*
# this one is right-associative (powers **)
term : comparison ((MUL | DIV) comparison)*
comparison : factor ((EQUAl | L_EQUAL | LESS
N_EQUAL | G_EQUAL | GREATER) factor)*
# these are all binary operations
factor : NUM | STR | variable
| ADD factor | SUB factor
| LPAREN expr RPAREN
# different types of 'base' types like integers
# also contains parenthesised expressions which are evalutaed first
在解析令牌方面,我使用了与 Ruslan 的博客中使用的相同的方法。这是一个将解析exponent 行的代码,尽管它的名称处理加法和减法,因为语法说表达式被解析为
exponent_expr (+ / -) exponent_expr
def exponent(self):
node = self.term()
while self.current_token.type in (ADD, SUB):
token = self.current_token
if token.type == ADD:
self.consume_token(ADD)
elif token.type == SUB:
self.consume_token(SUB)
node = BinaryOperation(left_node=node,
operator=token,
right_node=self.term())
return node
现在这可以很好地解析左关联标记(因为标记流自然地从左到右),但我被困在如何解析右关联指数上。查看这个预期的输入/输出以供参考:
>>> 2 ** 3 ** 2
# should be parsed as...
>>> 2 ** (3 ** 2)
# which is...
>>> 2 ** 9
# which returns...
512
# Mine, at the moment, parses it as...
>>> (2 ** 3) ** 2
# which is...
>>> 8 ** 2
# which returns...
64
为了解决这个问题,我尝试切换 BinaryOperation() 构造函数的左右节点,以使当前节点位于右侧,新节点位于左侧,但这只会使 2**5 解析为 5**2,这给了我 @987654335 @ 而不是预期的32。
我可以尝试什么方法?
【问题讨论】:
-
该语法为比较运算符提供了异常高的优先级。
-
是的,我刚刚意识到这一点。我错误地把它放在了底部,因为我认为那是更高的优先级,而实际上第一行是最低的优先级
标签: python parsing token right-to-left