我目前正在编写一个编译器,我正处于词法分析器阶段。
我知道lexer对输入流进行了标记。
但是,请考虑以下流:
int foo = 0;词法分析器的输出应该是:Keyword letter letter letter equals digit semicolon?然后解析器将letter letter letter还原为标识符?
发布于 2016-04-18 04:03:22
一般来说,词法分析器应该生成一个包含语言元素的结构流:操作符、标识符、关键字、注释等。这些结构应该标记词位的类型,并携带与其表示的词位类型相关的内容。
为了实现良好的错误报告,最好每个词位都包含有关开始行和列、结束行行和列(有些词位跨越多行)以及原始源文件(有时解析器必须处理包含文件和主文件)的信息。
对于那些包含可变内容(数字、标识符等)的语言元素,结构应该包含可变内容。
对于编译或程序分析,lexer可以去掉空格和注释。如果您打算解析/修改代码,则需要捕获注释。
示例输出可能具有指导性。对于OP示例的一个变体:
/* My test file */
int foo
= 0; // a declaration..。DMS的C前端生成以下词位(这是一个调试输出,在设计复杂的词法分析器时非常方便):
C:\DMS\Domains\C\GCC4\Tools\Lexer\Source>run ../domainlexer C:\temp\test.c
Lexer Stream Display 1.5.1
Using encoding Unicode-UTF-8?ANSI +CRLF +1 /^I
!! Lexer:ResetLexicalModeStack
!! after Lexer:PushLexicalMode:
Lexical Mode Stack:
1 C
File "C:/temp/test.c", line 1: /* My test file */
File "C:/temp/test.c", line 2:
File "C:/temp/test.c", line 3: int foo
!! Lexer:GotoLexicalMode 2 CMain
!! Lexeme @ Line 3 Col 1 ELine 3 ECol 4 Token 23: 'int' [VOID]=0000
<<< PreComments:
Comment 1 Type 1 Line 1 Column 1 `/* My test file */'
!! Lexeme @ Line 3 Col 4 ELine 3 ECol 5 Token 2: whitespace [VOID]=0000
!! Lexeme @ Line 3 Col 5 ELine 3 ECol 8 Token 210: IDENTIFIER [STRING]=`foo'
File "C:/temp/test.c", line 4: = 0; // a declaration
!! Lexer:GotoLexicalMode 1 C
!! Lexeme @ Line 3 Col 8 ELine 4 ECol 5 Token 2: whitespace [VOID]=0000
!! Lexer:GotoLexicalMode 2 CMain
!! Lexeme @ Line 4 Col 5 ELine 4 ECol 6 Token 113: '=' [VOID]=0000
!! Lexeme @ Line 4 Col 6 ELine 4 ECol 7 Token 2: whitespace [VOID]=0000
!! Lexeme @ Line 4 Col 7 ELine 4 ECol 8 Token 138: INT_LITERAL [NATURAL]=0
File "C:/temp/test.c", line 5:
!! Lexeme @ Line 4 Col 8 ELine 4 ECol 9 Token 98: ';' [VOID]=0000
>>> PostComments:
Comment 1 Type 2 Line 4 Column 10 `// a declaration'
File "C:/temp/test.c", line 5:
File "C:/temp/test.c", line 6:
File "C:/temp/test.c", line 7:
!! Lexer:GotoLexicalMode 1 C
!! Lexeme @ Line 4 Col 26 ELine 7 ECol 1 Token 2: whitespace [VOID]=0000
!! Lexeme @ Line 7 Col 1 ELine 7 ECol 1 Token 4: end_of_input_stream [VOID]=0000
!! Lexer:GotoLexicalMode 2 CMain
!! Lexeme @ Line 7 Col 1 ELine 7 ECol 1 Token 0: EndOfFile
11 lexemes processed.
0 lexical errors detected.
C:\DMS\Domains\C\GCC4\Tools\Lexer\Source>主要输出是标记为!!的行,每个行代表词法分析器生成的词位结构的内容。每个词位都包含:
最后一个"token“EndOfFile是在每个DMS lexer中隐式定义的。
这个调试跟踪还记录了词法分析器在词法模式之间的转换(许多词法分析器生成器具有多种模式,在这些模式中,它们对语言的不同部分进行了分析)。它在读取源代码行时显示它们。
发布于 2016-04-18 03:28:16
将"letter“作为中间步骤并没有实际的好处-相反,"foo”可能应该是一个标识符。否则,您也可以将int理解为"letter letter“,这没有多大意义。
发布于 2016-04-18 03:34:10
对于一般情况,没有简单的答案。
通常,如果语言的语法允许,让词法分析器识别“更高级别”的元素会更容易,比如标识符,甚至类型或变量。语法越动态,标记的解释越依赖于内部状态,如果是解析器,那么将解释放在解析器上可能会更容易。否则,lexer和parser之间的通信可能会变得过于复杂。(例如,考虑一种语言,其中int在一个位置是类型,在另一个位置是有效的变量名,在第三种情况下是language关键字)
经验法则:让词法分析器做所有保持语法简单的工作,而不会在词法分析器和解析器之间造成额外的复杂性。
https://stackoverflow.com/questions/36681102
复制相似问题