将线性标记解析为可用的数据结构

时间:2011-11-01 02:55:09

标签: parsing data-structures lexical-analysis

问题*

给定一些数据(文本),其中样式应用了松散定义的标记,例如:

The [blower]cat[elower] [weight 15]sat[normal] on the mat.[newline]

理想情况下,它可以表示为:

The <text class="lower">cat</text> <strong>sat</strong> on the mat.<br />

标记具有以下属性:

  • 标签表示从该点开始以给定方式格式化文本的指令
  • 可能存在结束标记,但仅适用于少量标记。其他标签是线性的(见第1点)
  • 每个标记都有自己的行为,可能会以不同的方式影响以前应用的标记
  • 添加或覆盖现有样式的线性标记隐含了一些嵌套
  • 元数据可能在标签之外(例如[beg] [xyz] cmd [end1]与标签相关,没有内容)

要求

  • 定义关于标记交互的规则(例如,[粗体]等样式标记由另一个样式标记关闭,例如[normal]或[light])
  • 某些内容的嵌套(不会像上面那样覆盖的标签会嵌套并相应地中断)
  • 将内存表示中定义好的映射定义为某种输出格式

思想

  • 将DOM解析为类似结构 - 尝试将标记分组为“集合”。遇到标记时,请关闭该集的活动标记并打开新标记。这会生成&lt; tag&gt;内容&lt; / tag&gt;。关于正确嵌套和关闭/重新打开标签的问题,以便您不会遇到重叠情况,例如&lt; b&gt; text&lt; i&gt; text&lt; / b&gt; text&lt; / i&gt;很烦人但很直接。

您将如何设计解析内容的数据结构或方法,以便一组规则可以帮助转换为定义良好的结构?

或者,您在解决此类问题时会看到的字段/区域的任何建议?

* 真实世界问题

1 个答案:

答案 0 :(得分:1)

这个问题与XML同构(至少就像你到目前为止所描述的那样)。你有引入和结束标记的语法,它主要是成对的[blower] ... [elower]和[weight 15] ... [normal]偶尔会有独立的[换行符]。

因此,如果您知道如何使用标记构建XML解析器,那么您也知道如何执行此操作。

如果你不这样做,你只需要一个语法(在EBNF中)和一个解析器生成器:

document =  fragment* ;

fragment = TEXT ;
fragment = '[blower]' fragment '[elower]' ;
fragment = '[weight' NATURAL ']' fragment '[normal]' ;
fragment =  other_start_tag fragment other_end_tag ;
fragment = '[newline]' ;

这需要一个非常简单的词法分析器和一个非常简单的解析器。 (参见FLEX和YACC作为例子)。 通过将操作附加到语法规则(参见YACC文档),您可以将DOM构建为一组树节点,因为解析器可以运行。许多其他解析器生成器也允许您在解析时构建树。