lib/sass/script/parser.rb in sass-3.3.0.alpha.256 vs lib/sass/script/parser.rb in sass-3.3.0.alpha.353
- old
+ new
@@ -20,11 +20,11 @@
end
# @param str [String, StringScanner] The source text to parse
# @param line [Fixnum] The line on which the SassScript appears.
# Used for error reporting and sourcemap building
- # @param offset [Fixnum] The character (not byte) offset in the line on which the SassScript appears.
+ # @param offset [Fixnum] The character (not byte) offset where the script starts in the line.
# Used for error reporting and sourcemap building
# @param options [{Symbol => Object}] An options hash;
# see {file:SASS_REFERENCE.md#sass_options the Sass options documentation}
def initialize(str, line, offset, options = {})
@options = options
@@ -79,11 +79,14 @@
raise e
end
# Parses the argument list for a mixin include.
#
- # @return [(Array<Script::Tree::Node>, {String => Script::Tree::Node}, Script::Tree::Node, Script::Tree::Node)]
+ # @return [(Array<Script::Tree::Node>,
+ # {String => Script::Tree::Node},
+ # Script::Tree::Node,
+ # Script::Tree::Node)]
# The root nodes of the positional arguments, keyword arguments, and
# splat argument(s). 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 = [], {}
@@ -211,15 +214,17 @@
# sub is the name of the production beneath it,
# and ops is a list of operators for this precedence level
def production(name, sub, *ops)
class_eval <<RUBY, __FILE__, __LINE__ + 1
def #{name}
- interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}) and return interp
+ interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect})
+ return interp if interp
return unless e = #{sub}
while tok = try_tok(#{ops.map {|o| o.inspect}.join(', ')})
if interp = try_op_before_interp(tok, e)
- return interp unless other_interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}, interp)
+ other_interp = try_ops_after_interp(#{ops.inspect}, #{name.inspect}, interp)
+ return interp unless other_interp
return other_interp
end
start_pos = source_position
e = node(Tree::Operation.new(e, assert_expr(#{sub.inspect}), tok.type), start_pos)
@@ -231,11 +236,12 @@
def unary(op, sub)
class_eval <<RUBY, __FILE__, __LINE__ + 1
def unary_#{op}
return #{sub} unless tok = try_tok(:#{op})
- interp = try_op_before_interp(tok) and return interp
+ interp = try_op_before_interp(tok)
+ return interp if interp
start_pos = source_position
node(Tree::UnaryOperation.new(assert_expr(:unary_#{op}), :#{op}), start_pos)
end
RUBY
end
@@ -245,48 +251,51 @@
def source_position
Sass::Source::Position.new(line, offset)
end
- def range(start_pos, end_pos=source_position)
+ def range(start_pos, end_pos = source_position)
Sass::Source::Range.new(start_pos, end_pos, @options[:filename], @options[:importer])
end
# @private
def lexer_class; Lexer; end
def map
start_pos = source_position
- return unless e = interpolation
+ e = interpolation
+ return unless e
return list e, start_pos unless @lexer.peek && @lexer.peek.type == :colon
key, value = map_pair(e)
map = node(Sass::Script::Tree::MapLiteral.new([[key, value]]), start_pos)
- while tok = try_tok(:comma)
+ while try_tok(:comma)
key, value = assert_expr(:map_pair)
map.pairs << [key, value]
end
map
end
- def map_pair(key=nil)
+ def map_pair(key = nil)
return unless key ||= interpolation
assert_tok :colon
return key, assert_expr(:interpolation)
end
def expr
start_pos = source_position
- return unless e = interpolation
+ e = interpolation
+ return unless e
list e, start_pos
end
def list(first, start_pos)
list = node(Sass::Script::Tree::ListLiteral.new([first], :comma), start_pos)
- while tok = try_tok(:comma)
- if interp = try_op_before_interp(tok, list)
- return interp unless other_interp = try_ops_after_interp([:comma], :expr, interp)
+ while (tok = try_tok(:comma))
+ if (interp = try_op_before_interp(tok, list))
+ other_interp = try_ops_after_interp([:comma], :expr, interp)
+ return interp unless other_interp
return other_interp
end
list.elements << assert_expr(:interpolation)
end
list.elements.size == 1 ? list.elements.first : list
@@ -295,36 +304,39 @@
production :equals, :interpolation, :single_eq
def try_op_before_interp(op, prev = nil)
return unless @lexer.peek && @lexer.peek.type == :begin_interpolation
wb = @lexer.whitespace?(op)
- str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]), op.source_range)
+ str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]),
+ op.source_range)
interp = node(
Script::Tree::Interpolation.new(prev, str, nil, wb, !:wa, :originally_text),
(prev || str).source_range.start_pos)
interpolation(interp)
end
def try_ops_after_interp(ops, name, prev = nil)
return unless @lexer.after_interpolation?
- return unless op = try_tok(*ops)
- interp = try_op_before_interp(op, prev) and return interp
+ op = try_tok(*ops)
+ return unless op
+ interp = try_op_before_interp(op, prev)
+ return interp if interp
wa = @lexer.whitespace?
- str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]), op.source_range)
+ str = literal_node(Script::Value::String.new(Lexer::OPERATORS_REVERSE[op.type]),
+ op.source_range)
str.line = @lexer.line
interp = node(
Script::Tree::Interpolation.new(prev, str, assert_expr(name), !:wb, wa, :originally_text),
(prev || str).source_range.start_pos)
- return interp
+ interp
end
def interpolation(first = space)
e = first
- while interp = try_tok(:begin_interpolation)
+ while (interp = try_tok(:begin_interpolation))
wb = @lexer.whitespace?(interp)
- line = @lexer.line
mid = parse_interpolated
wa = @lexer.whitespace?
e = node(
Script::Tree::Interpolation.new(e, mid, space, wb, wa),
(e || mid).source_range.start_pos)
@@ -332,16 +344,21 @@
e
end
def space
start_pos = source_position
- return unless e = or_expr
+ e = or_expr
+ return unless e
arr = [e]
- while e = or_expr
+ while (e = or_expr)
arr << e
end
- arr.size == 1 ? arr.first : node(Sass::Script::Tree::ListLiteral.new(arr, :space), start_pos)
+ if arr.size == 1
+ arr.first
+ else
+ node(Sass::Script::Tree::ListLiteral.new(arr, :space), start_pos)
+ end
end
production :or_expr, :and_expr, :or
production :and_expr, :eq_or_neq, :and
production :eq_or_neq, :relational, :eq, :neq
@@ -357,18 +374,19 @@
def ident
return funcall unless @lexer.peek && @lexer.peek.type == :ident
return if @stop_at && @stop_at.include?(@lexer.peek.value)
name = @lexer.next
- if color = Sass::Script::Value::Color::COLOR_NAMES[name.value.downcase]
+ if (color = Sass::Script::Value::Color::COLOR_NAMES[name.value.downcase])
return literal_node(Sass::Script::Value::Color.new(color), name.source_range)
end
literal_node(Script::Value::String.new(name.value, :identifier), name.source_range)
end
def funcall
- return raw unless tok = try_tok(:funcall)
+ tok = try_tok(:funcall)
+ return raw unless tok
args, keywords, splat, kwarg_splat = fn_arglist
assert_tok(:rparen)
node(Script::Tree::Funcall.new(tok.value, args, keywords, splat, kwarg_splat),
tok.source_range.start_pos, source_position)
end
@@ -389,11 +407,12 @@
var = node(Script::Tree::Variable.new(c.value), c.source_range)
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.")
+ raise SyntaxError.new(
+ "Required argument #{var.inspect} must come before any optional arguments.")
elsif try_tok(:splat)
splat = var
break
end
res << [var, val]
@@ -412,12 +431,13 @@
end
def arglist(subexpr, description)
args = []
keywords = Sass::Util::NormalizedMap.new
+ e = send(subexpr)
- return [args, keywords] unless e = send(subexpr)
+ return [args, keywords] unless e
loop do
if @lexer.peek && @lexer.peek.type == :colon
name = e
@lexer.expected!("comma") unless name.is_a?(Tree::Variable)
@@ -428,11 +448,11 @@
raise SyntaxError.new("Keyword argument \"#{name.to_sass}\" passed more than once")
end
keywords[name.name] = value
else
- if !keywords.empty?
+ unless keywords.empty?
raise SyntaxError.new("Positional arguments must come before keyword arguments.")
end
if try_tok(:splat)
splat = e
@@ -448,17 +468,19 @@
e = assert_expr(subexpr, description)
end
end
def raw
- return special_fun unless tok = try_tok(:raw)
+ tok = try_tok(:raw)
+ return special_fun unless tok
literal_node(Script::Value::String.new(tok.value), tok.source_range)
end
def special_fun
start_pos = source_position
- return paren unless tok = try_tok(:special_fun)
+ tok = try_tok(:special_fun)
+ return paren unless tok
first = literal_node(Script::Value::String.new(tok.value.first),
start_pos, start_pos.after(tok.value.first))
Sass::Util.enum_slice(tok.value[1..-1], 2).inject(first) do |l, (i, r)|
end_pos = i.source_range.end_pos
end_pos = end_pos.after(r) if r
@@ -485,37 +507,42 @@
@in_parens = was_in_parens
end
def variable
start_pos = source_position
- return string unless c = try_tok(:const)
+ c = try_tok(:const)
+ return string unless c
node(Tree::Variable.new(*c.value), start_pos)
end
def string
- return number unless first = try_tok(:string)
+ first = try_tok(:string)
+ return number unless first
str = literal_node(first.value, first.source_range)
return str unless try_tok(:begin_interpolation)
mid = parse_interpolated
last = assert_expr(:string)
node(Tree::StringInterpolation.new(str, mid, last), first.source_range.start_pos)
end
def number
- return selector unless tok = try_tok(:number)
+ tok = try_tok(:number)
+ return selector unless tok
num = tok.value
num.original = num.to_s unless @in_parens
literal_node(num, tok.source_range.start_pos)
end
def selector
- return literal unless tok = try_tok(:selector)
+ tok = try_tok(:selector)
+ return literal unless tok
node(tok.value, tok.source_range.start_pos)
end
def literal
- (t = try_tok(:color, :bool, :null)) && (return literal_node(t.value, t.source_range))
+ t = try_tok(:color, :bool, :null)
+ return literal_node(t.value, t.source_range) if t
end
# It would be possible to have unified #assert and #try methods,
# but detecting the method/token difference turns out to be quite expensive.
@@ -526,15 +553,17 @@
:fn_arglist => "function argument",
:splat => "...",
}
def assert_expr(name, expected = nil)
- (e = send(name)) && (return e)
+ e = send(name)
+ return e if e
@lexer.expected!(expected || EXPR_NAMES[name] || EXPR_NAMES[:default])
end
def assert_tok(*names)
- (t = try_tok(*names)) && (return t)
+ t = try_tok(*names)
+ return t if t
@lexer.expected!(names.map {|tok| Lexer::TOKEN_NAMES[tok] || tok}.join(" or "))
end
def try_tok(*names)
peeked = @lexer.peek