使用Lemon中的midaction规则解释" let"表达

时间:2015-06-06 15:34:28

标签: parsing interpreter lalr lemon

我试图写一个"玩具"使用Flex + Lemon的翻译,支持非常基本的" let"语法,其中变量X临时绑定到表达式。例如," letx 3 + 4 in x + 8"应评估为15。

从本质上讲,我喜欢"喜欢"要说的规则是:

expr(E) ::= LETX expr(N) IN expr(O). {
                                         environment->X = N;  
                                         E = O; 
                                     }

但是,在O作业完成之前,X = N评估后,这项工作无法完成。

据我所知,通常的解决办法是采取中等规则行动。 Lemon并没有明确地支持这一点,但我已经在其他地方阅读了syntactic sugar无论如何。

因此,在尝试解释X = N之前,我已尝试整理一项中等规则的操作,以便完成O的任务:

midruleaction ::=  /* mid rule */.                   { environment->X = N; }    
expr(E)  ::= LETX expr(N) IN midruleaction expr(O).  {  E = O; }

但这不会起作用,因为midruleaction规则无法访问N,或者至少我无法在柠檬文档/示例中看到。< / p>

我想我在这里遗漏了一些东西。我知道我可以建造一棵树,然后在第二次通过时走。我最终可能会这样做,但我想先了解如何更直接地解决这个问题。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

在解析器中立即评估它并不是一个非常可扩展的解决方案。见下文。

确实,中规则行动(大多数)是句法糖。然而,在大多数情况下,它们不是#34;标记物的语法糖。 (具有空右侧的非终端),而非代表生产前缀的非终端。例如,您可以像这样编写letx规则:

expr(E)     ::= letx_prefix IN expr(O). { E = O; }
letx_prefix ::= LETX expr(N).           { environment->X = N; }  

或者你可以这样做:

expr(E)       ::= LETX assigned_expr IN expr(O). { E = O; }
assigned_expr ::= expr(N).                       { environment->X = N; }

第一个是前缀desugaring;第二个是我使用的那个,因为我觉得它更好地区分了问题。重要的一点是environment->X = N;动作需要访问RHS前缀的语义值,因此它必须是前缀规则的一部分(至少包括其语义值所需的符号),而不是一个标记,根本不能访问任何语义值。

说了这么多,解析过程中的即时评估是一种非常有限的策略。它无法应对需要延迟评估的大量构造,例如循环和函数定义。它不能干净地应对可能抑制评估的结构,例如条件和短路操作器。 (这些可以使用MRA和包含评估抑制标志的有状态环境来处理,但是非常丑陋。)

另一个问题是,在发现语法错误之前,可能会对语法错误的表达式进行部分评估,并且对于用户来说,表达式的哪些部分尚未被评估,这可能不会立即显而易见。

总的来说,您最好在解析期间构建一个易于评估的AST,并在解析成功完成时评估AST。