在 flex 中包含额外的规则

Including additional rules with flex

我一直在研究一个使用 flex 的小型汇编器,但是,flex 规则列表相当长。理想情况下,我想通过将规则分成几个文件来解决这个问题,这些文件可以包含在主 lex 文件中。我的搜索没有找到任何相关信息,这让我相信这个功能可能不存在。如果它不存在,我会很好奇是否有人有其他建议。我目前唯一的替代方法是编写一个快速工具来预处理 lex 文件并构建一个新文件。这不是最漂亮的解决方案,但我想它确实有效。

所以这个问题归结为两个问题:

  1. 有没有办法在 flex 中包含额外的规则?
  2. 如果不是,您会建议哪些备选方案(如果它们与我已经提出的不同)?

如果有令人信服的理由,我并不严格反对转向不同的词法分析器。然而,在这种情况下,词法分析器需要能够生成 C 或 C++,两者都可以轻松合并到这个项目中。我确实认为这个选项是最后的选择。

flex 当然不包含任何类似于 C 预处理器 #include 指令的功能。

此外,使用 C 预处理器来预处理扫描器定义会有点笨拙,因为扫描器描述通常包括要转录到输出文件中的预处理器命令,而 C 预处理器没有任何机制来有条件地保留指令。

但是,没有什么可以阻止您简单地连接几个文件来生成扫描仪定义:

flex -o scanner.c scanner.options scanner.definitions keyword_rules.l other_rules.l

所以我已经尝试了一段时间的各种解决方案,终于有了一个我特别满意的解决方案。我最终使用 bash 来快速实现 "flex_include" 脚本。

在我解释语法添加之前,这是我想出的脚本:

#!/bin/bash
while read -r line
do
if [[ $line =~ "<<INCLUDE>>".* ]]; then
    file=$(echo $line | cut -d'"' -f2)
    while read -r line2
    do
        echo "$line2"
    done < $file
else
    echo "$line"
fi
done < 

这允许在 lex 文件中包含语法为 <<INCLUDE>> "my_file.l" 的文件。我选择了类似于 <<EOF>> 的命名约定,因此它非常适合 flex 语法。该脚本的使用相当简单,但有一个警告——管道不能直接工作。我不知道为什么会在顶部的 lex.yy.c 中生成两行额外的行。不过,我发现进程替换工作得很好:flex <(./flex_include.sh mips.l)。这个脚本在语法上非常宽容,所以请记住脚本会接受比它应该接受的更多的内容。它将搜索带有 <<INCLUDE>> 的单行,然后匹配该行上的引号字符串,忽略并删除该行上的所有其他内容。