haml-edge 2.3.179 → 2.3.180

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/README.md +88 -149
  3. data/VERSION +1 -1
  4. data/bin/css2sass +7 -1
  5. data/bin/sass-convert +7 -0
  6. data/lib/haml/exec.rb +95 -22
  7. data/lib/haml/template.rb +1 -1
  8. data/lib/haml/util.rb +50 -0
  9. data/lib/sass.rb +1 -1
  10. data/lib/sass/css.rb +38 -210
  11. data/lib/sass/engine.rb +121 -47
  12. data/lib/sass/files.rb +28 -19
  13. data/lib/sass/plugin.rb +32 -43
  14. data/lib/sass/repl.rb +1 -1
  15. data/lib/sass/script.rb +25 -6
  16. data/lib/sass/script/bool.rb +1 -0
  17. data/lib/sass/script/color.rb +2 -2
  18. data/lib/sass/script/css_lexer.rb +22 -0
  19. data/lib/sass/script/css_parser.rb +28 -0
  20. data/lib/sass/script/funcall.rb +17 -9
  21. data/lib/sass/script/functions.rb +46 -1
  22. data/lib/sass/script/interpolation.rb +42 -0
  23. data/lib/sass/script/lexer.rb +142 -34
  24. data/lib/sass/script/literal.rb +28 -12
  25. data/lib/sass/script/node.rb +57 -1
  26. data/lib/sass/script/number.rb +18 -3
  27. data/lib/sass/script/operation.rb +44 -8
  28. data/lib/sass/script/parser.rb +149 -24
  29. data/lib/sass/script/string.rb +50 -2
  30. data/lib/sass/script/unary_operation.rb +25 -10
  31. data/lib/sass/script/variable.rb +20 -11
  32. data/lib/sass/scss.rb +14 -0
  33. data/lib/sass/scss/css_parser.rb +39 -0
  34. data/lib/sass/scss/parser.rb +683 -0
  35. data/lib/sass/scss/rx.rb +112 -0
  36. data/lib/sass/scss/script_lexer.rb +13 -0
  37. data/lib/sass/scss/script_parser.rb +25 -0
  38. data/lib/sass/tree/comment_node.rb +58 -16
  39. data/lib/sass/tree/debug_node.rb +7 -2
  40. data/lib/sass/tree/directive_node.rb +38 -34
  41. data/lib/sass/tree/for_node.rb +6 -0
  42. data/lib/sass/tree/if_node.rb +13 -0
  43. data/lib/sass/tree/import_node.rb +26 -7
  44. data/lib/sass/tree/mixin_def_node.rb +18 -0
  45. data/lib/sass/tree/mixin_node.rb +16 -1
  46. data/lib/sass/tree/node.rb +98 -27
  47. data/lib/sass/tree/prop_node.rb +97 -20
  48. data/lib/sass/tree/root_node.rb +37 -0
  49. data/lib/sass/tree/rule_node.rb +88 -60
  50. data/lib/sass/tree/variable_node.rb +9 -5
  51. data/lib/sass/tree/while_node.rb +4 -0
  52. data/test/haml/results/filters.xhtml +1 -1
  53. data/test/haml/util_test.rb +28 -0
  54. data/test/sass/conversion_test.rb +884 -0
  55. data/test/sass/css2sass_test.rb +46 -21
  56. data/test/sass/engine_test.rb +680 -160
  57. data/test/sass/functions_test.rb +27 -0
  58. data/test/sass/more_results/more_import.css +1 -1
  59. data/test/sass/more_templates/more_import.sass +3 -3
  60. data/test/sass/plugin_test.rb +28 -8
  61. data/test/sass/results/compact.css +1 -1
  62. data/test/sass/results/complex.css +5 -5
  63. data/test/sass/results/compressed.css +1 -1
  64. data/test/sass/results/expanded.css +1 -1
  65. data/test/sass/results/import.css +3 -1
  66. data/test/sass/results/mixins.css +12 -12
  67. data/test/sass/results/nested.css +1 -1
  68. data/test/sass/results/parent_ref.css +4 -4
  69. data/test/sass/results/script.css +3 -3
  70. data/test/sass/results/scss_import.css +15 -0
  71. data/test/sass/results/scss_importee.css +2 -0
  72. data/test/sass/script_conversion_test.rb +153 -0
  73. data/test/sass/script_test.rb +44 -54
  74. data/test/sass/scss/css_test.rb +811 -0
  75. data/test/sass/scss/rx_test.rb +156 -0
  76. data/test/sass/scss/scss_test.rb +871 -0
  77. data/test/sass/scss/test_helper.rb +37 -0
  78. data/test/sass/templates/alt.sass +2 -2
  79. data/test/sass/templates/bork1.sass +1 -1
  80. data/test/sass/templates/import.sass +4 -4
  81. data/test/sass/templates/importee.sass +3 -3
  82. data/test/sass/templates/line_numbers.sass +1 -1
  83. data/test/sass/templates/mixins.sass +2 -2
  84. data/test/sass/templates/nested_mixin_bork.sass +1 -1
  85. data/test/sass/templates/options.sass +1 -1
  86. data/test/sass/templates/parent_ref.sass +2 -2
  87. data/test/sass/templates/script.sass +69 -69
  88. data/test/sass/templates/scss_import.scss +10 -0
  89. data/test/sass/templates/scss_importee.scss +1 -0
  90. data/test/sass/templates/units.sass +10 -10
  91. data/test/test_helper.rb +4 -4
  92. metadata +27 -2
