我不想重复 克苏鲁的答案, ,但我想使用Treetop匹配开口和关闭HTML标签的对。使用 这个语法, ,我可以匹配打开标签和关闭标签,但是现在我希望一条规则将它们俩绑在一起。我已经尝试了以下操作,但是使用此功能使我的解析器永远继续(无限循环):

rule html_tag_pair
  html_open_tag (!html_close_tag (html_tag_pair / '' / text / newline /
    whitespace))+ html_close_tag <HTMLTagPair>
end

我试图以递归括号的示例和负面的lookahead示例为基础 在Treetop Github页面上. 。我提到的其他规则如下:

rule newline
  [\n\r] {
    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)中也出现了同样的问题。我尚未在ActionMailer中检查Mikel的实现(可能他为此使用了嵌套的Mime Parser),但是在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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top