[Zope-Checkins] CVS: Zope/lib/python/Products/PluginIndexes/TextIndexNG/queryparser - queryparser.py:1.1.2.12

Andreas Jung andreas@digicool.com
Sat, 16 Feb 2002 08:35:51 -0500


Update of /cvs-repository/Zope/lib/python/Products/PluginIndexes/TextIndexNG/queryparser
In directory cvs.zope.org:/tmp/cvs-serv14698

Modified Files:
      Tag: ajung-textindexng-branch
	queryparser.py 
Log Message:
- integrated grammar and terminals definition. 
- code cleanup


=== Zope/lib/python/Products/PluginIndexes/TextIndexNG/queryparser/queryparser.py 1.1.2.11 => 1.1.2.12 ===
 """
 QueryParser class
+
+This module defines the grammar for TextIndexNG queries. It uses the
+kwParsing module. To rebuild the grammer, start this script using the
+'-g' option.
 """
 
 __version__ = '$Id$'
 
-
-import TextIndexG
+import os
 from Collector import Collector
 
+
+if not '__file__' in dir(): # HACK !
+    __file__ = os.getcwd()
+
+COMPILEDFILENAME     = os.path.join(os.path.dirname(__file__), "TextIndexG.py")
+MARSHALLEDFILENAME   = os.path.join(os.path.dirname(__file__), "TextIndexG.mar")
+
+GRAMMARSTRING ="""
+       expr :: 
+
+       @R R1                 ::  expr >> factor
+       @R R2                 ::  expr >> factor or factor
+       @R R3                 ::  expr >> factor factor
+
+       @R R4                 ::  factor >> term
+       @R R5a                ::  factor >> term and term
+       @R R5b                ::  factor >> term near term
+       @R R5c                ::  factor >> term quote term
+
+       @R R6a                ::  term   >> prox_str 
+       @R R6b                ::  term   >> str 
+       @R R7                 ::  term   >> openp expr closep
+"""
+
+Terminals = (
+       ('openp',      '\(',             'addOpenParens'),
+       ('closep',     '\)',             'addCloseParens'),
+       ('and',        'and',            'addOp'),
+       ('near',       'near',           'addOp'),
+       ('quote',      'quote',          'addOp'),
+       ('or',         'or',             'addOp'),
+       ('str',        '[\w\*\?]*',      'addWord'),
+       ('prox_str',   '#[\w\*\?]*',     'addProximityWord'),
+)
+
+
+def DeclareTerminals(Grammar):
+
+    for term, reg, f  in Terminals:
+        Grammar.Addterm(term, reg, '')
+
+def GrammarBuild():
+    """ generatesthe grammar and dump it to a file"""
+
+    import kjParseBuild
+
+    TextIndexG = kjParseBuild.NullCGrammar()
+    TextIndexG.SetCaseSensitivity(0) # grammar is not case sensitive for keywords
+    DeclareTerminals(TextIndexG)
+    TextIndexG.Nonterms("expr term factor ")
+    TextIndexG.Declarerules(GRAMMARSTRING)
+    TextIndexG.Compile()
+
+    print "dumping as python to "+COMPILEDFILENAME
+    outfile = open(COMPILEDFILENAME, "w")
+    TextIndexG.Reconstruct("TextIndexG",outfile,"GRAMMAR")
+    outfile.close()
+
+    print "dumping as binary to "+MARSHALLEDFILENAME
+    outfile = open(MARSHALLEDFILENAME, "w")
+    TextIndexG.MarshalDump(outfile)
+    outfile.close()
+
+    return TextIndexG
+
+try:
+    import TextIndexG
+except:
+    GrammarBuild()
+    import TextIndexG
+
+
 class QueryParser(Collector):
 
     """Query parser takes a TextIndexNG query strings and transforms it
        into a Python expression to be evaluated.
     """ 
 
-    QUOTEREGEX     = 'quote'
-    NEARREGEX      = 'near'
-    ANDREGEX       = 'and'
-    ORREGEX        = 'or'
-    STRREGEX       = '[\w\*\?]*'
-    OPENPREGEX     = '\('
-    CLOSEPREGEX    = '\)'
-
     def __init__(self):
 
         Collector.__init__(self)
@@ -48,13 +115,8 @@
 
     
     def DeclareTerminals(self):
-        self.TextIndexG.Addterm("openp",  self.OPENPREGEX,  self.addOpenParens)
-        self.TextIndexG.Addterm("closep", self.CLOSEPREGEX, self.addCloseParens)
-        self.TextIndexG.Addterm("and",    self.ANDREGEX,    self.addOp)
-        self.TextIndexG.Addterm("near",   self.NEARREGEX,   self.addOp)
-        self.TextIndexG.Addterm("quote",  self.QUOTEREGEX,  self.addOp)
-        self.TextIndexG.Addterm("or",     self.ORREGEX,     self.addOp)
-        self.TextIndexG.Addterm("str",    self.STRREGEX,    self.addWord)
+        for term, reg, f  in Terminals:
+            self.TextIndexG.Addterm(term, reg, getattr(self,f) )
 
 
     def BindRules(self): pass
@@ -70,33 +132,42 @@
 def test():
 
     import os, sys, re,traceback, atexit
-    import readline
 
     histfile = os.path.expanduser('~/.pyhist')
     try:
+        import readline
         readline.read_history_file(histfile)
-    except IOError: pass
-    atexit.register(readline.write_history_file,histfile)
-
-    print "loading grammar as python"
+        atexit.register(readline.write_history_file,histfile)
+    except: pass
 
     Context = { }
 
-
+    print "entering interactive query mode:"
     while 1:
 
         s = raw_input('> ')
-
         print s  
 
         try:
+
             P = QueryParser()
             res = P(s)        
-
             print 'res:',res
+
         except:
             traceback.print_exc()
 
+
 if __name__ == '__main__':
-    test()
+
+    import sys
+
+    if len(sys.argv)>1 and sys.argv[1]=='-g':
+
+        print "(re)generating the TextIndexG grammar in file TextIndexG.py"
+        Dummy = GrammarBuild()
+        print "(re)generation done."
+
+    else:
+        test()