Class Sass::Script::Parser
In: lib/sass/script/parser.rb
Parent: Object
Haml::Util Engine Color SyntaxError UnitConversionError StandardError Node Operation Literal UnaryOperation Funcall Variable Number String Bool EvaluationContext Node\n[lib/sass/css.rb\nlib/sass/tree/node.rb] DebugNode IfNode CommentNode ForNode MixinNode VariableNode ImportNode WhileNode MixinDefNode Repl CSS Environment Lexer Parser PropNode\n[lib/sass/css.rb\nlib/sass/tree/prop_node.rb] DirectiveNode\n[lib/sass/css.rb\nlib/sass/tree/directive_node.rb] RuleNode\n[lib/sass/css.rb\nlib/sass/tree/rule_node.rb] Rack lib/sass/repl.rb lib/sass/css.rb lib/sass/environment.rb lib/sass/error.rb lib/sass/engine.rb lib/sass/script/lexer.rb lib/sass/script/color.rb lib/sass/script/string.rb lib/sass/script/unary_operation.rb lib/sass/script/variable.rb lib/sass/script/funcall.rb lib/sass/script/operation.rb lib/sass/script/bool.rb lib/sass/script/parser.rb lib/sass/script/literal.rb lib/sass/script/node.rb lib/sass/script/number.rb lib/sass/script/functions.rb Functions Script Files lib/sass/tree/while_node.rb lib/sass/tree/if_node.rb lib/sass/tree/mixin_def_node.rb lib/sass/tree/debug_node.rb lib/sass/tree/for_node.rb lib/sass/tree/import_node.rb lib/sass/tree/prop_node.rb lib/sass/tree/node.rb lib/sass/tree/comment_node.rb lib/sass/tree/mixin_node.rb lib/sass/tree/directive_node.rb lib/sass/tree/rule_node.rb lib/sass/tree/variable_node.rb Tree lib/sass/plugin/rack.rb Plugin Sass dot/m_54_0.png

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

Methods

Public Class methods

@param str [String, StringScanner] The source text to parse @param line [Fixnum] The line on which the SassScript appears.

  Used for error reporting

@param offset [Fixnum] The number of characters in on which the SassScript appears.

  Used for error reporting

@param filename [String] The name of the file in which the SassScript appears.

  Used for error reporting

[Source]

    # File lib/sass/script/parser.rb, line 15
15:       def initialize(str, line, offset, filename = nil)
16:         @filename = filename
17:         @lexer = Lexer.new(str, line, offset, filename)
18:       end

Parses a SassScript expression.

@overload parse(str, line, offset, filename = nil) @return [Script::Node] The root node of the parse tree @see Parser#initialize @see Parser#parse

[Source]

    # File lib/sass/script/parser.rb, line 81
81:       def self.parse(*args)
82:         new(*args).parse
83:       end

Private Class methods

Defines a simple left-associative production. name is the name of the production, sub is the name of the production beneath it, and ops is a list of operators for this precedence level

[Source]

    # File lib/sass/script/parser.rb, line 92
92:         def production(name, sub, *ops)
93:           class_eval "            def \#{name}\n              return unless e = \#{sub}\n              while tok = try_tok(\#{ops.map {|o| o.inspect}.join(', ')})\n                e = Operation.new(e, assert_expr(\#{sub.inspect}), tok.type)\n              end\n              e\n            end\n"
94:         end

[Source]

     # File lib/sass/script/parser.rb, line 105
105:         def unary(op, sub)
106:           class_eval "            def unary_\#{op}\n              return \#{sub} unless try_tok(:\#{op})\n              UnaryOperation.new(assert_expr(:unary_\#{op}), :\#{op})\n            end\n"
107:         end

Public Instance methods

Parses a SassScript expression.

@return [Script::Node] The root node of the parse tree @raise [Sass::SyntaxError] if the expression isn‘t valid SassScript

[Source]

    # File lib/sass/script/parser.rb, line 37
37:       def parse
38:         expr = assert_expr :expr
39:         assert_done
40:         expr
41:       end

Parses a SassScript expression within an interpolated segment (`#{}`). This means that it stops when it comes across an unmatched `}`, which signals the end of an interpolated segment, it returns rather than throwing an error.

@return [Script::Node] The root node of the parse tree @raise [Sass::SyntaxError] if the expression isn‘t valid SassScript

[Source]

    # File lib/sass/script/parser.rb, line 27
27:       def parse_interpolated
28:         expr = assert_expr :expr
29:         assert_tok :end_interpolation
30:         expr
31:       end

Parses the argument list for a mixin definition.

@return [Array<Script::Node>] The root nodes of the arguments. @raise [Sass::SyntaxError] if the argument list isn‘t valid SassScript

