Анализатор CSS / HSS в правилах Treetop и вложенных таблиц стилей
Вопрос
Я новичок в Treetop и пытаюсь написать анализатор CSS / HSS.HSS дополняет базовую функциональность CSS вложенными стилями, переменными и своего рода смешанной функциональностью.
Я довольно близок к этому - анализатор может обрабатывать CSS - но я падаю духом, когда дело доходит до реализации стиля внутри стиль.например, g:
#rule #one {
#two {
color: red;
}
color: blue;
}
Я сделал два снимка с этого, один из которых обрабатывает пробелы, а другой - нет.Я не могу заставить ни то, ни другое приступить к работе.Документация treetop немного скудна, и я действительно чувствую, что упускаю что-то фундаментальное.Надеюсь, кто-нибудь сможет наставить меня на путь истинный.
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
Решение
Я предполагаю, что вы сталкиваетесь с левая рекурсия проблемы?Если это так, имейте в виду, что верхушка дерева производит анализаторы рекурсивного спуска, и как таковой, вы действительно не можете использовать левую рекурсию в своей грамматике.(Одна из главных причин, по которой я все еще предпочитаю ocamlyacc / ocamllex TreeTop, несмотря на его очень привлекательный внешний вид.) Это означает, что вам нужно преобразовать леворекурсивные формы в праворекурсивные.Поскольку вы, несомненно, владеете Книга Дракона (верно?), я направлю вас к разделам 4.3.3, 4.3.4 и 4.4.1, которые охватывают проблему.Как это обычно бывает, это трудно понять, но парсеры не зря заслужили свою репутацию.Там также есть приятный руководство по устранению левой рекурсии что ребята из ANTLR высказались по этому поводу.Это несколько специфично для ANTLR / ANTLRWorks, но это немного легче понять, чем то, что найдено в книге Дракона.Это одна из тех вещей, которая просто не имеет особого смысла для тех, кто не делал этого хотя бы несколько раз раньше.
Кроме того, небольшой комментарий: если вы собираетесь использовать TreeTop, я рекомендую сделать это вместо:
def ws
[\t ]*
end
Вряд ли вам когда-либо понадобится сопоставлять один пробельный символ, плюс это понадобится почти каждому правилу грамматики, поэтому имеет смысл назвать его как-нибудь очень коротко.Кстати, там являются преимущества отдельного этапа лексикации.Это один из них.
Другие советы
Похоже, кто- то опередил меня в этом:
Хотя я заметил, что они используют регулярные выражения и eval() для анализа входного файла, а не синтаксический анализатор.
Редактировать:Теперь они используют TreeTop!Как будто кто-то сделал всю тяжелую работу за меня.