我正在努力学习使用lex和yacc。这是关于lexing和定义lex规则的哲学问题。
假设您要为csv文件中的表格数据生成编译器。其中一个字段有缩写和连接数据。
VALUE1,VALUE2,I-40
VALUE3,VALUE4,US-66
最终,您关心道路是州际公路还是美国公路。当你使用这些值时,你是否应该对道路标识符进行标记,然后让编译器将I / US与数字分开并处理它,或者词法分析者应该在前端执行此操作?
答案 0 :(得分:1)
虽然这个问题非常开放,而且准确的答案可能是“它取决于”,但通常情况下,当lexing与上下文无关时,词法分析器的效果最佳。换句话说,如果字段I-40
应该被视为州际参考,无论它出现在哪里,那么在词法分析器中解释它可能是可以的。另一方面,如果需要解释某些字段而不需要解释其他字段,则在不同级别处理解释可能更合适。所以,例如:
M-Lee,"New York",I-40
I-40,Chicago,US-66
第二行的第一个字段中的I-40
是高速公路,还是只是某些看似高速公路的代码?在第二种情况下,使用像这样的解析器规则可能更合适:[1]
data: code ',' city ',' highway '\n' { $$ = MakeData($1,$3,$5); }
code: FIELD { $$ = MakeCode($1); }
city: FIELD { $$ = $1; }
highway: FIELD { $$ = MakeHighway($1); }
在第一种情况下,您可能有:
coded_data: CODE ',' FIELD ',' HIGHWAY '\n'
path_data: HIGHWAY ',' FIELD ',' HIGHWAY '\n'
假设FIELD
永远不会与CODE
或HIGHWAY
混淆。 (或者,您可以尝试将解析后的HIGHWAY
重新组合成一个简单的字段,但这也有点难看。)
所以,总的来说,我会选择以下策略之一:
在解析器调用的单独函数中处理词法解释(如上面的第一个示例所示)
在词法分析器中进行词法解释,利用flex
提供的正则表达式语言,但也保留未解释的字符串,并决定解析器中需要哪两个。 (在这种情况下,语义值更复杂struct
。)