139 lines
4.0 KiB
Python
Raw Permalink Normal View History

2012-04-03 13:36:08 +00:00
# -*- coding: utf8 -*-
2012-01-28 14:52:09 +00:00
"""
2012-04-03 13:36:08 +00:00
.. module:: lesscpy.plib.expression
:synopsis: Expression node.
2013-07-19 11:21:51 +02:00
2012-04-03 13:36:08 +00:00
Copyright (c)
See LICENSE for details.
2012-07-18 17:28:04 -04:00
.. moduleauthor:: Johann T. Mariusson <jtm@robot.is>
2012-01-28 14:52:09 +00:00
"""
import operator
2012-02-19 20:38:19 +00:00
from .node import Node
2012-02-25 17:08:08 +00:00
from lesscpy.lessc import utility
2012-02-25 17:34:23 +00:00
from lesscpy.lessc import color
2012-02-25 17:08:08 +00:00
2013-07-19 11:21:51 +02:00
2012-02-19 20:38:19 +00:00
class Expression(Node):
2013-07-19 11:21:51 +02:00
2012-04-03 13:36:08 +00:00
"""Expression node. Parses all expression except
color expressions, (handled in the color class)
"""
2013-07-19 11:21:51 +02:00
2012-02-25 17:08:08 +00:00
def parse(self, scope):
""" Parse Node
2012-04-03 13:36:08 +00:00
args:
scope (Scope): Scope object
raises:
SyntaxError
returns:
str
2012-02-25 17:08:08 +00:00
"""
assert(len(self.tokens) == 3)
2012-02-26 15:50:07 +00:00
expr = self.process(self.tokens, scope)
2012-02-25 17:08:08 +00:00
expr = [self.neg(t, scope) for t in expr]
2013-07-19 11:21:51 +02:00
A, O, B = [e[0]
if isinstance(e, tuple)
else e
2012-02-26 15:50:07 +00:00
for e in expr
2012-02-26 17:04:50 +00:00
if str(e).strip()]
2012-02-25 17:34:23 +00:00
try:
a, ua = utility.analyze_number(A, 'Illegal element in expression')
b, ub = utility.analyze_number(B, 'Illegal element in expression')
except SyntaxError:
return ' '.join([str(A), str(O), str(B)])
2012-02-25 17:08:08 +00:00
if(a is False or b is False):
2012-02-25 17:34:23 +00:00
return ' '.join([str(A), str(O), str(B)])
2012-02-25 17:08:08 +00:00
if ua == 'color' or ub == 'color':
2012-03-10 16:27:14 +00:00
return color.Color().process((A, O, B))
if a == 0 and O == '/':
# NOTE(saschpe): The ugliest but valid CSS since sliced bread: 'font: 0/1 a;'
return ''.join([str(A), str(O), str(B), ' '])
2012-02-25 17:08:08 +00:00
out = self.operate(a, b, O)
2013-07-19 11:21:51 +02:00
if isinstance(out, bool):
2012-04-04 12:33:49 +00:00
return out
2012-02-25 17:08:08 +00:00
return self.with_units(out, ua, ub)
2013-07-19 11:21:51 +02:00
2012-04-03 13:36:08 +00:00
def neg(self, value, scope):
"""Apply negativity.
args:
value (mixed): test value
scope (Scope): Current scope
raises:
SyntaxError
returns:
str
2012-02-25 17:08:08 +00:00
"""
2013-07-19 11:21:51 +02:00
if value and isinstance(value, list) and value[0] == '-':
2012-04-03 13:36:08 +00:00
val = value[1]
if len(value) > 1 and hasattr(value[1], 'parse'):
val = value[1].parse(scope)
2013-07-19 11:21:51 +02:00
if isinstance(val, str):
2012-04-03 13:36:08 +00:00
return '-' + val
return -val
return value
2013-07-19 11:21:51 +02:00
2012-04-03 13:36:08 +00:00
def with_units(self, val, ua, ub):
2013-07-19 11:21:51 +02:00
"""Return value with unit.
2012-04-03 13:36:08 +00:00
args:
val (mixed): result
ua (str): 1st unit
ub (str): 2nd unit
raises:
SyntaxError
returns:
str
2012-02-25 17:08:08 +00:00
"""
2013-07-19 11:21:51 +02:00
if not val:
return str(val)
2012-02-25 17:34:23 +00:00
if ua or ub:
if ua and ub:
if ua == ub:
2012-04-03 13:36:08 +00:00
return str(val) + ua
2012-02-25 17:34:23 +00:00
else:
2013-07-19 11:21:51 +02:00
# Nodejs version does not seem to mind mismatched
2012-06-25 08:18:49 +00:00
# units within expressions. So we choose the first
# as they do
# raise SyntaxError("Error in expression %s != %s" % (ua, ub))
return str(val) + ua
2012-02-25 17:34:23 +00:00
elif ua:
2012-04-03 13:36:08 +00:00
return str(val) + ua
2012-02-25 17:34:23 +00:00
elif ub:
2012-04-03 13:36:08 +00:00
return str(val) + ub
return repr(val)
2013-07-19 11:21:51 +02:00
2012-04-03 13:36:08 +00:00
def operate(self, vala, valb, oper):
"""Perform operation
args:
vala (mixed): 1st value
valb (mixed): 2nd value
oper (str): operation
returns:
mixed
2012-02-25 17:08:08 +00:00
"""
operation = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
'=': operator.eq,
'>': operator.gt,
'<': operator.lt,
'>=': operator.ge,
'=<': operator.le,
2012-04-03 13:36:08 +00:00
}.get(oper)
if operation is None:
raise SyntaxError("Unknown operation %s" % oper)
ret = operation(vala, valb)
if oper in '+-*/' and int(ret) == ret:
ret = int(ret)
return ret
2013-07-19 11:21:51 +02:00
2012-02-26 11:19:10 +00:00
def expression(self):
2012-04-03 13:36:08 +00:00
"""Return str representation of expression
returns:
str
2012-02-26 11:19:10 +00:00
"""
return utility.flatten(self.tokens)