Пример #1
0
    def parse_expression(self, expression):
        """
        Uses postfix evaluation of filter string.
        http://www.sunshine2k.de/coding/java/SimpleParser/SimpleParser.html
        """
        try:
            f = StringIO(expression)
            self._scanner = Scanner(self._lexicon, f, "query")

            while True:
                token = self._scanner.read()

                if token[0] in self._mapper:
                    self._mapper[token[0]](token[1])

                elif token[0] is None:
                    break

            if self._parenthesis_count != 0:
                raise InvalidQueryError("Invalid parenthesis count")

            while len(self._operator_stack) > 0:
                self._postfix_result.append(self._operator_stack.pop())

        except UnrecognizedInput as e:
            raise InvalidQueryError(str(e))

        finally:
            f.close()
Пример #2
0
    def parse_expression(self, expression):
        """
        Uses postfix evaluation of filter string.
        http://www.sunshine2k.de/coding/java/SimpleParser/SimpleParser.html
        """
        try:
            f = StringIO.StringIO(expression)
            self._scanner = Scanner(self._lexicon, f, 'query')

            while 1:
                token = self._scanner.read()

                if token[0] in self._mapper:
                    self._mapper[token[0]](token[1])

                elif token[0] is None:
                    break

            if self._parenthesis_count != 0:
                raise InvalidQueryError('Invalid parenthesis count')

            while len(self._operator_stack) > 0:
                self._postfix_result.append(self._operator_stack.pop())

        except UnrecognizedInput as e:
            raise InvalidQueryError(str(e))

        finally:
            f.close()
Пример #3
0
 def __init__(self, idl_text, name):
     f = cStringIO.StringIO(idl_text)
     Scanner.__init__(self, self.lex, f, name)
     self.parsed = [ ]
     self.errors = [ ]
     self.types = { }
     self.imports = { }
     self.comment = None
     self.cur = None
     self.namespace = None
     self.searchPath = None
     self.idl_text = idl_text
     self.name = name
     if name:
         searchPath = os.path.dirname(os.path.abspath(name))
         if os.environ.has_key('BARRISTER_PATH'):
             searchPath = searchPath + os.pathsep + os.environ['BARRISTER_PATH']
         self.searchPath = searchPath
Пример #4
0
 def begin(self, state_name):
     Scanner.begin(self, state_name)
Пример #5
0
 def __init__(self, info, name='<default>'):
     Scanner.__init__(self, self.lexicon, info, name)
