checkpoint expressions

This commit is contained in:
jtm
2012-02-26 15:50:07 +00:00
parent a34ea8dbaf
commit 5532eb88ee
10 changed files with 143 additions and 73 deletions

View File

@@ -67,13 +67,7 @@ class LessLexer:
'css_vendor_property',
'css_ident',
'css_number',
'>',
'&',
'*',
'+',
'-',
'/',
'~',
]
significant_ws += list(set(reserved.values()))

View File

@@ -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):

View File

@@ -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

View File

@@ -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])

View File

@@ -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)

View File

@@ -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:]

View File

@@ -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')

View File

@@ -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):

View File

@@ -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]

View File

@@ -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;
}