Frage

Ich will nicht eine Wiederholung von die Antwort Cthulhu, aber ich möchte Paare Öffnung zusammenpassen und mit Treetop HTML-Tags zu schließen. Mit diese Grammatik , kann ich öffnenden Tags und End-Tags entsprechen , aber jetzt möchte ich eine Regel, sie beide zusammen zu binden. Ich habe die folgende versucht, aber mit diesem macht mein Parser für immer weitergehen (Endlosschleife):

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

Ich habe versucht, diese aus dem rekursiven Klammern Beispiels zu stützen und das negative Vorschau Beispiel auf der Treetop Github Seite . Die anderen Regeln Ich habe verwiesen wird, sind wie folgt:

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

Ich weiß, ich werde zum Anpassen einzelnes Öffnens oder Schließen-Tags erlauben müssen, aber wenn ein Paar von HTML-Tags vorhanden ist, würde ich sie gerne als Paar zusammen zu bekommen. Es schien, saubersten, dies zu tun, indem sie mit meiner Grammatik übereinstimmt, aber vielleicht gibt es einen besseren Weg?

War es hilfreich?

Lösung

Sie können nur diese für jedes HTML-Tag-Paar entweder eine separate Regel unter Verwendung tun, oder eine semantische Prädikat verwendet wird. Das heißt, durch das Starttag speichern (in einem sempred), dann akzeptieren (in einem anderen sempred) einen schließenden Tag nur, wenn es den gleiche Tag ist. Das ist viel schwieriger, in Treetop zu tun, als es sein sollte, weil es kein geeigneter Ort ist, den Kontext zu speichern und Sie können den Parser-Stack nicht spähen, aber es ist möglich.

BTW, tritt das gleiche Problem MIME Grenzen beim Parsen (und in Markdown). Ich habe überprüft nicht Mikel Implementierung in Action (wahrscheinlich er verwendet einen verschachtelten Mime-Parser für die), aber es ist möglich, in Treetop.

http://github.com/cjheath /activefacts/blob/master/lib/activefacts/cql/parser.rb ich speichern Kontext in einem gefälschten Eingabestrom - können Sie sehen, welche Methoden es zur Unterstützung hat - weil „Eingang“ auf allen SyntaxNodes zur Verfügung steht. Ich habe eine andere Art des Grundes für sempreds dort verwenden, aber einige der Techniken anwendbar sind.

Andere Tipps

Hier ist eine wirklich einfache Grammatik, die ein semantisches Prädikat verwendet, um den Start-Tag das Schließschild zu entsprechen.

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top