Пример #6
0
class BaseQueryParser(object):
    """
    Base Query Parser class provides a basic implementation to parse the `query` argument
    i.e. Basic WHERE clause as used in SQL.

    Note: The base class only provides a partial implementation of the SQL where clause.
    """

    def __init__(self, expression=None):
        self.expression = expression

        self._state = 0
        self._parenthesis_count = 0

        self._operator_stack = []
        self._postfix_result = []
        self._condition = [0, 0, 0]
        self._in_collection = None
        self._identifiers = set()

        self._scanner = None
        self._lexicon = None
        self._mapper = None

        self._init()

        self.parse_expression(expression)

    def _init(self):
        comma = Str(",")
        whitespace = Rep1(Any(" \t\n"))
        open_parenthesis = Str("(")
        close_parenthesis = Str(")")

        letter = Range("AZaz")
        digit = Range("09")
        prefix = letter + Rep(letter) + Str(".")

        identifier = prefix + letter + Rep(letter | digit | Str("_"))
        comparators = NoCase(Str("=", "!=", "<", "<=", ">", ">=", "like", "in"))
        string_literal = Str("'") + Rep(AnyBut("'") | Str(" ") | Str("\\'")) + Str("'")
        integer_literal = Opt(Str("+", "-")) + Rep1(digit)
        float_literal = Opt(Str("+", "-")) + Rep1(digit) + Str(".") + Rep1(digit)

        operands = NoCase(Str("AND", "OR"))
        null = Str("NULL")

        COMMA = 1
        OPEN_PARENTHESIS = 2
        CLOSE_PARENTHESIS = 3
        NULL = 4
        OPERAND = 5
        COMPARATOR = 6
        STRING_LITERAL = 7
        INTEGER_LITERAL = 8
        FLOAT_LITERAL = 9
        IDENTIFIER = 10

        self._lexicon = Lexicon(
            [
                (whitespace, IGNORE),
                (comma, COMMA),
                (open_parenthesis, OPEN_PARENTHESIS),
                (close_parenthesis, CLOSE_PARENTHESIS),
                (null, NULL),
                (operands, OPERAND),
                (comparators, COMPARATOR),
                (string_literal, STRING_LITERAL),
                (integer_literal, INTEGER_LITERAL),
                (float_literal, FLOAT_LITERAL),
                (identifier, IDENTIFIER),
            ]
        )

        self._mapper = {
            COMMA: self.comma_handler,
            OPEN_PARENTHESIS: self.open_parenthesis_handler,
            CLOSE_PARENTHESIS: self.close_parenthesis_handler,
            NULL: self.null_handler,
            OPERAND: self.operand_handler,
            COMPARATOR: self.comparator_handler,
            STRING_LITERAL: self.string_literal_handler,
            INTEGER_LITERAL: self.integer_literal_handler,
            FLOAT_LITERAL: self.float_literal_handler,
            IDENTIFIER: self.identifier_handler,
        }

    @property
    def identifiers(self):
        return self._identifiers

    def parse_expression(self, expression):
        """
        Uses postfix evaluation of filter string.
        http://www.sunshine2k.de/coding/java/SimpleParser/SimpleParser.html
        """
        try:
            f = StringIO(expression)
            self._scanner = Scanner(self._lexicon, f, "query")

            while True:
                token = self._scanner.read()

                if token[0] in self._mapper:
                    self._mapper[token[0]](token[1])

                elif token[0] is None:
                    break

            if self._parenthesis_count != 0:
                raise InvalidQueryError("Invalid parenthesis count")

            while len(self._operator_stack) > 0:
                self._postfix_result.append(self._operator_stack.pop())

        except UnrecognizedInput as e:
            raise InvalidQueryError(str(e))

        finally:
            f.close()

    def comma_handler(self, text):
        if self._state == 3:
            return

        file, line, char_pos = self._scanner.position()
        msg = "Invalid token: Line: %d Char: %d" % (line, char_pos)
        raise InvalidQueryError(msg)

    def open_parenthesis_handler(self, text):
        if self._state == 3:
            self._in_collection = []
            return

        self._parenthesis_count += 1
        self._operator_stack.append("(")

    def close_parenthesis_handler(self, text):
        if self._state == 3:
            self._condition[2] = self._in_collection
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
            return

        if self._parenthesis_count <= 0:
            file, line, char_pos = self._scanner.position()
            msg = "Invalid parenthesis order: Line: %d Char: %d" % (line, char_pos)
            raise InvalidQueryError(msg)
        else:
            self._parenthesis_count -= 1

        while len(self._operator_stack) > 0:
            operator = self._operator_stack.pop()

            if operator == "(":
                break
            else:
                self._postfix_result.append(operator)

    def null_handler(self, text):
        if self._state == 2:
            self._condition[2] = None
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
        else:
            file, line, char_pos = self._scanner.position()
            msg = "NULL found out of order: Line: %d Char: %d" % (line, char_pos)
            raise InvalidQueryError(msg)

    def operand_handler(self, text):
        self._operator_stack.append(text.upper())

    def comparator_handler(self, text):
        if self._state == 1:
            self._condition[1] = text.upper()
            self._state = 3 if self._condition[1] == "IN" else 2
        else:
            file, line, char_pos = self._scanner.position()
            msg = "Comparator %r found out of order: Line: %d Char: %d" % (
                text,
                line,
                char_pos,
            )
            raise InvalidQueryError(msg)

    def string_literal_handler(self, text):
        if self._state == 2:
            self._condition[2] = text.strip("'")
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
        elif self._state == 3:
            self._in_collection.append(text.strip("'"))
        else:
            file, line, char_pos = self._scanner.position()
            msg = "String literal %r found out of order: Line: %d Char: %d" % (
                text,
                line,
                char_pos,
            )
            raise InvalidQueryError(msg)

    def integer_literal_handler(self, text):
        if self._state == 2:
            self._condition[2] = text.strip()
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
        elif self._state == 3:
            self._in_collection.append(text.strip())
        else:
            file, line, char_pos = self._scanner.position()
            msg = "Integer literal %s found out of order: Line: %d Char: %d" % (
                text,
                line,
                char_pos,
            )
            raise InvalidQueryError(msg)

    def float_literal_handler(self, text):
        if self._state == 2:
            self._condition[2] = text.strip()
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
        elif self._state == 3:
            self._in_collection.append(text.strip())
        else:
            file, line, char_pos = self._scanner.position()
            msg = "Integer literal %d found out of order: Line: %d Char: %d" % (
                text,
                line,
                char_pos,
            )
            raise InvalidQueryError(msg)

    def identifier_handler(self, text):
        if self._state == 0:
            self._condition[0] = text
            self._identifiers.add(text)
            self._state = 1
        elif self._state == 2:
            self._condition[2] = ("I", text)
            self._postfix_result.append(tuple(self._condition))
            self._identifiers.add(text)
            self._state = 0
        else:
            file, line, char_pos = self._scanner.position()
            msg = "Field %r found out of order: Line: %d Char: %d" % (
                text,
                line,
                char_pos,
            )
            raise InvalidQueryError(msg)

    def evaluate(self):
        return self._postfix_result

    def clear(self):
        self._state = 0
        self._parenthesis_count = 0

        self._operator_stack = []
        self._postfix_result = []
        self._condition = [0, 0, 0]
        self._identifiers = set()

        self._scanner = None

    def __str__(self):
        comparator = {
            "=": "__eq__",
            "!=": "__ne__",
            "<": "__lt__",
            "<=": "__le__",
            ">": "__gt__",
            ">=": "__ge__",
            "LIKE": "like",
            "IN": "in_",
        }

        operators = {"AND": "and_", "OR": "or_"}

        operands = []

        def condition_expansion(expr, field):
            operands.append("%s.%s ( %s )" % (field, comparator[expr[1]], expr[2]))

        for token in self._postfix_result:
            if isinstance(token, tuple):
                identifier = token[0]
                condition_expansion(token, identifier)

            elif isinstance(token, str) or isinstance(token, unicode):
                operand_2 = operands.pop()
                operand_1 = operands.pop()

                if token in operators:
                    operands.append(
                        "%s ( %s, %s )" % (operators[token], operand_1, operand_2)
                    )

        return operands.pop()
