我编写了一个实验性的函数评估器,它允许我将简单的函数绑定在一起,这样当变量发生变化时,依赖于这些变量的所有函数(以及依赖于这些函数的函数等)都会同时更新。我这样做的方式不是在输入函数时立即评估函数,而是存储函数。仅当请求输出值时,我才评估函数,并且每次请求输出值时都对其进行评估。
例如:
pi = 3.14159
rad = 5
area = pi * rad * rad
perim = 2 * pi * rad
我将“pi”和“rad”定义为变量(嗯,返回常量的函数),将“area”和“perim”定义为函数。每当“pi”或“rad”发生变化时,我都希望“area”和“perim”的结果会发生变化。同样,如果有任何函数依赖于“区域”或“周边”,那么它们的结果也会发生变化。
这一切都按预期工作。这里的问题是当用户引入递归时——无论是偶然的还是有意的。我的语法中没有逻辑——它只是一个评估器——所以我不能为用户提供一种“突破”递归的方法。我想完全阻止它发生,这意味着我需要一种方法来检测它并将有问题的输入声明为无效。
例如:
a = b
b = c
c = a
现在评估最后一行会导致 StackOverflowException(而前两行评估为 '0' - 未声明的变量/函数等于 0)。我想做的是检测循环逻辑情况并禁止用户输入这样的语句。无论循环逻辑隐藏多深,我都想这样做,但我不知道如何去做。
顺便说一句,在幕后,输入字符串通过简单的扫描器转换为标记,然后通过手写递归下降解析器转换为抽象语法树,然后评估 AST。语言是 C#,但我不是在寻找代码解决方案 - 仅逻辑就可以了。
注意:这是我用来了解解析器和编译器如何工作的个人项目,因此它不是关键任务 - 但是我从中获得的知识我确实计划在某些时候投入到现实生活中。你们可以提供的任何帮助将不胜感激。=)
编辑:如果有人好奇,我博客上的这篇文章描述了我为什么要学习这个,以及我从中得到了什么。