lib/sass/script/parser.rb in sass-3.2.0.alpha.278 vs lib/sass/script/parser.rb in sass-3.2.0.alpha.291
- old
+ new
@@ -72,61 +72,66 @@
raise e
end
# Parses the argument list for a mixin include.
#
- # @return [(Array<Script::Node>, {String => Script::Note})]
- # The root nodes of the arguments.
- # Keyword arguments are in a hash from names to values.
+ # @return [(Array<Script::Node>, {String => Script::Node}, Script::Node)]
+ # The root nodes of the positional arguments, keyword arguments, and
+ # splat argument. Keyword arguments are in a hash from names to values.
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
def parse_mixin_include_arglist
args, keywords = [], {}
if try_tok(:lparen)
- args, keywords = mixin_arglist || [[], {}]
+ args, keywords, splat = mixin_arglist || [[], {}]
assert_tok(:rparen)
end
assert_done
args.each {|a| a.options = @options}
keywords.each {|k, v| v.options = @options}
- return args, keywords
+ splat.options = @options if splat
+ return args, keywords, splat
rescue Sass::SyntaxError => e
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
raise e
end
# Parses the argument list for a mixin definition.
#
- # @return [Array<Script::Node>] The root nodes of the arguments.
+ # @return [(Array<Script::Node>, Script::Node)]
+ # The root nodes of the arguments, and the splat argument.
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
def parse_mixin_definition_arglist
- args = defn_arglist!(false)
+ args, splat = defn_arglist!(false)
assert_done
args.each do |k, v|
k.options = @options
v.options = @options if v
end
- args
+ splat.options = @options if splat
+ return args, splat
rescue Sass::SyntaxError => e
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
raise e
end
# Parses the argument list for a function definition.
#
- # @return [Array<Script::Node>] The root nodes of the arguments.
+ # @return [(Array<Script::Node>, Script::Node)]
+ # The root nodes of the arguments, and the splat argument.
# @raise [Sass::SyntaxError] if the argument list isn't valid SassScript
def parse_function_definition_arglist
- args = defn_arglist!(true)
+ args, splat = defn_arglist!(true)
assert_done
args.each do |k, v|
k.options = @options
v.options = @options if v
end
- args
+ splat.options = @options if splat
+ return args, splat
rescue Sass::SyntaxError => e
e.modify_backtrace :line => @lexer.line, :filename => @options[:filename]
raise e
end
@@ -322,41 +327,45 @@
node(Script::String.new(name.value, :identifier))
end
def funcall
return raw unless tok = try_tok(:funcall)
- args, keywords = fn_arglist || [[], {}]
+ args, keywords, splat = fn_arglist || [[], {}]
assert_tok(:rparen)
- node(Script::Funcall.new(tok.value, args, keywords))
+ node(Script::Funcall.new(tok.value, args, keywords, splat))
end
def defn_arglist!(must_have_parens)
if must_have_parens
assert_tok(:lparen)
else
- return [] unless try_tok(:lparen)
+ return [], nil unless try_tok(:lparen)
end
- return [] if try_tok(:rparen)
+ return [], nil if try_tok(:rparen)
res = []
+ splat = nil
must_have_default = false
loop do
line = @lexer.line
offset = @lexer.offset + 1
c = assert_tok(:const)
var = Script::Variable.new(c.value)
- if tok = try_tok(:colon)
+ if try_tok(:colon)
val = assert_expr(:space)
must_have_default = true
elsif must_have_default
raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments.")
+ elsif try_tok(:splat)
+ splat = var
+ break
end
res << [var, val]
break unless try_tok(:comma)
end
assert_tok(:rparen)
- res
+ return res, splat
end
def fn_arglist
arglist(:fn_arglist, :equals)
end
@@ -374,35 +383,24 @@
keywords = {name.underscored_name => assert_expr(subexpr, EXPR_NAMES[type])}
end
unless try_tok(:comma)
return [], keywords if keywords
+ return [], {}, e if try_tok(:splat)
return [e], {}
end
- other_args, other_keywords = assert_expr(type)
+ other_args, other_keywords, splat = assert_expr(type)
if keywords
- if !other_args.empty?
- raise SyntaxError.new("Positional arguments must come before keyword arguments")
+ if !other_args.empty? || splat
+ raise SyntaxError.new("Positional arguments must come before keyword arguments.")
elsif other_keywords[name.underscored_name]
raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
end
- return other_args, keywords.merge(other_keywords)
+ return other_args, keywords.merge(other_keywords), splat
else
- return [e, *other_args], other_keywords
+ return [e, *other_args], other_keywords, splat
end
- end
-
- def keyword_arglist
- return unless var = try_tok(:const)
- unless try_tok(:colon)
- return_tok!
- return
- end
- name = var[1]
- value = interpolation
- return {name => value} unless try_tok(:comma)
- {name => value}.merge(assert_expr(:keyword_arglist))
end
def raw
return special_fun unless tok = try_tok(:raw)
node(Script::String.new(tok.value))