在不使用`unput()`

时间:2018-01-29 17:41:04

标签: lex

让我们说我在flex中解析十六进制数字。我有这样的事情:

%x hexnumber
%%
"0x"                { BEGIN hexnumber }
<hexnumber>[0-9A-F] { process_digit(); }

这很好用; 0x前缀启动十六进制解析模式,然后依次处理每个数字。

问题是十六进制常量没有明确的终结符令牌。那么,我该如何切换回INITIAL状态?当我知道下一个字符不是数字常量的一部分时,它就被消耗了。

我总是可以使用unput()

将其推回输入流
<hexnumber>.        { unput(*yytext); BEGIN INITIAL; }

...但我非常不愿意这样做(因为使用unput()超出本问题范围的实施细节对我来说非常昂贵。)

我知道生成的状态机能够自动切换回INITIAL状态而不消耗下一个字符,因为否则[0-9A-F]+之类的规则将无法工作。有没有办法使用显式启动条件来实现这一目标?

1 个答案:

答案 0 :(得分:1)

使用yyless(0)代替unput(*yytext); yyless基本上是免费的,因为它只调整了几个指针。它不会尝试重新分配或移动输入缓冲区。 (当然,你还需要BEGIN(INITIAL)。)

更麻烦的解决方案是使用尾随上下文来区分十六进制字符后跟其他十六进制字符:

 [[:xdigit:]]/[[:xdigit:]]    process_digit();
 [[:xdigit:]]                 process_digit(); BEGIN(INITIAL);

但这不太灵活。