在为一种简单的编程语言构建某种解释器时,我偶然发现了一个有趣的问题。我称其为“符号超前”问题。
我这是什么意思?例如,在C / C ++编译器中,必须始终在代码上方的某个位置声明要使用的符号。像这样:
struct int_pair;
struct rectangle {
int_pair position;
int_pair size;
};
struct int_pair {
int x, y;
};
而不是这样:
struct rectangle {
int_pair position;
int_pair size;
};
struct int_pair {
int x, y;
};
在C#或Java中,可以在文件中随处使用任何符号:
public class Rectangle {
private IntPair position, size; // using IntPair before declaring it
}
public class IntPair {
public int Sum() { // using x and y before declaring it
return x + y;
}
public int x, y;
}
那我怎么了
我发现,在构建AST时,了解代码中的符号是否指向函数或变量或其他东西很有用,以便解释器可以确定以下代码应为什么样,从而改善了LOTTA的情况。这要求该符号已经在我的程序中的某个地方声明了,但是我真的不喜欢这种“ C”风格的编程。我想要的是一种类似于Java或C#的编程风格:声明可以在代码中的任何位置,您不受特定顺序的约束-解释器可以在构建AST时依赖于符号含义。
解决此问题的一种方法可能是建立某种超前算法,该算法会飞越程序并捕获所有相关符号,而别无其他。但是对我来说,这似乎很混乱且类似变通办法。
所以我的问题是,这就是想要用c#和Java声明内容的方式(请参阅上面的代码段),但是我想出了如何在解释器中实现此功能。所以我要一个想法/代码片段/算法/策略,让我提前了解符号及其含义。
非常感谢您的帮助。 :)
最佳答案
Java和C#的语法以这样的方式设计:即使您不知道子表达式的类型(包括标识符),诸如函数调用之类的表达式也是明确的。 C不是那样设计的。
语法清晰的优点之一是,您无需进行任何类型分析就可以创建AST,这意味着不需要预先声明。拥有AST之后,您就可以通过遍历解析树来进行所需的任何分析,例如针对调用站点检查函数原型。
无需同时进行所有分析。您可以根据需要在树上行走多次。这使组织代码变得更加容易,并且不会增加任何主要开销。