Lex:收集规则中未定义的所有文本

Lex: Gather all text not defined in rules

我正在尝试将先前规则未定义的所有文本收集到一个字符串中,并使用 lex 为其添加格式化字符串前缀。我想知道是否有这样做的标准方法。

例如,假设我有规则:

word1|word2|word3|word4  {printf("%s%s", "<>", yytext);}
[0-9]+  {printf("%s%s", "{}", yytext);}
everything else  {printf("%s%s", "[]", yytext);}

然后我尝试对字符串进行词法分析:

word1 this is some other text ; word2 98 foo bar .

我希望它在 运行 通过词法分析器时产生以下结果:

<>word1[] this is some other text ; <>word2[] {}98[] foo bar .

我尝试使用状态来执行此操作,但意识到我无法确定何时停止检查,例如:

%x OTHER

%%
. {yymore(); BEGIN OTHER;}
<OTHER>.|\n  yymore();
<OTHER>how to determine when to end?  {printf("%s%s", "[]", yytex); BEGIN INITIAL;}

执行此操作的好方法是什么?只要不满足另一条规则,是否有某种方式可以继续?

AFAIK,没有 "standard" 解决方案,但一个简单的方法是保留一些上下文(最后打印的前缀)并使用它来决定是否打印新前缀。例如,您可以使用这样的自定义打印机:

enum OutputType { NO_TOKEN = 0, WORD, NUMBER, OTHER };
void print_with_prefix(enum OutputType type, const char* token) {
  static enum OutputType prev = NO_TOKEN;
  const char* prefix = "";
  switch (type) {
    case WORD: prefix = "<>"; break;
    case NUMBER: prefix = "{}"; break;
    case OTHER: if (prev != OTHER) prefix = "[]"; break;
    default: assert(false);
  }
  prev = type;
  printf("%s%s", prefix, token);
}

然后您只需将对 printf 的调用更改为调用 print_with_prefix(并且,如所写,提供枚举值而不是字符串)。

对于 OTHER 的情况,您不需要做任何特殊的事情来积累令牌。刚刚

.   { print_with_prefix(OTHER, yytext); }

(我对空格和换行符的处理略过,但这只是概念上的。)