1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
# python yapps2.py grammar.g grammar.py
################################################################################
## Grammar compiled using Yapps:
%%
parser SassExpression:
ignore: "[ \r\t\n]+"
token COMMA: ","
token LPAR: "\\(|\\["
token RPAR: "\\)|\\]"
token END: "$"
token MUL: "[*]"
token DIV: "/"
token ADD: "[+]"
token SUB: "-\s"
token SIGN: "-(?![a-zA-Z_])"
token AND: "(?<![-\w])and(?![-\w])"
token OR: "(?<![-\w])or(?![-\w])"
token NOT: "(?<![-\w])not(?![-\w])"
token NE: "!="
token INV: "!"
token EQ: "=="
token LE: "<="
token GE: ">="
token LT: "<"
token GT: ">"
token STR: "'[^']*'"
token QSTR: '"[^"]*"'
token UNITS: "(?<!\s)(?:[a-zA-Z]+|%)(?![-\w])"
token NUM: "(?:\d+(?:\.\d*)?|\.\d+)"
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 BANG_IMPORTANT: "!important"
rule goal: expr_lst {{ v = expr_lst }}
END {{ return v }}
rule expr: and_expr {{ v = and_expr }}
(
OR and_expr {{ v = AnyOp(v, and_expr) }}
)* {{ return v }}
rule and_expr: not_expr {{ v = not_expr }}
(
AND not_expr {{ v = AllOp(v, not_expr) }}
)* {{ return v }}
rule not_expr: comparison {{ return comparison }}
| NOT not_expr {{ return NotOp(not_expr) }}
rule comparison: a_expr {{ v = a_expr }}
(
LT a_expr {{ v = BinaryOp(operator.lt, v, a_expr) }}
| GT a_expr {{ v = BinaryOp(operator.gt, v, a_expr) }}
| LE a_expr {{ v = BinaryOp(operator.le, v, a_expr) }}
| GE a_expr {{ v = BinaryOp(operator.ge, v, a_expr) }}
| EQ a_expr {{ v = BinaryOp(operator.eq, v, a_expr) }}
| NE a_expr {{ v = BinaryOp(operator.ne, v, a_expr) }}
)* {{ return v }}
rule a_expr: m_expr {{ v = m_expr }}
(
ADD m_expr {{ v = BinaryOp(operator.add, v, m_expr) }}
| SUB m_expr {{ v = BinaryOp(operator.sub, v, m_expr) }}
)* {{ return v }}
rule m_expr: u_expr {{ v = u_expr }}
(
MUL u_expr {{ v = BinaryOp(operator.mul, v, u_expr) }}
| DIV u_expr {{ v = BinaryOp(operator.truediv, v, u_expr) }}
)* {{ return v }}
rule u_expr: SIGN u_expr {{ return UnaryOp(operator.neg, u_expr) }}
| ADD u_expr {{ return UnaryOp(operator.pos, u_expr) }}
| atom {{ return atom }}
rule atom: LPAR expr_lst RPAR {{ return Parentheses(expr_lst) }}
| ID {{ return Literal(parse_bareword(ID)) }}
| BANG_IMPORTANT {{ return Literal(String(BANG_IMPORTANT, quotes=None)) }}
| FNCT {{ v = ArgspecLiteral([]) }}
LPAR [
argspec {{ v = argspec }}
] RPAR {{ return CallOp(FNCT, v) }}
| NUM [
UNITS {{ return Literal(NumberValue(float(NUM), unit=UNITS.lower())) }}
] {{ return Literal(NumberValue(float(NUM))) }}
| 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 argspec: argspec_item {{ v = [argspec_item] }}
(
COMMA
argspec_item {{ v.append(argspec_item) }}
)* {{ return ArgspecLiteral(v) }}
rule argspec_item: {{ var = None }}
[
VAR
[ ":" {{ var = VAR }}
] {{ else: self._rewind() }}
]
expr_slst {{ return (var, expr_slst) }}
rule expr_lst: expr_slst {{ v = [expr_slst] }}
(
COMMA
expr_slst {{ v.append(expr_slst) }}
)* {{ return ListLiteral(v) if len(v) > 1 else v[0] }}
rule expr_slst: expr {{ v = [expr] }}
(
expr {{ v.append(expr) }}
)* {{ return ListLiteral(v, comma=False) if len(v) > 1 else v[0] }}
%%
### Grammar ends.
################################################################################
|