我正在为一种语言编写一个解释器,其中函数可以用作运算符。但是,函数内容只能在运行时知道。
为此,我考虑了两个解决方案:
我选择了后者,因为我看到在分别解析执行方面有很多优点。
现在谈到实施,我很想看看有哪些选择。我最初的想法是一个shift reduce parser,但我在构造解析器方面没什么经验。
示例:
LHS op RHS : LHS * RHS /* define a binary operator 'op' */
var : 3 /* define a variable */
print 5 op var /* should print 15 */
LHS op RHS : LHS / RHS /* Re-define op */
print var op var /* Should print 1 */
在最后一种情况下,解析器将从词法分析器中获取:“id
id
id
id
”。只有在运行时我才知道'op'id是一个操作符。
答案 0 :(得分:2)
(根据要求发布评论结果。)
解决方案#1绝对是丑陋的,实施起来很复杂,而且不需要,我同意。解决方案#2到目前为止更容易实现和理解。您也可以允许运算符的自定义关联性和优先级,只要这些是静态已知的。主要的是这些事实在解析时已知。
对于实际解析,大多数解析器都可以正常工作,因为围绕id的任何两个表达式都是自定义中缀运算符的应用程序(如果允许自定义优先级和关联性,则不太常见,在这种情况下,您需要一个算法允许在解析时根据每个运营商确定那些)。无论哪种情况,我个人最喜欢的是“Top Down Operator Precedence Parser”或Pratt解析器。我发现以下资源(按照对我有用的顺序,YMMV)描述得很好:
算法的两个属性使它非常适合这个问题:
[*]我亲自为500行Python中的一个非常大的(只缺少case
,多维数组,也许是一些模糊的细微之处)Pascal子集编写了一个解析器,并且工作了2-3天,其余的只是缺失,因为当时使用的软件的其他部分更有趣,我没有理由实施其余部分。