如何在 flex lexer 中声明和重用字符 class?

How to declare and reuse a character class in flex lexer?

通常情况下,当你想重用一个正则表达式时,你可以在声明部分的flex中声明它。默认情况下,它们将被括号括起来。例如:

num_seq [0-9]+

%%

{num_seq} return INT;  // will become ([0-9]+)

{num_seq}\.{num_seq} return FLOAT;  // will become ([0-9]+)\.([0-9]+)

但是,我想重复使用一些字符 类。我可以定义自定义 类 如 [:alpha:][:alnum:] 等吗?玩具 例如:

chars [a-zA-Z]

%%

  // will become (([a-zA-Z]){-}[aeiouAEIOU])+  // ill-formed
  // desired ([a-zA-Z]{-}[aeiouAEIOU])+  // correct
({chars}{-}[aeiouAEIOU])+ return ONLY_CONS;

({chars}{-}[a-z])+ return ONLY_UPPER;

({chars}{-}[A-Z])+ return ONLY_LOWER;

但是目前,由于在它们周围添加了括号,因此无法编译。是否有适当的方法或至少有解决方法来实现此目的?

这有时可能会有用,但不幸的是它从未在 flex 中实现。您可以在 lex 兼容模式下通过 运行 flex 抑制宏替换周围的自动括号,但这可能会产生其他不良影响。

Posix 要求正则表达式括号语法包括,除了预定义字符 类,

…character class expressions of the form: [:<em>name</em>:] … in those locales where the name keyword has been given a charclass definition in the LC_CTYPE category.

很遗憾,flex 没有实现这个要求。为 flex 打补丁并不太难做到这一点,但由于没有可移植的机制允许用户将 char类 添加到他们的语言环境——而且,事实上,许多标准 C 库实现缺乏适当的语言环境支持—— - 几乎没有动力进行此更改。

看了所有这些选项后,我最终说服自己,最简单的可移植解决方案是预处理 flex 输入文件,用一组基于 name 的字符替换 [:name:]。由于该字符序列不太可能出现在 flex 输入文件中,因此使用 sed 或 python 进行 simple-minded 搜索和替换就足够了;正确解析 flex 输入文件对我来说似乎比它的价值更麻烦。