Class: CSS::Parser

Inherits:
Object
  • Object
show all
Includes:
Nodes
Defined in:
lib/css/parser.rb

Overview

Parser based on CSS Syntax Module Level 4 §5, with the nesting extensions described in CSS Nesting Module Level 1 / Syntax 4. drafts.csswg.org/css-syntax/

Constant Summary collapse

EOF_TOKEN =

Shared sentinel returned past the end of the token stream. It has no position, which is why ParseError messages at EOF show no ‘line:col:` prefix.

Token.new(:eof).freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tokens) ⇒ Parser

Returns a new instance of Parser.



30
31
32
33
# File 'lib/css/parser.rb', line 30

def initialize(tokens)
  @tokens = tokens
  @pos    = 0
end

Class Method Details

.parse_block_contents(input, **opts) ⇒ Object



17
# File 'lib/css/parser.rb', line 17

def parse_block_contents(input, **opts)         = build(input, **opts).parse_block_contents

.parse_comma_separated_values(input, **opts) ⇒ Object



20
# File 'lib/css/parser.rb', line 20

def parse_comma_separated_values(input, **opts) = build(input, **opts).parse_comma_separated_values

.parse_component_value(input, **opts) ⇒ Object



18
# File 'lib/css/parser.rb', line 18

def parse_component_value(input, **opts)        = build(input, **opts).parse_component_value

.parse_component_values(input, **opts) ⇒ Object



19
# File 'lib/css/parser.rb', line 19

def parse_component_values(input, **opts)       = build(input, **opts).parse_component_values

.parse_declaration(input, **opts) ⇒ Object



16
# File 'lib/css/parser.rb', line 16

def parse_declaration(input, **opts)            = build(input, **opts).parse_declaration

.parse_rule(input, **opts) ⇒ Object



15
# File 'lib/css/parser.rb', line 15

def parse_rule(input, **opts)                   = build(input, **opts).parse_rule

.parse_stylesheet(input, **opts) ⇒ Object



14
# File 'lib/css/parser.rb', line 14

def parse_stylesheet(input, **opts)             = build(input, **opts).parse_stylesheet

Instance Method Details

#parse_block_contentsObject

§5.4.4. Used for parsing the contents of a ‘style=“…”` attribute, `@page` blocks, and similar contexts where there is no enclosing `{}`.



76
77
78
# File 'lib/css/parser.rb', line 76

def parse_block_contents
  Block.new(items: collect_block_items(stop_at_close_brace: false))
end

#parse_comma_separated_valuesObject

§5.3.9. Empty input produces ‘[[]]`; a trailing comma produces a trailing empty group.



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/css/parser.rb', line 104

def parse_comma_separated_values
  groups  = []
  current = []

  loop do
    case peek.type
    when :eof
      groups << current
      return groups
    when :comma
      consume
      groups << current
      current = []
    else
      current << consume_component_value
    end
  end
end

#parse_component_valueObject

§5.3.7.



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/css/parser.rb', line 81

def parse_component_value
  skip_whitespace

  parse_error!('expected a component value') if peek.type == :eof

  cv = consume_component_value

  skip_whitespace

  parse_error!("unexpected token after component value: #{peek.type}") unless peek.type == :eof

  cv
end

#parse_component_valuesObject

§5.3.8.



96
97
98
99
100
# File 'lib/css/parser.rb', line 96

def parse_component_values
  values = []
  values << consume_component_value until peek.type == :eof
  values
end

#parse_declarationObject

§5.3.5. Per spec, trailing tokens after the declaration are ignored.



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/css/parser.rb', line 62

def parse_declaration
  skip_whitespace

  parse_error!('expected a declaration') unless peek.type == :ident

  decl = try_consume_declaration

  parse_error!('invalid declaration') unless decl

  decl
end

#parse_ruleObject

§5.3.4.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/css/parser.rb', line 41

def parse_rule
  skip_whitespace

  parse_error!('expected a rule, got end of input') if peek.type == :eof

  rule = if peek.type == :at_keyword
           consume_at_rule(nested: false)
         else
           consume_qualified_rule(nested: false)
         end

  parse_error!('invalid rule') if rule.nil?

  skip_whitespace

  parse_error!("unexpected token after rule: #{peek.type}") unless peek.type == :eof

  rule
end

#parse_stylesheetObject

§5.3.3.



36
37
38
# File 'lib/css/parser.rb', line 36

def parse_stylesheet
  Stylesheet.new(rules: consume_rule_list(top_level: true))
end