@@ -8,6 +8,23 @@ module Sass::Script
8
8
  # @return [{Symbol => Object}]
9
9
  attr_reader :options
10
10
 
11
+ # The context in which this node was parsed,
12
+ # which determines how some operations are performed.
13
+ #
14
+ # Can be `:equals`, which means it's part of a `$var = val` or `prop = val` assignment,
15
+ # or `:default`, which means it's anywhere else
16
+ # (including `$var: val` and `prop: val` assignments,
17
+ # `#{}`-interpolations,
18
+ # and other script contexts such as `@if` conditions).
19
+ #
20
+ # @return [Symbol]
21
+ attr_reader :context
22
+
23
+ # The line of the document on which this node appeared.
24
+ #
25
+ # @return [Fixnum]
26
+ attr_accessor :line
27
+
11
28
  # Sets the options hash for this node,
12
29
  # as well as for all child nodes.
13
30
  # See {file:SASS_REFERENCE.md#sass_options the Sass options documentation}.
@@ -18,12 +35,33 @@ module Sass::Script
18
35
  children.each {|c| c.options = options}
19
36
  end
20
37
 
38
+ # Sets the options hash for this node,
39
+ # as well as for all child nodes.
40
+ #
41
+ # @param context [Symbol]
42
+ # @see #context
43
+ def context=(context)
44
+ @context = context
45
+ children.each {|c| c.context = context}
46
+ end
47
+
48
+ # Creates a new script node.
49
+ def initialize
50
+ @context = :default
51
+ end
52
+
21
53
  # Evaluates the node.
22
54
  #
55
+ # \{#perform} shouldn't be overridden directly;
56
+ # instead, override \{#\_perform}.
57
+ #
23
58
  # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
24
59
  # @return [Literal] The SassScript object that is the value of the SassScript
25
60
  def perform(environment)
26
- raise NotImplementedError.new("All subclasses of Sass::Script::Node must override #perform.")
61
+ _perform(environment)
62
+ rescue Sass::SyntaxError => e
63
+ e.modify_backtrace(:line => line)
64
+ raise e
27
65
  end
28
66
 
29
67
  # Returns all child nodes of this node.
@@ -32,5 +70,23 @@ module Sass::Script
32
70
  def children
33
71
  raise NotImplementedError.new("All subclasses of Sass::Script::Node must override #children.")
34
72
  end
73
+
74
+ # Returns the text of this SassScript expression.
75
+ #
76
+ # @return [String]
77
+ def to_sass
78
+ raise NotImplementedError.new("All subclasses of Sass::Script::Node must override #to_sass.")
79
+ end
80
+
81
+ protected
82
+
83
+ # Evaluates this node.
84
+ #
85
+ # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
86
+ # @return [Literal] The SassScript object that is the value of the SassScript
87
+ # @see #perform
88
+ def _perform(environment)
89
+ raise NotImplementedError.new("All subclasses of Sass::Script::Node must override #_perform.")
90
+ end
35
91
  end
36
92
  end
@@ -25,6 +25,8 @@ module Sass::Script
25
25
  # @return [Array<String>]
26
26
  attr_reader :denominator_units
27
27
 
28
+ attr_accessor :original
29
+
28
30
  # The precision with which numbers will be printed to CSS files.
29
31
  # For example, if this is `1000.0`,
