我如何手动编写复杂的公式解析器?

时间:2010-05-26 21:38:50

标签: language-agnostic compiler-construction parsing interpreter formula

嗯,这是语言不可知的,我更喜欢用C#或F#来做,但我现在更感兴趣的是“无论如何都会这样做”。

我想要完成的事情是:

a)我想学习它 - 这次是关于我的自我,这是一个有趣的项目,我想向自己展示我是非常擅长这些东西

b)我对EBNF知之甚少(虽然我还不知道,运营商优先级如何在EBNF中运行 - Irony.NET做得对,我查看了这些例子,但这对我来说有点不祥)

c)我的解析器应该可以这样:5 *(3 +(2 - 9 *(5/7))+ 9)例如,给我正确的结果

d)坦率地说,这似乎是为我编写编译器甚至是解释器的最大问题。我甚至可以生成64位汇编代码(我可以手动编写汇编程序),但公式解析器...

e)另一个想法:即使是简单的计算机(就像我的旧款Sharp 1246S只有大约2kB的RAM)也可以做到这一点......它不会那么难,对吧?甚至非常非常古老的编程语言都有公式评估...... BASIC是从1964年开始的,它们已经可以计算出我所提出的公式类型

f)一些想法,一些灵感就足够了 - 我根本不知道如何做运算符优先级和括号 - 但是,我知道它涉及AST并且很多人使用堆栈< / p>

那么,您怎么看?

4 个答案:

答案 0 :(得分:5)

您应该了解Recursive Descent parsers

通过以下10种不同的方式查看Code Golf练习:

Code Golf: Mathematical expression evaluator (that respects PEMDAS)

这些“高尔夫”解决方案中的一些是以不同方式编码的递归下降解析器。

你会发现只做表达式解析是编译器中最简单的事情。解析语言的其余部分比较困难,但理解代码元素如何交互以及如何生成良好的代码要困难得多。

您可能还对如何使用BNF表达解析器感兴趣,以及如何使用该BNF执行某些操作。这里的 具有显式BNF和隐式AST作为基础的example of how to parse and manipulate algebra symbolically。这不是编译器传统上所做的,但其所做的机制深深植根于编译器技术。

答案 1 :(得分:1)

传统上,计算机上的公式处理器使用POSTFIX表示法。他们使用堆栈,弹出2个项目作为操作数,弹出第三个项目作为操作符,然后推送结果。

你想要的是一个INFIX到POSTFIX表示法转换器,这真的很简单。一旦你进行后缀处理是你做过的最简单的事情。

答案 2 :(得分:1)

对于在PHP中实现的基于堆栈的解析器,它使用Djikstra的分流码算法将中缀转换为后缀表示法,并且支持具有不同数量参数的函数,您可以查看PHPExcel计算的源代码发动机

答案 3 :(得分:0)

如果你想寻找一个现有的解决方案,我可以推荐一个工作,PSR-0兼容的分流码算法实现:https://github.com/andig/php-shunting-yard/tree/dev