我是Treetop的新手并尝试编写CSS/HSS解析器.HSS通过嵌套样式,变量和一种mixin功能增强了CSS的基本功能.
我非常接近 - 解析器可以处理CSS - 但是在实现样式中的样式时我会堕落.例如:
#rule #one {
#two {
color: red;
}
color: blue;
}
Run Code Online (Sandbox Code Playgroud)
我对它进行了两次射击,一次是处理空白,一次是处理空白.我不能上班.树梢文件有点稀疏,我真的觉得我缺少一些基本的东西.希望有人可以帮我.
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
线束代码:
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
Run Code Online (Sandbox Code Playgroud)
我假设您遇到了左递归问题?如果是这样,请记住 TreeTop 生成递归下降解析器,因此,您不能在语法中真正使用左递归。(尽管它的外观非常性感,但我仍然更喜欢 ocamlyacc/ocamllex 而不是 TreeTop 的主要原因之一。)这意味着您需要从左递归形式转换为右递归形式。既然您毫无疑问拥有《龙之书》(对吗?),我将引导您阅读涵盖该问题的 4.3.3、4.3.4 和 4.4.1 节。正如典型的那样,它很难理解,但解析器的声誉并不是白来的。还有一个很好的左递归消除教程,是 ANTLR 的人针对这个主题发布的。它在某种程度上是 ANTLR/ANTLRworks 特有的,但比 Dragon Book 中的内容更容易理解。对于以前至少做过几次的人来说,这是一件没有多大意义的事情。
另外,小评论,如果您要使用 TreeTop,我建议您这样做:
def ws
[\t ]*
end
Run Code Online (Sandbox Code Playgroud)
您不太可能需要匹配单个空白字符,而且几乎每个语法规则都需要它,因此将其命名为非常短的名称是有意义的。顺便说一句,单独的词法分析步骤有一些优点。这是其中之一。