30
32
  # `3.1415926` will be printed as `3.142`.
@@ -65,7 +67,7 @@ module Sass::Script
65
67
  end
66
68
  end
67
69
 
68
- # The SassScript binary `-` operation (e.g. `!a - !b`).
70
+ # The SassScript binary `-` operation (e.g. `$a - $b`).
69
71
  # Its functionality depends on the type of its argument:
70
72
  #
71
73
  # {Number}
@@ -85,7 +87,14 @@ module Sass::Script
85
87
  end
86
88
  end
87
89
 
88
- # The SassScript unary `-` operation (e.g. `-!a`).
90
+ # The SassScript unary `+` operation (e.g. `+$a`).
91
+ #
92
+ # @return [Number] The value of this number
93
+ def unary_plus
94
+ self
95
+ end
96
+
97
+ # The SassScript unary `-` operation (e.g. `-$a`).
89
98
  #
90
99
  # @return [Number] The negative value of this number
91
100
  def unary_minus
@@ -127,7 +136,11 @@ module Sass::Script
127
136
  # @return [Literal] The result of the operation
128
137
  def div(other)
129
138
  if other.is_a? Number
130
- operate(other, :/)
139
+ res = operate(other, :/)
140
+ if self.original && other.original && context != :equals
141
+ res.original = "#{self.original}/#{other.original}"
142
+ end
143
+ res
131
144
  else
132
145
  super
133
146
  end
@@ -214,6 +227,7 @@ module Sass::Script
214
227
  # @raise [Sass::SyntaxError] if this number has units that can't be used in CSS
215
228
  # (e.g. `px*in`)
216
229
  def to_s
230
+ return original if original
217
231
  raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units?
218
232
  inspect
219
233
  end
@@ -235,6 +249,7 @@ module Sass::Script
235
249
  end
236
250
  "#{value}#{unit_str}"
237
251
  end
252
+ alias_method :to_sass, :inspect
238
253
 
239
254
  # @return [Fixnum] The integer value of the number
240
255
  # @raise [Sass::SyntaxError] if the number isn't an integer
@@ -4,11 +4,16 @@ require 'sass/script/number'
4
4
  require 'sass/script/color'
5
5
  require 'sass/script/functions'
6
6
  require 'sass/script/unary_operation'
7
+ require 'sass/script/interpolation'
7
8
 
8
9
  module Sass::Script
9
10
  # A SassScript parse node representing a binary operation,
10
- # such as `!a + !b` or `"foo" + 1`.
11
+ # such as `$a + $b` or `"foo" + 1`.
11
12
  class Operation < Node
13
+ attr_reader :operand1
14
+ attr_reader :operand2
15
+ attr_reader :operator
16
+
12
17
  # @param operand1 [Script::Node] The parse-tree node
13
18
  # for the right-hand side of the operator
14
19
  # @param operand2 [Script::Node] The parse-tree node
@@ -19,6 +24,7 @@ module Sass::Script
19
24
  @operand1 = operand1
20
25
  @operand2 = operand2
21
26
  @operator = operator
27
+ super()
22
28
  end
23
29
 
24
30
  # @return [String] A human-readable s-expression representation of the operation
@@ -26,14 +32,44 @@ module Sass::Script
26
32
  "(#{@operator.inspect} #{@operand1.inspect} #{@operand2.inspect})"
27
33
  end
28
34
 
35
+ # @see Node#to_sass
36
+ def to_sass
37
+ pred = Sass::Script::Parser.precedence_of(@operator)
38
+ o1 = operand_to_sass pred, @operand1
39
+ o2 = operand_to_sass pred, @operand2
40
+ sep =
41
+ case @operator
42
+ when :comma; ", "
43
+ when :concat; " "
44
+ else; " #{Lexer::OPERATORS_REVERSE[@operator]} "
45
+ end
46
+ "#{o1}#{sep}#{o2}"
47
+ end
48
+
49
+ # Returns the operands for this operation.
50
+ #
51
+ # @return [Array<Node>]
52
+ # @see Node#children
53
+ def children
54
+ [@operand1, @operand2]
55
+ end
56
+
57
+ protected
58
+
29
59
  # Evaluates the operation.
30
60
  #
31
61
  # @param environment [Sass::Environment] The environment in which to evaluate the SassScript
32
62
  # @return [Literal] The SassScript object that is the value of the operation
33
63
  # @raise [Sass::SyntaxError] if the operation is undefined for the operands
