2013-01-07 70 views
0

我正在爲CSS文件編寫一個簡單的ruby解析器,而且我非常難以獲得一塊CSS(即選擇器以及緊跟在花括號之後的所有內容它)作爲一個紅寶石物體,我可以執行我的黑暗和討厭的魔法。Ruby:解析純文本的結構化塊

理想情況下,我想獲得每個屬性/值和選擇器的紅寶石散列。有沒有什麼清楚和容易理解的方式如何做到這一點?

+2

你真的想不自己做呢?否則[在Ruby中尋找CSS解析器](http://stackoverflow.com/questions/5161681/looking-for-a-css-parser-in-ruby) – tokland

+0

是的。我正在編寫一個簡單的腳本,這個腳本將在我的同事之間共享,並且我希望儘量減少安裝麻煩。我也不想浪費資源來使用我只能使用三種功能的寶石。 – Nekkoru

+1

@Nekkoru從頭開始寫一些重複現有功能的東西會浪費更少的資源? –

回答

1

每個人都應該寫一個解析器。

這應該讓你開始...

require 'parslet' 
require 'ostruct' 
require 'pp' 

class Parser < Parslet::Parser 
    rule(:opencurl) { str('{') } 
    rule(:closecurl) { str('}') } 
    rule(:space)  { str(' ') } 
    rule(:space?)  { space.maybe } 
    rule(:comma)  { str(',') } 
    rule(:semi)  { str(';') } 
    rule(:colon)  { str(':') } 
    rule(:eol)  { str("\r").maybe >> str("\n") } 
    rule(:eol?)  { eol.maybe } 
    rule(:indent?) { str(" ").repeat(0) } 
    rule(:ws?)  {indent? >> eol? >> indent?} 

    rule(:value)  { (semi.absent? >> any).repeat(1).as(:value) } #cheating 

    rule(:word)  { match['a-zA-Z0-9'].repeat(1) } 
    rule(:property) { (word >> (str("-") >> word).repeat(0)).as(:property) } 
    rule(:setting) { (indent? >> property >> colon >> indent? >> value >> semi >> eol?) } 
    rule(:body?)  { setting.repeat(0).as(:body) } 
    rule(:block)  { opencurl >> ws? >> body? >> ws? >> closecurl >> ws? } 
    rule(:selector_expression) { (opencurl.absent? >> any).repeat(1) } #cheating 
    rule(:scope)  { ws? >> selector_expression.as("selector") >> indent? >> block.as(:settings) } 

    rule(:css?)  { (eol.repeat(0) >> scope).repeat(0) } 
    root(:css?) 
end 

class MyTransform < Parslet::Transform 
    rule(:property => simple(:p), :value => simple(:v)) { OpenStruct.new(p:p,v:v) } 
    rule(:body => sequence(:b)) { b.each_with_object({}){|i,o| o[i.p] = i.v} } 
end 

css = <<-css 
    h2{ background-image: url(abc);} 
    #bob { 
    background-image: url(abc); 
    background-color: red; 
} 
css 

par = Parser.new.parse(css) 
tar = MyTransform.new.apply(par) 
pp tar 

輸出:

[{"selector"=>"h2", :settings=>{"background-image"=>"url(abc)"}}, 
{"selector"=>"#bob ", 
    :settings=> 
    {"background-image"=>"url(abc)", "background-color"=>"red"}}]