diff options
author | Eevee (Alex Munroe) <eevee.git@veekun.com> | 2013-08-14 16:57:45 -0700 |
---|---|---|
committer | Eevee (Alex Munroe) <eevee.git@veekun.com> | 2013-08-23 15:54:31 -0700 |
commit | 650fe58375f01bc960038a65ac1d33f39a0d9242 (patch) | |
tree | a6d9dca5e9a10ff13668c52364c8567ca8292a8d | |
parent | 73dd6b1d65fca0b0b200f49212f4d33175bb8992 (diff) | |
download | pyscss-650fe58375f01bc960038a65ac1d33f39a0d9242.tar.gz |
Make variables in url() work. Greatly simplify #{} parsing.
-rw-r--r-- | scss/expression.parsley | 48 | ||||
-rw-r--r-- | scss/expression.py | 32 | ||||
-rw-r--r-- | scss/tests/files/original-doctests/001-variables.scss | 2 |
3 files changed, 37 insertions, 45 deletions
diff --git a/scss/expression.parsley b/scss/expression.parsley index 39255b9..aad3878 100644 --- a/scss/expression.parsley +++ b/scss/expression.parsley @@ -86,7 +86,7 @@ atom = ( | '[' comma_list:node ']' -> Parentheses(node) # URL literal - | 'u' 'r' 'l' '(' (string | uri):s ')' -> FunctionLiteral('url', s) + | 'u' 'r' 'l' '(' inside_url:s ')' -> FunctionLiteral('url', s) # Function call | identifier:name '(' argspec:args ')' -> CallOp(name, args) @@ -118,36 +118,36 @@ atom = ( # TODO I'm not entirely sure any of these character classes are correct # TODO ruby sass appears to preserve escapes -uri = ( - escape - | anything:ch ?(ord(ch) > 32 and ch not in ' !"$\'()') -> ch - )*:s -> Literal(String(''.join(s), quotes=None)) +inside_url = ( + interpolation:node -> node + | variable:name -> Variable(name) + | ( + escape + | '#' ~'{' + | anything:ch ?(ord(ch) > 32 and ch not in ' !"#$\'()') -> ch + )+:s -> Literal(String(''.join(s), quotes=None)) + | string_part(')'):s -> Literal(String(s, quotes=None)) + )*:nodes + -> Interpolation(nodes, quotes=None) string = ( - '"' string_contents('"'):node '"' -> node - | '\'' string_contents('\''):node '\'' -> node + '"' string_contents('"' '"'):node '"' -> node + | '\'' string_contents('\'' '\''):node '\'' -> node ) interpolation = '#' '{' expression:node '}' -> node -string_contents :quote = ( - ( - string_part(quote):before - -> Literal(String(before, quotes=quote)) - ):retval - ( - ( - interpolation:node - string_part(quote):after - -> Interpolation(retval, node, Literal(String(after, quotes=quote)), quotes=quote) - ):retval - )* - ) -> retval - -string_part :quote = <( +string_contents :end :quotes = + ( + interpolation:node -> node + | string_part(end):s -> Literal(String(s, quotes=quotes)) + )*:nodes + -> Interpolation(nodes, quotes=quotes) + +string_part :end = <( '#' ~'{' - | anything:ch ?(ch not in ('#', quote)) - )*> + | anything:ch ?(ch not in ('#', end)) + )+> ### Function definitions and arguments diff --git a/scss/expression.py b/scss/expression.py index 7a8a4af..ebec7e2 100644 --- a/scss/expression.py +++ b/scss/expression.py @@ -82,6 +82,8 @@ def get_grammar(): from parsley import wrapGrammar from ometa.grammar import loadGrammar grammar = loadGrammar(scss, 'expression', globals(), superclass=GrammarBase) + def tracer(rule, rule_offset, pos): + print("trace @", pos, ">", repr(rule)) _grammar = wrapGrammar(grammar) return _grammar @@ -541,30 +543,20 @@ class ArgspecLiteral(Expression): class Interpolation(Expression): - def __init__(self, left, expr, right, quotes): - self.left = left - self.expr = expr - self.right = right + def __init__(self, parts, quotes=None): + self.parts = parts self.quotes = quotes def evaluate(self, calculator, divide=False): - left_scss = self.left.evaluate(calculator) - if not isinstance(left_scss, String): - raise TypeError("Expected left side of interpolation to be String, got %r" % (left,)) - left = left_scss.value - - right_scss = self.right.evaluate(calculator) - if not isinstance(right_scss, String): - raise TypeError("Expected right side of interpolation to be String, got %r" % (left,)) - right = right_scss.value - - expr = self.expr.evaluate(calculator) - if isinstance(expr, String): - middle = expr.value - else: - middle = expr.render() + ret = [] + for part in self.parts: + expr = part.evaluate(calculator) + if isinstance(expr, String): + ret.append(expr.value) + else: + ret.append(expr.render()) - return String(left + middle + right, quotes=self.quotes) + return String(''.join(ret), quotes=self.quotes) def parse_bareword(word): diff --git a/scss/tests/files/original-doctests/001-variables.scss b/scss/tests/files/original-doctests/001-variables.scss index 7e2edc1..dc7e8ff 100644 --- a/scss/tests/files/original-doctests/001-variables.scss +++ b/scss/tests/files/original-doctests/001-variables.scss @@ -1,6 +1,6 @@ @option compress:no, short_colors:yes, reverse_colors:yes; @variables { - $path = ../img/tmpl1/png; + $path = '../img/tmpl1/png'; $color1 = #FF00FF; $border = border-top: 1px solid $color1; } |