sass 3.3.0.alpha.149 → 3.3.0.alpha.162
Sign up to get free protection for your applications and to get access to all the features.
- data/REVISION +1 -1
- data/VERSION +1 -1
- data/VERSION_DATE +1 -1
- data/lib/sass/css.rb +1 -1
- data/lib/sass/engine.rb +4 -4
- data/lib/sass/environment.rb +1 -1
- data/lib/sass/exec.rb +1 -1
- data/lib/sass/media.rb +15 -15
- data/lib/sass/script.rb +32 -7
- data/lib/sass/script/css_lexer.rb +2 -2
- data/lib/sass/script/css_parser.rb +1 -1
- data/lib/sass/script/functions.rb +246 -232
- data/lib/sass/script/lexer.rb +24 -32
- data/lib/sass/script/parser.rb +84 -65
- data/lib/sass/script/tree.rb +14 -0
- data/lib/sass/script/tree/funcall.rb +242 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +30 -13
- data/lib/sass/script/tree/list_literal.rb +65 -0
- data/lib/sass/script/tree/literal.rb +46 -0
- data/lib/sass/script/{node.rb → tree/node.rb} +10 -10
- data/lib/sass/script/{operation.rb → tree/operation.rb} +16 -27
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +4 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +7 -8
- data/lib/sass/script/tree/variable.rb +56 -0
- data/lib/sass/script/value.rb +10 -0
- data/lib/sass/script/{arg_list.rb → value/arg_list.rb} +5 -20
- data/lib/sass/script/value/base.rb +222 -0
- data/lib/sass/script/{bool.rb → value/bool.rb} +2 -2
- data/lib/sass/script/{color.rb → value/color.rb} +22 -20
- data/lib/sass/script/{list.rb → value/list.rb} +15 -28
- data/lib/sass/script/{null.rb → value/null.rb} +3 -3
- data/lib/sass/script/{number.rb → value/number.rb} +19 -19
- data/lib/sass/script/{string.rb → value/string.rb} +7 -7
- data/lib/sass/scss/parser.rb +14 -4
- data/lib/sass/selector.rb +26 -26
- data/lib/sass/selector/abstract_sequence.rb +1 -1
- data/lib/sass/selector/simple.rb +6 -7
- data/lib/sass/source/position.rb +13 -0
- data/lib/sass/supports.rb +4 -4
- data/lib/sass/tree/comment_node.rb +3 -3
- data/lib/sass/tree/css_import_node.rb +7 -7
- data/lib/sass/tree/debug_node.rb +2 -2
- data/lib/sass/tree/directive_node.rb +2 -2
- data/lib/sass/tree/each_node.rb +2 -2
- data/lib/sass/tree/extend_node.rb +4 -4
- data/lib/sass/tree/for_node.rb +4 -4
- data/lib/sass/tree/function_node.rb +4 -4
- data/lib/sass/tree/media_node.rb +3 -3
- data/lib/sass/tree/mixin_def_node.rb +4 -4
- data/lib/sass/tree/mixin_node.rb +6 -6
- data/lib/sass/tree/prop_node.rb +23 -15
- data/lib/sass/tree/return_node.rb +2 -2
- data/lib/sass/tree/rule_node.rb +3 -3
- data/lib/sass/tree/variable_node.rb +2 -2
- data/lib/sass/tree/visitors/convert.rb +2 -2
- data/lib/sass/tree/visitors/deep_copy.rb +5 -5
- data/lib/sass/tree/visitors/perform.rb +7 -7
- data/lib/sass/tree/visitors/set_options.rb +6 -6
- data/lib/sass/tree/visitors/to_css.rb +1 -1
- data/lib/sass/tree/warn_node.rb +2 -2
- data/lib/sass/tree/while_node.rb +2 -2
- data/lib/sass/util.rb +2 -2
- data/test/sass/engine_test.rb +6 -6
- data/test/sass/functions_test.rb +20 -20
- data/test/sass/plugin_test.rb +2 -2
- data/test/sass/script_test.rb +38 -29
- data/test/test_helper.rb +1 -1
- metadata +23 -19
- data/lib/sass/script/funcall.rb +0 -238
- data/lib/sass/script/literal.rb +0 -221
- data/lib/sass/script/variable.rb +0 -58
data/lib/sass/script/lexer.rb
CHANGED
@@ -16,26 +16,29 @@ module Sass
|
|
16
16
|
# `value`: \[`Object`\]
|
17
17
|
# : The Ruby object corresponding to the value of the token.
|
18
18
|
#
|
19
|
-
# `
|
20
|
-
# : The
|
21
|
-
#
|
22
|
-
# `offset`: \[`Fixnum`\]
|
23
|
-
# : The number of characters into the line the SassScript token appeared (1-based).
|
19
|
+
# `source_range`: [`Sass::Source::Range`\]
|
20
|
+
# : The range in the source file in which the token appeared.
|
24
21
|
#
|
25
22
|
# `pos`: \[`Fixnum`\]
|
26
23
|
# : The scanner position at which the SassScript token appeared.
|
27
|
-
Token = Struct.new(:type, :value, :
|
24
|
+
Token = Struct.new(:type, :value, :source_range, :pos)
|
28
25
|
|
29
26
|
# The line number of the lexer's current position.
|
30
27
|
#
|
31
28
|
# @return [Fixnum]
|
32
|
-
|
29
|
+
def line
|
30
|
+
return @line unless @tok
|
31
|
+
@tok.source_range.start_pos.line
|
32
|
+
end
|
33
33
|
|
34
34
|
# The number of bytes into the current line
|
35
35
|
# of the lexer's current position (1-based).
|
36
36
|
#
|
37
37
|
# @return [Fixnum]
|
38
|
-
|
38
|
+
def offset
|
39
|
+
return @offset unless @tok
|
40
|
+
@tok.source_range.start_pos.offset
|
41
|
+
end
|
39
42
|
|
40
43
|
# A hash from operator strings to the corresponding token types.
|
41
44
|
OPERATORS = {
|
@@ -174,8 +177,8 @@ module Sass
|
|
174
177
|
def unpeek!
|
175
178
|
if @tok
|
176
179
|
@scanner.pos = @tok.pos
|
177
|
-
@line = @tok.line
|
178
|
-
@offset = @tok.offset
|
180
|
+
@line = @tok.source_range.start_pos.line
|
181
|
+
@offset = @tok.source_range.start_pos.offset
|
179
182
|
end
|
180
183
|
end
|
181
184
|
|
@@ -219,12 +222,11 @@ module Sass
|
|
219
222
|
|
220
223
|
def read_token
|
221
224
|
return if done?
|
225
|
+
start_pos = source_position
|
226
|
+
start_index = @scanner.pos
|
222
227
|
return unless value = token
|
223
|
-
type, val
|
224
|
-
|
225
|
-
|
226
|
-
val.line = @line if val.is_a?(Script::Node)
|
227
|
-
Token.new(type, val, @line, @offset - size, @scanner.pos - size)
|
228
|
+
type, val = value
|
229
|
+
Token.new(type, val, range(start_pos), @scanner.pos - @scanner.matched_size)
|
228
230
|
end
|
229
231
|
|
230
232
|
def whitespace
|
@@ -259,7 +261,6 @@ module Sass
|
|
259
261
|
end
|
260
262
|
|
261
263
|
def string(re, open)
|
262
|
-
start_pos = source_position
|
263
264
|
return unless scan(STRING_REGULAR_EXPRESSIONS[[re, open]])
|
264
265
|
if @scanner[2] == '#{' #'
|
265
266
|
@scanner.pos -= 2 # Don't actually consume the #{
|
@@ -268,50 +269,41 @@ module Sass
|
|
268
269
|
end
|
269
270
|
str =
|
270
271
|
if re == :uri
|
271
|
-
Script::String.new("#{'url(' unless open}#{@scanner[1]}#{')' unless @scanner[2] == '#{'}")
|
272
|
+
Script::Value::String.new("#{'url(' unless open}#{@scanner[1]}#{')' unless @scanner[2] == '#{'}")
|
272
273
|
else
|
273
|
-
Script::String.new(@scanner[1].gsub(/\\(['"]|\#\{)/, '\1'), :string)
|
274
|
+
Script::Value::String.new(@scanner[1].gsub(/\\(['"]|\#\{)/, '\1'), :string)
|
274
275
|
end
|
275
|
-
str.source_range = range(start_pos)
|
276
276
|
[:string, str]
|
277
277
|
end
|
278
278
|
|
279
279
|
def number
|
280
|
-
start_pos = source_position
|
281
280
|
return unless scan(REGULAR_EXPRESSIONS[:number])
|
282
281
|
value = @scanner[2] ? @scanner[2].to_f : @scanner[3].to_i
|
283
282
|
value = -value if @scanner[1]
|
284
|
-
script_number = Script::Number.new(value, Array(@scanner[4]))
|
285
|
-
script_number.source_range = range(start_pos)
|
283
|
+
script_number = Script::Value::Number.new(value, Array(@scanner[4]))
|
286
284
|
[:number, script_number]
|
287
285
|
end
|
288
286
|
|
289
287
|
def color
|
290
|
-
start_pos = source_position
|
291
288
|
return unless s = scan(REGULAR_EXPRESSIONS[:color])
|
292
289
|
raise Sass::SyntaxError.new(<<MESSAGE.rstrip) unless s.size == 4 || s.size == 7
|
293
290
|
Colors must have either three or six digits: '#{s}'
|
294
291
|
MESSAGE
|
295
292
|
value = s.scan(/^#(..?)(..?)(..?)$/).first.
|
296
293
|
map {|num| num.ljust(2, num).to_i(16)}
|
297
|
-
script_color = Script::Color.new(value)
|
298
|
-
script_color.source_range = range(start_pos)
|
294
|
+
script_color = Script::Value::Color.new(value)
|
299
295
|
[:color, script_color]
|
300
296
|
end
|
301
297
|
|
302
298
|
def bool
|
303
|
-
start_pos = source_position
|
304
299
|
return unless s = scan(REGULAR_EXPRESSIONS[:bool])
|
305
|
-
script_bool = Script::Bool.new(s == 'true')
|
306
|
-
script_bool.source_range = range(start_pos)
|
300
|
+
script_bool = Script::Value::Bool.new(s == 'true')
|
307
301
|
[:bool, script_bool]
|
308
302
|
end
|
309
303
|
|
310
304
|
def null
|
311
|
-
start_pos = source_position
|
312
305
|
return unless scan(REGULAR_EXPRESSIONS[:null])
|
313
|
-
script_null = Script::Null.new
|
314
|
-
script_null.source_range = range(start_pos)
|
306
|
+
script_null = Script::Value::Null.new
|
315
307
|
[:null, script_null]
|
316
308
|
end
|
317
309
|
|
@@ -331,7 +323,7 @@ MESSAGE
|
|
331
323
|
|
332
324
|
def special_val
|
333
325
|
return unless scan(/!important/i)
|
334
|
-
[:string, Script::String.new("!important")]
|
326
|
+
[:string, Script::Value::String.new("!important")]
|
335
327
|
end
|
336
328
|
|
337
329
|
def ident_op
|
data/lib/sass/script/parser.rb
CHANGED
@@ -3,7 +3,7 @@ require 'sass/script/lexer'
|
|
3
3
|
module Sass
|
4
4
|
module Script
|
5
5
|
# The parser for SassScript.
|
6
|
-
# It parses a string of code into a tree of {Script::Node}s.
|
6
|
+
# It parses a string of code into a tree of {Script::Tree::Node}s.
|
7
7
|
class Parser
|
8
8
|
# The line number of the parser's current position.
|
9
9
|
#
|
@@ -36,14 +36,12 @@ module Sass
|
|
36
36
|
# which signals the end of an interpolated segment,
|
37
37
|
# it returns rather than throwing an error.
|
38
38
|
#
|
39
|
-
# @return [Script::Node] The root node of the parse tree
|
39
|
+
# @return [Script::Tree::Node] The root node of the parse tree
|
40
40
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
41
41
|
def parse_interpolated
|
42
|
-
start_pos = source_position
|
43
42
|
expr = assert_expr :expr
|
44
43
|
assert_tok :end_interpolation
|
45
44
|
expr.options = @options
|
46
|
-
expr.source_range = range(start_pos)
|
47
45
|
expr
|
48
46
|
rescue Sass::SyntaxError => e
|
49
47
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
@@ -52,14 +50,12 @@ module Sass
|
|
52
50
|
|
53
51
|
# Parses a SassScript expression.
|
54
52
|
#
|
55
|
-
# @return [Script::Node] The root node of the parse tree
|
53
|
+
# @return [Script::Tree::Node] The root node of the parse tree
|
56
54
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
57
55
|
def parse
|
58
|
-
start_pos = source_position
|
59
56
|
expr = assert_expr :expr
|
60
57
|
assert_done
|
61
58
|
expr.options = @options
|
62
|
-
expr.source_range = range(start_pos)
|
63
59
|
expr
|
64
60
|
rescue Sass::SyntaxError => e
|
65
61
|
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
|
@@ -70,7 +66,7 @@ module Sass
|
|
70
66
|
# ending it when it encounters one of the given identifier tokens.
|
71
67
|
#
|
72
68
|
# @param [#include?(String)] A set of strings that delimit the expression.
|
73
|
-
# @return [Script::Node] The root node of the parse tree
|
69
|
+
# @return [Script::Tree::Node] The root node of the parse tree
|
74
70
|
# @raise [Sass::SyntaxError] if the expression isn't valid SassScript
|
75
71
|
def parse_until(tokens)
|
76
72
|
@stop_at = tokens
|
@@ -85,7 +81,7 @@ module Sass
|
|
85
81
|
|
86
82
|
# Parses the argument list for a mixin include.
|
87
83
|
#
|
88
|
-
# @return [(Array<Script::Node>, {String => Script::Node}, Script::Node)]
|
84
|
+
# @return [(Array<Script::Tree::Node>, {String => Script::Tree::Node}, Script::Tree::Node)]
|
89
85
|
# The root nodes of the positional arguments, keyword arguments, and
|
90
86
|
# splat argument. Keyword arguments are in a hash from names to values.
|
91
87
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
@@ -108,7 +104,7 @@ module Sass
|
|
108
104
|
|
109
105
|
# Parses the argument list for a mixin definition.
|
110
106
|
#
|
111
|
-
# @return [(Array<Script::Node>, Script::Node)]
|
107
|
+
# @return [(Array<Script::Tree::Node>, Script::Tree::Node)]
|
112
108
|
# The root nodes of the arguments, and the splat argument.
|
113
109
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
114
110
|
def parse_mixin_definition_arglist
|
@@ -128,7 +124,7 @@ module Sass
|
|
128
124
|
|
129
125
|
# Parses the argument list for a function definition.
|
130
126
|
#
|
131
|
-
# @return [(Array<Script::Node>, Script::Node)]
|
127
|
+
# @return [(Array<Script::Tree::Node>, Script::Tree::Node)]
|
132
128
|
# The root nodes of the arguments, and the splat argument.
|
133
129
|
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
|
134
130
|
def parse_function_definition_arglist
|
@@ -149,7 +145,7 @@ module Sass
|
|
149
145
|
# Parse a single string value, possibly containing interpolation.
|
150
146
|
# Doesn't assert that the scanner is finished after parsing.
|
151
147
|
#
|
152
|
-
# @return [Script::Node] The root node of the parse tree.
|
148
|
+
# @return [Script::Tree::Node] The root node of the parse tree.
|
153
149
|
# @raise [Sass::SyntaxError] if the string isn't valid SassScript
|
154
150
|
def parse_string
|
155
151
|
unless (peek = @lexer.peek) &&
|
@@ -170,7 +166,7 @@ module Sass
|
|
170
166
|
# Parses a SassScript expression.
|
171
167
|
#
|
172
168
|
# @overload parse(str, line, offset, filename = nil)
|
173
|
-
# @return [Script::Node] The root node of the parse tree
|
169
|
+
# @return [Script::Tree::Node] The root node of the parse tree
|
174
170
|
# @see Parser#initialize
|
175
171
|
# @see Parser#parse
|
176
172
|
def self.parse(*args)
|
@@ -225,9 +221,7 @@ module Sass
|
|
225
221
|
end
|
226
222
|
|
227
223
|
start_pos = source_position
|
228
|
-
e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
|
229
|
-
e.line = start_pos.line
|
230
|
-
e.source_range = range(start_pos)
|
224
|
+
e = node(Tree::Operation.new(e, assert_expr(#{sub.inspect}), tok.type), start_pos)
|
231
225
|
end
|
232
226
|
e
|
233
227
|
end
|
@@ -239,10 +233,8 @@ RUBY
|
|
239
233
|
def unary_#{op}
|
240
234
|
return #{sub} unless tok = try_tok(:#{op})
|
241
235
|
interp = try_op_before_interp(tok) and return interp
|
242
|
-
|
243
|
-
|
244
|
-
op.line = line
|
245
|
-
op
|
236
|
+
start_pos = source_position
|
237
|
+
node(Tree::UnaryOperation.new(assert_expr(:unary_#{op}), :#{op}), start_pos)
|
246
238
|
end
|
247
239
|
RUBY
|
248
240
|
end
|
@@ -254,10 +246,6 @@ RUBY
|
|
254
246
|
Sass::Source::Position.new(line, offset)
|
255
247
|
end
|
256
248
|
|
257
|
-
def token_start_position(token)
|
258
|
-
Sass::Source::Position.new(token.line, token.offset)
|
259
|
-
end
|
260
|
-
|
261
249
|
def range(start_pos, end_pos=source_position)
|
262
250
|
Sass::Source::Range.new(start_pos, end_pos, @options[:filename], @options[:importer])
|
263
251
|
end
|
@@ -269,15 +257,15 @@ RUBY
|
|
269
257
|
interp = try_ops_after_interp([:comma], :expr) and return interp
|
270
258
|
start_pos = source_position
|
271
259
|
return unless e = interpolation
|
272
|
-
list = node(
|
260
|
+
list = node(Sass::Script::Tree::ListLiteral.new([e], :comma), start_pos)
|
273
261
|
while tok = try_tok(:comma)
|
274
262
|
if interp = try_op_before_interp(tok, list)
|
275
263
|
return interp unless other_interp = try_ops_after_interp([:comma], :expr, interp)
|
276
264
|
return other_interp
|
277
265
|
end
|
278
|
-
list.
|
266
|
+
list.elements << assert_expr(:interpolation)
|
279
267
|
end
|
280
|
-
list.
|
268
|
+
list.elements.size == 1 ? list.elements.first : list
|
281
269
|
end
|
282
270
|
|
283
271
|
production :equals, :interpolation, :single_eq
|
@@ -285,10 +273,10 @@ RUBY
|
|
285
273
|
def try_op_before_interp(op, prev = nil)
|
286
274
|
return unless @lexer.peek && @lexer.peek.type == :begin_interpolation
|
287
275
|
wb = @lexer.whitespace?(op)
|
288
|
-
str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
|
289
|
-
|
290
|
-
|
291
|
-
|
276
|
+
str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]), op.source_range)
|
277
|
+
interp = node(
|
278
|
+
Script::Tree::Interpolation.new(prev, str, nil, wb, !:wa, :originally_text),
|
279
|
+
(prev || str).source_range.start_pos)
|
292
280
|
interpolation(interp)
|
293
281
|
end
|
294
282
|
|
@@ -298,12 +286,11 @@ RUBY
|
|
298
286
|
interp = try_op_before_interp(op, prev) and return interp
|
299
287
|
|
300
288
|
wa = @lexer.whitespace?
|
301
|
-
str = Script::String.new(Lexer::OPERATORS_REVERSE[op.type])
|
289
|
+
str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]), op.source_range)
|
302
290
|
str.line = @lexer.line
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
interp.source_range = range(start_pos)
|
291
|
+
interp = node(
|
292
|
+
Script::Tree::Interpolation.new(prev, str, assert_expr(name), !:wb, wa, :originally_text),
|
293
|
+
(prev || str).source_range.start_pos)
|
307
294
|
return interp
|
308
295
|
end
|
309
296
|
|
@@ -314,8 +301,9 @@ RUBY
|
|
314
301
|
line = @lexer.line
|
315
302
|
mid = parse_interpolated
|
316
303
|
wa = @lexer.whitespace?
|
317
|
-
e =
|
318
|
-
|
304
|
+
e = node(
|
305
|
+
Script::Tree::Interpolation.new(e, mid, space, wb, wa),
|
306
|
+
(e || mid).source_range.start_pos)
|
319
307
|
end
|
320
308
|
e
|
321
309
|
end
|
@@ -327,7 +315,7 @@ RUBY
|
|
327
315
|
while e = or_expr
|
328
316
|
arr << e
|
329
317
|
end
|
330
|
-
arr.size == 1 ? arr.first : node(
|
318
|
+
arr.size == 1 ? arr.first : node(Sass::Script::Tree::ListLiteral.new(arr, :space), start_pos)
|
331
319
|
end
|
332
320
|
|
333
321
|
production :or_expr, :and_expr, :or
|
@@ -347,17 +335,18 @@ RUBY
|
|
347
335
|
return if @stop_at && @stop_at.include?(@lexer.peek.value)
|
348
336
|
|
349
337
|
name = @lexer.next
|
350
|
-
if color = Color::COLOR_NAMES[name.value.downcase]
|
351
|
-
return
|
338
|
+
if color = Sass::Script::Value::Color::COLOR_NAMES[name.value.downcase]
|
339
|
+
return literal_node(Sass::Script::Value::Color.new(color), name.source_range)
|
352
340
|
end
|
353
|
-
|
341
|
+
literal_node(Script::Value::String.new(name.value, :identifier), name.source_range)
|
354
342
|
end
|
355
343
|
|
356
344
|
def funcall
|
357
345
|
return raw unless tok = try_tok(:funcall)
|
358
346
|
args, keywords, splat = fn_arglist || [[], {}]
|
359
347
|
assert_tok(:rparen)
|
360
|
-
node(Script::Funcall.new(tok.value, args, keywords, splat),
|
348
|
+
node(Script::Tree::Funcall.new(tok.value, args, keywords, splat),
|
349
|
+
tok.source_range.start_pos, source_position)
|
361
350
|
end
|
362
351
|
|
363
352
|
def defn_arglist!(must_have_parens)
|
@@ -373,8 +362,7 @@ RUBY
|
|
373
362
|
must_have_default = false
|
374
363
|
loop do
|
375
364
|
c = assert_tok(:const)
|
376
|
-
var = Script::Variable.new(c.value)
|
377
|
-
var.source_range = range(c.offset)
|
365
|
+
var = node(Script::Tree::Variable.new(c.value), c.source_range)
|
378
366
|
if try_tok(:colon)
|
379
367
|
val = assert_expr(:space)
|
380
368
|
must_have_default = true
|
@@ -407,7 +395,7 @@ RUBY
|
|
407
395
|
loop do
|
408
396
|
if @lexer.peek && @lexer.peek.type == :colon
|
409
397
|
name = e
|
410
|
-
@lexer.expected!("comma") unless name.is_a?(Variable)
|
398
|
+
@lexer.expected!("comma") unless name.is_a?(Tree::Variable)
|
411
399
|
assert_tok(:colon)
|
412
400
|
value = assert_expr(subexpr, description)
|
413
401
|
|
@@ -431,17 +419,26 @@ RUBY
|
|
431
419
|
end
|
432
420
|
|
433
421
|
def raw
|
422
|
+
start_pos = source_position
|
434
423
|
return special_fun unless tok = try_tok(:raw)
|
435
|
-
|
424
|
+
literal_node(Script::Value::String.new(tok.value), tok.source_range)
|
436
425
|
end
|
437
426
|
|
438
427
|
def special_fun
|
428
|
+
start_pos = source_position
|
439
429
|
return paren unless tok = try_tok(:special_fun)
|
440
|
-
first =
|
430
|
+
first = literal_node(Script::Value::String.new(tok.value.first),
|
431
|
+
start_pos, start_pos.after(tok.value.first))
|
441
432
|
Sass::Util.enum_slice(tok.value[1..-1], 2).inject(first) do |l, (i, r)|
|
442
|
-
|
443
|
-
|
444
|
-
|
433
|
+
end_pos = i.source_range.end_pos
|
434
|
+
end_pos = end_pos.after(r) if r
|
435
|
+
node(
|
436
|
+
Script::Tree::Interpolation.new(
|
437
|
+
l, i,
|
438
|
+
r && literal_node(Script::Value::String.new(r),
|
439
|
+
i.source_range.end_pos, end_pos),
|
440
|
+
false, false),
|
441
|
+
start_pos, end_pos)
|
445
442
|
end
|
446
443
|
end
|
447
444
|
|
@@ -451,8 +448,9 @@ RUBY
|
|
451
448
|
@in_parens = true
|
452
449
|
start_pos = source_position
|
453
450
|
e = expr
|
451
|
+
end_pos = source_position
|
454
452
|
assert_tok(:rparen)
|
455
|
-
return e || node(
|
453
|
+
return e || node(Sass::Script::Tree::ListLiteral.new([], :space), start_pos, end_pos)
|
456
454
|
ensure
|
457
455
|
@in_parens = was_in_parens
|
458
456
|
end
|
@@ -460,31 +458,27 @@ RUBY
|
|
460
458
|
def variable
|
461
459
|
start_pos = source_position
|
462
460
|
return string unless c = try_tok(:const)
|
463
|
-
node(Variable.new(*c.value), start_pos
|
461
|
+
node(Tree::Variable.new(*c.value), start_pos)
|
464
462
|
end
|
465
463
|
|
466
464
|
def string
|
467
465
|
return number unless first = try_tok(:string)
|
468
|
-
|
469
|
-
|
470
|
-
line = @lexer.line
|
466
|
+
str = literal_node(first.value, first.source_range)
|
467
|
+
return str unless try_tok(:begin_interpolation)
|
471
468
|
mid = parse_interpolated
|
472
469
|
last = assert_expr(:string)
|
473
|
-
|
474
|
-
interp.line = line
|
475
|
-
interp.source_range = range(start_pos)
|
476
|
-
interp
|
470
|
+
node(Tree::StringInterpolation.new(str, mid, last), first.source_range.start_pos)
|
477
471
|
end
|
478
472
|
|
479
473
|
def number
|
480
474
|
return literal unless tok = try_tok(:number)
|
481
475
|
num = tok.value
|
482
476
|
num.original = num.to_s unless @in_parens
|
483
|
-
num
|
477
|
+
literal_node(num, tok.source_range.start_pos)
|
484
478
|
end
|
485
479
|
|
486
480
|
def literal
|
487
|
-
(t = try_tok(:color, :bool, :null)) && (return t.value)
|
481
|
+
(t = try_tok(:color, :bool, :null)) && (return literal_node(t.value, t.source_range))
|
488
482
|
end
|
489
483
|
|
490
484
|
# It would be possible to have unified #assert and #try methods,
|
@@ -517,10 +511,35 @@ RUBY
|
|
517
511
|
@lexer.expected!(EXPR_NAMES[:default])
|
518
512
|
end
|
519
513
|
|
520
|
-
|
521
|
-
|
514
|
+
# @overload node(value, source_range)
|
515
|
+
# @param value [Sass::Script::Value::Base]
|
516
|
+
# @param source_range [Sass::Source::Range]
|
517
|
+
# @overload node(value, start_pos, end_pos = source_position)
|
518
|
+
# @param value [Sass::Script::Value::Base]
|
519
|
+
# @param start_pos [Sass::Source::Position]
|
520
|
+
# @param end_pos [Sass::Source::Position]
|
521
|
+
def literal_node(value, source_range_or_start_pos, end_pos = source_position)
|
522
|
+
node(Sass::Script::Tree::Literal.new(value), source_range_or_start_pos, end_pos)
|
523
|
+
end
|
524
|
+
|
525
|
+
# @overload node(node, source_range)
|
526
|
+
# @param node [Sass::Script::Tree::Node]
|
527
|
+
# @param source_range [Sass::Source::Range]
|
528
|
+
# @overload node(node, start_pos, end_pos = source_position)
|
529
|
+
# @param node [Sass::Script::Tree::Node]
|
530
|
+
# @param start_pos [Sass::Source::Position]
|
531
|
+
# @param end_pos [Sass::Source::Position]
|
532
|
+
def node(node, source_range_or_start_pos, end_pos = source_position)
|
533
|
+
source_range =
|
534
|
+
if source_range_or_start_pos.is_a?(Sass::Source::Range)
|
535
|
+
source_range_or_start_pos
|
536
|
+
else
|
537
|
+
range(source_range_or_start_pos, end_pos)
|
538
|
+
end
|
539
|
+
|
540
|
+
node.line = source_range.start_pos.line
|
541
|
+
node.source_range = source_range
|
522
542
|
node.filename = @options[:filename]
|
523
|
-
node.source_range = range(start_pos, end_pos) if end_pos
|
524
543
|
node
|
525
544
|
end
|
526
545
|
end
|