5

私は Treetop を初めて使用し、CSS/HSS パーサーを作成しようとしています。HSS は、ネストされたスタイル、変数、および一種の mixin 機能を使用して、CSS の基本機能を強化します。

私はかなり近いです - パーサーは CSS を処理できます - しかし、スタイルにスタイルを実装することになると、私は落ち込みます。例えば:

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

1 つは空白を処理し、もう 1 つは空白を処理しません。私はどちらもうまく機能させることができません。ツリートップのドキュメントは少しまばらで、基本的なものが欠けているように感じます。うまくいけば、誰かが私をまっすぐにすることができます。

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

ハーネスコード:

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
4

2 に答える 2

3

左再帰の問題が発生していると思いますか?その場合、TreeTop はrecursive descent parser を生成することに注意してください。そのため、文法で左再帰を実際に使用することはできません。(非常にセクシーな外観にもかかわらず、私が今でも TreeTop よりも ocamllyacc/ocamllex を好む主な理由の 1 つです。) これは、左再帰形式から右再帰形式に変換する必要があることを意味します。あなたは間違いなくDragon Bookを所有しているので(そうですか?)、この問題をカバーするセクション 4.3.3、4.3.4、および 4.4.1 を紹介します。よくあることですが、理解するのは難しいですが、パーサーはただで評判を得たわけではありません。素敵な左再帰除去チュートリアルもありますANTLRの連中がこの問題に取り組んだこと。ANTLR/ANTLRworks 固有のものですが、Dragon Book にあるものよりも少し理解しやすいです。これは、少なくとも数回はやったことがない人にとっては、まったく意味をなさないことの 1 つです。

また、ちょっとしたコメントですが、TreeTop を使用する場合は、代わりに次のようにすることをお勧めします。

def ws
  [\t ]*
end

単一の空白文字に一致させる必要はほとんどなく、ほぼすべての文法規則で必要になるため、非常に短い名前を付けるのが理にかなっています。ちなみに、個別の字句解析ステップに利点があります。これはそれらの1つです。

于 2009-06-10T01:52:43.857 に答える
1

誰かが私を打ち負かしたようです:

http://lesscss.org/

パーサーではなく、正規表現と eval() を使用して入力ファイルを解析していることに気付きましたが。

編集:今、彼らは TreeTop を使用しています! 誰かが私のために一生懸命働いたようなものです。

于 2009-06-17T14:09:33.137 に答える