Пример #1
0
class CSSParser:

    ######################################
    ### Grammar

    def __init__(self, debug=False):
        self.debug = debug
        self.lexer = CSSLexer(debug=self.debug)
        self.tokens = self.lexer.tokens
        self.parser = yacc.yacc(module=self, debug=debug, write_tables=0)
        self.selectors = []

    def parse(self, data):
        if data:
            if self.debug:
                self.lexer.debug(data)
            return self.parser.parse(data, self.lexer.lexer)
        else:
            return []

    def p_stylesheet(self, p):
        """stylesheet : CDO
                      | CDC
                      | statements
        """
        p[0] = p[1]
        logging.debug("FOUND STYLESHEET: {0}".format(p[0]))

    def p_statements(self, p):
        """statements : statement statements
                      | statement
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND STATEMENTS: {0}".format(p[0]))

    def p_statement(self, p):
        """statement : ruleset
                     | import
                     | namespace
                     | page
                     | font-face
                     | media
        """
        p[0] = p[1]
        logging.debug("FOUND STATEMENT: {0}".format(p[0]))

    ##########################################################
    ### Import

    def p_import(self, p):
        """import : IMPORT_SYM STRING import_term ';'
                  | IMPORT_SYM STRING ';'
                  | IMPORT_SYM URI import_term ';'
                  | IMPORT_SYM URI ';'
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND IMPORT: {0}".format(p[0]))

    def p_import_term(self, p):
        """import_term : IDENT ',' import_term
                       | IDENT
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND IMPORT TERM: {0}".format(p[0]))

    ##########################################################
    ### At Rule: namespace

    def p_namespace(self, p):
        """namespace : NAMESPACE_SYM IDENT STRING ';'
                     | NAMESPACE_SYM IDENT URI ';'
                     | NAMESPACE_SYM STRING ';'
                     | NAMESPACE_SYM URI ';'
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND NAMESPACE: {0}".format(p[0]))

    ##########################################################
    ### At Rule: page

    def p_page(self, p):
        """page : PAGE_SYM IDENT pseudo_page '{' declarations '}'
                | PAGE_SYM pseudo_page '{' declarations '}'
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND PAGE: {0}".format(p[0]))

    def p_pseudo_page(self, p):
        """pseudo_page : ':' IDENT"""
        p[0] = p[1] + p[2]
        logging.debug("FOUND PSEUDO PAGE: {0}".format(p[0]))

    ##########################################################
    ### At Rule: font-face

    def p_font_face(self, p):
        """font-face : FONT_FACE_SYM '{' declarations '}'"""
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND FONT FACE: {0}".format(p[0]))

    ##########################################################
    ### At Rule: media query

    def p_media(self, p):
        """media : MEDIA_SYM media_query_list '{' ruleset '}'
                 | MEDIA_SYM media_query_list '{' '}'
                 | MEDIA_SYM '{' '}'
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND MEDIA LIST: {0}".format(p[0]))

    def p_media_query_list(self, p):
        """media_query_list : media_query ',' media_query_list
                            | media_query
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND MEDIA LIST: {0}".format(p[0]))

    def p_media_query(self, p):
        """media_query : ONLY media_expressions
                       | NOT media_expressions
                       | media_expressions
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND MEDIA QUERY: {0}".format(p[0]))

    def p_media_expressions(self, p):
        """media_expressions : media_expression AND media_expressions
                             | media_expression
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND MEDIA EXPRESSIONS: {0}".format(p[0]))

    def p_media_expression(self, p):
        """media_expression : '(' IDENT ':' expr ')'
                            | '(' IDENT ')'
                            | IDENT
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND MEDIA EXPRESSION: {0}".format(p[0]))

    def p_expr(self, p):
        """expr : helper expr
                | helper
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND EXPR: {0}".format(p[0]))

    def p_helper(self, p):
        """helper : ',' term
                  | '\' term
                  | term
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND HELPER: {0}".format(p[0]))

    def p_unary_operator(self, p):
        """unary_operator : '+'
                          | '-'
                          |
        """
        p[0] = p[1]
        logging.debug("FOUND UNARY OPERATOR: {0}".format(p[0]))

    def p_term(self, p):
        """term : unary_operator NUMBER
                | unary_operator PERCENTAGE
                | unary_operator DIMENSION
                | STRING
                | IDENT
                | URI
                | function
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND TERM: {0}".format(p[0]))

    def p_function(self, p):
        """function : FUNCTION expr ')'"""
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND TERM: {0}".format(p[0]))

    ##########################################################
    ### Ruleset

    def p_ruleset(self, p):
        """ruleset : selector_group '{' declarations '}'
                   | selector_group '{' '}'
                   | '{' declarations '}'
                   | '{' '}'
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND RULESET: {0}".format(p[0]))

    def p_declarations(self, p):
        """declarations : declaration ';' declarations
                        | declaration ';'
                        | declaration
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND DECLARATIONS: {0}".format(p[0]))

    def p_declaration(self, p):
        """declaration : property ':' values"""
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND DECLARATION: {0}".format(p[0]))

    def p_property(self, p):
        """property : IDENT"""
        p[0] = p[1]
        logging.debug("FOUND PROPERTY: {0}".format(p[0]))

    def p_values(self, p):
        """values : value ',' values
                  | value values
                  | value
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND VALUES: {0}".format(p[0]))

    def p_value(self, p):
        """value : any"""
        #        | block
        #        | ATKEYWORD
        p[0] = p[1]
        logging.debug("FOUND VALUE: {0}".format(p[0]))

    def p_anys(self, p):
        """anys : any ',' anys
                | any anys
                | any
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND VALUES: {0}".format(p[0]))

    def p_any(self, p):
        """any : DIMENSION
               | URI
               | PERCENTAGE
               | IDENT
               | STRING
               | NUMBER
               | HASH
               | INCLUDES
               | DASHMATCH
               | FUNCTION anys ')'
               | FUNCTION ')'
               | '(' anys ')'
               | '(' ')'
               | '[' anys ']'
               | '[' ']'
        """
        # UNICODE-RANGE, DELIM
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND ANY: {0}".format(p[0]))

    ##########################################################
    ### Selectors, Selector Groups, Simple Selector Sequences

    def p_selector_group(self, p):
        """selector_group : selector ',' selector_group
                          | selector
        """
        #                 | selector selector_group
        self.selectors.append(p[1])
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND SELECTOR GROUP: {0}".format(p[0]))

    def p_selector(self, p):
        """selector : simple_selector_sequence
                    | simple_selector_sequence combinator selector
                    | simple_selector_sequence selector
        """
        p[0] = reduce(lambda x, y: x + " " + y, p[1:])
        logging.debug("FOUND SELECTOR: {0}".format(p[0]))

    def p_combinator(self, p):
        """combinator : '+'
                      | '>'
                      | '~'
        """
        # | S
        p[0] = p[1]
        logging.debug("FOUND COMBINATOR: {0}".format(p[0]))

    def p_simple_selector_sequence(self, p):
        """simple_selector_sequence : type_selector sss_types
                                    | type_selector
                                    | universal_selector sss_types
                                    | universal_selector
                                    | sss_types
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND SIMPLE SELECTOR SEQUENCE: {0}".format(p[0]))

    def p_sss_types(self, p):
        """sss_types : sss_type sss_types
                     | sss_type
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND SIMPLE SELECTOR SEQUENCE TYPES: {0}".format(p[0]))

    def p_sss_type(self, p):
        """sss_type : HASH
                    | class
                    | attrib
                    | pseudo
                    | negation
        """
        p[0] = p[1]
        logging.debug("FOUND SIMPLE SELECTOR SEQUENCE TYPE: {0}".format(p[0]))

    def p_type_selector(self, p):
        """type_selector : namespace_prefix element_name
                         | element_name
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND TYPE SELECTOR: {0}".format(p[0]))

    def p_universal_selector(self, p):
        """universal_selector : namespace_prefix '*'
                              | '*'
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND UNIVERSAL SELECTOR: {0}".format(p[0]))

    def p_namespace_prefix(self, p):
        """namespace_prefix : IDENT '|'
                            | '*' '|'
                            | '|'
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND NAMESPACE PREFIX: {0}".format(p[0]))

    def p_element_name(self, p):
        """element_name : IDENT"""
        p[0] = p[1]
        logging.debug("FOUND ELEMENT NAME: {0}".format(p[0]))

    def p_class(self, p):
        """class : '.' IDENT"""
        p[0] = p[1] + p[2]
        logging.debug("FOUND CLASS: {0}".format(p[0]))

    #######################################################
    ### Pseudo, Expression, Negation

    def p_pseudo(self, p):
        """pseudo : ':' ':' IDENT
                  | ':' ':' functional_pseudo
                  | ':' IDENT
                  | ':' functional_pseudo
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND PSEUDO: {0}".format(p[0]))

    def p_functional_pseudo(self, p):
        """functional_pseudo : FUNCTION expressions ')'"""
        p[0] = p[1] + p[2] + p[3]
        logging.debug("FOUND PSEUDO FUNCTION: {0}".format(p[0]))

    def p_expressions(self, p):
        """expressions : expression expressions
                       | expression
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND EXPRESSIONS: {0}".format(p[0]))

    def p_expression(self, p):
        """expression : '+'
                      | '-'
                      | NUMBER
                      | STRING
                      | IDENT
        """
        #             | DIMENSION
        p[0] = p[1]
        logging.debug("FOUND EXPRESSION {0}".format(p[0]))

    def p_negation(self, p):
        """negation : ':' NOTFUNC negation_arg ')'"""
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND NEGATION: {0}".format(p[0]))

    def p_negation_arg(self, p):
        """negation_arg : type_selector
                        | universal_selector
                        | HASH
                        | class
                        | attrib
                        | pseudo
        """
        p[0] = p[1]
        logging.debug("FOUND NEGATION ARG: {0}".format(p[0]))

    ######################################################
    ### Attributes

    def p_attrib(self, p):
        """attrib : '[' namespace_prefix IDENT attrib_value ']'
                  | '[' namespace_prefix IDENT ']'
                  | '[' IDENT attrib_value ']'
                  | '[' IDENT ']'
        """
        p[0] = reduce(lambda x, y: x + y, p[1:])
        logging.debug("FOUND ATTRIBUTE: {0}".format(p[0]))

    def p_attrib_value(self, p):
        """attrib_value : attrib_selector_op IDENT
                        | attrib_selector_op STRING
        """
        p[0] = p[1] + p[2]
        logging.debug("FOUND ATTRIBUTE VALUE: {0}".format(p[0]))

    def p_attrib_selector_op(self, p):
        """attrib_selector_op : PREFIXMATCH
                              | SUFFIXMATCH
                              | SUBSTRINGMATCH
                              | '='
                              | INCLUDES
                              | DASHMATCH
        """
        p[0] = p[1]
        logging.debug("FOUND SELECTOR OP: {0}".format(p[0]))

    def p_error(self, p):
        logging.debug("Syntax error at '{0}'".format(p))
Пример #2
0
 def __init__(self, debug=False):
     self.debug = debug
     self.lexer = CSSLexer(debug=self.debug)
     self.tokens = self.lexer.tokens
     self.parser = yacc.yacc(module=self, debug=debug, write_tables=0)
     self.selectors = []