| 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 |