Frage

Ich bin neu in Treetop und versuchen, einen CSS / HSS-Parser zu schreiben. HSS erweitert die Basisfunktionalität von CSS mit verschachtelten Formaten, Variablen und eine Art mixin Funktionalität.

Ich bin ziemlich nah - der Parser CSS umgehen kann - aber ich umfallen, wenn es um die Implementierung einer Art kommt in einen Stil. z:

#rule #one {
  #two {
    color: red;
  }
  color: blue;
}

Ich habe zwei Schüsse auf sie genommen, eine, die Leerzeichen behandelt und eine, die nicht der Fall ist. Ich kann nicht ganz bekommen entweder zu arbeiten. Die Baumwipfel Dokumentation ist ein wenig spärlich, und ich fühle mich wirklich wie ich grundlegende etwas fehlt bin. Hoffentlich kann mir jemand gerade eingestellt.

A:

 grammar Stylesheet

      rule stylesheet
        space* style*
      end

      rule style
        selectors space* '{' space* properties? space* '}' space*
      end

      rule properties
        property space* (';' space* property)* ';'?
      end

      rule property
        property_name space* [:] space* property_value
      end

      rule property_name
        [^:;}]+
      end

      rule property_value
        [^:;}]+
      end

      rule space
        [\t ]
      end

      rule selectors
        selector space* ([,] space* selector)*
      end

      rule selector
        element (space+ ![{] element)*
      end

      rule element
        class / id
      end

      rule id
        [#] [a-zA-Z-]+
      end

      rule class
       [.] [a-zA-Z-]+
      end
end

B:

grammar Stylesheet

  rule stylesheet
   style*
  end

  rule style
    selectors closure
  end

  rule closure
    '{' ( style / property )* '}'
  end

  rule property
    property_name ':' property_value ';'
  end

  rule property_name
    [^:}]+
    <PropertyNode>
  end

  rule property_value
    [^;]+
    <PropertyNode>
  end

  rule selectors
    selector ( !closure ',' selector )*
    <SelectorNode>
  end

  rule selector
    element ( space+ !closure element )*
    <SelectorNode>
  end

  rule element
    class / id
  end

  rule id
    ('#' [a-zA-Z]+)
  end

  rule class
    ('.' [a-zA-Z]+)
  end

  rule space
    [\t ]
  end

end

Harness-Code:

require 'rubygems'
require 'treetop'

class PropertyNode < Treetop::Runtime::SyntaxNode
  def value
    "property:(#{text_value})"
  end
end

class SelectorNode < Treetop::Runtime::SyntaxNode
  def value
    "--> #{text_value}"
  end
end

Treetop.load('css')

parser = StylesheetParser.new
parser.consume_all_input = false

string = <<EOS
#hello-there .my-friend {
  font-family:Verdana;
  font-size:12px;
}
.my-friend, #is-cool {
  font: 12px Verdana;
  #he .likes-jam, #very-much {asaads:there;}
  hello: there;
}
EOS

root_node = parser.parse(string)

def print_node(node, output = [])
  output << node.value if node.respond_to?(:value)
  node.elements.each {|element| print_node(element, output)} if node.elements
  output
end

puts print_node(root_node).join("\n") if root_node

#puts parser.methods.sort.join(',')
puts parser.input
puts string[0...parser.failure_index] + '<--'
puts parser.failure_reason
puts parser.terminal_failures
War es hilfreich?

Lösung

Ich nehme an, Sie laufen in Linksrekursion Probleme? Wenn ja, bedenken Sie, dass TreeTop produziert Rekursiver Abstieg , und als solche können Sie‘ t wirklich Linksrekursion in Ihrer Grammatik verwenden. (Einer der Hauptgründe, warum ich immer noch lieber ocamlyacc / ocamllex über TreeTop trotz seines sehr sexy Aussehen.) Das heißt, Sie müssen von links rekursive Formen nach rechts Rekursion konvertieren. Da Sie besitzen zweifellos die Drachen Buch (oder?), Ich ll leiten Sie zu den Abschnitten 4.3.3, 4.3.4 und 4.4.1, die das Thema abdecken. Wie typisch ist, ist es schwer zu verstehen, aber Parser nicht bekamen ihren Ruf für nichts. Es ist auch ein schönes Linksrekursion Beseitigung Tutorial dass die ANTLR Jungs setzen auf das Thema auf. Es ist etwas ANTLR / ANTLRWorks spezifisch, aber es ist etwas leichter zu verstehen als das, was in den Drachen Buch gefunden hat. Dies ist eines jener Dinge, die einfach nicht immer eine ganze Menge Sinn für jedermann machen, das es zumindest ein paar Mal, bevor nicht getan hat.

Auch kleinere Kommentar, wenn Sie TreeTop verwenden werden, empfehle, ich diese statt:

def ws
  [\t ]*
end

Sie sind nicht wahrscheinlich jemals brauchen ein einzelnes Leerzeichen entsprechen, und fast jede Grammatikregel es brauchen wird, so macht es Sinn, es zu benennen etwas sehr kurz. Übrigens gibt sind Vorteile auf einen separaten lexing Schritt. Dies ist einer von ihnen.

Andere Tipps

Sieht aus wie jemand, mich zu schlagen es:

http://lesscss.org/

Auch wenn ich merke, dass sie reguläre Ausdrücke und ein eval () verwenden, um die Eingabedatei, anstatt ein Parser zu analysieren.

Edit: Jetzt benutzen sie TreeTop! Es ist wie jemand die ganze harte Arbeit für mich getan hat.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top