1

我正在为一些类似 Java 的语言制作一个简单的解析器(仅用于学习目的)。我无法确定语句是否是变量声明。这可能是我的词法分析器的问题(这真的很草率)。如果词法分析器看到一些文本,它只是将其标记为标识符,即使该文本是关键字或类型。将它们区分开来的工作交给了解析器。

到目前为止,这已经奏效,但现在我正在尝试解析变量声明,就像这里的这个:

int x = 3;

问题是我不知道如何确定这是否是变量声明。如果我只查看第一个标记并发现它是一个“标识符”,那并不能告诉我任何信息,因为这行代码也以一个标识符开头:

System.out.print("hi");

像这样的语句由解析器的另一部分处理。

我想到的另一个解决方案是检查第一个标记是否是一种类型。例如,我可以有一个看起来像这样的方法:

boolean isType(String t) {
    if( t.equals("int")  ||
        t.equals("long") ||
        t.equals("char") ||
        /* et cetera */ )
        return true;
    else return false;
} 

这样做的问题是它只允许特定的一组类型。由于我的小语言被编译为 Java 字节码,因此我需要它来将任意类识别为类型。

所以我的问题是:是否可以在不知道所有可能的变量类型的情况下确定语句是否是变量声明?

4

4 回答 4

2

另一种解决方案是让解析器和词法分析器使用符号表进行协作。一旦解析器确定已经声明了一个新的类型名称,它将将该名称作为类型名称插入符号表中。反过来,词法分析器会查询符号表以查看新的类似标识符的单词是否是类型名称,并相应地选择正确的标记类型。

然而,也有一些并发症。

  • 如果语言允许内部作用域将类型名称重新定义为另一种类型的名称或非类型标识符,则符号表必须理解作用域,并且解析器必须在作用域结束时通知符号表。
  • 如果语言允许类型名称在某些上下文中成为普通标识符,则解析器必须能够处理它。
  • 如果解析器回溯,它还必须记住撤消符号表更改。

它不像让词法分析器忽略上下文那样干净,但作为回报(在某些情况下)它允许解析器避免过度的前瞻和回溯;尽管我认为 Java 解析器不一定需要这种帮助。

于 2012-08-09T06:55:48.640 回答
1

当您阅读第一个单词时,您不知道它是否是声明,但您不需要。

当你得到下一个分隔符时,你就知道它是做什么用的了。

于 2012-08-08T19:39:36.797 回答
1

大约 4 年前,我不得不为一堂课做这种风格的东西。虽然我不记得“官方”方式的所有细节,但是

我会做的是,我会向前看,在未来的符号中确定它是否是一个变量声明,也就是说Benjamin Gruenbaum,如果你看到一个合法的标识符(在一行的开头)后跟另一个合法的标识符,而不是第一个可能是变量声明。

于 2012-08-08T19:39:47.347 回答
1

您可能应该阅读有关编译器设计的书,并且可能在尝试之前查看 lex 和 yacc 代码。或者你可以谷歌写一个编译器

IIRC,已经有一段时间了,首先将源文件分解为解析树,然后遍历解析树以生成目标代码。当您分解源文件时,您会根据关键字标记列表检查每个标记。

在您的示例中,您的词法分析器会看到“int”,并对其进行处理,查找必须跟随关键字(或在它之前,取决于您的语言定义)的变量声明。

这看起来很容易,但是大多数人使用 flex 或 lex 之类的工具来创建解析树是有原因的。

于 2012-08-08T19:40:02.987 回答