如何区分某些标识符和变量声明?

时间:2012-08-08 19:31:45

标签: java compiler-construction javac

我正在为一些类似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 个答案:

答案 0 :(得分:2)

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

然而,有一些并发症。

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

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

答案 1 :(得分:1)

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

当你得到下一个分隔符时,你知道它是什么。

答案 2 :(得分:1)

大约4年前,我不得不为一堂课做点什么。虽然我不记得“官方”方式的所有细节,但是

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

答案 3 :(得分:1)

您可能应该阅读有关编译器设计的书籍,并且在尝试之前可能会查看lex和yacc代码。或者你可以google writing a compiler

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

在你的例子中,你的词法分析器会看到'int',并处理它,寻找必须在关键字后面的变量声明(或在它之前,取决于你的语言定义)。

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