checkpoint expressions
This commit is contained in:
@@ -67,13 +67,7 @@ class LessLexer:
|
||||
'css_vendor_property',
|
||||
'css_ident',
|
||||
'css_number',
|
||||
'>',
|
||||
'&',
|
||||
'*',
|
||||
'+',
|
||||
'-',
|
||||
'/',
|
||||
'~',
|
||||
]
|
||||
significant_ws += list(set(reserved.values()))
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ class LessParser(object):
|
||||
""" block_decl : block_open declaration_list brace_close
|
||||
"""
|
||||
try:
|
||||
block = Block(list(p)[1:-1])
|
||||
block = Block(list(p)[1:-1], p.lineno(3))
|
||||
if not self.scope.in_mixin():
|
||||
block.parse(self.scope)
|
||||
self.scope.add_block(block)
|
||||
@@ -187,6 +187,7 @@ class LessParser(object):
|
||||
except SyntaxError as e:
|
||||
self.handle_error(e, p)
|
||||
p[0] = None
|
||||
self.scope.pop()
|
||||
|
||||
def p_block_replace(self, p):
|
||||
""" block_decl : identifier ';'
|
||||
@@ -224,6 +225,7 @@ class LessParser(object):
|
||||
""" mixin_decl : open_mixin declaration_list brace_close
|
||||
"""
|
||||
p[0] = None
|
||||
self.scope.pop()
|
||||
|
||||
def p_open_mixin(self, p):
|
||||
""" open_mixin : class t_popen mixin_args t_pclose brace_open
|
||||
@@ -287,7 +289,7 @@ class LessParser(object):
|
||||
""" variable_decl : variable ':' style_list ';'
|
||||
"""
|
||||
try:
|
||||
v = Variable(list(p)[1:])
|
||||
v = Variable(list(p)[1:], p.lineno(4))
|
||||
v.parse(self.scope)
|
||||
if self.scope.in_mixin():
|
||||
self.stash[v.name] = v
|
||||
@@ -307,10 +309,11 @@ class LessParser(object):
|
||||
| prop_open empty ';'
|
||||
| prop_open less_arguments ';'
|
||||
"""
|
||||
p[0] = Property(list(p)[1:-1])
|
||||
l = len(p)
|
||||
p[0] = Property(list(p)[1:-1], p.lineno(l-1))
|
||||
|
||||
def p_prop_open_ie_hack(self, p):
|
||||
""" prop_open : oper_mul prop_open
|
||||
""" prop_open : '*' prop_open
|
||||
"""
|
||||
p[0] = (p[1][0], p[2][0])
|
||||
|
||||
@@ -354,7 +357,7 @@ class LessParser(object):
|
||||
def p_identifier(self, p):
|
||||
""" identifier : identifier_list
|
||||
"""
|
||||
p[0] = Identifier(p[1])
|
||||
p[0] = Identifier(p[1], 0)
|
||||
|
||||
def p_identifier_list_aux(self, p):
|
||||
""" identifier_list : identifier_list ',' identifier_group
|
||||
@@ -370,7 +373,7 @@ class LessParser(object):
|
||||
|
||||
def p_identifier_group_op(self, p):
|
||||
""" identifier_group : identifier_group child_selector ident_parts
|
||||
| identifier_group oper_add ident_parts
|
||||
| identifier_group '+' ident_parts
|
||||
| identifier_group general_sibling_selector ident_parts
|
||||
"""
|
||||
p[1].extend([p[2]])
|
||||
@@ -402,8 +405,8 @@ class LessParser(object):
|
||||
|
||||
def p_selector(self, p):
|
||||
""" selector : combinator
|
||||
| oper_mul
|
||||
| oper_add
|
||||
| '*'
|
||||
| '+'
|
||||
| child_selector
|
||||
| general_sibling_selector
|
||||
"""
|
||||
@@ -453,7 +456,7 @@ class LessParser(object):
|
||||
| '~' istring
|
||||
| '~' css_string
|
||||
"""
|
||||
p[0] = Call(list(p)[1:])
|
||||
p[0] = Call(list(p)[1:], 0)
|
||||
|
||||
#
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -488,16 +491,16 @@ class LessParser(object):
|
||||
#
|
||||
|
||||
def p_expression_aux(self, p):
|
||||
""" expression : expression oper_add expression
|
||||
| expression oper_sub expression
|
||||
| expression oper_mul expression
|
||||
| expression oper_div expression
|
||||
| word oper_div expression
|
||||
""" expression : expression '+' expression
|
||||
| expression '-' expression
|
||||
| expression '/' expression
|
||||
| expression '*' expression
|
||||
| word '/' expression
|
||||
"""
|
||||
p[0] = Expression(list(p)[1:])
|
||||
p[0] = Expression(list(p)[1:], 0)
|
||||
|
||||
def p_expression_p_neg(self, p):
|
||||
""" expression : oper_sub t_popen expression t_pclose
|
||||
""" expression : '-' t_popen expression t_pclose
|
||||
"""
|
||||
p[0] = [p[1], p[3]]
|
||||
|
||||
@@ -529,7 +532,7 @@ class LessParser(object):
|
||||
p[0] = String(p)
|
||||
|
||||
def p_variable_neg(self, p):
|
||||
""" variable : oper_sub variable
|
||||
""" variable : '-' variable
|
||||
"""
|
||||
p[0] = '-' + p[2]
|
||||
|
||||
@@ -597,29 +600,6 @@ class LessParser(object):
|
||||
"""
|
||||
p[0] = tuple(list(p)[1:])
|
||||
|
||||
def p_oper_add(self, p):
|
||||
""" oper_add : '+' t_ws
|
||||
| '+'
|
||||
"""
|
||||
p[0] = tuple(list(p)[1:])
|
||||
|
||||
def p_oper_sub(self, p):
|
||||
""" oper_sub : '-' t_ws
|
||||
| '-'
|
||||
"""
|
||||
p[0] = tuple(list(p)[1:])
|
||||
|
||||
def p_oper_mul(self, p):
|
||||
""" oper_mul : '*' t_ws
|
||||
| '*'
|
||||
"""
|
||||
p[0] = tuple(list(p)[1:])
|
||||
|
||||
def p_oper_div(self, p):
|
||||
""" oper_div : '/' t_ws
|
||||
| '/'
|
||||
"""
|
||||
p[0] = tuple(list(p)[1:])
|
||||
|
||||
def p_child_selector(self, p):
|
||||
""" child_selector : '>' t_ws
|
||||
@@ -642,7 +622,6 @@ class LessParser(object):
|
||||
def p_scope_close(self, p):
|
||||
""" brace_close : '}'
|
||||
"""
|
||||
self.scope.pop()
|
||||
p[0] = p[1]
|
||||
|
||||
def p_empty(self, p):
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""
|
||||
"""
|
||||
from . import utility
|
||||
|
||||
class Scope(list):
|
||||
def __init__(self, init=False):
|
||||
super().__init__()
|
||||
@@ -86,4 +88,15 @@ class Scope(list):
|
||||
self[0]['__variables__'].update(scope[0]['__variables__'])
|
||||
self[0]['__blocks__'].extend(scope[0]['__blocks__'])
|
||||
self[0]['__names__'].extend(scope[0]['__names__'])
|
||||
|
||||
def swap(self, name):
|
||||
"""
|
||||
"""
|
||||
if name.startswith('@@'):
|
||||
var = self.variables(name[1:])
|
||||
if var is False: raise SyntaxError('Unknown variable %s' % name)
|
||||
name = '@' + utility.destring(var.value[0])
|
||||
var = self.variables(name)
|
||||
if var is False: raise SyntaxError('Unknown variable %s' % name)
|
||||
return var.value
|
||||
|
||||
@@ -4,14 +4,5 @@ from .node import Node
|
||||
import lesscpy.lessc.utility as utility
|
||||
class Call(Node):
|
||||
def parse(self, scope):
|
||||
self.parsed = [p.parse(scope)
|
||||
if hasattr(p, 'parse')
|
||||
else p
|
||||
for p in utility.flatten(self.tokens)]
|
||||
return self
|
||||
|
||||
def format(self, fills):
|
||||
return ''.join([p.format(fills)
|
||||
if hasattr(p, 'format')
|
||||
else p
|
||||
for p in self.parsed])
|
||||
parsed = self.process(self.tokens, scope)
|
||||
return ''.join([p for p in parsed])
|
||||
|
||||
@@ -10,14 +10,13 @@ class Expression(Node):
|
||||
@param list: current scope
|
||||
"""
|
||||
assert(len(self.tokens) == 3)
|
||||
expr = [t.parse(scope) if hasattr(t, 'parse')
|
||||
else t
|
||||
for t in self.tokens]
|
||||
expr = self.process(self.tokens, scope)
|
||||
expr = [self.neg(t, scope) for t in expr]
|
||||
A, O, B = [e[0]
|
||||
if type(e) is tuple
|
||||
else e
|
||||
for e in expr]
|
||||
for e in expr
|
||||
if e != ' ']
|
||||
try:
|
||||
a, ua = utility.analyze_number(A, 'Illegal element in expression')
|
||||
b, ub = utility.analyze_number(B, 'Illegal element in expression')
|
||||
@@ -68,7 +67,7 @@ class Expression(Node):
|
||||
'-': '__sub__',
|
||||
'*': '__mul__',
|
||||
'/': '__truediv__'
|
||||
}.get(o[0])
|
||||
}.get(o)
|
||||
v = getattr(a, operation)(b)
|
||||
if v is NotImplemented:
|
||||
v = getattr(b, operation)(a)
|
||||
|
||||
@@ -10,7 +10,10 @@ class Identifier(Node):
|
||||
if scope:
|
||||
scopename.extend(scope.scopename)
|
||||
scopename = ''.join(scopename)
|
||||
name = ''.join(utility.flatten(self.tokens))
|
||||
name = ''.join([t + ' '
|
||||
if t in '*>~+'
|
||||
else t
|
||||
for t in utility.flatten(self.tokens)])
|
||||
if name.startswith('&'):
|
||||
scopename = scopename.strip()
|
||||
name = name[1:]
|
||||
|
||||
@@ -1,11 +1,39 @@
|
||||
"""
|
||||
"""
|
||||
from lesscpy.lessc import utility
|
||||
class Node(object):
|
||||
def __init__(self, p):
|
||||
def __init__(self, p, ln):
|
||||
self.tokens = p
|
||||
self.lineno = ln
|
||||
|
||||
def parse(self, scope):
|
||||
return self
|
||||
|
||||
def process(self, tokens, scope):
|
||||
"""
|
||||
"""
|
||||
while True:
|
||||
tokens = list(utility.flatten(tokens))
|
||||
done = True
|
||||
if any(t for t in tokens if hasattr(t, 'parse')):
|
||||
tokens = [t.parse(scope)
|
||||
if hasattr(t, 'parse')
|
||||
else t
|
||||
for t in tokens]
|
||||
done = False
|
||||
if any(t for t in tokens if utility.is_variable(t)):
|
||||
tokens = self.replace_variables(tokens, scope)
|
||||
done = False
|
||||
if done: break
|
||||
return tokens
|
||||
|
||||
def replace_variables(self, tokens, scope):
|
||||
"""
|
||||
"""
|
||||
return [scope.swap(t)
|
||||
if utility.is_variable(t)
|
||||
else t
|
||||
for t in tokens]
|
||||
|
||||
def format(self, fills):
|
||||
return str(type(self))
|
||||
raise ValueError('No defined format')
|
||||
|
||||
@@ -15,12 +15,14 @@ class Property(Node):
|
||||
self.property = ''.join(property)
|
||||
self.parsed = []
|
||||
if style:
|
||||
style = self.preprocess(style)
|
||||
self.parsed = [p.parse(scope)
|
||||
if hasattr(p, 'parse')
|
||||
else p
|
||||
for p in utility.flatten(style)]
|
||||
self.parsed = [p for p in self.parsed if p]
|
||||
self.parsed = self.process(style, scope)
|
||||
# style = self.replace_variables(style, scope)
|
||||
# style = self.preprocess(style)
|
||||
# self.parsed = [p.parse(scope)
|
||||
# if hasattr(p, 'parse')
|
||||
# else p
|
||||
# for p in style]
|
||||
# self.parsed = [p for p in self.parsed if p]
|
||||
return self
|
||||
|
||||
def preprocess(self, style):
|
||||
|
||||
@@ -5,4 +5,6 @@ class Variable(Node):
|
||||
def parse(self, scope):
|
||||
"""
|
||||
"""
|
||||
self.name = self.tokens.pop(0)
|
||||
self.name = self.tokens.pop(0)
|
||||
self.value = self.tokens[1]
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
@a: 2;
|
||||
@x: @a * @a;
|
||||
@y: @x + 1;
|
||||
@z: @x * 2 + @y;
|
||||
|
||||
|
||||
.variables {
|
||||
width: @z + 1cm; // 14cm
|
||||
}
|
||||
|
||||
@b: @a * 10;
|
||||
@c: #888;
|
||||
|
||||
@fonts: "Trebuchet MS", Verdana, sans-serif;
|
||||
@f: @fonts;
|
||||
|
||||
@quotes: "~" "~";
|
||||
@q: @quotes;
|
||||
|
||||
.variables {
|
||||
height: @b + @x + 0px; // 24px
|
||||
color: @c;
|
||||
font-family: @f;
|
||||
quotes: @q;
|
||||
}
|
||||
|
||||
.redefinition {
|
||||
@var: 4;
|
||||
@var: 2;
|
||||
@var: 3;
|
||||
three: @var;
|
||||
}
|
||||
|
||||
.values {
|
||||
@a: 'Trebuchet';
|
||||
@multi: 'A', B, C;
|
||||
font-family: @a, @a, @a;
|
||||
color: @c !important;
|
||||
url: url(@a);
|
||||
multi: something @multi, @a;
|
||||
}
|
||||
|
||||
.variable-names {
|
||||
@var: 'hello';
|
||||
@name: 'var';
|
||||
name: @@name;
|
||||
}
|
||||
|
||||
.alpha {
|
||||
@var: 42;
|
||||
filter: alpha(opacity=@var);
|
||||
}
|
||||
|
||||
@lazy: @j;
|
||||
@j: 100%;
|
||||
|
||||
.lazy-eval {
|
||||
width: @lazy;
|
||||
}
|
||||
Reference in New Issue
Block a user