谷歌的新语言“Go”在其网站上说:
该语言的设计易于分析,无需符号表即可解析
我当然不是这些问题的专家,但我认为符号表是所有使用变量的语言的编译器通用的基本结构,而 Go 显然使用变量。我不明白什么?
谷歌的新语言“Go”在其网站上说:
该语言的设计易于分析,无需符号表即可解析
我当然不是这些问题的专家,但我认为符号表是所有使用变量的语言的编译器通用的基本结构,而 Go 显然使用变量。我不明白什么?
解析意味着仅仅弄清楚程序结构:将模块分成语句/声明,将表达式分解为子表达式等。您最终会得到一个树结构,称为“解析树”或“抽象语法树”( AST)。
显然,C++ 需要一个符号表来进行解析。
本页讨论了C++ 需要符号表来解析的一些原因。
当然,解析只是编译的一部分,你需要一个符号表来做一个完整的编译。
然而,解析本身在编写分析工具(例如,哪个模块导入了哪个模块)时很有用。因此,简化解析过程意味着更容易编写代码分析工具。
@正义是对的。稍微扩展一下,在 C 中唯一实际棘手的部分是将类型与变量区分开来。特别是当你看到这个时:
T t;
您需要知道这T
是一种合法解析的类型。这是您必须在符号表中查找的内容。只要在解析继续时将类型添加到符号表中,这相对容易弄清楚。您不需要在编译器中做太多额外的工作:要么T
存在于表中,要么不存在。
在 C++ 中,事情要复杂得多。有大量模棱两可或可能模棱两可的结构。最明显的是这个:
B::C (c);
除了不清楚B
是a class
、atypedef
还是namespace
_ _是一个重载的对象)。您需要符号表来进行解析,尽管仍然可以足够快地继续解析,因为符号的类型在符号表中。C
c
C
c
operator()
当模板加入时,事情变得比这更糟糕。如果C (c)
是在模板中,您可能不知道在模板的实际定义中,C 是类型还是函数/对象。这是因为模板可以声明C
为类型或变量。这意味着您需要符号表,但您没有符号表——而且在实际声明模板之前您不能拥有符号表。更糟糕的是,仅仅拥有符号的类型并不一定足够:您可能会想出需要符号所代表类型的完整信息的情况,包括大小、对齐方式和其他特定于机器的信息。
这一切都有几个实际效果。我要说的最重要的两个是:
解释和编译绝对需要符号表或类似的东西。几乎所有语言都是如此。
在 C 和 C++ 中,即使是解析语言也需要符号表。
要解析大多数语言,您需要知道名称何时是变量、类型或函数,以消除某些结构的歧义。Go 没有这种模棱两可的结构。
例如:
int x = Foo(bar);
Foo 可以是类型或函数,它们由不同的 AST 类型表示。基本上,解析器不必对符号进行查找就知道如何构造 AST。语法和 AST 比大多数语言都简单。真的很酷。
符号表很慢,通常不需要。所以去选择离开它。其他函数式语言也不需要。快速查找需要哈希,但要支持嵌套范围,您需要将名称推送/弹出到堆栈中。简单的符号表被实现为线性搜索堆栈,更好的符号表被实现为每个符号一个堆栈的哈希。但是,搜索必须在运行时完成。
词法范围语言的解释和编译绝对不需要符号表或类似的。只有动态范围的符号才需要符号表,而一些具有严格类型语言的编译器需要某种内部符号表来保存类型注释。
在 C 和 C++ 中,即使解析语言也需要符号表,因为您需要存储全局变量和函数的类型和声明。
词法范围的符号不存储在符号表中,而是作为块框架中名称的索引列表存储,就像在函数式语言中一样。这些索引是在编译时计算的。所以运行时访问是立即的。离开范围会使这些变量无法自动访问,因此您不需要从命名空间/符号表中推送/弹出名称。
没有一等函数的函数式语言通常需要将它们的函数名存储在符号表中。作为语言设计者,您尝试将函数绑定到词法,以便能够摆脱符号表中的动态名称查找。