From 3069f3e9e2e995cc93857666998d2e5dfd2a84eb Mon Sep 17 00:00:00 2001 From: "German M. Bravo" Date: Wed, 14 Aug 2013 19:32:57 -0500 Subject: Cleaned up grammar --- scss/src/grammar/grammar.g | 55 ++++++++++++++-------------- scss/src/grammar/grammar.py | 88 +++++++++++++++++++++++---------------------- 2 files changed, 72 insertions(+), 71 deletions(-) diff --git a/scss/src/grammar/grammar.g b/scss/src/grammar/grammar.g index 8798018..20c0a2f 100644 --- a/scss/src/grammar/grammar.g +++ b/scss/src/grammar/grammar.g @@ -31,13 +31,32 @@ parser SassExpression: token COLOR: "#(?:[a-fA-F0-9]{6}|[a-fA-F0-9]{3})(?![a-fA-F0-9])" token VAR: "\$[-a-zA-Z0-9_]+" token FNCT: "[-a-zA-Z_][-a-zA-Z0-9_]*(?=\()" - token ID: "[-a-zA-Z_][-a-zA-Z0-9_]*" + token ID: "!?[-a-zA-Z_][-a-zA-Z0-9_]*" token BANG_IMPORTANT: "!important" - rule goal: expr_lst {{ v = expr_lst }} - END {{ return v }} + rule goal: expr_lst END {{ return expr_lst }} - rule expr: and_expr {{ v = and_expr }} + rule expr_lst: expr_item {{ v = [expr_item] }} + ( + COMMA [ + expr_item {{ v.append(expr_item) }} + ] {{ else: v.append((None, Literal(Undefined()))) }} + )* {{ return ListLiteral(v) if len(v) > 1 else v[0][1] }} + + rule expr_item: {{ var = None }} + [ + VAR [ + ":" {{ var = VAR }} + ] {{ else: self._rewind() }} + ] + expr_slst {{ return (var, expr_slst) }} + + rule expr_slst: or_expr {{ v = [(None, or_expr)] }} + ( + or_expr {{ v.append((None, or_expr)) }} + )* {{ return ListLiteral(v, comma=False) if len(v) > 1 else v[0][1] }} + + rule or_expr: and_expr {{ v = and_expr }} ( OR and_expr {{ v = AnyOp(v, and_expr) }} )* {{ return v }} @@ -78,36 +97,16 @@ parser SassExpression: rule atom: ID {{ return Literal(parse_bareword(ID)) }} | BANG_IMPORTANT {{ return Literal(String(BANG_IMPORTANT, quotes=None)) }} - | LPAR {{ expr_lst = ListLiteral([]) }} + | LPAR {{ expr_lst = ListLiteral() }} [ expr_lst ] RPAR {{ return Parentheses(expr_lst) }} - | FNCT LPAR {{ expr_lst = ArgspecLiteral([]) }} + | FNCT LPAR {{ expr_lst = ListLiteral() }} [ expr_lst ] RPAR {{ return CallOp(FNCT, expr_lst) }} - | NUM [ - UNITS {{ return Literal(NumberValue(float(NUM), unit=UNITS.lower())) }} - ] {{ return Literal(NumberValue(float(NUM))) }} + | NUM {{ UNITS = None }} + [ UNITS ] {{ return Literal(NumberValue(float(NUM), unit=UNITS)) }} | STR {{ return Literal(String(STR[1:-1], quotes="'")) }} | QSTR {{ return Literal(String(QSTR[1:-1], quotes='"')) }} | COLOR {{ return Literal(ColorValue(ParserValue(COLOR))) }} | VAR {{ return Variable(VAR) }} - - rule expr_lst: expr_item {{ v = [expr_item] }} - ( - COMMA - expr_item {{ v.append(expr_item) }} - )* {{ return ListLiteral(v) if len(v) > 1 else v[0] }} - - rule expr_item: {{ var = None }} - [ - VAR - [ ":" {{ var = VAR }} - ] {{ else: self._rewind() }} - ] - expr_slst {{ return (var, expr_slst) }} - - rule expr_slst: expr {{ v = [expr] }} - ( - expr {{ v.append(expr) }} - )* {{ return ListLiteral(v, comma=False) if len(v) > 1 else v[0] }} %% ### Grammar ends. ################################################################################ diff --git a/scss/src/grammar/grammar.py b/scss/src/grammar/grammar.py index e89be20..2651d94 100644 --- a/scss/src/grammar/grammar.py +++ b/scss/src/grammar/grammar.py @@ -39,7 +39,7 @@ class SassExpressionScanner(Scanner): ('COLOR', '#(?:[a-fA-F0-9]{6}|[a-fA-F0-9]{3})(?![a-fA-F0-9])'), ('VAR', '\\$[-a-zA-Z0-9_]+'), ('FNCT', '[-a-zA-Z_][-a-zA-Z0-9_]*(?=\\()'), - ('ID', '[-a-zA-Z_][-a-zA-Z0-9_]*'), + ('ID', '!?[-a-zA-Z_][-a-zA-Z0-9_]*'), ('BANG_IMPORTANT', '!important'), ] @@ -56,14 +56,43 @@ class SassExpressionScanner(Scanner): class SassExpression(Parser): def goal(self): expr_lst = self.expr_lst() - v = expr_lst END = self._scan('END') - return v + return expr_lst + + def expr_lst(self): + expr_item = self.expr_item() + v = [expr_item] + while self._peek(self.expr_lst_rsts) == 'COMMA': + COMMA = self._scan('COMMA') + if self._peek(self.expr_lst_rsts_) not in self.expr_lst_rsts: + expr_item = self.expr_item() + v.append(expr_item) + else: v.append((None, Literal(Undefined()))) + return ListLiteral(v) if len(v) > 1 else v[0][1] + + def expr_item(self): + var = None + if self._peek(self.expr_item_rsts) == 'VAR': + VAR = self._scan('VAR') + if self._peek(self.expr_item_rsts_) == '":"': + self._scan('":"') + var = VAR + else: self._rewind() + expr_slst = self.expr_slst() + return (var, expr_slst) - def expr(self): + def expr_slst(self): + or_expr = self.or_expr() + v = [(None, or_expr)] + while self._peek(self.expr_slst_rsts) not in self.expr_lst_rsts: + or_expr = self.or_expr() + v.append((None, or_expr)) + return ListLiteral(v, comma=False) if len(v) > 1 else v[0][1] + + def or_expr(self): and_expr = self.and_expr() v = and_expr - while self._peek(self.expr_rsts) == 'OR': + while self._peek(self.or_expr_rsts) == 'OR': OR = self._scan('OR') and_expr = self.and_expr() v = AnyOp(v, and_expr) @@ -173,7 +202,7 @@ class SassExpression(Parser): return Literal(String(BANG_IMPORTANT, quotes=None)) elif _token_ == 'LPAR': LPAR = self._scan('LPAR') - expr_lst = ListLiteral([]) + expr_lst = ListLiteral() if self._peek(self.atom_rsts) not in self.atom_chks: expr_lst = self.expr_lst() RPAR = self._scan('RPAR') @@ -181,17 +210,17 @@ class SassExpression(Parser): elif _token_ == 'FNCT': FNCT = self._scan('FNCT') LPAR = self._scan('LPAR') - expr_lst = ArgspecLiteral([]) + expr_lst = ListLiteral() if self._peek(self.atom_rsts) not in self.atom_chks: expr_lst = self.expr_lst() RPAR = self._scan('RPAR') return CallOp(FNCT, expr_lst) elif _token_ == 'NUM': NUM = self._scan('NUM') + UNITS = None if self._peek(self.atom_rsts_) == 'UNITS': UNITS = self._scan('UNITS') - return Literal(NumberValue(float(NUM), unit=UNITS.lower())) - return Literal(NumberValue(float(NUM))) + return Literal(NumberValue(float(NUM), unit=UNITS)) elif _token_ == 'STR': STR = self._scan('STR') return Literal(String(STR[1:-1], quotes="'")) @@ -205,50 +234,23 @@ class SassExpression(Parser): VAR = self._scan('VAR') return Variable(VAR) - def expr_lst(self): - expr_item = self.expr_item() - v = [expr_item] - while self._peek(self.expr_lst_rsts) == 'COMMA': - COMMA = self._scan('COMMA') - expr_item = self.expr_item() - v.append(expr_item) - return ListLiteral(v) if len(v) > 1 else v[0] - - def expr_item(self): - var = None - if self._peek(self.expr_item_rsts) == 'VAR': - VAR = self._scan('VAR') - if self._peek(self.expr_item_rsts_) == '":"': - self._scan('":"') - var = VAR - else: self._rewind() - expr_slst = self.expr_slst() - return (var, expr_slst) - - def expr_slst(self): - expr = self.expr() - v = [expr] - while self._peek(self.expr_slst_rsts) not in self.expr_lst_rsts: - expr = self.expr() - v.append(expr) - return ListLiteral(v, comma=False) if len(v) > 1 else v[0] - m_expr_chks = set(['MUL', 'DIV']) comparison_rsts = set(['LPAR', 'QSTR', 'RPAR', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'COMMA', 'GT', 'END', 'SIGN', 'ADD', 'FNCT', 'STR', 'VAR', 'EQ', 'ID', 'AND', 'GE', 'NOT', 'OR']) atom_rsts = set(['LPAR', 'BANG_IMPORTANT', 'END', 'COLOR', 'QSTR', 'SIGN', 'NOT', 'ADD', 'NUM', 'FNCT', 'STR', 'VAR', 'RPAR', 'ID']) u_expr_chks = set(['LPAR', 'COLOR', 'QSTR', 'NUM', 'FNCT', 'STR', 'VAR', 'BANG_IMPORTANT', 'ID']) m_expr_rsts = set(['LPAR', 'SUB', 'QSTR', 'RPAR', 'MUL', 'DIV', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'COMMA', 'GT', 'END', 'SIGN', 'GE', 'FNCT', 'STR', 'VAR', 'EQ', 'ID', 'AND', 'ADD', 'NOT', 'OR']) - expr_lst_rsts = set(['END', 'COMMA', 'RPAR']) - and_expr_rsts = set(['AND', 'LPAR', 'RPAR', 'END', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'COMMA', 'FNCT', 'STR', 'NOT', 'ID', 'BANG_IMPORTANT', 'OR']) + expr_lst_rsts_ = set(['LPAR', 'BANG_IMPORTANT', 'END', 'COLOR', 'QSTR', 'SIGN', 'NOT', 'ADD', 'NUM', 'COMMA', 'FNCT', 'STR', 'VAR', 'RPAR', 'ID']) + a_expr_rsts = set(['LPAR', 'SUB', 'QSTR', 'RPAR', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'COMMA', 'GT', 'END', 'SIGN', 'GE', 'FNCT', 'STR', 'VAR', 'EQ', 'ID', 'AND', 'ADD', 'NOT', 'OR']) + or_expr_rsts = set(['LPAR', 'RPAR', 'BANG_IMPORTANT', 'END', 'COLOR', 'QSTR', 'ID', 'VAR', 'ADD', 'NUM', 'COMMA', 'FNCT', 'STR', 'NOT', 'SIGN', 'OR']) u_expr_rsts = set(['LPAR', 'COLOR', 'QSTR', 'SIGN', 'ADD', 'NUM', 'FNCT', 'STR', 'VAR', 'BANG_IMPORTANT', 'ID']) - expr_rsts = set(['LPAR', 'RPAR', 'BANG_IMPORTANT', 'END', 'COLOR', 'QSTR', 'ID', 'VAR', 'ADD', 'NUM', 'COMMA', 'FNCT', 'STR', 'NOT', 'SIGN', 'OR']) - atom_chks = set(['END', 'RPAR']) + expr_lst_rsts = set(['END', 'COMMA', 'RPAR']) + expr_item_rsts = set(['LPAR', 'COLOR', 'QSTR', 'SIGN', 'NOT', 'ADD', 'NUM', 'FNCT', 'STR', 'VAR', 'BANG_IMPORTANT', 'ID']) not_expr_rsts = set(['LPAR', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'FNCT', 'STR', 'NOT', 'BANG_IMPORTANT', 'ID']) atom_rsts_ = set(['LPAR', 'SUB', 'QSTR', 'RPAR', 'VAR', 'MUL', 'DIV', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'COMMA', 'GT', 'END', 'SIGN', 'GE', 'FNCT', 'STR', 'UNITS', 'EQ', 'ID', 'AND', 'ADD', 'NOT', 'OR']) - expr_item_rsts = set(['LPAR', 'COLOR', 'QSTR', 'SIGN', 'NOT', 'ADD', 'NUM', 'FNCT', 'STR', 'VAR', 'BANG_IMPORTANT', 'ID']) + atom_chks = set(['END', 'RPAR']) comparison_chks = set(['GT', 'GE', 'NE', 'LT', 'LE', 'EQ']) a_expr_chks = set(['ADD', 'SUB']) - a_expr_rsts = set(['LPAR', 'SUB', 'QSTR', 'RPAR', 'BANG_IMPORTANT', 'LE', 'COLOR', 'NE', 'LT', 'NUM', 'COMMA', 'GT', 'END', 'SIGN', 'GE', 'FNCT', 'STR', 'VAR', 'EQ', 'ID', 'AND', 'ADD', 'NOT', 'OR']) + and_expr_rsts = set(['AND', 'LPAR', 'RPAR', 'END', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'COMMA', 'FNCT', 'STR', 'NOT', 'ID', 'BANG_IMPORTANT', 'OR']) expr_item_rsts_ = set(['LPAR', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', '":"', 'STR', 'NOT', 'BANG_IMPORTANT', 'ID', 'FNCT']) expr_slst_rsts = set(['LPAR', 'RPAR', 'END', 'COLOR', 'QSTR', 'SIGN', 'VAR', 'ADD', 'NUM', 'COMMA', 'FNCT', 'STR', 'NOT', 'BANG_IMPORTANT', 'ID']) -- cgit v1.2.1