编译器设计:“未声明变量”是语法错误还是语义错误?

时间:2012-11-02 20:45:34

标签: parsing compiler-construction semantics syntactic-sugar typechecking

在类型检查期间或解析输入时是否会产生这种类型的错误? 应该在什么类型下解决错误?

4 个答案:

答案 0 :(得分:2)

我认为这是一种语义错误,因为即使你使用的是以前没有绑定的标识符,你的语言就会解析得很好 - 即。句法分析只检查程序是否具有良好的形式。语义分析实际上会检查您的程序是否具有有效含义 - 例如。绑定,范围或打字。正如@pst所说,你可以在解析过程中进行范围检查,但这是一个实现细节。 AFAIK旧的编译器曾经这样做是为了节省一些时间和空间,但我认为如果你没有一些硬性能/内存限制,这种方法是有问题的。

答案 1 :(得分:1)

该程序符合语言语法,因此它在语法上是正确的。语言语法不包含任何语句,例如“必须声明标识符”,并且实际上没有任何方法可以这样做。在Algol-68项目中,试图按照这些方法构建一个两级语法失败了,据我所知,还没有尝试过。

每个含义(如果有)是语义问题。 Frank deRemer将这类问题称为“静态语义”。

答案 2 :(得分:0)

在我看来,这不是严格意义上的语法错误 - 也不是语义错误。如果我要为静态类型的编译语言(如C或C ++)实现它,那么我不会将检查放入解析器(因为解析器实际上无法检查这个错误),而是代码生成器(处理抽象语法树并将其转换为汇编代码的编译器部分。所以在我看来,它存在于语法和语义错误之间:它是一个与语法相关的错误,只能通过对代码执行语义分析来检查。

如果我们考虑使用原始脚本语言,直接执行AST(没有编译为字节码且没有JIT),那么它就是评估器/执行器函数本身,它会遍历AST并找到未声明的变量 - 在这种情况下,这将是一个运行时错误。不同之处在于“AST_walk()”例程位于程序生命周期的不同部分(编译时和运行时),如果语言是脚本或编译的话。

答案 3 :(得分:0)

对于语言 - 并且有很多 - 需要声明标识符,具有未声明标识符的程序格式错误,因此缺少声明显然是语法错误。

处理此问题的常用方法是在符号表中包含有关符号的信息,以便解析可以使用此信息。

以下是标识符类型如何影响解析的几个示例:

C / C ++

经典案例:

(a)-b;

取决于a,这是演员或减法:

#include <stdio.h>

#if TYPEDEF
typedef double a;
#else
double a = 3.0;
#endif

int main() {
  int b = 3;
  printf("%g\n", (a)-b);
  return 0;
}

因此,如果根本没有声明a,编译器必须拒绝该程序语法不正确(这正是标准使用的单词。)

XML

这个很简单:

<block>Hello, world</blob>

这是格式不正确的XML,但无法通过CFG检测到。 (尽管如此,所有XML解析器都会正确地拒绝它作为格式错误。)对于HTML / SGML,在某些明确定义的情况下可以省略end-tags,解析是棘手的,但仍然是确定性的;再一次,标签的精确声明将决定有效输入的解析,并且很容易得出根据声明进行不同解析的输入。

好的,不是编程语言。我有很多其他的编程语言示例,但我认为这可能会触发其他一些直觉。

考虑两个语法正确的句子:

The sheep is in the meadow.
The sheep are in the meadow.

现在,怎么样:

The cow is in the meadow.
(*) The cow are in the meadow.

第二句是可理解的,虽然含糊不清(名词或动词是错误的吗?)但它肯定不是语法正确的。但是为了知道(和其他类似的例子),我们必须知道sheep有一个没有标记的复数。实际上,许多动物都有无标记的复数,所以我认为以下所有都是语法:

The caribou are in the meadow.
The antelope are in the meadow.
The buffalo are in the meadow.

但绝对不是:

(*) The mouse are in the meadow.
(*) The bird are in the meadow.


似乎存在一种常见的误解,即因为语法分析器使用无上下文语法分析器,所以语法分析限制来解析上下文无关语法。事实并非如此。

对于C(和系列),语法分析器使用符号表来帮助它进行解析。在XML的情况下,它使用标记栈,在泛化SGML(包括HTML)的情况下,它也使用标记声明。因此,整体上考虑的语法分析器比CFG更强大,而CFG只是分析的一部分。

给定程序通过语法分析的事实并不意味着它在语义上是正确的。例如,语法分析器需要知道a是否是一个类型才能正确解析(a)-b,但它不需要知道转换是否实际上是可能的,在这种情况下在a是变量的情况下,a是一种类型,或者ba可以被有意义地减去。这些验证可以在构建解析树之后的类型分析期间发生,但它们仍然是编译时错误。