5

我是 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

乙:

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 产生递归下降解析器,因此,您不能真正在语法中使用左递归。(尽管它的外观非常性感,但我仍然更喜欢 ocamlyacc/ocamllex 而非 TreeTop 的主要原因之一。)这意味着您需要从左递归形式转换为右递归形式。既然您无疑拥有《龙之书》(对吗?),我将引导您查看涵盖该问题的第 4.3.3、4.3.4 和 4.4.1 节。就像典型的那样,这很难理解,但解析器并不是一无所获。还有一个不错的左递归消除教程ANTLR 的人提出了这个问题。它有点特定于 ANTLR/ANTLRworks,但它比 Dragon Book 中的内容更容易理解。对于以前至少没有做过几次的人来说,这是其中一件根本没有意义的事情。

另外,小评论,如果您要使用 TreeTop,我建议您这样做:

def ws
  [\t ]*
end

您不太可能需要匹配单个空格字符,而且几乎所有语法规则都需要它,因此将其命名为非常短的名称是有意义的。顺便说一下,单独的词法分析步骤有一些优点。这是其中之一。

于 2009-06-10T01:52:43.857 回答
1

看起来有人打败了我:

http://lesscss.org/

尽管我注意到他们使用正则表达式和 eval() 来解析输入文件而不是解析器。

编辑:现在他们使用 TreeTop!就像有人为我做了所有的努力。

于 2009-06-17T14:09:33.137 回答