From 64b496093c25c99f814005476bb6fe250002e1fe Mon Sep 17 00:00:00 2001 From: jtm Date: Sun, 8 Apr 2012 13:17:22 +0000 Subject: [PATCH] work --- lesscpy/lessc/parser.py | 90 ++++++---------------------------------- lesscpy/lessc/scope.py | 2 +- lesscpy/plib/block.py | 6 ++- lesscpy/plib/deferred.py | 14 +++---- lesscpy/plib/mixin.py | 23 +++++----- lesscpy/plib/variable.py | 8 ++-- 6 files changed, 41 insertions(+), 102 deletions(-) diff --git a/lesscpy/lessc/parser.py b/lesscpy/lessc/parser.py index 04e60f7..d8e592e 100644 --- a/lesscpy/lessc/parser.py +++ b/lesscpy/lessc/parser.py @@ -81,30 +81,16 @@ class LessParser(object): self.scope.push() self.target = filename self.result = self.parser.parse(filename, lexer=self.lex, debug=debuglevel) - self.post_parse(self.result) + self.post_parse() - def post_parse(self, lst): - """Post process stage. less.js seems to allow calls to mixins not - yet declared. Deferreds are used in place of real mixins. After - parsing we go over the parse tree and reparse deferred's. - args: - lst (list): Parse list + def post_parse(self): """ - if type(lst) is list: - for u in lst: self.post_parse(u) - elif type(lst) is Block: + """ + for pu in self.result: try: - lst.parsed = list(utility.flatten([t.parse(self.scope, self.verbose) - if type(t) is Deferred else t - for t in lst.parsed])) + pu.parse(self.scope) except SyntaxError as e: - self.handle_error(e, 0, 'W') - self.post_parse(lst.parsed) - elif type(lst) is Deferred: - try: - lst = lst.parse(self.scope, True) - except SyntaxError as e: - self.handle_error(e, lst.lineno, 'W') + self.handle_error(e, 0) def scopemap(self): """ Output scopemap. @@ -195,16 +181,9 @@ class LessParser(object): def p_block(self, p): """ block_decl : block_open declaration_list brace_close """ - try: - block = Block(list(p)[1:-1], p.lineno(3)) - if not self.scope.in_mixin: - block.parse(self.scope) - p[0] = block - except SyntaxError as e: - self.handle_error(e, p.lineno(3)) - p[0] = None + p[0] = Block(list(p)[1:-1], p.lineno(3)) self.scope.pop() - self.scope.add_block(block) + self.scope.add_block(p[0]) def p_block_replace(self, p): """ block_decl : identifier ';' @@ -215,18 +194,7 @@ class LessParser(object): p[0] = block.copy(self.scope) else: # fallback to mixin. Allow calls to mixins without parens - mixin = self.scope.mixins(m.raw()) - if mixin: - res = None - for m in mixin: - try: - res = m.call(self.scope) - except SyntaxError as e: - self.handle_error(e, p.lineno(2)) - if res: break - p[0] = res - else: - self.handle_error('Call unknown block `%s`' % m.raw(True), p.lineno(2)) + p[0] = Deferred(p[1], None, p.lineno(2)) def p_block_open(self, p): """ block_open : identifier brace_open @@ -242,11 +210,11 @@ class LessParser(object): """ block_open : css_font_face t_ws brace_open """ p[0] = Identifier([p[1], p[2]]).parse(self.scope) - # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def p_mixin(self, p): """ mixin_decl : open_mixin declaration_list brace_close """ @@ -311,34 +279,8 @@ class LessParser(object): def p_call_mixin(self, p): """ call_mixin : identifier t_popen mixin_args_list t_pclose ';' """ - # Try with scope first - p[1].parse(self.scope) - mixin = self.scope.mixins(p[1].raw()) - if not mixin: - p[1].parse(None) - mixin = self.scope.mixins(p[1].raw()) - res = False - if mixin: - for m in mixin: - try: - if self.scope.in_mixin: - res = Deferred(m, p[3], p.lineno(4)) - else: - res = m.call(self.scope, p[3]) - if res: break - except SyntaxError as e: - self.handle_error(e, p.lineno(4)) - elif not p[3] or not p[3][0]: - # fallback to block. Allow calls of name() to blocks - block = self.scope.blocks(p[1].raw()) - if block: - res = block.copy(self.scope) - else: - if self.scope.in_mixin: - res = Deferred(p[1], p[3], p.lineno(4)) - if res is False: - res = Deferred(p[1], p[3], p.lineno(4)) - p[0] = res + p[1].parse(None) + p[0] = Deferred(p[1], p[3], p.lineno(4)) def p_mixin_args_arguments(self, p): """ mixin_args_list : less_arguments @@ -418,13 +360,7 @@ class LessParser(object): def p_variable_decl(self, p): """ variable_decl : variable ':' style_list ';' """ - try: - v = Variable(list(p)[1:], p.lineno(4)) - v.parse(self.scope) - self.scope.add_variable(v) - except SyntaxError as e: - self.handle_error(e, p.lineno(2)) - p[0] = None + p[0] = Variable(list(p)[1:-1], p.lineno(4)) # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/lesscpy/lessc/scope.py b/lesscpy/lessc/scope.py index de34c07..cfb2dda 100644 --- a/lesscpy/lessc/scope.py +++ b/lesscpy/lessc/scope.py @@ -64,7 +64,7 @@ class Scope(list): Args: mixin (Mixin): Mixin object """ - raw = mixin.name.raw() + raw = mixin.tokens[0][0].raw() if raw in self._mixins: self._mixins[raw].append(mixin) else: diff --git a/lesscpy/plib/block.py b/lesscpy/plib/block.py index 4b2902d..10799d9 100644 --- a/lesscpy/plib/block.py +++ b/lesscpy/plib/block.py @@ -29,12 +29,13 @@ class Block(Node): self """ if not self.parsed: + scope.push() self.name, inner = self.tokens if not inner: inner = [] self.parsed = [p.parse(scope) for p in inner if p and type(p) is not type(self)] - self.parsed = list(utility.flatten(self.parsed)) + self.parsed = [p for p in utility.flatten(self.parsed) if p] if not inner: self.inner = [] else: @@ -42,6 +43,7 @@ class Block(Node): if p and type(p) is type(self)] if self.inner: self.inner = [p.parse(scope) for p in self.inner] + scope.pop() return self def raw(self, clean=False): @@ -72,7 +74,7 @@ class Block(Node): 'proplist': ''.join([p.fmt(fills) for p in self.parsed if p]), }) out.append(f % fills) - if self.inner: + if hasattr(self, 'inner'): if self.name.subparse: # @media inner = ''.join([p.fmt(fills) for p in self.inner]) inner = inner.replace(fills['nl'], diff --git a/lesscpy/plib/deferred.py b/lesscpy/plib/deferred.py index ebde016..3dafb13 100644 --- a/lesscpy/plib/deferred.py +++ b/lesscpy/plib/deferred.py @@ -19,8 +19,7 @@ class Deferred(Node): mixin (Mixin): Mixin object args (list): Call arguments """ - self.mixin = mixin - self.args = args + self.tokens = [mixin, args] self.lineno = lineno def parse(self, scope, error=False): @@ -30,17 +29,18 @@ class Deferred(Node): returns: mixed """ - if hasattr(self.mixin, 'call'): - return self.mixin.call(scope, self.args) - mixins = scope.mixins(self.mixin.raw()) + mixin, args = self.tokens + if hasattr(mixin, 'call'): + return mixin.call(scope, args) + mixins = scope.mixins(mixin.raw()) if mixins: for mixin in mixins: - res = mixin.call(scope, self.args) + res = mixin.call(scope, args) if res: return res else: res = self if error: - raise SyntaxError('NameError `%s`' % self.mixin.raw(True)) + raise SyntaxError('NameError `%s`' % mixin.raw(True)) return res def fmt(self, fills): diff --git a/lesscpy/plib/mixin.py b/lesscpy/plib/mixin.py index 370f32e..e1bb63f 100644 --- a/lesscpy/plib/mixin.py +++ b/lesscpy/plib/mixin.py @@ -28,7 +28,7 @@ class Mixin(Node): self """ self.name, args, self.guards = self.tokens[0] - self.args = list(utility.flatten(args)) if args else [] + self.args = [a for a in utility.flatten(args) if a] self.body = Block([None, self.tokens[1]], 0) self.scope = copy.deepcopy(scope[-1]) return self @@ -52,22 +52,19 @@ class Mixin(Node): """ arguments = zip(args, [' '] * len(args)) if args and args[0] else None if self.args: - parsed = [v.parse(scope) - if hasattr(v, 'parse') else v + parsed = [v if hasattr(v, 'parse') else v for v in copy.deepcopy(self.args)] args = args if type(args) is list else [args] vars = [self._parse_arg(var, arg, scope) for arg, var in itertools.zip_longest([a for a in args], parsed)] - for var in vars: - if var: scope.add_variable(var) + for var in vars: + if var: var.parse(scope) if not arguments: arguments = [v.value for v in vars if v] if not arguments: arguments = '' - scope.add_variable(Variable(['@arguments', - None, - arguments]).parse(scope)) + Variable(['@arguments', None, arguments]).parse(scope) def _parse_arg(self, var, arg, scope): """ @@ -78,9 +75,10 @@ class Mixin(Node): if utility.is_variable(arg[0]): tmp = scope.variables(arg[0]) if not tmp: return None - var.value = tmp.value + val = tmp.value else: - var.value = arg + val = arg + var = Variable(var.tokens[:-1] + [val]) else: #arg if utility.is_variable(var): @@ -89,9 +87,10 @@ class Mixin(Node): elif utility.is_variable(arg[0]): tmp = scope.variables(arg[0]) if not tmp: return None - var = Variable([var, None, tmp.value]).parse(scope) + val = tmp.value else: - var = Variable([var, None, arg]).parse(scope) + val = arg + var = Variable([var, None, arg]) else: return None return var diff --git a/lesscpy/plib/variable.py b/lesscpy/plib/variable.py index d6e2417..1acc31b 100644 --- a/lesscpy/plib/variable.py +++ b/lesscpy/plib/variable.py @@ -17,13 +17,15 @@ class Variable(Node): returns: self """ - self.name = self.tokens.pop(0) - self.value = self.tokens[1] + self.name, _, self.value = self.tokens if type(self.name) is tuple: if len(self.name) > 1: self.name, pad = self.name self.value.append(pad) else: self.name = self.name[0] - return self + scope.add_variable(self) + + def fmt(self, fills): + return ''