题
可能有人请给我约当它需要看看进一步的声明,以便能够使当前的时刻正确的语义动作如何处理的情况下一些建议/想法?例如,当有人写一些不支持“前声明”编程语言的翻译器/编译一个众所周知的发生。让我们的示例:
foo(123);//<-- our parser targets here. we estimate we have a function
// invocation, but we have no idea about foo declaration/prototype,
// so we can't be sure that "foo" takes one integer argument.
void foo(int i){
//...
}
这是很清楚的,我们必须有至少两个通行证。首先,我们分析所有函数声明,并得到所有需要的信息,如:量参数的函数接受,它们的类型,然后我们能够处理的函数调用和解决如上的困难。如果我们走这条路,我们将必须使用一些 AST 穿越机制/游客做所有这些通行证。在这种情况下,我们必须处理AST穿越/应用的访问者,我们必须说“再见”,以凤凰建设的所有美景在我们的解析器直接集成。
你会如何面对呢?
解决方案
[第二回答,语义] 这个特殊的例子恰好是简单的。你可以做的是又未申报的功能所做的记录函数调用,实际参数类型。当你以后遇到一个函数声明,你检查是否有前面的那些(更好)匹配到这个新的功能函数调用。你会明显只在解析的最后检测错误,监守最后一行可以引入缺失的功能。但该行之后,尚未在所有匹配的任何函数调用是错误的。
现在,问题是,这适用于简单的语义。如果你看一下更复杂的语言 - 例如用C ++ - 等功能的模板 - 它不再能够在一个简单的表来做这种查找。您需要专门的脊髓痨在结构符合您的语言结构。一个AST只是没有对那些的最佳结构,更不用说分析过程中的部分AST。
其他提示
如果你想在第一阶段结束时做两遍,而不是语义检查,你可以有TE功能,通过你的行为称为知道通过他们在,所以,如果你有一些动作
[functionCall(name, args)]
[functionDef(name, args, body)]
它们将被定义是这样的(不正确的精神语法,但你明白了吧)
functionCall(string name, vector<string> args)
{
if (!first_pass) {
// check args for validity
// whatever else you need to do
}
}
functionDef(string name, vector<string> args, ... body)
{
if (first_pass)
// Add function decleration to symbol table
else
// define function
}
我觉得你提出毫无假设。举例来说,“这是很清楚的,我们必须有至少两道”。不,它不是。如果语法是使得foo(123)
只能被解析为function-name "(" expression ")"
,再一个通就足够了。
所以我会建议来设计你的语法解析明确。避免不能孤立地解析构建体,例如避免对声明elesewhere dependendencies。