34
- def perform(environment)
64
+ def _perform(environment)
35
65
  literal1 = @operand1.perform(environment)
36
66
  literal2 = @operand2.perform(environment)
67
+
68
+ if @operator == :concat && context == :equals
69
+ literal1 = Sass::Script::String.new(literal1.value) if literal1.is_a?(Sass::Script::String)
70
+ literal2 = Sass::Script::String.new(literal2.value) if literal2.is_a?(Sass::Script::String)
71
+ end
72
+
37
73
  begin
38
74
  res = literal1.send(@operator, literal2)
39
75
  res.options = environment.options
@@ -44,12 +80,12 @@ module Sass::Script
44
80
  end
45
81
  end
46
82
 
47
- # Returns the operands for this operation.
48
- #
49
- # @return [Array<Node>]
50
- # @see Node#children
51
- def children
52
- [@operand1, @operand2]
83
+ private
84
+
85
+ def operand_to_sass(pred, op)
86
+ return "(#{op.to_sass})" if op.is_a?(Operation) &&
87
+ Sass::Script::Parser.precedence_of(op.operator) < pred
88
+ op.to_sass
53
89
  end
54
90
  end
55
91
  end
@@ -5,6 +5,13 @@ module Sass
5
5
  # The parser for SassScript.
6
6
  # It parses a string of code into a tree of {Script::Node}s.
7
7
  class Parser
8
+ # The line number of the parser's current position.
9
+ #
10
+ # @return [Fixnum]
11
+ def line
12
+ @lexer.line
13
+ end
14
+
8
15
  # @param str [String, StringScanner] The source text to parse
9
16
  # @param line [Fixnum] The line on which the SassScript appears.
10
17
  # Used for error reporting
@@ -14,7 +21,7 @@ module Sass
14
21
  # see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
15
22
  def initialize(str, line, offset, options = {})
16
23
  @options = options
17
- @lexer = Lexer.new(str, line, offset, options)
24
+ @lexer = lexer_class.new(str, line, offset, options)
18
25
  end
19
26
 
20
27
  # Parses a SassScript expression within an interpolated segment (`#{}`).
@@ -29,6 +36,9 @@ module Sass
29
36
  assert_tok :end_interpolation
30
37
  expr.options = @options
31
38
  expr
39
+ rescue Sass::SyntaxError => e
40
+ e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
41
+ raise e
32
42
  end
33
43
 
34
44
  # Parses a SassScript expression.
@@ -40,6 +50,26 @@ module Sass
40
50
  assert_done
41
51
  expr.options = @options
42
52
  expr
53
+ rescue Sass::SyntaxError => e
54
+ e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
55
+ raise e
56
+ end
57
+
58
+ # Parses a SassScript expression,
59
+ # ending it when it encounters one of the given identifier tokens.
60
+ #
61
+ # @param [#include?(String)] A set of strings that delimit the expression.
62
+ # @return [Script::Node] The root node of the parse tree
63
+ # @raise [Sass::SyntaxError] if the expression isn't valid SassScript
64
+ def parse_until(tokens)
65
+ @stop_at = tokens
66
+ expr = assert_expr :expr
67
+ assert_done
68
+ expr.options = @options
69
+ expr
70
+ rescue Sass::SyntaxError => e
71
+ e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
72
+ raise e
43
73
  end
44
74
 
45
75
  # Parses the argument list for a mixin include.
@@ -57,6 +87,9 @@ module Sass
57
87
 
58
88
  args.each {|a| a.options = @options}
59
89
  args
90
+ rescue Sass::SyntaxError => e
91
+ e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
92
+ raise e
60
93
  end
61
94
 
62
95
  # Parses the argument list for a mixin definition.
@@ -77,6 +110,9 @@ module Sass
77
110
  v.options = @options if v
78
111
  end
79
112
  args
113
+ rescue Sass::SyntaxError => e
114
+ e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
115
+ raise e
80
116
  end
81
117
 
82
118
  # Parses a SassScript expression.
@@ -89,7 +125,28 @@ module Sass
89
125
  new(*args).parse
90
126
  end
91
127
 
128
+ # @private
129
+ PRECEDENCE = [
130
+ :comma, :concat, :or, :and,
131
+ [:eq, :neq],
132
+ [:gt, :gte, :lt, :lte],
133
+ [:plus, :minus],
134
+ [:times, :div, :mod],
135
+ ]
136
+
92
137
  class << self
