From 930e7382d41f450f8aa4bb29649204683a07353a Mon Sep 17 00:00:00 2001 From: "Eevee (Alex Munroe)" Date: Fri, 23 Aug 2013 16:21:43 -0700 Subject: Map literals in Parsley, and a few other minor fixes. - Labels for some of the rules. - Faux goal_argspec rule to play nicely with parse_expression. - Wrap ParseErrors in SassParseError. - Ruby's interp-and-slash test now passes exactly. - Don't render nulls in an interpolation. --- scss/expression.parsley | 24 ++++++++++++++++++++++-- scss/expression.py | 8 +++++--- scss/tests/test_expression.py | 3 +-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/scss/expression.parsley b/scss/expression.parsley index 77b41fa..8fc35bf 100644 --- a/scss/expression.parsley +++ b/scss/expression.parsley @@ -38,7 +38,7 @@ spaced_list = single_expression:head ( )*:tails -> ListLiteral([head] + tails, comma=False) if tails else head -single_expression = or_test +single_expression = or_test ^(single expression) or_test = and_test:head ( 'o' 'r' @@ -97,6 +97,9 @@ atom = ( # TODO kill this off | '[' comma_list:node ']' -> Parentheses(node) + # Map literal + | map + # URL literal | 'u' 'r' 'l' '(' inside_url:s ')' -> FunctionLiteral('url', s) @@ -135,6 +138,21 @@ atom = ( # Variable | variable:name -> Variable(name) ) + ^(single value) + + +### Map literals +map = '(' ows + ( map_pair:pair ows ',' ows -> pair )*:pairs + ( map_pair:pair ows !(pairs.append(pair)) )? + ')' + -> MapLiteral(pairs) + +map_pair = + single_expression:key + ows ':' ows + spaced_list:value + -> (key, value) ### Strings, literals, and interpolation @@ -174,6 +192,8 @@ string_part :end = <( ### Function definitions and arguments +goal_argspec = argspec + argspec = ( argspec_item:node ows ',' ows @@ -186,7 +206,7 @@ argspec = ( argspec_item = ows ( - ( variable:name ows ':' ows -> name )?:name + ( variable:name ows ':' ows -> Variable(name) )?:name spaced_list:value -> (name, value) ) diff --git a/scss/expression.py b/scss/expression.py index ebec7e2..bd19031 100644 --- a/scss/expression.py +++ b/scss/expression.py @@ -29,7 +29,7 @@ log = logging.getLogger(__name__) FATAL_UNDEFINED = True -from ometa.runtime import EOFError, OMetaBase, expected +from ometa.runtime import EOFError, OMetaBase, ParseError, expected import string HEXDIGITS = frozenset(string.hexdigits) WHITESPACE = frozenset(' \n\r\t\f') @@ -224,7 +224,7 @@ class Calculator(object): ast = getattr(parser, target)() print(repr(ast)) - except SyntaxError as e: + except (SyntaxError, ParseError) as e: raise SassParseError(e, expression=expr, expression_pos=parser._char_pos) self.ast_cache[key] = ast @@ -551,7 +551,9 @@ class Interpolation(Expression): ret = [] for part in self.parts: expr = part.evaluate(calculator) - if isinstance(expr, String): + if expr.is_null: + pass + elif isinstance(expr, String): ret.append(expr.value) else: ret.append(expr.render()) diff --git a/scss/tests/test_expression.py b/scss/tests/test_expression.py index a16950e..848d9ce 100644 --- a/scss/tests/test_expression.py +++ b/scss/tests/test_expression.py @@ -43,8 +43,7 @@ def test_reference_operations(): assert calc('$width/2') == Number(500, "px") # uses a variable; does division assert calc('(500px/2)') == Number(250, "px") # uses parens; does division assert calc('5px + 8px/2px') == Number(9, "px") # uses +; does division - # TODO: Ruby doesn't include these spaces - assert calc('#{$font-size}/#{$line-height}') == String('12px / 30px') + assert calc('#{$font-size}/#{$line-height}') == String('12px/30px') # uses #{}; does no division # Color operations -- cgit v1.2.1