work
This commit is contained in:
@@ -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))
|
||||
|
||||
#
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ''
|
||||
|
||||
|
||||
Reference in New Issue
Block a user