设计语言词库

时间:2016-05-20 12:37:06

标签: parsing language-design lexer

我目前正在创建编程语言。我已经完成了我的整个设计,并且正在为它创建Lexer。我过去创造了许多词法分析器和词法分析器,但是如果存在的话,我们从未采用过“标准”。

是否应该创建词法分析器的特定方式以最大限度地使用尽可能多的解析器?

因为我设计我的方式,它们看起来如下:

代码:

int main() {
    printf("Hello, World!");
}

词法:

[
KEYWORD:INT, IDENTIFIER:"main", LEFT_ROUND_BRACKET, RIGHT_ROUNDBRACKET, LEFT_CURLY_BRACKET,
IDENTIFIER:"printf", LEFT_ROUND_BRACKET, STRING:"Hello, World!", RIGHT_ROUND_BRACKET, COLON,
RIGHT_CURLY_BRACKET
]

这是应该制作Lexer的方式吗? 另外作为旁注,创建Lexer后我的下一步应该是什么?我真的不想使用像ANTLR或Lex + Yacc或Flex + Bison等的东西。我我是从零开始做的。

2 个答案:

答案 0 :(得分:2)

如果您不想使用解析器生成器[注1],那么您的词法分析器如何向解析器提供信息绝对取决于您。

即使您使用解析器生成器,也有许多细节将依赖于项目。有时,词法分析器使用每个标记调用解析器是很方便的;如果解析器调用词法分析器,则其他时间会更容易;在某些情况下,您希望拥有一个与每个组件分开交互的驱动程序。很明显,您的令牌的精确数据类型因项目而异,这也会对您的沟通方式产生影响。

就个人而言,我会避免使用全局变量(如在原始的yacc / lex协议中),但这是一般风格问题。

大多数词法分析器在流模式下工作,而不是将整个输入标记化,然后将标记向量处理为更高的功率。一次对一个令牌进行标记有许多优点,特别是如果标记化是依赖于上下文的,并且,让我们面对它,几乎所有语言在其语法中都有一些某处的杂质。但是,这完全取决于你。

祝你的项目好运。

注意:

  1. 您是否也放弃使用编译器并在汇编程序甚至二进制文件中从头开始编写所有代码?

答案 1 :(得分:1)

  

是否应该创建词法分析器的特定方法,以最大限度地使用尽可能多的解析器?

在我看过的词法分析器中,规范的API非常小。基本上是这样的:

Token readNextToken();

词法分析器维护对源文本及其内部指针的引用,指向它当前所在的位置。然后,每次调用它时,它都会扫描并返回下一个标记。

令牌类型通常具有:

  • “type”枚举,它是哪种令牌:字符串,运算符,标识符等。“EOF”通常有特殊种类,这意味着在输入结束后生成的特殊终结符令牌,以及“ERROR”用于语法错误来自词汇语法的罕见情况。这主要是源中没有未终止的字符串文字或完全未知的字符。
  • 令牌的源文本。
  • 有时文字在lexing期间被转换为正确的值表示,在这种情况下你也会有这个值。因此,数字标记将“123”作为文本,但也具有数字 123.或者您可以在解析/编译期间执行此操作。
  • 令牌源文件中的位置。这是用于错误报告。通常是基于1的行和列,但也可以只是起始和结束字节偏移。后者生产起来要快一些,如果需要可以懒惰地转换成行和列。

根据你的语法,你可能也需要能够回放词法分析器。