我有一个程序应该根据命令行参数对输入进行词法分析。因此,要求是 1/2
被词法化为:
NUMBER
SLASH
NUMBER
...当给定一个命令行参数时,词法分析为:
FREEFORM_TOKEN
...当给定另一个命令行参数时。我使用的工具是 flex。
我想知道 flex 是否可以支持这种用例。我的规则是:
[0-9]+(.[0-9]+)?([eE][-+]?[0-9]+)? {
yylval->d = atof(yytext);
return NUMBER;
}
[A-Za-z0-9_.]([A-Za-z0-9_./]*[A-Za-z0-9_.])? {
yylval->s = strdup(yytext);
return FREEFORM_TOKEN;
}
我能否通过 if 语句简单地动态打开/关闭然后标记,如下所示:
[0-9]+(.[0-9]+)?([eE][-+]?[0-9]+)? {
yylval->d = atof(yytext);
return NUMBER;
}
[A-Za-z0-9_.]([A-Za-z0-9_./]*[A-Za-z0-9_.])? {
if (cmd_line_argument_given)
{
yylval->s = strdup(yytext);
return FREEFORM_TOKEN;
}
}
...或者 .l 文件中的长正则表达式是否存在问题,这会导致 1/2
匹配但不返回任何内容?
在实践中我应该如何实现这个要求?
我应该这样做吗:
<INITIAL,CMDOPT>[0-9]+(.[0-9]+)?([eE][-+]?[0-9]+)? {
yylval->d = atof(yytext);
return NUMBER;
}
<CMDOPT>[A-Za-z0-9_.]([A-Za-z0-9_./]*[A-Za-z0-9_.])? {
yylval->s = strdup(yytext);
return FREEFORM_TOKEN;
}
...然后执行 BEGIN(CMDOPT)
如果我想打开 FREEFORM_TOKEN
并且将其保留在 INITIAL
状态,如果我想关闭 FREEFORM_TOKEN
?然后所有规则都将具有 INITIAL
和 CMDOPT
状态,但 FREEFORM_TOKEN
除外,它只有 CMDOPT
状态。
最佳答案
I'm wondering whether flex can support this use case.
是的,以各种方式。
Can I simply dynamically turn on/off then token by an if statement, like this:
不,那不是(完全)其中一种方法。如果您只是将是否采取任何行 Action 为条件,那么当没有采取行动时, token 将被静默消耗,而不是根据不同的规则进行匹配。
在这种情况下,要让 flex 回退到不同的规则,您可以使用 the REJECT()
directive .这指示 flex 改为应用与输入(或其前缀)匹配的下一个最佳规则。
请注意,REJECT
完全出现在您的扫描器定义中会使整个扫描器变慢。这是您可以为扫描仪性能做的最糟糕的事情。但实际上这对您来说可能不是问题。
How in practice should I implement this requirement?
Should I [use start conditions] instead [?]
开始条件通常是在不同规则子集中进行选择的更好选择。正如@Cheatah 首先观察到的,您可以使用 yy_push_state()
在扫描开始之前适本地设置开始条件。这是我的建议。
如果您确实使用开始条件,那么您可以通过使用其中两个来简化您的规则,每个语法选项一个,并使它们包含。然后,您未标记任何开始条件的所有规则将适用于两者,您只需标记那些特定于一个或另一个开始条件的规则。
关于c - 动态打开和关闭 flex token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57465900/