我现在和Flex / Bison一起工作了大约6个小时,这是我第一个无法解决问题的问题:
我有以下文件......
state state1: {
1-3: 255
4: 255
}
...我使用cat和|传递给我的flex / bison程序。 flex文件包含以下行:
\bstate\b { return STATE; }
并进一步向下:
.* { fprintf(stderr, "Lexer error on line %d: \"%s\"\n", linenum, yytext); exit(-1); }
应该认为\ bstate \ b应该在文件中匹配,但事实并非如此。相反,我得到以下输出:
"exer error on line 1: "state state1: {
这在很多方面都很奇怪。首先,Lexer接缝中的L被替换为“,但更重要的是,状态没有得到匹配。为什么???
当然\ bstate \ b位于。*之前,它们位于右侧。
感谢您的帮助, 扬
答案 0 :(得分:4)
(F)Lex不会在输入中搜索匹配项。它会尝试当前输入位置的所有模式,并选择与大多数文本匹配的模式,或者如果多个文本匹配相同数量的文本则选择最早的模式。下一个lex匹配将从前一个匹配开始。
.*
与该行的其余部分匹配。 \bstate\b
只匹配七个字符。所以.*
会获胜。但\bstate\b
实际上并不匹配,因为这是lex,而不是<在此处插入您最喜欢的正则表达式语法>而\b
表示退格,就像在C程序中一样。
字母L被引号覆盖的原因可能是您的输入文件是在Windows上创建的,并且在行尾有\ r \ n。 .*
将匹配包含\r
的回车符号。因此,当你打印"%s"\n
时,字符串中替换%s的最后一个字符是回车符,这会导致光标移动到当前行中的第一个点,直到那个时间点为L在里面。然后将“打印在L的顶部,最后打印换行符,开始换行。
没有Lex相当于单词边界断言\b
,但这很少是一个问题。几乎所有编程语言的词法扫描器都必须解决保留字也与标识符模式匹配的问题;但是,最长匹配和第一匹配规则的组合使得这很容易实现。简而言之,总是首先放置保留字模式。例如:
do { return DO; }
double { return DOUBLE; }
if { return IF; }
/* ... */
[a-z][a-z0-9]* { return ID; }
您放置do
和double
的顺序在上面的示例中无关紧要,因为double
更长,但我总觉得您应该将保留字放在字母中为了整洁。但重要的是ID模式是最后一个,因为它也匹配所有保留字。
现在考虑一下lexing一个以保留字开头的标识符会发生什么,例如dog
。在这种情况下,DO模式和ID模式都将匹配,但ID匹配更长,因此它会赢,尽管稍后。