我现在正在使用一个词法分析器程序,我使用的是Java。我一直在研究这个问题的答案,但直到现在我还没有找到任何答案。下面是我的问题:
输入:
System.out.println ("Hello World");
预期输出:
Lexeme----------------------Token
System [Key_Word]
. [Object_Accessor]
out [Key_Word]
. [Object_Accessor]
println [Key_Word]
( [left_Parenthesis]
"Hello World" [String_Literal]
) [right_Parenthesis]
; [statement_separator]
我还是一个初学者,所以我希望你们能帮助我。谢谢。
6条答案
按热度按时间qco9c6ql1#
手工编写简单的词法分析器既不需要ANTLR也不需要Dragon book,即使是更完整语言的词法分析器也是如此(像Java)手工编写并不是非常复杂。显然,如果你有一个工业任务,你可能想考虑像ANTLR或一些lex变体这样的工业强度工具,但是为了学习词法分析是如何工作的,手写可能会被证明是一个有用的练习。我想是这样的,因为你说你还是个初学者。
这是一个简单的词法分析器,用Java编写,针对Scheme类语言的一个子集,是我在看到这个问题后编写的,我认为代码相对容易理解,即使你以前从未见过词法分析器,仅仅是因为打断一串字符(在本例中为
String
)转换为令牌流(在本例中为List<Token>
)并不难,如果您有疑问,我可以尝试更深入地解释。使用示例:
一旦你写了一两个这样的简单的lexer,你就会对这个问题如何分解有一个很好的了解。然后探索如何使用像lex这样的自动化工具会很有趣。基于正则表达式的匹配器背后的理论并不太难。但要完全理解还需要一段时间。我认为手工编写词法分析器可以激发学习的动力,并帮助您更好地掌握问题,而不是深入研究将正则表达式转换为有限自动化的理论(首先是NFA,然后是NFA到DFA),等等...涉足那个理论可能会一次接受很多东西,而且很容易被淹没。
就个人而言,尽管Dragon Book很好,而且非常全面,但其覆盖范围可能不是最容易理解的,因为它的目标是完整,而不一定是可访问的。在打开Dragon Book之前,您可能需要尝试一些其他的编译器文本。这里有一些免费的书籍,它们有相当不错的介绍性覆盖范围,恕我直言:
http://www.ethoberon.ethz.ch/WirthPubl/CBEAll.pdf
http://www.diku.dk/~torbenm/Basics/
一些关于正则表达式实现的文章(自动词法分析通常使用正则表达式)
http://swtch.com/~rsc/regexp/
hjzp0vay2#
ANTLR 4将使用
Java.g4
参考语法来执行此操作。根据您希望Unicode转义序列的处理与语言规范的紧密程度,您有两个选项。ANTLRInputStream
Package 在JavaUnicodeInputStream
中,JavaUnicodeInputStream
在将Unicode转义序列提供给lexer之前根据JLS处理它们。编辑:这个语法生成的标记的名称与您的表稍有不同。
Key_Word
令牌为Identifier
Object_Accessor
令牌为DOT
left_Parenthesis
令牌为LPAREN
String_Literal
令牌为StringLiteral
right_Parenthesis
令牌为RPAREN
statement_separator
令牌为SEMI
9lowa7mx3#
词法分析本身就是一个主题,通常与编译器设计和分析有关。在编写代码之前,你应该先阅读它。我最喜欢的关于这个主题的书是Dragon,它会给予你一个很好的编译器设计介绍,甚至提供了所有编译器阶段的伪代码,你可以很容易地将其翻译成Java并从那里转移。
简而言之,主要思想是使用有限状态机解析输入,并将其划分为属于特定类的标记(例如,在您所需的输出中的括号或关键字)。状态机构建过程实际上是此分析的唯一困难部分,Dragon Book将为您提供对此事情的深入了解。
798qvoo84#
你可以使用像
Lex & Bison
这样的C库或者Antlr
这样的Java库。词法分析可以通过制作自动机来完成。我给你举个小例子:假设你需要标记一个字符串,其中关键字(语言)是
{'echo', '.', ' ', 'end')
,我所说的关键字是指语言只包含以下关键字。我的lexer应该输出
现在,要为这样一个记号生成器构建自动机,我可以这样开始
上图可能很糟糕,但是你有一个用
S
表示的开始状态,现在你使用E
并进入其他状态,现在你期望N
或C
分别出现在END
和ECHO
中。你不断地使用字符并在这个简单的有限状态机中到达不同的状态。最终,你到达某个Emit
状态,例如在消耗了E
,N
,D
您到达END
的emit状态,它发出令牌,然后您返回到start
状态。此循环将一直持续,直到您有字符流进入令牌化器。对于无效字符,您可以根据设计抛出错误或忽略。jmo0nnb35#
CookCC(https://github.com/coconut2015/cookcc)为Java生成一个非常快、小、零依赖的词法分析器。
bpsygsoo6#
编写一个程序来制作一个简单的词法分析器,它将从给定的字符流中构建一个符号表。您需要读取一个名为“input.txt”的文件来收集所有字符。为简单起见,输入文件将是一个没有头文件和方法的C/Java/Python程序(主程序的主体)。然后你将识别所有的数值,标识符,关键字,数学运算符,逻辑运算符和其他[distinct]。2更多细节请看例子。3你可以假设,每个关键字后面都有一个空格。