【问题标题】:Call flex yy_push_state() from bison parser从野牛解析器调用 flex yy_push_state()
【发布时间】:2015-02-06 04:32:24
【问题描述】:

是否可以从野牛生成的解析器中调用yy_push_state()?如何做到这一点?

context:
    /* empty */ { $$ = NULL; yy_push_state(SOME_STATE); }
;

rule:
    context operator STRING { create_expr($2, $3); }
;

我希望能够从解析器调用yy_push_state(),并且还想知道这是否是一种可接受的做法。如果不是,那么与词法分析器通信它应该推送状态的替代方法是什么?

在这种特定情况下,只有解析器知道何时推送SOME_STATE

【问题讨论】:

    标签: bison flex-lexer


    【解决方案1】:

    这当然是可能的,但有一个巨大的警告。在我提供的示例中,为什么您觉得需要这样做对我来说并不明显;可能有替代方案,但如果不了解有关用例的更多详细信息,就不可能提供任何建议。

    这是警告。在您提供的示例中,状态推送是由标记生成生成的;从概念上(甚至在实践中)您可以使用中间规则操作:

    rule:                 { yy_push_state(SOME_STATE); }
          operator STRING { create_expr($2, $3); }
    

    当空生产减少时会发生状态推送;在读取operator 的第一个标记之前可能会或可能不会发生,但在大多数情况下会在之后。因此,例如,如果打算更改词法分析器以识别(或不识别)特定于上下文的运算符,那么它可能会失败。

    bison 如果在解析中的那个点完全不需要前瞻令牌,通常会立即减少(没有前瞻令牌),但不能保证这种行为,恕我直言不应该依赖。其他解析器(例如 yacc)不这样做;较旧的野牛版本没有 IIRC,至少有可能不同的解析器类型(IELR、GLR)可能对是否需要先行令牌有不同的看法。

    因此,总的来说,最好为已读取前瞻令牌的可能情况做好准备(例如,这就是为什么需要复制yytext),同时注意不要做出假设它会被阅读。

    如果您的状态更改足够稳健,请继续在解析器中执行 yy_push_state

    例如,假设operation 不可为空,并且状态更改将更改识别STRING 的规则,但不会对operator 中可能出现的任何标记的词法扫描产生任何影响.在这种情况下,yy_push_state 是安全的。

    我见过这种黑客尝试的一个地方是尝试解析 awk 和 javascript 等语言,其中 / 可能是除法运算符或正则表达式文字的开头。在这种情况下,可以让解析器更改正则表达式中的词法状态:

    // Lexer
    "/"  { return '/';
           /* No semantics, the parser will know what it means */
         }
    <REGEX> {
       /* Lots of rules here. But unescaped / is just the same as above */
       "/"  { return '/';
              /* No semantics, the parser will know what it means */
            }
    }
    
    // Parser
    expr: { BEGIN(REGEX); } '/' regex { BEGIN(INITIAL); } '/'
        | expr '/' expr
        | ...
    

    在上述情况下,状态更改不会影响词​​法分析器处理 / 的方式,因此如果该斜杠被识别为开始(或结束)正则表达式,则状态更改将发生就在扫描 / 令牌之前或(更有可能)之后。如果词法分析器尝试(不必要,但这似乎是一种诱惑)为 / 的两种不同用途返回不同的标记,这将不会起作用;一个好的指导原则是词法分析器对标记的语义了解得越少越好。

    【讨论】:

    • 我真的很感谢您的考虑,您刚刚提供的示例再好不过了。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多