Анализатор CSS / HSS в правилах Treetop и Nested Stylesheet - PullRequest
5 голосов
/ 24 апреля 2009

Я новичок в Treetop и пытаюсь написать синтаксический анализатор CSS / HSS. HSS дополняет базовую функциональность CSS вложенными стилями, переменными и своего рода функциональностью смешивания.

Я довольно близок - синтаксический анализатор может обрабатывать CSS - но я не согласен с реализацией стиля в стиле. например:

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

Я сделал два снимка: один пробел, другой - нет. Я не могу заставить их работать. Древовидная документация немного скудна, и я действительно чувствую, что упускаю что-то фундаментальное. Надеюсь, кто-нибудь может меня поправить.

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

Ответы [ 2 ]

3 голосов
/ 10 июня 2009

Я полагаю, у вас проблема с левой рекурсией ? Если это так, имейте в виду, что TreeTop создает парсеры рекурсивного спуска , и поэтому вы не можете использовать рекурсию слева в своей грамматике. (Одна из главных причин, по которой я до сих пор предпочитаю ocamlyacc / ocamllex, а не TreeTop, несмотря на его очень сексуальный внешний вид.) Это означает, что вам необходимо преобразовать рекурсивные формы слева в рекурсию справа. Поскольку вы, несомненно, владеете Книгой Дракона (верно?), Я направлю вас к разделам 4.3.3, 4.3.4 и 4.4.1, которые освещают эту проблему. Как правило, это трудно понять, но парсеры не получили свою репутацию ни за что. Также есть хороший левый учебник по устранению рекурсии , который ребята из АНТЛР поставили на эту тему. Это несколько специфично для ANTLR / ANTLR, но это немного легче понять, чем то, что можно найти в Книге Дракона. Это одна из тех вещей, которые просто не имеют большого смысла для тех, кто не делал этого хотя бы несколько раз раньше.

Также, небольшой комментарий, если вы собираетесь использовать TreeTop, я рекомендую сделать это вместо:

def ws
  [\t ]*
end

Вам вряд ли когда-либо понадобится соответствовать одному пробелу, плюс оно понадобится практически каждому грамматическому правилу, поэтому имеет смысл назвать его очень коротким. Кстати, у есть преимуществ для отдельного шага лексирования. Это один из них.

1 голос
/ 17 июня 2009

Похоже, кто-то избил меня до этого:

http://lesscss.org/

Хотя я заметил, что они используют регулярные выражения и eval () для анализа входного файла, а не анализатора.

Редактировать: теперь они используют TreeTop! Как будто кто-то сделал всю тяжелую работу за меня.

...