如何在解释器中处理赋值和变量语法

时间:2018-12-15 22:39:39

标签: parsing context-free-grammar

大多数解释器使您可以在其控制台上键入以下内容:

>> a = 2
>> a+3
5
>>

我的问题是通常使用什么机制来处理这种语法?解析器可以某种方式区分分配和表达式,即使它们都可以以数字或字母开头。只有当我们检索第二个令牌时,您才知道是否有分配。过去,我先看了两个标记,如果第二个标记不是等号,我会将这些标记推回到词法流中,并假定它是一个表达式。我想可以将作业视为一种表达,我认为某些语言也可以。我曾想过使用左分解,但看不到它起作用。

例如

assignment = variable A
A = '=' expression | empty

更新,我在StackOverflow上发现了这个问题,该问题解决了相同的问题:How to modify parsing grammar to allow assignment and non-assignment statements?

1 个答案:

答案 0 :(得分:1)

从您如何描述方法-做一些前瞻性标记来决定如何处理事情-听起来像您正在尝试沿着LL(1)的方式编写某种自上而下的解析器或LL(2)解析器,并且您试图立即确定要解析的表达式是变量赋值还是算术表达式。您可以通过多种方式很自然地解析此类表达式,并且它们实质上涉及弱化这两个假设之一。

我们执行此操作的第一种方法是从使用自上而下的解析器(例如LL(1)或LL(2)解析器)切换到其他内容(例如LR(0)或SLR(1)解析器)。这些解析器通过在决定输入内容之前先读取输入字符串的较大前缀来进行自底向上工作。在您的情况下,自下而上的解析器可能会通过查看变量并认为“好吧,我将要读取要打印的表达式或赋值语句来工作,但到目前为止,我仍然无法看到提交给任何一个”,然后扫描更多令牌以查看下一步。如果他们看到等号,那就太好了!这是一份作业说明。如果他们看到其他东西,那就太好了!不是。对此的好处是,如果您使用的是标准的自底向上解析算法,例如LR(0),SLR(1),LALR(1)或LR(1),则您可能会发现解析器通常可以处理这些问题都很好,不需要特殊的逻辑。

另一个选择是假设=是合法的二进制运算符,与其他任何运算一样,解析整个表达式,然后检查您解析的内容是否为合法的赋值语句。例如,如果使用Dijkstra的shunting-yard算法进行解析,则可以为整体表达式恢复解析树,而不管它是算术表达式还是赋值。然后,您可以走解析树,询问类似问题

  • 如果顶级操作是赋值,那么左侧是单个变量吗?

  • 如果顶级操作不是赋值,那么这里是否存在我们需要摆脱的嵌套赋值语句?

换句话说,您不仅要解析合法的语句,还可以分析更广泛的语句,然后执行后处理步骤来丢弃所有无效的语句。