在运行时从语法构建解析器

时间:2011-09-12 18:36:09

标签: c++ parsing runtime grammar parser-generator

C ++的许多(大多数)正则表达式库允许在运行时从字符串创建表达式。是否有人知道任何C ++解析器生成器允许在运行时将表示为字符串的语法(最好是BNF)提供给生成器?我发现的所有实现都要求运行显式代码生成器,或者需要通过巧妙的模板元编程来表达语法。

5 个答案:

答案 0 :(得分:4)

构建一个接受语法作为输入的递归下降,回溯解析器应该很容易。您可以将所有规则缩减为以下形式(或表现得如下):

 A = B C D ;

通过递归下降解析这样的规则很容易:调用一个对应于找到B的例程,然后找到一个找到C的例程,然后找一个找到D的例程。鉴于你正在做一般解析器,你总是可以调用一个“parse_next_sentential_form(x)”函数,并将所需形式的名称(终端或非终结令牌)传递为x(例如,“B”,“C”,“D”)。

在处理这样的规则时,解析器想要生成A,通过找到B,然后是C,然后是D.为了找到B(或C或D),你想要一个索引的规则集所有左侧都是相同的,因此可以轻松枚举B生成规则,并递归处理其内容。如果您的解析器出现故障,它只会回溯。

这不是一个闪电般快速的解析器,但如果实施得好,应该不会很糟糕。

还可以使用Earley解析器,它通过创建部分处理规则的状态来解析。

如果你想要快速,我想你可以简单地把Bison的胆量带入库中。然后,如果你有语法文本或语法规则(Bison的不同入口点),你可以启动它并让它在内存中生成它的表(它必须以某种形式)。不要吐出来;只需构建一个使用它们的LR解析引擎。 Voila,即时高效的解析器生成。 如果你这样做,你必须担心语法的歧义和你的语法的LALR(1);前两个解决方案适用于任何上下文无关语法。

答案 1 :(得分:1)

我不知道现有的库。但是,如果性能和稳健性并不重要,那么您可以分离生物或任何其他生成C代码的工具(通过popen(3)或类似代码),在生成的代码上分离gcc,将其链接到共享库并加载库通过dlopen(3)/ dlsym(3)。在Windows上 - DLL和LoadLibrary()代替。

答案 2 :(得分:1)

最简单的选择是嵌入一些脚本语言甚至是一个成熟的VM(例如,Mono),并在其上运行生成的解析器。 Lua有一个非常强大的JIT编译器,不错的元编程功能和几个可以使用的Packrat实现,所以可能它是最省力的方式。

答案 3 :(得分:1)

我刚遇到这个http://cocom.sourceforge.net/ammunition++-13.html
最后一个是Earley Parser,它似乎把语法作为一个字符串。
其中一项功能是:

  

公共函数`parse_grammar'

         `int parse_grammar (int strict_p, const char *description)'
     

是另一个将解析器调整为给定语法的函数。     语法由字符串`description'给出。     描述与YACC类似。

实际代码位于http://sourceforge.net/projects/cocom/

修改

较新的版本位于https://github.com/vnmakarov/yaep

答案 4 :(得分:-1)

boost::spirit是一个C ++解析框架,可用于在运行时动态构造解析器。