[Zope-CVS] CVS: Products/ZCTextIndex - IQueryParser.py:1.1.2.1 QueryParser.py:1.1.2.1
Guido van Rossum
guido@python.org
Tue, 30 Apr 2002 16:20:15 -0400
Update of /cvs-repository/Products/ZCTextIndex
In directory cvs.zope.org:/tmp/cvs-serv17061
Added Files:
Tag: TextIndexDS9-branch
IQueryParser.py QueryParser.py
Log Message:
Query Parser.
=== Added File Products/ZCTextIndex/IQueryParser.py ===
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Query Parser Interface."""
import Interface
class IQueryParser(Interface.Base):
"""Interface for Query Parsers."""
def parseQuery(query):
"""Parse a query string.
Return a parse tree (which implements IQueryParseTree).
"""
class IQueryParseTree(Interface.Base):
"""Interface for parse trees returned by parseQuery()."""
def nodeType():
"""Return the node type.
This is one of 'AND', 'OR', 'NOT', or 'ATOM'.
"""
def getValue():
"""Return a node-type specific value.
For node type: Return:
'AND' a list of parse trees
'OR' a list of parse trees
'NOT' a parse tree
'ATOM' a string
"""
=== Added File Products/ZCTextIndex/QueryParser.py ===
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Query Parser."""
import re
class ParseError(Exception):
pass
class QueryParser:
def __init__(self):
pass # This parser has no persistent state
def parseQuery(self, query):
# Lexical analysis
tokens = re.findall(r"[()]|[^\s()]+", query)
self.__tokens = tokens
self.__tokens.append(None) # EOF token
self.__index = 0
# Syntactical analysis
tree = self._parseOrExpr()
self._require(None)
return tree
# Recursive descent parser
def _require(self, token):
if not self._check(token):
t = self.__tokens[self.__index]
raise ParseError, "Token %r required, %r found" % (token, t)
def _check(self, token):
if self.__tokens[self.__index] == token:
self.__index += 1
return 1
else:
return 0
def _get(self):
t = self.__tokens[self.__index]
self.__index += 1
return t
def _parseOrExpr(self):
L = []
L.append(self._parseAndExpr())
while self._check("OR"):
L.append(self._parseAndExpr())
if len(L) == 1:
return L[0]
else:
return OrNode(L)
def _parseAndExpr(self):
L = []
L.append(self._parseNotExpr())
while self._check("AND"):
L.append(self._parseNotExpr())
if len(L) == 1:
return L[0]
else:
return AndNode(L)
def _parseNotExpr(self):
if self._check("NOT"):
return NotNode(self._parseTerm())
else:
return self._parseTerm()
def _parseTerm(self):
if self._check("("):
tree = self._parseOrExpr()
self._require(")")
else:
t = self._get()
if t in [")", "AND", "OR", "NOT", None]:
raise ParseError("Token %r not expected" % t)
tree = AtomNode(t)
return tree
class ParseTreeNode:
_nodeType = None
def __init__(self, value):
self._value = value
def nodeType(self):
return self._nodeType
def getValue(self):
return self._value
class NotNode(ParseTreeNode):
_nodeType = "NOT"
class AndNode(ParseTreeNode):
_nodeType = "AND"
class OrNode(ParseTreeNode):
_nodeType = "OR"
class AtomNode(ParseTreeNode):
_nodeType = "ATOM"