【问题标题】:Modifying/Filtering yytext before calling yymore()在调用 yymore() 之前修改/过滤 yytext
【发布时间】:2014-04-26 14:46:18
【问题描述】:

假设我有以下内容:

pattern { /* 在此处过滤/处理然后调用 */ yymore(); }

我想做的是在调用 yymore() 之前过滤/处理 yytext 中的一些内容。 yytext 的长度永远不会增长,只会通过处理变得更短。这需要能够缩短 yytext。作为一个起点,我试图看看是否有一种简单的方法来例如删除 yytext 的最后一个字符,但做一些幼稚的事情,比如

yytext[yyleng-1] = '\0'; yyleng--;

行不通。 yymore() 似乎在 NIL 字符之后附加了一些东西,这表明 flex 生成的代码中有一些指针指向 yytext 的当前结尾。有没有一些惯用的方式来做到这一点,而不必编写更复杂的规则集?

像 yyless 这样的东西会把东西放回输入流中,这不是我想要的。

【问题讨论】:

    标签: flex-lexer


    【解决方案1】:

    你不能在 C 版本的 'flex' 中这样做,因为yytext 直接指向输入缓冲区。这不是副本。如果您修改输入缓冲区,您将把事情搞砸。 flex 非常小心地处理每个字符一次且仅一次,并且除了您提供给它的源之外,它不会做任何额外的缓冲。我相信它在执行操作时会暂时将 NUL 放入缓冲区,并在操作返回时再次将其取出,因此它必须有一个指向 NUL 所在位置的指针。

    我会在适当的地方将该处理转移到语法中,您必须已经复制了yytext.

    【讨论】:

    • 是否有一些关于 flex 内部如何进行缓冲区管理的好资料,还是我只需要阅读它生成的资料的来源?为了提高效率,我假设 flex 会一次从文件中读取很多内容,因此它会有一个输入缓冲区,其中包含的内容比读入 yytext 的内容要多。在这种情况下,yytext 不能指向该缓冲区,因为它是一个以 nil 结尾的字符串,因此 yytext[yyleng] 不能同时包含从输入流中读取的下一个字符以及 nil。
    • 我在很多 (很多) 年前通过彻底阅读源代码并通过与 Vern Paxson 的一些邮件交流了解到这一切正在进行中。 flex 的全部动机是 Vern 致力于“世界上最快的数据采集程序”,并且没有任何东西 - nothing - 被允许妨碍。多年后,他甚至不承认 C++ 版本中的虚函数。
    • @EdvardFagerholm: yytext[yyleng] 不能同时同时持有 NUL 和下一个字符(当然,除非下一个字符是 NUL),但 EJP 的回答是 100% 正确的: flex 保存下一个字符,覆盖一个 0,执行动作,然后恢复输入缓冲区。实现您正在寻找的通常策略是将过滤后的文本值增量复制到累加器中; GNU 软件通常为此使用 obstack,从而最大限度地减少重新分配复制。 (gnu.org/software/libc/manual/html_node/Obstacks.html)
    • 谢谢大家。这正是我想知道的,我只会阅读源代码。我试图避免使用外部缓冲区作为累加器来保存内存和复制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    • 2020-07-14
    • 1970-01-01
    • 2015-12-25
    相关资源
    最近更新 更多