在Treetop语法中匹配标签对

我不想重复Cthulhu的答案,但我希望使用Treetop匹配开启和关闭HTML标签的对。使用这个语法,我可以匹配开始标记和结束标记,但现在我想要一个规则将它们绑在一起。我已尝试过以下内容,但使用此方法会使我的解析器永远继续(无限循环):
rule html_tag_pair
  html_open_tag (!html_close_tag (html_tag_pair / '' / text / newline /
    whitespace))+ html_close_tag <HTMLTagPair>
end
我试图将此基于递归括号示例和Treetop Github页面上的否定前瞻示例。我引用的其他规则如下:
rule newline
  [nr] {
    def content
      :newline
    end
  }
end

rule tab
  "t" {
    def content
      :tab
    end
  }
end

rule whitespace
  (newline / tab / [s]) {
    def content
      :whitespace
    end
  }
end

rule text
  [^<]+ {
    def content
      [:text, text_value]
    end
  }
end

rule html_open_tag
  "<" html_tag_name attribute_list ">" <HTMLOpenTag>
end

rule html_empty_tag
  "<" html_tag_name attribute_list whitespace* "/>" <HTMLEmptyTag>
end

rule html_close_tag
  "</" html_tag_name ">" <HTMLCloseTag>
end

rule html_tag_name
  [A-Za-z0-9]+ {
    def content
      text_value
    end
  }
end

rule attribute_list
  attribute* {
    def content
      elements.inject({}){ |hash, e| hash.merge(e.content) }
    end
  }
end

rule attribute
  whitespace+ html_tag_name "=" quoted_value {
    def content
      {elements[1].content => elements[3].content}
    end
  }
end

rule quoted_value
  ('"' [^"]* '"' / "'" [^']* "'") {
    def content
      elements[1].text_value
    end
  }
end
我知道我需要允许匹配单个开始或结束标签,但如果存在一对HTML标签,我想将它们作为一对组合在一起。通过将它们与我的语法相匹配来做到这一点似乎最干净,但也许有更好的方法呢?     
已邀请:
您只能使用每个HTML标记对的单独规则或使用语义谓词来执行此操作。也就是说,通过保存开始标记(在一个sempred中),然后仅在它是相同的标记时接受(在另一个sempred中)结束标记。这在Treetop中要比应该做的要困难得多,因为没有方便的地方来保存上下文而你无法查看解析器堆栈,但它是可能的。 顺便说一句,在解析MIME边界(和Markdown)时会出现同样的问题。我没有检查过MikM在ActionMailer中的实现(可能他使用了嵌套的Mime解析器),但在Treetop中它是可能的。 在http://github.com/cjheath/activefacts/blob/master/lib/activefacts/cql/parser.rb中我将上下文保存在假输入流中 - 您可以看到它必须支持哪些方法 - 因为“输入”是适用于所有语法节点。我有一个不同的理由在那里使用sempreds,但有些技术是适用的。     
这是一个非常简单的语法,它使用语义谓词将结束标记与起始标记相匹配。
grammar SimpleXML
  rule document
    (text / tag)*
  end

  rule text
    [^<]+
  end

  rule tag
    "<" [^>]+ ">" (text / tag)* "</" [^>]+ &{|seq| seq[1].text_value == seq[5].text_value } ">"
  end
end
    

要回复问题请先登录注册