使用BNF语法提取信息

时间:2012-06-12 14:20:57

标签: c++ parsing bnf information-extraction

我想从一组文本中提取信息并能够查询它。

这个文本主体的结构将由BNF语法(或变体)指定,并且要提取的信息将在运行时指定(此时查询的语法无关紧要。)

所以要求很简单,真的:

  • 接收一些结构化的文本
  • 使用语法将其加载为可利用的形式以进行解析
  • 运行查询以选择部分内容

为了举例说明,假设我们有这样的语法(采用自定义的BNF格式):

<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<id> ::= 15 * digit

<hex> ::= 10 * (<digit> | a | b | c | d | e | f)

<anything> ::= <digit> | .... (all characters)

<match> ::= <id> (" " <hex>)*

<nomatch> ::= "." <anything>*

<line> ::= (<match> | <nomatch> | "") [<CR>] <LF>

<text> ::= <line>+

这样的文字符合要求:

012345678901234
012345678901234 abcdef0123

Nor the previous line nor this one would match

然后我想列出规则中出现的所有标签,例如使用类似XPath的语法:

match//id

将返回一个列表。


这听起来相对容易,除了我有两个很大的限制因素:

  • BNF语法应该在运行时读取(来自字符串/矢量的结构)
  • 查询也将在运行时读取

一些准确性:

  • 语法预计不会经常改变,因此产生内存结构的“编译”步骤是可以接受的(也许是实现良好速度所必需的)
  • 速度至关重要,即想收集部分的奖励积分
  • 有可能使回调消除歧义的奖励积分(例如,有时必要的消歧信息可能需要数据库访问)
  • 多部分语法的奖励积分(支持模块化和语法元素的重用)

我知道lex / yacc和flex / bison,但是他们似乎只创建了要编译的C / C ++代码,这不是我所关注的。

  

你知道一个健壮的库(最好是免费的和开源的)可以将“BNF语法”转换为“即时”的解析器,并使用这个解析器从文本体中生成结构化的内存输出?

编辑:我对替代方案持开放态度。目前,这个想法可能是正则表达式可以允许这种提取,但是考虑到所涉及的语法的复杂性,这可能会很快变得难看,因此保持正则表达式将是一项非常可怕的任务。此外,通过分离语法和提取,我希望能够为不同的提取需求重用相同的语法,而不是每次都有略微不同的正则表达式。

2 个答案:

答案 0 :(得分:2)

我有一个专有的解决方案,可以将语法源转换为内存表示。结果是纯数据结构。任何代码都可以使用它。我也有C ++类实际上实现了解析器。规则处理程序实现为虚拟方法。

我们的解决方案与YACC / Bison之间的主要区别在于没有生成C / C ++代码。这意味着可以重新加载语法而无需重新编译应用程序。语法可以使用在规则处理程序的代码中使用的应用程序ID进行注释。

答案 1 :(得分:1)

GOLD解析器系统生成一个LALR解析表,在运行时可以显式加载AFAIK。我相信它有一个C ++“解析”引擎,因此应该易于集成。

你已经阅读了你的语法,派了一个子进程来获取GOLD解析器生成器来生成表,然后调用你的有线GOLD解析器进行加载和解析。

我不知道如何将操作附加到缩减中,您可能希望这样做。 我对GOLD没有具体经验。 “金”运气给你。