문제

I'm writing a simple ruby parser for CSS files and I'm kind of stumped on how I can get a block of CSS (that is, a selector and everything between curly braces immediately following it) as a ruby object on which I can perform my dark and nasty magic.

Ideally, I would like to get a ruby hash with each attribute / value and the selector. Is there any clear and easy to understand way how to do this?

도움이 되었습니까?

해결책

As mentioned in the comments it's silly to do it yourself beyond a fun exercise. I'd read the css file into a string and then scan it with regular expressions.

Ruby - Convert File to String

http://www.ruby-doc.org/core-1.9.3/String.html#method-i-scan

for testing the regex: http://rubular.com/

다른 팁

Everyone should write a parser.

This should get you started...

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

Outputs:

[{"selector"=>"h2", :settings=>{"background-image"=>"url(abc)"}},
 {"selector"=>"#bob ",
  :settings=>
   {"background-image"=>"url(abc)", "background-color"=>"red"}}]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top