【问题标题】:When writing a compiler, how are tokens checked?编写编译器时,如何检查标记?
【发布时间】:2015-11-21 02:32:57
【问题描述】:

当遇到某个关键字时,编译器是否使用 if 语句?编写编译器的人在检查代码时是否应该将它们用于大多数操作?或者有没有更有效的方法?例如,当我根据符号表测试一个符号并且它作为一个有效的“令牌”返回时,我是否必须使用 if 语句来确定对每个关键字执行什么操作,因为它看起来相当低效,例如伪代码:

/*Each keyword/token in my compiler has a numerical representation which is what the symbol table returns back for example #define IF 0 and so on*/  
if(Token == IF){
  //This will be done to generate the AST representation for IF statements
}else if(Token == ELSE){
  //This will be done to generate the AST representation of an if statement
}else if(Token == INT){
  //This will be done to generate the AST represnetation of an integer
}

【问题讨论】:

  • 注意:“符号表”有所不同,您在此处的使用具有误导性。你的意思是令牌。而且通常没有“令牌表”。您可能想了解编译器构造,例如经典的 Niklaus Wirth 同名书籍(免费下载,入门非常简单)..
  • 不,我相信我的用法是完全可以接受的这里。但我确实同意你的观点,我应该澄清一下。
  • 但这在编译器中不称为符号表!请正确理解条款。无论如何,这不是编译器(或解释器)的工作方式。不要为成熟的短语发明新的解释。当您提出问题时,这将导致您无处可去。
  • 最终澄清。好的,所以看起来我只是感到困惑。 IDK 为什么我应该知道它的含义,因为我有时会在汇编程序中遇到重复符号错误。符号是特定类型的特定用户定义事物,而不是类型本身
  • 简单地说:符号表是编译器在解析代码中查找名称定义以查找类型和其他属性(例如结构、联合、成员、变量/constant,可能是值等)如果遇到名称。没错。这些是解析器中的符号。对于扫描仪/词法分析器,符号是像,%+ 这样的字符。这就是你在这里使用的。但是对于编译器上下文,它们并不那么相关,因为它们通常只是从输入中读取并由词法分析器形成标记。您通常没有要查找的表,但使用例如状态机。

标签: c compiler-construction lexical-analysis


【解决方案1】:

你的意思是什么类型的编译器? 如果性能很重要,你可能想要回调之类的东西,这样,使用关键字作为键,回调函数作为值,所以伪代码如下所示:

func *fp = funcTbl.get(Token);
if (fp) { fp(); }

您也可以尝试递归下降。与关键字相关的函数在它们预期的位置被调用。

最后但并非最不重要的一点,你写的也不错。

【讨论】:

  • 1) 这是 C,不是 C++。 2)你是什么意思? OP 需要一个解析器;通常不会使用回调,而是根据语法结构直接调用函数。如果您在代码中的两个不同位置具有相同的语义,则说明您的解析器做错了。
  • C 代码是完全可以接受的,事实上它在这里比 C++ 更可取,因为我不像 C 那样熟悉 C++,这就是为什么我在标签中指定 C 而不是 C++ 它也将是C 和 C++ 程序员都可以理解,这意味着如果有人有类似的问题,则可能存在更多样化的目标受众。
  • @Olaf 我不确定你是如何得到 C++ 的含义的,因为funcTbl.get(Token) 是有效的 C。这个例子是递归下降 [如上所述] 解析的变体。
  • 没有声明是不可能看到的。
  • @Olaf 你知道答案吗,或者有什么可以帮助我的吗?我不想学习任何不良的编码习惯。
【解决方案2】:

假设您已经将源语言从字符串表示拆分为一系列词法标记,下一步是使用 parser 从标记构建 AST。

编译的解析阶段主要实现两个目标:

  • 它会检查您的语言的语法正确性,如果您的输入无法根据您的语法结构进行解析,则会引发错误。
  • 它会生成源代码的 AST 表示

编译器是否使用 if 语句来决定如果一个 遇到某个关键字?

不,您的解析器应该分析一系列词汇标记,并根据您的语言语法结构检查它们。

解析是计算机科学中一个广为人知的主题,可以通过不同的方式进行处理。它不能在您上面提供的示例代码片段中轻松实现。在现实的编程语言中,您需要考虑语法可能是模棱两可的,并且简单的预测解析器适用于所有语法,并且需要某种回溯。如果你不理解这个概念,我建议你为此使用 Parser 生成器,例如Bison

此图简要概述了最重要的编译阶段,可以帮助您了解其管道结构。

几十年来,许多学者就如何最好地“分而治之”这样一项艰巨的任务对这一过程进行了改进。我强烈建议您遵循它。

如需进一步阅读,请查看Modern Compiler Implementation in Java by Andrew Appel

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 2015-02-11
    • 1970-01-01
    • 2012-06-10
    • 2013-07-10
    相关资源
    最近更新 更多