138
+ # Returns an integer representing the precedence
139
+ # of the given operator.
140
+ # A lower integer indicates a looser binding.
141
+ #
142
+ # @private
143
+ def precedence_of(op)
144
+ PRECEDENCE.each_with_index do |e, i|
145
+ return i if Array(e).include?(op)
146
+ end
147
+ raise "[BUG] Unknown operator #{op}"
148
+ end
149
+
93
150
  private
94
151
 
95
152
  # Defines a simple left-associative production.
@@ -101,7 +158,9 @@ module Sass
101
158
  def #{name}
102
159
  return unless e = #{sub}
103
160
  while tok = try_tok(#{ops.map {|o| o.inspect}.join(', ')})
161
+ line = @lexer.line
104
162
  e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
163
+ e.line = line
105
164
  end
106
165
  e
107
166
  end
@@ -112,7 +171,10 @@ RUBY
112
171
  class_eval <<RUBY
113
172
  def unary_#{op}
114
173
  return #{sub} unless try_tok(:#{op})
115
- UnaryOperation.new(assert_expr(:unary_#{op}), :#{op})
174
+ line = @lexer.line
175
+ op = UnaryOperation.new(assert_expr(:unary_#{op}), :#{op})
176
+ op.line = line
177
+ op
116
178
  end
117
179
  RUBY
118
180
  end
@@ -120,12 +182,28 @@ RUBY
120
182
 
121
183
  private
122
184
 
123
- production :expr, :concat, :comma
185
+ # @private
186
+ def lexer_class; Lexer; end
187
+
188
+ production :expr, :interpolation, :comma
189
+
190
+ def interpolation
191
+ e = concat
192
+ while interp = try_tok(:begin_interpolation)
193
+ wb = @lexer.whitespace?(interp)
194
+ line = @lexer.line
195
+ mid = parse_interpolated
196
+ wa = @lexer.whitespace?
197
+ e = Script::Interpolation.new(e, mid, concat, wb, wa)
198
+ e.line = line
199
+ end
200
+ e
201
+ end
124
202
 
125
203
  def concat
126
204
  return unless e = or_expr
127
205
  while sub = or_expr
128
- e = Operation.new(e, sub, :concat)
206
+ e = node(Operation.new(e, sub, :concat))
129
207
  end
130
208
  e
131
209
  end
@@ -135,36 +213,44 @@ RUBY
135
213
  production :eq_or_neq, :relational, :eq, :neq
136
214
  production :relational, :plus_or_minus, :gt, :gte, :lt, :lte
137
215
  production :plus_or_minus, :times_div_or_mod, :plus, :minus
138
- production :times_div_or_mod, :unary_minus, :times, :div, :mod
216
+ production :times_div_or_mod, :unary_plus, :times, :div, :mod
139
217
 
218
+ unary :plus, :unary_minus
140
219
  unary :minus, :unary_div
141
220
  unary :div, :unary_not # For strings, so /foo/bar works
142
221
  unary :not, :funcall
143
222
 
144
223
  def funcall
145
- return paren unless name = try_tok(:ident)
224
+ return raw unless @lexer.peek && @lexer.peek.type == :ident
225
+ return if @stop_at && @stop_at.include?(@lexer.peek.value)
226
+
227
+ name = @lexer.next
146
228
  # An identifier without arguments is just a string
147
229
  unless try_tok(:lparen)
148
- filename = @options[:filename]
149
- warn(<<END)
150
- DEPRECATION WARNING:
151
- On line #{name.line}, character #{name.offset}#{" of '#{filename}'" if filename}
152
- Implicit strings have been deprecated and will be removed in version 3.0.
153
- '#{name.value}' was not quoted. Please add double quotes (e.g. "#{name.value}").
154
- END
155
- Script::String.new(name.value)
230
+ if color = Color::HTML4_COLORS[name.value]
231
+ return node(Color.new(color))
232
+ end
233
+ node(Script::String.new(name.value, :identifier))
156
234
  else
157
235
  args = arglist || []
158
236
  assert_tok(:rparen)
159
- Script::Funcall.new(name.value, args)
237
+ node(Script::Funcall.new(name.value, args))
160
238
  end
161
239
  end
162
240
 
163
241
  def defn_arglist(must_have_default)
242
+ line = @lexer.line
243
+ offset = @lexer.offset + 1
164
244
  return unless c = try_tok(:const)
165
245
  var = Script::Variable.new(c.value)
166
- if try_tok(:single_eq)
246
+ if tok = (try_tok(:colon) || try_tok(:single_eq))
167
247
  val = assert_expr(:concat)
248
+
249
+ if tok.type == :single_eq
250
+ val.context = :equals
251
+ Script.equals_warning("mixin argument defaults", "$#{c.value}",
252
+ val.to_sass, false, line, offset, @options[:filename])
253
+ end
168
254
  elsif must_have_default
169
255
  raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments.")
170
256
  end
@@ -174,46 +260,80 @@ END
174
260
  end
175
261
 
176
262
  def arglist
177
- return unless e = concat
263
+ return unless e = interpolation
178
264
  return [e] unless try_tok(:comma)
179
265
  [e, *arglist]
180
266
  end
181
267
 
268
+ def raw
269
+ return special_fun unless tok = try_tok(:raw)
270
+ node(Script::String.new(tok.value))
271
+ end
272
+
273
+ def special_fun
274
+ return paren unless tok = try_tok(:special_fun)
275
+ first = node(Script::String.new(tok.value.first))
276
+ Haml::Util.enum_slice(tok.value[1..-1], 2).inject(first) do |l, (i, r)|
277
+ Script::Interpolation.new(
278
+ l, i, r && node(Script::String.new(r)),
279
+ false, false)
280
+ end
281
+ end
282
+
182
283
  def paren
183
284
  return variable unless try_tok(:lparen)
285
+ was_in_parens = @in_parens
286
+ @in_parens = true
184
287
  e = assert_expr(:expr)
185
288
  assert_tok(:rparen)
186
289
  return e
290
+ ensure
291
+ @in_parens = was_in_parens
187
292
  end
188
293
 
189
294
  def variable
190
295
  return string unless c = try_tok(:const)
191
- Variable.new(c.value)
296
+ node(Variable.new(*c.value))
192
297
  end
193
298
 
194
299
  def string
195
- return literal unless first = try_tok(:string)
300
+ return number unless first = try_tok(:string)
196
301
  return first.value unless try_tok(:begin_interpolation)
302
+ line = @lexer.line
197
303
  mid = parse_interpolated
198
304
  last = assert_expr(:string)
199
- Operation.new(first.value, Operation.new(mid, last, :plus), :plus)
305
+ op = Operation.new(first.value, node(Operation.new(mid, last, :plus)), :plus)
306
+ op.line = line
307
+ op
308
+ end
309
+
310
+ def number
311
+ return literal unless tok = try_tok(:number)
312
+ num = tok.value
313
+ num.original = num.to_s unless @in_parens
314
+ num
200
315
  end
201
316
 
202
317
  def literal
203
- (t = try_tok(:number, :color, :bool)) && (return t.value)
318
+ (t = try_tok(:color, :bool)) && (return t.value)
204
319
  end
205
320
 
206
321
  # It would be possible to have unified #assert and #try methods,
207
322
  # but detecting the method/token difference turns out to be quite expensive.
208
323
 
324
+ EXPR_NAMES = {
325
+ :string => "string",
326
+ :default => "expression (e.g. 1px, bold)",
327
+ }
328
+
209
329
  def assert_expr(name)
210
330
  (e = send(name)) && (return e)
211
- raise Sass::SyntaxError.new("Expected expression, was #{@lexer.done? ? 'end of text' : "#{@lexer.peek.type} token"}.")
331
+ @lexer.expected!(EXPR_NAMES[name] || EXPR_NAMES[:default])
212
332
  end
213
333
 
214
334
  def assert_tok(*names)
215
335
  (t = try_tok(*names)) && (return t)
216
- raise Sass::SyntaxError.new("Expected #{names.join(' or ')} token, was #{@lexer.done? ? 'end of text' : "#{@lexer.peek.type} token"}.")
336
+ @lexer.expected!(names.map {|tok| Lexer::TOKEN_NAMES[tok] || tok}.join(" or "))
217
337
  end
218
338
 
219
339
  def try_tok(*names)
@@ -223,7 +343,12 @@ END
223
343
 
224
344
  def assert_done
225
345
  return if @lexer.done?
226
- raise Sass::SyntaxError.new("Unexpected #{@lexer.peek.type} token.")
346
+ @lexer.expected!(EXPR_NAMES[:default])
347
+ end
348
+
349
+ def node(node)
350
+ node.line = @lexer.line
351
+ node
227
352
  end
228
353
  end
229
354
  end