Commits

Shu Zong Chen committed 074a831

Initial import

Comments (0)

Files changed (2)

+import ply.lex
+import ply.yacc
+
+class CSSLexer(object):
+    def __init__(self, **kwargs):
+        self.lexer = ply.lex.lex(object=self, **kwargs)
+        
+    tokens = (
+        'OPEN_BRACE',
+        'CLOSE_BRACE',
+        'COLON',
+        'COMMA',
+        'SEMICOLON',
+        'SELECTOR',
+        'PROPERTY',
+        'VALUE',
+    )
+    states = (
+        ('define', 'exclusive'),
+        ('value', 'exclusive'),
+    )
+
+    t_SELECTOR = r'[^ \r\n\t;:\{\}]+'
+    def t_OPEN_BRACE(self, t):
+        r'\{'
+        t.lexer.begin('define')
+        return t 
+
+    def t_define_CLOSE_BRACE(self, t):
+        r'\}'
+        t.lexer.begin('INITIAL')
+        return t
+
+    t_define_PROPERTY = r'[^ \r\n\t;:\{\}\'"]+'
+    
+    def t_define_COLON(self, t):
+        r':'
+        t.lexer.begin('value')
+        return t
+        
+    t_value_VALUE = r'([^ \r\t\n\{\};:\'"]+|\'(\\.|[^\'])*\'|"(\\.|[^"])*")+'
+    def t_value_SEMICOLON(self, t):
+        r';'
+        t.lexer.begin('define')
+        return t
+
+    t_ANY_COMMA = r','
+    t_ANY_ignore = ' \t\r\n'
+    def t_ANY_error(self, t):
+        t.lexer.skip(1)
+
+    def parse(self, fh):
+        data = fh.read()
+        self.lexer.input(data)
+
+    def run_parser(self, fh):
+        self.build()
+        self.parse(fh)
+        while True:
+            tok = self.lexer.token()
+            if not tok:
+                break;
+            print tok
+
+class CSSParser(object):
+    def __init__(self, **kwargs):
+        self.tokens = CSSLexer.tokens
+        self.parser = ply.yacc.yacc(module=self)
+        self.lexer = CSSLexer()
+        
+    def p_stylesheet(self, p):
+        '''stylesheet : stylesheet ruleset
+                      | ruleset'''
+        if (len(p) == 3):
+            p[0] = p[1]
+            p[0].append(p[2])
+        else:
+            p[0] = []
+            p[0].append(p[1])
+    
+    def p_ruleset(self, p):
+        'ruleset : selectors OPEN_BRACE rules CLOSE_BRACE'
+        p[0] = dict(selector=p[1], rules=p[3])
+    
+    def p_rules(self, p):
+        '''rules : rules rule
+                 | rule
+                 | empty'''
+        if (len(p) == 3):
+            p[0] = p[1]
+            p[0].append(p[2])
+        else:
+            p[0] = []
+            p[0].append(p[1])
+    
+    def p_rule(self, p):
+        'rule : PROPERTY COLON values SEMICOLON'
+        p[0] = (p[1], p[3])
+    
+    def p_values(self, p):
+        '''values : values COMMA VALUE
+                  | values VALUE
+                  | VALUE'''
+        if (len(p) == 4):
+            p[0] = p[1] + ", " + p[3]
+        elif (len(p) == 3):
+            p[0] = p[1] + " " + p[2]
+        else:
+            p[0] = p[1]
+        
+    def p_selectors(self, p):
+        '''selectors : selectors COMMA SELECTOR
+                     | selectors SELECTOR
+                     | SELECTOR
+                     | empty'''
+        if (len(p) == 4):
+            p[0] = p[1] + ", " + p[3]
+        elif (len(p) == 3):
+            p[0] = p[1] + " " + p[2]
+        else:
+            p[0] = p[1]
+            
+    def p_empty(self, p):
+        'empty :'
+        p[0] = None
+    
+    def p_error(self, p):
+        print "Syntax error with",p.type
+        ply.yacc.token()
+        ply.yacc.errok()
+        
+    
+    def parse_string(self, data):
+        result = self.parser.parse(data, lexer = self.lexer.lexer)
+        print result
+
+if __name__ == "__main__":
+    with open('example.css', 'r') as fh:
+        data = fh.read()
+    cssparser = CSSParser()
+    cssparser.parse_string(data)
+body{
+font-size:10px;
+font-weight:bold;
+}
+table a{
+margin: 0px auto;
+}
+table tbody tr td span{
+  padding : 10px;
+}
+.might_be_tricky{
+	padding: 20em 5em;
+}
+#stuff, #otherstuff{
+	background-image: url('/blah.png');
+}
+cheater{
+}
+blah{}
+blahc
+{
+
+}
+.very_tricky:after{
+    content: "blah \"blah\";;'..'{}";
+}
+.very_tricky:before{
+    content: 'blah \'\';;;a"sdl"f{}kj';
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.