我如何解析包含bison / flex?

时间:2017-01-17 10:46:51

标签: c++11 bison flex-lexer

我想通过解析链接器脚本来执行以下示例

example.ld

MEMORY 
{
  INCLUDE example_include.ld 
}

example_include.ld

rom   : ORIGIN = 0, LENGTH = 256K

我找到了一些代码可以做到这一点,但它是c flex / bison,我使用c ++ flex / bison。

我发现我可以使用yyFlexLexer lexer; 它提供了我:yy_create_buffer()等等......

这是我在binutils / ld / ldlex.l中找到的代码。也许它可以帮助我。

void
lex_push_file (FILE *file, const char *name, unsigned int sysrooted)
{
    if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
    {
      einfo ("%F:includes nested too deeply\n");
    }
  file_name_stack[include_stack_ptr] = name;
  lineno_stack[include_stack_ptr] = lineno;
  sysrooted_stack[include_stack_ptr] = input_flags.sysrooted;
  include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;

  include_stack_ptr++;
  lineno = 1;
  input_flags.sysrooted = sysrooted;
  yyin = file;
  yy_switch_to_buffer (yy_create_buffer (yyin, YY_BUF_SIZE));
}

我的问题是,我找不到一个好的例子或文档,如何使用c ++ bison / flex?例如,我无法使用yyin,因为它受到保护而非公开。

1 个答案:

答案 0 :(得分:2)

最简单的解决方案是递归调用解析器,将其传递给要解析的文件。有关如何将外部解析器与内部解析器的环境信息(即解析状态)进行通信的确切细节将在很大程度上取决于内部数据结构的性质,因此我甚至不打算冒险猜测。如果你正在做的就是构建一个AST(这几乎总是最好的解决方案,即使它一见钟情似乎也没什么吸引力),那么除了让解析器将AST返回给调用者之外你不需要做任何事情。它成功解析了一个文件。

解析器(或其管理器)通常会创建一个新的Lexer对象来扫描提供的输入文件;由于C ++扫描仪是完全可重入的,因此两个词法分析器的共存不会带来任何困难。这避免了使用缓冲区堆栈,并且通常是一个更清洁的解决方案。

这避免了在bison / flex解析器中处理“includes”的经典问题,这是一个天真的解决方案允许语法上下文从包含的文件泄漏回包含文件。如果包含的文件包含未终止的块(或未终止的注释),则该语法上下文可能会在包含的末尾继续处于活动状态,从而导致不直观且常常误导性的错误消息。递归策略将在包含文件的末尾触发语法错误,这也将使错误恢复更容易。

免责声明:我真的不喜欢flex和bison生成的扫描仪和解析器的C ++接口。也许有一天我会改变主意;我承认这可能只是知识上的懒惰。在任何情况下,除了一些玩具之外,我构建的唯一解析器使用C API,即使我用C ++编写动作(我经常这样做)。所以我在这里没有提供任何示例代码,但我认为这并不特别困难。