From 1724574d5ab6a1a013fd2729cff964f82234ff8a Mon Sep 17 00:00:00 2001 From: jtm Date: Sat, 24 Mar 2012 17:23:14 +0000 Subject: [PATCH] more functions --- lesscpy/lessc/lexer.py | 23 +++++++++----- lesscpy/lessc/parser.py | 37 +++++++++++++++++++++- lesscpy/plib/block.py | 2 -- lesscpy/plib/call.py | 56 ++++++++++++++++++++++++++++------ lesscpy/plib/identifier.py | 2 ++ lesscpy/plib/mixin.py | 2 -- lesscpy/test/css/calls.css | 5 +++ lesscpy/test/css/calls.min.css | 1 + lesscpy/test/less/calls.less | 5 +++ 9 files changed, 111 insertions(+), 22 deletions(-) diff --git a/lesscpy/lessc/lexer.py b/lesscpy/lessc/lexer.py index 78d7ecd..7fd98e3 100644 --- a/lesscpy/lessc/lexer.py +++ b/lesscpy/lessc/lexer.py @@ -19,7 +19,7 @@ class LessLexer: states = ( ('parn', 'inclusive'), ) - literals = ',>{}=%!/*-+:;~&'; + literals = ',<>{}=%!/*-+:;~&'; tokens = [ 'css_ident', 'css_dom', @@ -41,6 +41,9 @@ class LessLexer: 'less_comment', 'less_string', 'less_open_format', + 'less_when', + 'less_and', + 'less_not', 't_ws', 't_popen', @@ -82,7 +85,7 @@ class LessLexer: def t_css_filter(self, t): (r'\[[^\]]*\]' '|(not|lang|nth-[a-z\-]+)\(.+\)' - '|and[ \t]\(.+\)') + '|and[ \t]\([^><]+\)') return t def t_css_ms_filter(self, t): @@ -112,6 +115,12 @@ class LessLexer: t.type = 'css_color' except ValueError: pass + elif v == 'when': + t.type = 'less_when' + elif v == 'and': + t.type = 'less_and' + elif v == 'not': + t.type = 'less_not' elif v in css.propertys: t.type = 'css_property' t.value = t.value.strip() @@ -132,11 +141,15 @@ class LessLexer: r'\#[0-9]([0-9a-f]{5}|[0-9a-f]{2})' return t + def t_css_number(self, t): + r'-?(\d*\.\d+|\d+)(s|%|in|ex|[ecm]m|p[txc]|deg|g?rad|ms?|k?hz)?' + return t + def t_parn_css_uri(self, t): (r'data:[^\)]+' '|(([a-z]+://)?' '(' - '([\.\w:]+[\\/][\\/]?)+' + '([\.a-z:]+[\w\.:]*[\\/][\\/]?)+' '|([a-z][\w\.\-]+(\.[a-z0-9]+))' '(\#[a-z]+)?)' ')+') @@ -152,10 +165,6 @@ class LessLexer: '|\\\[^\r\n\s0-9a-f])*)') return t - def t_css_number(self, t): - r'-?(\d*\.\d+|\d+)(s|%|in|ex|[ecm]m|p[txc]|deg|g?rad|ms?|k?hz)?' - return t - def t_newline(self, t): r'[\n\r]+' t.lexer.lineno += t.value.count('\n') diff --git a/lesscpy/lessc/parser.py b/lesscpy/lessc/parser.py index a27b4fd..2626798 100644 --- a/lesscpy/lessc/parser.py +++ b/lesscpy/lessc/parser.py @@ -200,7 +200,10 @@ class LessParser(object): def p_block_open(self, p): """ block_open : identifier brace_open """ - p[1].parse(self.scope) + try: + p[1].parse(self.scope) + except SyntaxError as e: + pass p[0] = p[1] self.scope.current = p[1] @@ -223,11 +226,38 @@ class LessParser(object): def p_open_mixin(self, p): """ open_mixin : identifier t_popen mixin_args t_pclose brace_open + | identifier t_popen mixin_args t_pclose mixin_guard brace_open """ p[1].parse(self.scope) p[0] = [p[1], p[3]] +# if len(p) > 6: +# p[0].append(p[5]) self.scope.in_mixin = True + def p_mixin_guard(self, p): + """ mixin_guard : less_when mixin_guard_cond + | less_when less_not mixin_guard_cond + """ + pass + + def p_mixin_guard_cond(self, p): + """ mixin_guard_cond : mixin_guard_cond ',' mixin_guard_cond + | mixin_guard_cond less_and mixin_guard_cond + | t_popen argument mixin_guard_cmp argument t_pclose + | t_popen argument t_pclose + """ + pass + + def p_mixin_guard_cmp(self, p): + """ mixin_guard_cmp : '>' + | '<' + | '=' + | '!' '=' + | '>' '=' + | '<' '=' + """ + pass + def p_call_mixin(self, p): """ call_mixin : identifier t_popen mixin_args t_pclose ';' """ @@ -387,6 +417,11 @@ class LessParser(object): | page filter """ p[0] = Identifier(p[1], 0) + + def p_identifier_istr(self, p): + """ identifier : t_popen '~' istring t_pclose + """ + p[0] = Identifier(Call([p[2], p[3]]), 0) def p_identifier_list_aux(self, p): """ identifier_list : identifier_list ',' identifier_group diff --git a/lesscpy/plib/block.py b/lesscpy/plib/block.py index 27bdd0d..356c4aa 100644 --- a/lesscpy/plib/block.py +++ b/lesscpy/plib/block.py @@ -4,8 +4,6 @@ import re, copy from .node import Node from lesscpy.lessc import utility class Block(Node): - pass - def parse(self, scope): """ """ diff --git a/lesscpy/plib/call.py b/lesscpy/plib/call.py index aab6059..1eb9b74 100644 --- a/lesscpy/plib/call.py +++ b/lesscpy/plib/call.py @@ -1,6 +1,6 @@ """ """ -import re +import re, math from urllib.parse import quote as urlquote from .node import Node import lesscpy.lessc.utility as utility @@ -8,9 +8,11 @@ import lesscpy.lessc.color as Color class Call(Node): def parse(self, scope): + """ + """ if not self.parsed: - name = ''.join(self.tokens.pop(0)) - parsed = self.process(self.tokens, scope) + name = ''.join(self.tokens[0]) + parsed = self.process(self.tokens[1:], scope) if name == '%(': name = 'sformat' elif name == '~': @@ -31,7 +33,7 @@ class Call(Node): self.parsed = name + ''.join([p for p in parsed]) return self.parsed - def e(self, string): + def e(self, string, *args): """ Less Escape. @param string: value @return string @@ -58,20 +60,24 @@ class Call(Node): format = format.replace('%A', '%s') return format % tuple(items) - def increment(self, v): + def increment(self, *args): """ Increment function @param Mixed: value @return: incremented value """ - n, u = utility.analyze_number(v) + if(len(args) > 1): + raise SyntaxError('Wrong number of arguments') + n, u = utility.analyze_number(args[0]) return utility.with_unit(n+1, u) - def decrement(self, v): + def decrement(self, *args): """ Decrement function @param Mixed: value @return: incremented value """ - n, u = utility.analyze_number(v) + if(len(args) > 1): + raise SyntaxError('Wrong number of arguments') + n, u = utility.analyze_number(args[0]) return utility.with_unit(n-1, u) def add(self, *args): @@ -79,12 +85,42 @@ class Call(Node): @param list: values @return: int """ + if(len(args) <= 1): + raise SyntaxError('Wrong number of arguments') return sum([int(v) for v in args]) - def round(self, v): + def round(self, *args): """ Round number @param Mixed: value @return: rounded value """ - n, u = utility.analyze_number(v) + if(len(args) > 1): + raise SyntaxError('Wrong number of arguments') + n, u = utility.analyze_number(args[0]) return utility.with_unit(round(float(n)), u) + + def ceil(self, *args): + """ + """ + if(len(args) > 1): + raise SyntaxError('Wrong number of arguments') + n, u = utility.analyze_number(args[0]) + return utility.with_unit(math.ceil(n), u) + + def floor(self, *args): + """ + """ + if(len(args) > 1): + raise SyntaxError('Wrong number of arguments') + n, u = utility.analyze_number(args[0]) + return utility.with_unit(math.floor(n), u) + + def percentage(self, *args): + """ + """ + if(len(args) > 1): + raise SyntaxError('Wrong number of arguments') + n, u = utility.analyze_number(args[0]) + n = int(n * 100.0) + u = '%' + return utility.with_unit(n, u) diff --git a/lesscpy/plib/identifier.py b/lesscpy/plib/identifier.py index 415d909..1f9389d 100644 --- a/lesscpy/plib/identifier.py +++ b/lesscpy/plib/identifier.py @@ -13,6 +13,8 @@ class Identifier(Node): '@media', '@keyframes', '@-moz-keyframes', '@-webkit-keyframes' ) + if self.tokens and hasattr(self.tokens, 'parse'): + self.tokens = self.tokens.parse(scope) if self.tokens and self.tokens[0] in self._subp: name = list(utility.flatten(self.tokens)) self.subparse = True diff --git a/lesscpy/plib/mixin.py b/lesscpy/plib/mixin.py index d4ba0d3..da96ef1 100644 --- a/lesscpy/plib/mixin.py +++ b/lesscpy/plib/mixin.py @@ -73,9 +73,7 @@ class Mixin(Node): body = copy.deepcopy(self.body) self.parse_args(args, scope) scope.update([self.scope], -1) - body.parse(scope) r = list(utility.flatten([body.parsed, body.inner])) - utility.rename(r, scope) return r diff --git a/lesscpy/test/css/calls.css b/lesscpy/test/css/calls.css index 5897f6e..e8b028c 100644 --- a/lesscpy/test/css/calls.css +++ b/lesscpy/test/css/calls.css @@ -18,3 +18,8 @@ format-multiple: "hello earth 2"; format-url-encode: 'red is %23ff0000'; } +#more { + width: 1px; + height: 1px; + top: 50%; +} diff --git a/lesscpy/test/css/calls.min.css b/lesscpy/test/css/calls.min.css index b111af6..74e263f 100644 --- a/lesscpy/test/css/calls.min.css +++ b/lesscpy/test/css/calls.min.css @@ -1,3 +1,4 @@ #standard{width:16;height:undefined("self");border-width:5;variable:11;decrement:9;rounded:10;roundedpx:3px;} #escapes{escaped:-Some::weird(#thing, y);escaped1:-Some::weird(#thing, z);eformat:rgb(32, 128, 64);} #format{format:"rgb(32, 128, 64)";format-string:"hello world";format-multiple:"hello earth 2";format-url-encode:'red is %23ff0000';} +#more{width:1px;height:1px;top:50%;} diff --git a/lesscpy/test/less/calls.less b/lesscpy/test/less/calls.less index 059fc0e..95e8e8e 100644 --- a/lesscpy/test/less/calls.less +++ b/lesscpy/test/less/calls.less @@ -22,4 +22,9 @@ format-string: %("hello %s", "world"); format-multiple: %("hello %s %d", "earth", 2); format-url-encode: %('red is %A', #ff0000); +} +#more { + width: ceil(5/3.0px); + height: floor(5.0/3px); + top: percentage(0.5); } \ No newline at end of file