OLD | NEW |
| (Empty) |
1 # To debug the grammar see comment block on how to debug the pyparsing grammar | |
2 # in the MEDIA section. | |
3 | |
4 " SCSS Grammars." | |
5 from pyparsing import Word, Suppress, Literal, alphanums, SkipTo, oneOf, ZeroOrM
ore, Optional, OneOrMore, Forward, cStyleComment, Combine, dblSlashComment, quot
edString, Regex, lineEnd, Group, White | |
6 | |
7 | |
8 __all__ = ("STYLESHEET", "OTHER_VALUE", "quotedString", "EXPRESSION", "IDENT", "
PATH", "VARIABLE", "VAR_DEFINITION", | |
9 "VARIABLES", "FUNCTION", "COLOR_VALUE", "SCSS_COMMENT", "CSS_COMMENT"
, "IMPORT", "STYLET", "RULESET", | |
10 "DECLARATION", "DECLARATION_NAME", "SELECTOR_TREE", "SELECTOR_GROUP",
"SELECTOR", "MIXIN", "INCLUDE", | |
11 "MIXIN_PARAM", "EXTEND", "FONT_FACE", "OPTION", "FUNCTION_DEFINITION"
, "FUNCTION_RETURN", | |
12 "IF", "ELSE", "IF_BODY", "FOR", "FOR_BODY", "CHARSET", "MEDIA", "WARN
", "SEP_VAL_STRING", "POINT", | |
13 "PERCENTAGE_VALUE", "ANIMATION_DECLARATIONS", "ANIMATION_BODY", "REPE
AT_VALUE", | |
14 ) | |
15 | |
16 | |
17 # Base css word and literals | |
18 COMMA, COLON, SEMICOLON = [Suppress(c) for c in ",:;"] | |
19 OPT_SEMICOLON = Optional(SEMICOLON) | |
20 LACC, RACC, LPAREN, RPAREN = [Suppress(c) for c in "{}()"] | |
21 LLACC, LRACC, LBRACK, RBRACK, LLPAREN, LRPAREN = [Literal(c) for c in "{}[]()"] | |
22 | |
23 # Comment | |
24 CSS_COMMENT = cStyleComment + Optional(lineEnd) | |
25 SCSS_COMMENT = dblSlashComment | |
26 | |
27 IDENT = Regex(r"-?[a-zA-Z_][-a-zA-Z0-9_]*") | |
28 COLOR_VALUE = Regex(r"#[a-zA-Z0-9]{3,6}") | |
29 VARIABLE = Regex(r"-?\$[-a-zA-Z_][-a-zA-Z0-9_]*") | |
30 PERCENTAGE_VALUE = Regex(r"-?\d+(?:\.\d*)?|\.\d+") + '%' | |
31 OTHER_VALUE = Regex(r"-?\d+(?:\.\d*)?|\.\d+") + Optional(oneOf("em ex px cm mm i
n pt pc deg fr s ")) | |
32 NUMBER_VALUE = PERCENTAGE_VALUE | OTHER_VALUE | |
33 REPEAT_VALUE = Suppress("[") + Regex(r"-?\d+(?:\.\d*)?|\.\d+") + Suppress("]") | |
34 PATH = Regex(r"[-\w\d_\.]*\/{1,2}[-\w\d_\.\/]*") | Regex(r"((https?|ftp|file):((
//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)") | |
35 POINT_PART = (NUMBER_VALUE | Regex(r"(top|bottom|left|right)")) | |
36 POINT = POINT_PART + POINT_PART | |
37 | |
38 # Values | |
39 EXPRESSION = Forward() | |
40 INTERPOLATION_VAR = Suppress("#") + LACC + EXPRESSION + RACC | |
41 SIMPLE_VALUE = NUMBER_VALUE | PATH | IDENT | COLOR_VALUE | quotedString | REPEAT
_VALUE | |
42 DIV_STRING = SIMPLE_VALUE + OneOrMore(Literal("/") + SIMPLE_VALUE) | |
43 | |
44 PARAMS = LPAREN + (POINT|EXPRESSION) + ZeroOrMore(COMMA + (POINT|EXPRESSION)) +
RPAREN | |
45 FUNCTION = Regex(r"-?[a-zA-Z_][-a-zA-Z0-9_]*") + PARAMS | |
46 VALUE = FUNCTION | VARIABLE | SIMPLE_VALUE | |
47 PARENS = LPAREN + EXPRESSION + RPAREN | |
48 MATH_OPERATOR = Regex(r"(\+|-|/|\*|and|or|==|!=|<=|<|>|>=)\s+") | |
49 EXPRESSION << ((VALUE | PARENS) + ZeroOrMore(MATH_OPERATOR + (VALUE | PARENS))) | |
50 | |
51 # Declaration | |
52 TERM = Optional(LLPAREN) + ( DIV_STRING | EXPRESSION | INTERPOLATION_VAR ) + Opt
ional(LRPAREN) + Optional(",") | |
53 DECLARATION_NAME = Optional("*") + OneOrMore(IDENT | INTERPOLATION_VAR) | |
54 DECLARATION = Forward() | |
55 DECLARATION << ( | |
56 DECLARATION_NAME + | |
57 ":" + | |
58 ZeroOrMore(TERM) + | |
59 Optional("!important") + | |
60 Optional(LACC + OneOrMore(DECLARATION | CSS_COMMENT | SCSS_COMMENT) + RA
CC) + | |
61 OPT_SEMICOLON ) | |
62 | |
63 # Selectors | |
64 ELEMENT_NAME = Combine(OneOrMore(IDENT | '&')) | Literal("*") | |
65 ATTRIB = LBRACK + SkipTo("]") + RBRACK | |
66 CLASS_NAME = Word('.', alphanums + "-_") | |
67 HASH = Regex(r"#[-a-zA-Z_][-a-zA-Z0-9_]*") | |
68 FILTER = HASH | CLASS_NAME | ATTRIB | |
69 | |
70 ## PSEUDO = Regex(r':{1,2}[A-Za-z0-9-_]+') | |
71 PSEUDO = Regex(r':{1,2}[^\s;{}]+') | |
72 COMBINATOR = ZeroOrMore(Word("+>", max=1)) | |
73 | |
74 SELECTOR_TREE = Forward() | |
75 SELECTOR = OneOrMore(Combine(ELEMENT_NAME | FILTER | INTERPOLATION_VAR | PSEUDO)
) | |
76 SELECTOR.leaveWhitespace() | |
77 #SELECTOR_GROUP = SELECTOR + ZeroOrMore((Word("+>", max=1)) + SELECTOR) | |
78 SELECTOR_GROUP = SELECTOR + ZeroOrMore(COMBINATOR + SELECTOR) | |
79 SELECTOR_GROUP.skipWhitespace = True | |
80 #SELECTOR_TREE = SELECTOR_GROUP + ZeroOrMore(COMMA + SELECTOR_GROUP) | |
81 ##TLL Workaround | |
82 SELECTOR_TREE << ( | |
83 SELECTOR_GROUP + ZeroOrMore(Word(",>+", max=1) + SELECTOR_GROU
P) | |
84 ) | |
85 | |
86 # @debug | |
87 DEBUG = "@debug" + EXPRESSION + OPT_SEMICOLON | |
88 | |
89 # @warn | |
90 WARN = "@warn" + quotedString + OPT_SEMICOLON | |
91 | |
92 # @include | |
93 INCLUDE_MIXIN = IDENT + Optional(PARAMS) | |
94 INCLUDE = "@include" + Optional(INCLUDE_MIXIN | quotedString) + OPT_SEMICOLON | |
95 | |
96 # @extend | |
97 EXTEND = "@extend" + OneOrMore(ELEMENT_NAME | FILTER | INTERPOLATION_VAR | PSEUD
O) + OPT_SEMICOLON | |
98 | |
99 # SCSS variable assigment | |
100 SEP_VAL_STRING = EXPRESSION + OneOrMore(COMMA + EXPRESSION) | |
101 VAR_DEFINITION = Regex(r"\$[a-zA-Z_][-a-zA-Z0-9_]*") + COLON + (SEP_VAL_STRING |
EXPRESSION ) + Optional("!default") + OPT_SEMICOLON | |
102 | |
103 RULESET = Forward() | |
104 IF = Forward() | |
105 #CONTENT = CSS_COMMENT | SCSS_COMMENT | WARN | DEBUG | IF | INCLUDE | VAR_DEFINI
TION | RULESET | DECLARATION | STYLET | |
106 CONTENT = CSS_COMMENT | SCSS_COMMENT | WARN | DEBUG | IF | INCLUDE | VAR_DEFINIT
ION | RULESET | DECLARATION | |
107 | |
108 # SCSS control directives | |
109 IF_BODY = LACC + ZeroOrMore(CONTENT) + RACC | |
110 ELSE = Suppress("@else") + LACC + ZeroOrMore(CONTENT) + RACC | |
111 IF << ( | |
112 ( Suppress("@if") | Suppress("@else if") ) + EXPRESSION + IF_BODY + Opti
onal(ELSE)) | |
113 | |
114 FOR_BODY = ZeroOrMore(CONTENT) | |
115 FOR = "@for" + VARIABLE + Suppress("from") + VALUE + (Suppress("through") | Supp
ress("to")) + VALUE + LACC + FOR_BODY + RACC | |
116 | |
117 RULESET << ( | |
118 SELECTOR_TREE + | |
119 LACC + ZeroOrMore(CONTENT | FOR | EXTEND) + RACC ) | |
120 | |
121 # SCSS mixin | |
122 MIXIN_PARAM = VARIABLE + Optional(COLON + EXPRESSION) | |
123 MIXIN_PARAMS = LPAREN + ZeroOrMore(COMMA | MIXIN_PARAM) + RPAREN | |
124 MIXIN = "@mixin" + IDENT + Group(Optional(MIXIN_PARAMS)) + LACC + ZeroOrMore(CON
TENT | FOR) + RACC | |
125 | |
126 # SCSS function | |
127 FUNCTION_RETURN = "@return" + VARIABLE + OPT_SEMICOLON | |
128 FUNCTION_BODY = LACC + ZeroOrMore(VAR_DEFINITION) + FUNCTION_RETURN + RACC | |
129 FUNCTION_DEFINITION = "@function" + IDENT + Group(MIXIN_PARAMS) + FUNCTION_BODY | |
130 | |
131 # Root elements | |
132 OPTION = "@option" + OneOrMore(IDENT + COLON + IDENT + Optional(COMMA)) + OPT_SE
MICOLON | |
133 IMPORT = "@import" + FUNCTION + OPT_SEMICOLON | |
134 #MEDIA = "@media" + IDENT + ZeroOrMore("," + IDENT) + LLACC + ZeroOrMore( CONTEN
T | MIXIN | FOR ) + LRACC | |
135 FONT_FACE = "@font-face" + LLACC + ZeroOrMore(DECLARATION) + LRACC | |
136 VARIABLES = ( Literal("@variables") | Literal('@vars') ) + LLACC + ZeroOrMore(VA
R_DEFINITION) + RACC | |
137 PSEUDO_PAGE = ":" + IDENT | |
138 PAGE = "@page" + Optional(IDENT) + Optional(PSEUDO_PAGE) + LLACC + ZeroOrMore(DE
CLARATION) + LRACC | |
139 CHARSET = "@charset" + IDENT + OPT_SEMICOLON | |
140 | |
141 #TODO(terry): Added MEDIA syntax from CSS3 | |
142 #media | |
143 # : MEDIA_SYM S* media_query_list '{' S* ruleset* '}' S* | |
144 # ; | |
145 #media_query_list | |
146 # : S* [media_query [ ',' S* media_query ]* ]? | |
147 # ; | |
148 #media_query | |
149 # : [ONLY | NOT]? S* media_type S* [ AND S* expression ]* | |
150 # | expression [ AND S* expression ]* | |
151 # ; | |
152 #media_type | |
153 # : IDENT | |
154 # ; | |
155 #expression | |
156 # : '(' S* media_feature S* [ ':' S* expr ]? ')' S* | |
157 # ; | |
158 #media_feature | |
159 # : IDENT | |
160 MEDIA_NEXT_EXPRESSION = Literal(":") + EXPRESSION | |
161 MEDIA_EXPRESSION = LPAREN + IDENT + Optional(MEDIA_NEXT_EXPRESSION) + RPAREN | |
162 MEDIA_AND_QUERY = Optional(Literal("and") | COMMA) + MEDIA_EXPRESSION | |
163 MEDIA_QUERY_LIST = Optional(Optional(Literal("ONLY") | Literal('NOT')) + IDENT +
ZeroOrMore(MEDIA_AND_QUERY)) | Optional(MEDIA_EXPRESSION + ZeroOrMore(MEDIA_EXP
RESSION)) | |
164 MEDIA = "@media" + MEDIA_QUERY_LIST + LLACC + ZeroOrMore( CONTENT | MIXIN | FOR
) + RACC | |
165 | |
166 # Below example on how to debug grammar built with pyparsing: | |
167 # | |
168 #MEDIA.setName("@media").setDebug() | |
169 #MEDIA_QUERY_LIST.setName("MEDIA_QUERY_LIST").setDebug() | |
170 #MEDIA_QUERY.setName("MEDIA_QUERY").setDebug() | |
171 #MEDIA_AND_QUERY.setName("MEDIA_AND_QUERY").setDebug() | |
172 #MEDIA_EXPRESSION.setName("MEDIA_EXPRESSION").setDebug() | |
173 #MEDIA_NEXT_EXPRESSION.setName("MEDIA_NEXT_EXPRESSION").setDebug() | |
174 #EXPRESSION.setName("EXPRESSION").setDebug() | |
175 # | |
176 # Output character offset of origijnal line parsed all pyparsing are offset from | |
177 # this input. | |
178 # | |
179 #print (' '*9).join(map(str,range(11))) | |
180 #print (''.join(map(str,range(10))))*15 | |
181 #print "@media all and (min-device-width: 769px) and (max-device-width: 1280px)
{_ .sm-root {_ left: 310px;_ }_}" | |
182 #print | |
183 | |
184 #TODO(terry): Added webit-keyframes animation this needs to be @keyframes with | |
185 # @-webkit-keyframes mapping to @keyframes. Also, need more stuff | |
186 # for animation like timing functions for keyframes see: | |
187 # | |
188 # http://www.w3.org/TR/css3-animations/#timing-functions-for-keyframes- | |
189 | |
190 KEYFRAME_SELECTORS = PERCENTAGE_VALUE | IDENT | Literal("from") | Literal("to") | |
191 ANIMATION_DECLARATIONS = LLACC + ZeroOrMore( CONTENT | MIXIN | FOR ) + LRACC | |
192 ANIMATION_PARAMS = KEYFRAME_SELECTORS + ANIMATION_DECLARATIONS | |
193 ANIMATION_BODY = LLACC + ZeroOrMore(ANIMATION_PARAMS) + LRACC | |
194 ANIMATION = "@-webkit-keyframes" + White() + IDENT + ANIMATION_BODY | |
195 # TODO(jmesserly): Need to support other browser prefixes. | |
196 | |
197 #@stylet | |
198 STYLET_BODY = LACC + ZeroOrMore(CONTENT) + RACC | |
199 STYLET = "@stylet" + ELEMENT_NAME + STYLET_BODY | |
200 | |
201 # Css stylesheet | |
202 STYLESHEET = ZeroOrMore( | |
203 FONT_FACE | |
204 | CHARSET | |
205 | OPTION | |
206 | MEDIA | |
207 | PAGE | |
208 | CONTENT | |
209 | FUNCTION_DEFINITION | |
210 | MIXIN | |
211 | INCLUDE | |
212 | FOR | |
213 | IMPORT | |
214 | VARIABLES | |
215 | EXPRESSION | |
216 | ANIMATION | |
217 | STYLET | |
218 ) | |
OLD | NEW |