2

クトゥルフの答えを繰り返したくありませんが、Treetopを使用してHTMLタグの開始と終了のペアを一致させたいと思います。この文法を使用して、開始タグと終了タグを一致させることができますが、ここでは、両方を結び付けるルールが必要です。私は次のことを試しましたが、これを使用すると、パーサーが永久に続行されます(無限ループ)。

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

これは、TreetopGithubページの再帰的な括弧の例とネガティブな先読みの例に基づいて作成しようとしていました。私が参照した他のルールは次のとおりです。

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タグのペアが存在する場合は、それらをペアとしてまとめたいと思います。それらを私の文法と一致させることによってこれを行うのが最もきれいに見えましたが、おそらくもっと良い方法がありますか?

4

2 に答える 2

5

これは、セマンティック述語を使用して終了タグを開始タグに一致させる非常に単純な文法です。

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
于 2012-11-22T18:24:00.613 に答える
1

これを行うには、HTMLタグのペアごとに個別のルールを使用するか、セマンティック述語を使用する必要があります。つまり、開始タグを(sempredに)保存してから、同じタグである場合にのみ終了タグを(別のsempredに)受け入れます。Treetopでこれを行うのは、コンテキストを保存するのに便利な場所がなく、パーサースタックを覗き見できないため、本来よりもはるかに困難ですが、それは可能です。

ところで、同じ問題がMIME境界の解析(およびMarkdown)でも発生します。ActionMailerでMikelの実装をチェックしていません(おそらく彼はそのためにネストされたMimeパーサーを使用しています)が、Treetopでは可能です。

http://github.com/cjheath/activefacts/blob/master/lib/activefacts/cql/parser.rbで、コンテキストを偽の入力ストリームに保存します-サポートする必要のあるメソッドを確認できます-「入力」はすべてのSyntaxNodeで利用できます。そこでsempredを使用する理由はさまざまですが、いくつかの手法を適用できます。

于 2012-08-31T00:45:11.993 に答える