[Source]

    # File lib/sass/script/parser.rb, line 63
63:       def parse_mixin_definition_arglist
64:         args = []
65: 
66:         if try_tok(:lparen)
67:           args = defn_arglist(false) || args
68:           assert_tok(:rparen)
69:         end
70:         assert_done
71: 
72:         args
73:       end

Parses the argument list for a mixin include.

@return [Array<Script::Node>] The root nodes of the arguments. @raise [Sass::SyntaxError] if the argument list isn‘t valid SassScript

[Source]

    # File lib/sass/script/parser.rb, line 47
47:       def parse_mixin_include_arglist
48:         args = []
49: 
50:         if try_tok(:lparen)
51:           args = arglist || args
52:           assert_tok(:rparen)
53:         end
54:         assert_done
55: 
56:         args
57:       end

Private Instance methods

[Source]

     # File lib/sass/script/parser.rb, line 171
171:       def arglist
172:         return unless e = concat
173:         return [e] unless try_tok(:comma)
174:         [e, *arglist]
175:       end

[Source]

     # File lib/sass/script/parser.rb, line 219
219:       def assert_done
220:         return if @lexer.done?
221:         raise Sass::SyntaxError.new("Unexpected #{@lexer.peek.type} token.")
222:       end

It would be possible to have unified assert and try methods, but detecting the method/token difference turns out to be quite expensive.

[Source]

     # File lib/sass/script/parser.rb, line 204
204:       def assert_expr(name)
205:         (e = send(name)) && (return e)
206:         raise Sass::SyntaxError.new("Expected expression, was #{@lexer.done? ? 'end of text' : "#{@lexer.peek.type} token"}.")
207:       end

[Source]

     # File lib/sass/script/parser.rb, line 209
209:       def assert_tok(*names)
210:         (t = try_tok(*names)) && (return t)
211:         raise Sass::SyntaxError.new("Expected #{names.join(' or ')} token, was #{@lexer.done? ? 'end of text' : "#{@lexer.peek.type} token"}.")
212:       end

[Source]

     # File lib/sass/script/parser.rb, line 120
120:       def concat
121:         return unless e = or_expr
122:         while sub = or_expr
123:           e = Operation.new(e, sub, :concat)
124:         end
125:         e
126:       end

[Source]

     # File lib/sass/script/parser.rb, line 158
158:       def defn_arglist(must_have_default)
159:         return unless c = try_tok(:const)
160:         var = Script::Variable.new(c.value)
161:         if try_tok(:single_eq)
162:           val = assert_expr(:concat)
163:         elsif must_have_default
164:           raise SyntaxError.new("Required argument #{var.inspect} must come before any optional arguments.", @line)
165:         end
166: 
167:         return [[var, val]] unless try_tok(:comma)
168:         [[var, val], *defn_arglist(val)]
169:       end

[Source]

     # File lib/sass/script/parser.rb, line 139
139:       def funcall
140:         return paren unless name = try_tok(:ident)
141:         # An identifier without arguments is just a string
142:         unless try_tok(:lparen)
143:           warn("DEPRECATION WARNING:\nOn line \#{name.line}, character \#{name.offset}\#{\" of '\#{@filename}'\" if @filename}\nImplicit strings have been deprecated and will be removed in version 2.4.\n'\#{name.value}' was not quoted. Please add double quotes (e.g. \"\#{name.value}\").\n")
144:           Script::String.new(name.value)
145:         else
146:           args = arglist || []
147:           assert_tok(:rparen)
148:           Script::Funcall.new(name.value, args)
149:         end
150:       end

[Source]

     # File lib/sass/script/parser.rb, line 197
197:       def literal
198:         (t = try_tok(:number, :color, :bool)) && (return t.value)
199:       end

[Source]

     # File lib/sass/script/parser.rb, line 177
177:       def paren
178:         return variable unless try_tok(:lparen)
179:         e = assert_expr(:expr)
180:         assert_tok(:rparen)
181:         return e
182:       end

[Source]

     # File lib/sass/script/parser.rb, line 189
189:       def string
190:         return literal unless first = try_tok(:string)
191:         return first.value unless try_tok(:begin_interpolation)
192:         mid = parse_interpolated
193:         last = assert_expr(:string)
194:         Operation.new(first.value, Operation.new(mid, last, :plus), :plus)
195:       end

[Source]

     # File lib/sass/script/parser.rb, line 214
214:       def try_tok(*names)
215:         peeked =  @lexer.peek
216:         peeked && names.include?(peeked.type) && @lexer.next
217:       end

[Source]

     # File lib/sass/script/parser.rb, line 184
184:       def variable
185:         return string unless c = try_tok(:const)
186:         Variable.new(c.value)
187:       end

[Validate]