augustl (owner)

Forks

  • gist: 135500 by Numbers Fixed the typos - ie.. divi... created Wed Jun 24 13:30:54 -0700 2009

Revisions

gist: 135486 Download_button fork
public
Description:
Work in progress lesscss.org parser, based on treetop
Public Clone URL: git://gist.github.com/135486.git
Embed All Files: show embed
lib/less/engine.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module Less
  class Engine
    attr_reader :css
    attr_reader :parser, :build_handler, :root_node
    
    def initialize(less)
      @less = less.dup
      @parser = LessGrammarParser.new
      @build_handler = BuildHandler.new
      parse
      @css = build_handler.to_css
    end
    
    def parse
      preparse_less
      @root_node = parser.parse(@less)
      if @root_node
        @root_node.build(build_handler)
      else
        raise [parser.failure_column, parser.failure_index, parser.failure_line, parser.failure_reason].join(" -- ")
      end
    end
    
    private
    
    def preparse_less
      # Remove comments
      @less.gsub!(/\/\*[^\/\*]+\*\//, "")
      
      # Remove void whitespace
      @less.gsub!(/\s+/, " ")
    end
  end
end
lib/less/engine/build_handler.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
module Less
  class BuildHandler
    attr_reader :variables, :rules
    
    def initialize
      @variables = {}
      @rules = []
    end
    
    def to_css
      rules.map {|r| r.to_css }.join("\n")
    end
  end
end
lib/less/engine/rule.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
module Less
  class Engine
    class Rule
      attr_reader :selector
      def initialize(selector)
        @selector = selector
      end
      
      def to_css
        "#{selector} { }"
      end
    end
  end
end
lib/less/less_grammar.treetop #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
grammar LessGrammar
  rule primary
    (css_rule / variable_declaration)+ {
      def build(engine)
        elements.each {|e| e.build(engine) }
      end
    }
  end
  
  rule variable_declaration
    whitespace "@" variable_name ":" whitespace declaration_value ";" whitespace {
      def build(engine)
        engine.variables[variable_name.text_value] = declaration_value.text_value
      end
    }
  end
  
  rule variable_reference
    "@" variable_name (whitespace variable_operation)?
  end
  
  rule variable_operation
    operand whitespace number
  end
  
  rule variable_name
    [a-zA-Z0-9\-_]+
  end
  
  rule css_rule
    whitespace selectors rule_block whitespace {
      def build(engine)
        engine.rules << Less::Engine::Rule.new(selectors.text_value)
        rule_block.build(engine)
      end
    }
  end
  
  rule selectors
    [#\.a-zA-Z0-9<>\[\]='"~\|, ]+
  end
  
  rule rule_block
    "{" rule_block_content "}" {
      def build(engine)
        rule_block_content.build(engine)
      end
    }
  end
  
  rule rule_block_content
    (css_rule / declaration / [ ])+ {
      def build(engine)
        elements.each {|e| e.build(engine) if e.respond_to?(:build) }
      end
    }
  end
  
  rule declaration
    whitespace (css_declaration / mixin) whitespace
  end
  
  rule css_declaration
    declaration_key ":" whitespace (variable_reference / declaration_value) ";"
  end
  
  rule mixin
    "." [a-zA-Z0-9\-_]+ ";"
  end
  
  rule declaration_key
    [a-z\-]+
  end
  
  rule operand
    addition / subtraction / multiplication / divition
  end
  
  rule addition
    "*"
  end
  
  rule subtraction
    "-"
  end
  
  rule multiplication
    "*"
  end
  
  rule divition
    "/"
  end
  
  rule number
    [0-9]+
  end
  
  rule declaration_value
    [^;]+
  end
  
  rule whitespace
    [ ]*
  end
end
test/engine_test.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
require 'test_helper'
 
class EngineTest < Test::Unit::TestCase
  def test_basic
    less = ".haz {
color: red;
text-decoration:none;
}
@my_var: 5;
#foo {
background-color: red;
.bar {
text-decoration: none;
.haxor;
#baz {
color: red;
}
}
}"
 
    @engine = Less::Engine.new(less)
    
    p @engine.build_handler.rules
    # => [#<Less::Engine::Rule:0x106ba48 @selector=".haz ">, #<Less::Engine::Rule:0x106b9e4 @selector="#foo ">, #<Less::Engine::Rule:0x106b944 @selector=".bar ">, #<Less::Engine::Rule:0x106b6d8 @selector="#baz ">]
    p @engine.build_handler.variables
    # => {"my_var"=>"5"}
  end
end