class Sass::Script::Parser

It parses a string of code into a tree of {Script::Node}s.
The parser for SassScript.

def self.parse(*args)

Other tags:
    See: Parser#parse -
    See: Parser#initialize -

Returns:
  • (Script::Node) - The root node of the parse tree

Overloads:
  • parse(str, line, offset, filename = nil)
def self.parse(*args)
  new(*args).parse
end

def arglist

def arglist
  return unless e = concat
  return [e] unless try_tok(:comma)
  [e, *arglist]
end

def assert_done

def assert_done
  return if @lexer.done?
  raise Sass::SyntaxError.new("Unexpected #{@lexer.peek.type} token.")
end

def assert_expr(name)

def assert_expr(name)
  (e = send(name)) && (return e)
  raise Sass::SyntaxError.new("Expected expression, was #{@lexer.done? ? 'end of text' : "#{@lexer.peek.type} token"}.")
end

def assert_tok(*names)

def assert_tok(*names)
  (t = try_tok(*names)) && (return t)
  raise Sass::SyntaxError.new("Expected #{names.join(' or ')} token, was #{@lexer.done? ? 'end of text' : "#{@lexer.peek.type} token"}.")
end

def concat

def concat
  return unless e = or_expr
  while sub = or_expr
    e = Operation.new(e, sub, :concat)
  end
  e
end

def defn_arglist(must_have_default)

def defn_arglist(must_have_default)
  return unless c = try_tok(:const)
  var = Script::Variable.new(c.value)
  if try_tok(:single_eq)
    val = assert_expr(:concat)
  elsif must_have_default
    raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments.", @line)
  end
  return [[var, val]] unless try_tok(:comma)
  [[var, val], *defn_arglist(val)]
end

def funcall

def funcall
  return paren unless name = try_tok(:ident)
  # An identifier without arguments is just a string
  unless try_tok(:lparen)
    warn(<<END)
ATION WARNING:
e #{name.line}, character #{name.offset}#{" of '#{@filename}'" if @filename}
it strings have been deprecated and will be removed in version 3.0.
e.value}' was not quoted. Please add double quotes (e.g. "#{name.value}").
    Script::String.new(name.value)
  else
    args = arglist || []
    assert_tok(:rparen)
    Script::Funcall.new(name.value, args)
  end
end

def initialize(str, line, offset, filename = nil)

Parameters:
  • filename (String) -- The name of the file in which the SassScript appears.
  • offset (Fixnum) -- The number of characters in on which the SassScript appears.
  • line (Fixnum) -- The line on which the SassScript appears.
  • str (String, StringScanner) -- The source text to parse
def initialize(str, line, offset, filename = nil)
  @filename = filename
  @lexer = Lexer.new(str, line, offset, filename)
end

def literal

def literal
  (t = try_tok(:number, :color, :bool)) && (return t.value)
end

def paren

def paren
  return variable unless try_tok(:lparen)
  e = assert_expr(:expr)
  assert_tok(:rparen)
  return e
end

def parse

Raises:
  • (Sass::SyntaxError) - if the expression isn't valid SassScript

Returns:
  • (Script::Node) - The root node of the parse tree
def parse
  expr = assert_expr :expr
  assert_done
  expr
end

def parse_interpolated

Raises:
  • (Sass::SyntaxError) - if the expression isn't valid SassScript

Returns:
  • (Script::Node) - The root node of the parse tree
def parse_interpolated
  expr = assert_expr :expr
  assert_tok :end_interpolation
  expr
end

def parse_mixin_definition_arglist

Raises:
  • (Sass::SyntaxError) - if the argument list isn't valid SassScript

Returns:
  • (Array) - The root nodes of the arguments.
def parse_mixin_definition_arglist
  args = []
  if try_tok(:lparen)
    args = defn_arglist(false) || args
    assert_tok(:rparen)
  end
  assert_done
  args
end

def parse_mixin_include_arglist

Raises:
  • (Sass::SyntaxError) - if the argument list isn't valid SassScript

Returns:
  • (Array) - The root nodes of the arguments.
def parse_mixin_include_arglist
  args = []
  if try_tok(:lparen)
    args = arglist || args
    assert_tok(:rparen)
  end
  assert_done
  args
end

def production(name, sub, *ops)

and ops is a list of operators for this precedence level
sub is the name of the production beneath it,
name is the name of the production,
Defines a simple left-associative production.
def production(name, sub, *ops)
  class_eval <<RUBY
    def #{name}
      return unless e = #{sub}
      while tok = try_tok(#{ops.map {|o| o.inspect}.join(', ')})
        e = Operation.new(e, assert_expr(#{sub.inspect}), tok.type)
      end
      e
    end
end

def string

def string
  return literal unless first = try_tok(:string)
  return first.value unless try_tok(:begin_interpolation)
  mid = parse_interpolated
  last = assert_expr(:string)
  Operation.new(first.value, Operation.new(mid, last, :plus), :plus)
end

def try_tok(*names)

def try_tok(*names)
  peeked =  @lexer.peek
  peeked && names.include?(peeked.type) && @lexer.next
end

def unary(op, sub)

def unary(op, sub)
  class_eval <<RUBY
    def unary_#{op}
      return #{sub} unless try_tok(:#{op})
      UnaryOperation.new(assert_expr(:unary_#{op}), :#{op})
    end
end

def variable

def variable
  return string unless c = try_tok(:const)
  Variable.new(c.value)
end