Пример #7
0
 def begin(self, state_name):
     Scanner.begin(self, state_name)
Пример #8
0
 def __init__(self, info, name='<default>'):
     Scanner.__init__(self, self.lexicon, info, name)
Пример #9
0
 def __init__(self, f):
     Scanner.__init__(self, self.lexicon, f)
     self.stack = []
     self.begin('start')
     self.result = 0
Пример #10
0
class BaseQueryParser(object):
    """
    Base Query Parser class provides a basic implementation to parse the `query` argument
    i.e. Basic WHERE clause as used in SQL.

    Note: The base class only provides a partial implementation of the SQL where clause.
    """

    def __init__(self, expression=None):
        self.expression = expression

        self._state = 0
        self._parenthesis_count = 0

        self._operator_stack = []
        self._postfix_result = []
        self._condition = [0, 0, 0]
        self._in_collection = None
        self._identifiers = set()

        self._scanner = None
        self._lexicon = None
        self._mapper = None

        self._init()

        self.parse_expression(expression)

    def _init(self):
        comma = Str(',')
        whitespace = Rep1(Any(' \t\n'))
        open_parenthesis = Str('(')
        close_parenthesis = Str(')')

        letter = Range('AZaz')
        digit = Range('09')
        prefix = letter + Rep(letter) + Str('.')

        identifier = prefix + letter + Rep(letter | digit | Str('_'))
        comparators = NoCase(Str('=', '!=', '<', '<=', '>', '>=', 'like', 'in'))
        string_literal = Str('\'') + Rep(AnyBut('\'') | Str(' ') | Str("\\'")) + Str('\'')
        integer_literal = Opt(Str('+', '-')) + Rep1(digit)
        float_literal = Opt(Str('+', '-')) + Rep1(digit) + Str('.') + Rep1(digit)

        operands = NoCase(Str('AND', 'OR'))
        null = Str('NULL')

        COMMA = 1
        OPEN_PARENTHESIS = 2
        CLOSE_PARENTHESIS = 3
        NULL = 4
        OPERAND = 5
        COMPARATOR = 6
        STRING_LITERAL = 7
        INTEGER_LITERAL = 8
        FLOAT_LITERAL = 9
        IDENTIFIER = 10

        self._lexicon = Lexicon([
            (whitespace, IGNORE),
            (comma, COMMA),
            (open_parenthesis, OPEN_PARENTHESIS),
            (close_parenthesis, CLOSE_PARENTHESIS),
            (null, NULL),
            (operands, OPERAND),
            (comparators, COMPARATOR),
            (string_literal, STRING_LITERAL),
            (integer_literal, INTEGER_LITERAL),
            (float_literal, FLOAT_LITERAL),
            (identifier, IDENTIFIER)
        ])

        self._mapper = {
            COMMA: self.comma_handler,
            OPEN_PARENTHESIS: self.open_parenthesis_handler,
            CLOSE_PARENTHESIS: self.close_parenthesis_handler,
            NULL: self.null_handler,
            OPERAND: self.operand_handler,
            COMPARATOR: self.comparator_handler,
            STRING_LITERAL: self.string_literal_handler,
            INTEGER_LITERAL: self.integer_literal_handler,
            FLOAT_LITERAL: self.float_literal_handler,
            IDENTIFIER: self.identifier_handler,
        }

    @property
    def identifiers(self):
        return self._identifiers

    def parse_expression(self, expression):
        """
        Uses postfix evaluation of filter string.
        http://www.sunshine2k.de/coding/java/SimpleParser/SimpleParser.html
        """
        try:
            f = StringIO.StringIO(expression)
            self._scanner = Scanner(self._lexicon, f, 'query')

            while 1:
                token = self._scanner.read()

                if token[0] in self._mapper:
                    self._mapper[token[0]](token[1])

                elif token[0] is None:
                    break

            if self._parenthesis_count != 0:
                raise InvalidQueryError('Invalid parenthesis count')

            while len(self._operator_stack) > 0:
                self._postfix_result.append(self._operator_stack.pop())

        except UnrecognizedInput as e:
            raise InvalidQueryError(str(e))

        finally:
            f.close()

    def comma_handler(self, text):
        if self._state == 3:
            return

        file, line, char_pos = self._scanner.position()
        msg = 'Invalid token: Line: %d Char: %d' % (line, char_pos)
        raise InvalidQueryError(msg)

    def open_parenthesis_handler(self, text):
        if self._state == 3:
            self._in_collection = []
            return

        self._parenthesis_count += 1
        self._operator_stack.append('(')

    def close_parenthesis_handler(self, text):
        if self._state == 3:
            self._condition[2] = self._in_collection
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
            return

        if self._parenthesis_count <= 0:
            file, line, char_pos = self._scanner.position()
            msg = 'Invalid parenthesis order: Line: %d Char: %d' % (line, char_pos)
            raise InvalidQueryError(msg)
        else:
            self._parenthesis_count -= 1

        while len(self._operator_stack) > 0:
            operator = self._operator_stack.pop()

            if operator == '(':
                break
            else:
                self._postfix_result.append(operator)

    def null_handler(self, text):
        if self._state == 2:
            self._condition[2] = None
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
        else:
            file, line, char_pos = self._scanner.position()
            msg = 'NULL found out of order: Line: %d Char: %d' % (line, char_pos)
            raise InvalidQueryError(msg)

    def operand_handler(self, text):
        self._operator_stack.append(text.upper())

    def comparator_handler(self, text):
        if self._state == 1:
            self._condition[1] = text.upper()
            self._state = 3 if self._condition[1] == 'IN' else 2
        else:
            file, line, char_pos = self._scanner.position()
            msg = 'Comparator %r found out of order: Line: %d Char: %d' % (text, line, char_pos)
            raise InvalidQueryError(msg)

    def string_literal_handler(self, text):
        if self._state == 2:
            self._condition[2] = text.strip("'")
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
        elif self._state == 3:
            self._in_collection.append(text.strip("'"))
        else:
            file, line, char_pos = self._scanner.position()
            msg = 'String literal %r found out of order: Line: %d Char: %d' % (text, line, char_pos)
            raise InvalidQueryError(msg)

    def integer_literal_handler(self, text):
        if self._state == 2:
            self._condition[2] = text.strip()
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
        elif self._state == 3:
            self._in_collection.append(text.strip())
        else:
            file, line, char_pos = self._scanner.position()
            msg = 'Integer literal %s found out of order: Line: %d Char: %d' % (text, line, char_pos)
            raise InvalidQueryError(msg)

    def float_literal_handler(self, text):
        if self._state == 2:
            self._condition[2] = text.strip()
            self._postfix_result.append(tuple(self._condition))
            self._state = 0
        elif self._state == 3:
            self._in_collection.append(text.strip())
        else:
            file, line, char_pos = self._scanner.position()
            msg = 'Integer literal %d found out of order: Line: %d Char: %d' % (text, line, char_pos)
            raise InvalidQueryError(msg)

    def identifier_handler(self, text):
        if self._state == 0:
            self._condition[0] = text
            self._identifiers.add(text)
            self._state = 1
        elif self._state == 2:
            self._condition[2] = ('I', text)
            self._postfix_result.append(tuple(self._condition))
            self._identifiers.add(text)
            self._state = 0
        else:
            file, line, char_pos = self._scanner.position()
            msg = 'Field %r found out of order: Line: %d Char: %d' % (text, line, char_pos)
            raise InvalidQueryError(msg)

    def evaluate(self):
        return self._postfix_result

    def clear(self):
        self._state = 0
        self._parenthesis_count = 0

        self._operator_stack = []
        self._postfix_result = []
        self._condition = [0, 0, 0]
        self._identifiers = set()

        self._scanner = None

    def __str__(self):
        comparator = {
            '=': '__eq__',
            '!=': '__ne__',
            '<': '__lt__',
            '<=': '__le__',
            '>': '__gt__',
            '>=': '__ge__',
            'LIKE': 'like',
            'IN': 'in_'
        }

        operators = {
            'AND': 'and_',
            'OR': 'or_'
        }

        operands = []

        def condition_expansion(expr, field):
            operands.append('%s.%s ( %s )' % (field, comparator[expr[1]], expr[2]))

        for token in self._postfix_result:
            if isinstance(token, tuple):
                identifier = token[0]
                condition_expansion(token, identifier)

            elif isinstance(token, str) or isinstance(token, unicode):
                operand_2 = operands.pop()
                operand_1 = operands.pop()

                if token in operators:
                    operands.append('%s ( %s, %s )' % (operators[token], operand_1, operand_2))

        return operands.pop()
Пример #11
0
 def __init__(self, f):
     Scanner.__init__(self, self.lexicon, f)
     self.stack = []
     self.begin('start')
     self.result = 0