sbsv2/raptor/python/pyparsing.py
author raptorbot <raptorbot@systemstesthead.symbian.intra>
Fri, 18 Dec 2009 19:57:42 +0000
branchwip
changeset 117 ecf683438dc6
parent 3 e1eecf4d390d
permissions -rw-r--r--
Don't mess around with EPOCROOT until actually entering raptor so we know what the original was Put the original epocroot back on the front of the whatcomp output. This allows what output to be either relative or absolute depending on what your epocroot is.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     1
# module pyparsing.py
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     2
#
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     3
# Copyright (c) 2003-2006  Paul T. McGuire
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     4
#
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     5
# Permission is hereby granted, free of charge, to any person obtaining
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     6
# a copy of this software and associated documentation files (the
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     7
# "Software"), to deal in the Software without restriction, including
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     8
# without limitation the rights to use, copy, modify, merge, publish,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
     9
# distribute, sublicense, and/or sell copies of the Software, and to
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    10
# permit persons to whom the Software is furnished to do so, subject to
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    11
# the following conditions:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    12
#
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    13
# The above copyright notice and this permission notice shall be
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    14
# included in all copies or substantial portions of the Software.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    15
#
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    17
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    18
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    19
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    20
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    21
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    22
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    23
#
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    24
#from __future__ import generators
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    25
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    26
__doc__ = \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    27
"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    28
pyparsing module - Classes and methods to define and execute parsing grammars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    29
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    30
The pyparsing module is an alternative approach to creating and executing simple grammars, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    31
vs. the traditional lex/yacc approach, or the use of regular expressions.  With pyparsing, you
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    32
don't need to learn a new syntax for defining grammars or matching expressions - the parsing module 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    33
provides a library of classes that you use to construct the grammar directly in Python.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    34
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    35
Here is a program to parse "Hello, World!" (or any greeting of the form "<salutation>, <addressee>!")::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    36
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    37
    from pyparsing import Word, alphas
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    38
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    39
    # define grammar of a greeting
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    40
    greet = Word( alphas ) + "," + Word( alphas ) + "!" 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    41
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    42
    hello = "Hello, World!"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    43
    print hello, "->", greet.parseString( hello )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    44
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    45
The program outputs the following::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    46
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    47
    Hello, World! -> ['Hello', ',', 'World', '!']
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    48
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    49
The Python representation of the grammar is quite readable, owing to the self-explanatory 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    50
class names, and the use of '+', '|' and '^' operators.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    51
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    52
The parsed results returned from parseString() can be accessed as a nested list, a dictionary, or an 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    53
object with named attributes.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    54
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    55
The pyparsing module handles some of the problems that are typically vexing when writing text parsers:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    56
 - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello  ,  World  !", etc.)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    57
 - quoted strings
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    58
 - embedded comments
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    59
"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    60
__version__ = "1.4.5"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    61
__versionTime__ = "16 December 2006 07:20"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    62
__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    63
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    64
import string
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    65
import copy,sys
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    66
import warnings
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    67
import re
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    68
import sre_constants
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    69
import xml.sax.saxutils
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    70
#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    71
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    72
def _ustr(obj):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    73
    """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    74
       str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    75
       then < returns the unicode object | encodes it with the default encoding | ... >.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    76
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    77
    try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    78
        # If this works, then _ustr(obj) has the same behaviour as str(obj), so
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    79
        # it won't break any existing code.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    80
        return str(obj)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    81
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    82
    except UnicodeEncodeError, e:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    83
        # The Python docs (http://docs.python.org/ref/customization.html#l2h-182)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    84
        # state that "The return value must be a string object". However, does a
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    85
        # unicode object (being a subclass of basestring) count as a "string
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    86
        # object"?
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    87
        # If so, then return a unicode object:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    88
        return unicode(obj)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    89
        # Else encode it... but how? There are many choices... :)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    90
        # Replace unprintables with escape codes?
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    91
        #return unicode(obj).encode(sys.getdefaultencoding(), 'backslashreplace_errors')
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    92
        # Replace unprintables with question marks?
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    93
        #return unicode(obj).encode(sys.getdefaultencoding(), 'replace')
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    94
        # ...
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    95
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    96
def _str2dict(strg):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    97
    return dict( [(c,0) for c in strg] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    98
    #~ return set( [c for c in strg] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
    99
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   100
class _Constants(object):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   101
    pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   102
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   103
alphas     = string.lowercase + string.uppercase
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   104
nums       = string.digits
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   105
hexnums    = nums + "ABCDEFabcdef"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   106
alphanums  = alphas + nums    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   107
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   108
class ParseBaseException(Exception):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   109
    """base exception class for all parsing runtime exceptions"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   110
    __slots__ = ( "loc","msg","pstr","parserElement" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   111
    # Performance tuning: we construct a *lot* of these, so keep this
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   112
    # constructor as small and fast as possible        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   113
    def __init__( self, pstr, loc, msg, elem=None ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   114
        self.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   115
        self.msg = msg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   116
        self.pstr = pstr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   117
        self.parserElement = elem
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   118
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   119
    def __getattr__( self, aname ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   120
        """supported attributes by name are:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   121
            - lineno - returns the line number of the exception text
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   122
            - col - returns the column number of the exception text
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   123
            - line - returns the line containing the exception text
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   124
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   125
        if( aname == "lineno" ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   126
            return lineno( self.loc, self.pstr )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   127
        elif( aname in ("col", "column") ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   128
            return col( self.loc, self.pstr )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   129
        elif( aname == "line" ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   130
            return line( self.loc, self.pstr )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   131
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   132
            raise AttributeError, aname
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   133
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   134
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   135
        return "%s (at char %d), (line:%d, col:%d)" % ( self.msg, self.loc, self.lineno, self.column )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   136
    def __repr__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   137
        return _ustr(self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   138
    def markInputline( self, markerString = ">!<" ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   139
        """Extracts the exception line from the input string, and marks 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   140
           the location of the exception with a special symbol.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   141
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   142
        line_str = self.line
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   143
        line_column = self.column - 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   144
        if markerString:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   145
            line_str = "".join( [line_str[:line_column], markerString, line_str[line_column:]])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   146
        return line_str.strip()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   147
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   148
class ParseException(ParseBaseException):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   149
    """exception thrown when parse expressions don't match class"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   150
    """supported attributes by name are:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   151
        - lineno - returns the line number of the exception text
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   152
        - col - returns the column number of the exception text
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   153
        - line - returns the line containing the exception text
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   154
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   155
    pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   156
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   157
class ParseFatalException(ParseBaseException):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   158
    """user-throwable exception thrown when inconsistent parse content
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   159
       is found; stops all parsing immediately"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   160
    pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   161
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   162
class ReparseException(ParseBaseException):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   163
    def __init_( self, newstring, restartLoc ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   164
        self.newParseText = newstring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   165
        self.reparseLoc = restartLoc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   166
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   167
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   168
class RecursiveGrammarException(Exception):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   169
    """exception thrown by validate() if the grammar could be improperly recursive"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   170
    def __init__( self, parseElementList ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   171
        self.parseElementTrace = parseElementList
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   172
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   173
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   174
        return "RecursiveGrammarException: %s" % self.parseElementTrace
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   175
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   176
class ParseResults(object):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   177
    """Structured parse results, to provide multiple means of access to the parsed data:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   178
       - as a list (len(results))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   179
       - by list index (results[0], results[1], etc.)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   180
       - by attribute (results.<resultsName>)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   181
       """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   182
    __slots__ = ( "__toklist", "__tokdict", "__doinit", "__name", "__parent", "__accumNames" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   183
    def __new__(cls, toklist, name=None, asList=True, modal=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   184
        if isinstance(toklist, cls):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   185
            return toklist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   186
        retobj = object.__new__(cls)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   187
        retobj.__doinit = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   188
        return retobj
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   189
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   190
    # Performance tuning: we construct a *lot* of these, so keep this
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   191
    # constructor as small and fast as possible
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   192
    def __init__( self, toklist, name=None, asList=True, modal=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   193
        if self.__doinit:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   194
            self.__doinit = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   195
            self.__name = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   196
            self.__parent = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   197
            self.__accumNames = {}
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   198
            if isinstance(toklist, list):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   199
                self.__toklist = toklist[:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   200
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   201
                self.__toklist = [toklist]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   202
            self.__tokdict = dict()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   203
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   204
        # this line is related to debugging the asXML bug
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   205
        #~ asList = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   206
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   207
        if name:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   208
            if not modal:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   209
                self.__accumNames[name] = 0
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   210
            if isinstance(name,int):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   211
                name = _ustr(name) # will always return a str, but use _ustr for consistency
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   212
            self.__name = name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   213
            if not toklist in (None,'',[]):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   214
                if isinstance(toklist,basestring): 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   215
                    toklist = [ toklist ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   216
                if asList:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   217
                    if isinstance(toklist,ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   218
                        self[name] = (toklist.copy(),-1)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   219
                    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   220
                        self[name] = (ParseResults(toklist[0]),-1)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   221
                    self[name].__name = name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   222
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   223
                    try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   224
                        self[name] = toklist[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   225
                    except (KeyError,TypeError):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   226
                        self[name] = toklist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   227
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   228
    def __getitem__( self, i ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   229
        if isinstance( i, (int,slice) ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   230
            return self.__toklist[i]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   231
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   232
            if i not in self.__accumNames:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   233
                return self.__tokdict[i][-1][0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   234
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   235
                return ParseResults([ v[0] for v in self.__tokdict[i] ])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   236
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   237
    def __setitem__( self, k, v ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   238
        if isinstance(v,tuple):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   239
            self.__tokdict[k] = self.__tokdict.get(k,list()) + [v]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   240
            sub = v[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   241
        elif isinstance(k,int):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   242
            self.__toklist[k] = v
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   243
            sub = v
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   244
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   245
            self.__tokdict[k] = self.__tokdict.get(k,list()) + [(v,0)]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   246
            sub = v
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   247
        if isinstance(sub,ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   248
            sub.__parent = self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   249
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   250
    def __delitem__( self, i ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   251
        if isinstance(i,(int,slice)):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   252
            del self.__toklist[i]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   253
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   254
            del self._tokdict[i]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   255
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   256
    def __contains__( self, k ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   257
        return self.__tokdict.has_key(k)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   258
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   259
    def __len__( self ): return len( self.__toklist )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   260
    def __nonzero__( self ): return len( self.__toklist ) > 0
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   261
    def __iter__( self ): return iter( self.__toklist )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   262
    def keys( self ): 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   263
        """Returns all named result keys."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   264
        return self.__tokdict.keys()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   265
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   266
    def items( self ): 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   267
        """Returns all named result keys and values as a list of tuples."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   268
        return [(k,self[k]) for k in self.__tokdict.keys()]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   269
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   270
    def values( self ): 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   271
        """Returns all named result values."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   272
        return [ v[-1][0] for v in self.__tokdict.values() ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   273
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   274
    def __getattr__( self, name ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   275
        if name not in self.__slots__:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   276
            if self.__tokdict.has_key( name ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   277
                if name not in self.__accumNames:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   278
                    return self.__tokdict[name][-1][0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   279
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   280
                    return ParseResults([ v[0] for v in self.__tokdict[name] ])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   281
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   282
                return ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   283
        return None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   284
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   285
    def __add__( self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   286
        ret = self.copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   287
        ret += other
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   288
        return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   289
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   290
    def __iadd__( self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   291
        if other.__tokdict:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   292
            offset = len(self.__toklist)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   293
            addoffset = ( lambda a: (a<0 and offset) or (a+offset) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   294
            otheritems = other.__tokdict.items()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   295
            otherdictitems = [(k,(v[0],addoffset(v[1])) ) for (k,vlist) in otheritems for v in vlist]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   296
            for k,v in otherdictitems:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   297
                self[k] = v
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   298
                if isinstance(v[0],ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   299
                    v[0].__parent = self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   300
        self.__toklist += other.__toklist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   301
        self.__accumNames.update( other.__accumNames )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   302
        del other
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   303
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   304
       
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   305
    def __repr__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   306
        return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   307
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   308
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   309
        out = "["
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   310
        sep = ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   311
        for i in self.__toklist:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   312
            if isinstance(i, ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   313
                out += sep + _ustr(i)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   314
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   315
                out += sep + repr(i)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   316
            sep = ", "
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   317
        out += "]"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   318
        return out
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   319
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   320
    def _asStringList( self, sep='' ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   321
        out = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   322
        for item in self.__toklist:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   323
            if out and sep:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   324
                out.append(sep)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   325
            if isinstance( item, ParseResults ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   326
                out += item._asStringList()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   327
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   328
                out.append( _ustr(item) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   329
        return out
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   330
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   331
    def asList( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   332
        """Returns the parse results as a nested list of matching tokens, all converted to strings."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   333
        out = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   334
        for res in self.__toklist:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   335
            if isinstance(res,ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   336
                out.append( res.asList() )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   337
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   338
                out.append( res )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   339
        return out
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   340
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   341
    def asDict( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   342
        """Returns the named parse results as dictionary."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   343
        return dict( self.items() )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   344
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   345
    def copy( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   346
        """Returns a new copy of a ParseResults object."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   347
        ret = ParseResults( self.__toklist )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   348
        ret.__tokdict = self.__tokdict.copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   349
        ret.__parent = self.__parent
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   350
        ret.__accumNames.update( self.__accumNames )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   351
        ret.__name = self.__name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   352
        return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   353
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   354
    def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   355
        """Returns the parse results as XML. Tags are created for tokens and lists that have defined results names."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   356
        nl = "\n"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   357
        out = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   358
        namedItems = dict( [ (v[1],k) for (k,vlist) in self.__tokdict.items() for v in vlist ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   359
        nextLevelIndent = indent + "  "
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   360
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   361
        # collapse out indents if formatting is not desired
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   362
        if not formatted:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   363
            indent = ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   364
            nextLevelIndent = ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   365
            nl = ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   366
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   367
        selfTag = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   368
        if doctag is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   369
            selfTag = doctag
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   370
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   371
            if self.__name:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   372
                selfTag = self.__name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   373
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   374
        if not selfTag:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   375
            if namedItemsOnly:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   376
                return ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   377
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   378
                selfTag = "ITEM"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   379
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   380
        out += [ nl, indent, "<", selfTag, ">" ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   381
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   382
        worklist = self.__toklist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   383
        for i,res in enumerate(worklist):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   384
            if isinstance(res,ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   385
                if i in namedItems:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   386
                    out += [ res.asXML(namedItems[i], namedItemsOnly and doctag is None, nextLevelIndent,formatted)]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   387
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   388
                    out += [ res.asXML(None, namedItemsOnly and doctag is None, nextLevelIndent,formatted)]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   389
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   390
                # individual token, see if there is a name for it
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   391
                resTag = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   392
                if i in namedItems:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   393
                    resTag = namedItems[i]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   394
                if not resTag:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   395
                    if namedItemsOnly:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   396
                        continue
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   397
                    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   398
                        resTag = "ITEM"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   399
                xmlBodyText = xml.sax.saxutils.escape(_ustr(res))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   400
                out += [ nl, nextLevelIndent, "<", resTag, ">", xmlBodyText, "</", resTag, ">" ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   401
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   402
        out += [ nl, indent, "</", selfTag, ">" ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   403
        return "".join(out)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   404
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   405
    def __lookup(self,sub):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   406
        for k,vlist in self.__tokdict.items():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   407
            for v,loc in vlist:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   408
                if sub is v:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   409
                    return k
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   410
        return None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   411
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   412
    def getName(self):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   413
        """Returns the results name for this token expression."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   414
        if self.__name:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   415
            return self.__name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   416
        elif self.__parent:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   417
            par = self.__parent
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   418
            if par:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   419
                return par.__lookup(self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   420
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   421
                return None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   422
        elif (len(self) == 1 and 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   423
               len(self.__tokdict) == 1 and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   424
               self.__tokdict.values()[0][0][1] in (0,-1)):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   425
            return self.__tokdict.keys()[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   426
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   427
            return None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   428
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   429
    def dump(self,indent='',depth=0):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   430
        """Diagnostic method for listing out the contents of a ParseResults.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   431
           Accepts an optional indent argument so that this string can be embedded
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   432
           in a nested display of other data."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   433
        out = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   434
        out.append( indent+str(self.asList()) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   435
        keys = self.items()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   436
        keys.sort()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   437
        for k,v in keys:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   438
            if out:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   439
                out.append('\n')
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   440
            out.append( "%s%s- %s: " % (indent,('  '*depth), k) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   441
            if isinstance(v,ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   442
                if v.keys():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   443
                    #~ out.append('\n')
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   444
                    out.append( v.dump(indent,depth+1) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   445
                    #~ out.append('\n')
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   446
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   447
                    out.append(str(v))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   448
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   449
                out.append(str(v))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   450
        #~ out.append('\n')
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   451
        return "".join(out)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   452
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   453
    # add support for pickle protocol
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   454
    def __getstate__(self):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   455
        return ( self.__toklist,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   456
                 ( self.__tokdict.copy(),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   457
                   self.__parent,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   458
                   self.__accumNames,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   459
                   self.__name ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   460
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   461
    def __setstate__(self,state):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   462
        self.__toklist = state[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   463
        self.__tokdict, \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   464
        self.__parent, \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   465
        inAccumNames, \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   466
        self.__name = state[1]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   467
        self.__accumNames = {}
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   468
        self.__accumNames.update(inAccumNames)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   469
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   470
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   471
def col (loc,strg):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   472
    """Returns current column within a string, counting newlines as line separators.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   473
   The first column is number 1.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   474
   """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   475
    return (loc<len(strg) and strg[loc] == '\n') and 1 or loc - strg.rfind("\n", 0, loc)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   476
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   477
def lineno(loc,strg):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   478
    """Returns current line number within a string, counting newlines as line separators.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   479
   The first line is number 1.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   480
   """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   481
    return strg.count("\n",0,loc) + 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   482
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   483
def line( loc, strg ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   484
    """Returns the line of text containing loc within a string, counting newlines as line separators.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   485
       """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   486
    lastCR = strg.rfind("\n", 0, loc)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   487
    nextCR = strg.find("\n", loc)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   488
    if nextCR > 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   489
        return strg[lastCR+1:nextCR]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   490
    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   491
        return strg[lastCR+1:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   492
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   493
def _defaultStartDebugAction( instring, loc, expr ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   494
    print "Match",expr,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   495
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   496
def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   497
    print "Matched",expr,"->",toks.asList()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   498
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   499
def _defaultExceptionDebugAction( instring, loc, expr, exc ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   500
    print "Exception raised:", exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   501
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   502
def nullDebugAction(*args):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   503
    """'Do-nothing' debug action, to suppress debugging output during parsing."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   504
    pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   505
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   506
class ParserElement(object):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   507
    """Abstract base level parser element class."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   508
    DEFAULT_WHITE_CHARS = " \n\t\r"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   509
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   510
    def setDefaultWhitespaceChars( chars ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   511
        """Overrides the default whitespace chars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   512
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   513
        ParserElement.DEFAULT_WHITE_CHARS = chars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   514
    setDefaultWhitespaceChars = staticmethod(setDefaultWhitespaceChars)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   515
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   516
    def __init__( self, savelist=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   517
        self.parseAction = list()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   518
        self.failAction = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   519
        #~ self.name = "<unknown>"  # don't define self.name, let subclasses try/except upcall
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   520
        self.strRepr = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   521
        self.resultsName = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   522
        self.saveAsList = savelist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   523
        self.skipWhitespace = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   524
        self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   525
        self.copyDefaultWhiteChars = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   526
        self.mayReturnEmpty = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   527
        self.keepTabs = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   528
        self.ignoreExprs = list()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   529
        self.debug = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   530
        self.streamlined = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   531
        self.mayIndexError = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   532
        self.errmsg = ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   533
        self.modalResults = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   534
        self.debugActions = ( None, None, None )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   535
        self.re = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   536
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   537
    def copy( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   538
        """Make a copy of this ParserElement.  Useful for defining different parse actions
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   539
           for the same parsing pattern, using copies of the original parse element."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   540
        cpy = copy.copy( self )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   541
        cpy.parseAction = self.parseAction[:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   542
        cpy.ignoreExprs = self.ignoreExprs[:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   543
        if self.copyDefaultWhiteChars:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   544
            cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   545
        return cpy
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   546
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   547
    def setName( self, name ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   548
        """Define name for this expression, for use in debugging."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   549
        self.name = name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   550
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   551
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   552
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   553
    def setResultsName( self, name, listAllMatches=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   554
        """Define name for referencing matching tokens as a nested attribute 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   555
           of the returned parse results.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   556
           NOTE: this returns a *copy* of the original ParserElement object;
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   557
           this is so that the client can define a basic element, such as an
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   558
           integer, and reference it in multiple places with different names.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   559
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   560
        newself = self.copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   561
        newself.resultsName = name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   562
        newself.modalResults = not listAllMatches
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   563
        return newself
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   564
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   565
    def normalizeParseActionArgs( f ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   566
        """Internal method used to decorate parse actions that take fewer than 3 arguments,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   567
           so that all parse actions can be called as f(s,l,t)."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   568
        STAR_ARGS = 4
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   569
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   570
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   571
            restore = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   572
            if isinstance(f,type):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   573
                restore = f
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   574
                f = f.__init__
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   575
            if f.func_code.co_flags & STAR_ARGS:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   576
                return f
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   577
            numargs = f.func_code.co_argcount
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   578
            if hasattr(f,"im_self"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   579
                numargs -= 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   580
            if restore:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   581
                f = restore
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   582
        except AttributeError:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   583
            try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   584
                # not a function, must be a callable object, get info from the
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   585
                # im_func binding of its bound __call__ method
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   586
                if f.__call__.im_func.func_code.co_flags & STAR_ARGS:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   587
                    return f
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   588
                numargs = f.__call__.im_func.func_code.co_argcount
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   589
                if hasattr(f.__call__,"im_self"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   590
                    numargs -= 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   591
            except AttributeError:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   592
                # not a bound method, get info directly from __call__ method
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   593
                if f.__call__.func_code.co_flags & STAR_ARGS:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   594
                    return f
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   595
                numargs = f.__call__.func_code.co_argcount
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   596
                if hasattr(f.__call__,"im_self"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   597
                    numargs -= 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   598
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   599
        #~ print "adding function %s with %d args" % (f.func_name,numargs)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   600
        if numargs == 3:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   601
            return f
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   602
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   603
            if numargs == 2:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   604
                def tmp(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   605
                    return f(l,t)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   606
            elif numargs == 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   607
                def tmp(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   608
                    return f(t)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   609
            else: #~ numargs == 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   610
                def tmp(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   611
                    return f()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   612
            return tmp
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   613
    normalizeParseActionArgs = staticmethod(normalizeParseActionArgs)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   614
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   615
    def setParseAction( self, *fns ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   616
        """Define action to perform when successfully matching parse element definition.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   617
           Parse action fn is a callable method with 0-3 arguments, called as fn(s,loc,toks),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   618
           fn(loc,toks), fn(toks), or just fn(), where:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   619
            - s   = the original string being parsed
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   620
            - loc = the location of the matching substring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   621
            - toks = a list of the matched tokens, packaged as a ParseResults object
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   622
           If the functions in fns modify the tokens, they can return them as the return
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   623
           value from fn, and the modified list of tokens will replace the original.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   624
           Otherwise, fn does not need to return any value."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   625
        self.parseAction = map(self.normalizeParseActionArgs, list(fns))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   626
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   627
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   628
    def addParseAction( self, *fns ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   629
        """Add parse action to expression's list of parse actions. See setParseAction_."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   630
        self.parseAction += map(self.normalizeParseActionArgs, list(fns))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   631
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   632
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   633
    def setFailAction( self, fn ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   634
        """Define action to perform if parsing fails at this expression. 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   635
           Fail acton fn is a callable function that takes the arguments 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   636
           fn(s,loc,expr,err) where:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   637
            - s = string being parsed
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   638
            - loc = location where expression match was attempted and failed
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   639
            - expr = the parse expression that failed
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   640
            - err = the exception thrown
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   641
           The function returns no value.  It may throw ParseFatalException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   642
           if it is desired to stop parsing immediately."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   643
        self.failAction = fn
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   644
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   645
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   646
    def skipIgnorables( self, instring, loc ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   647
        exprsFound = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   648
        while exprsFound:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   649
            exprsFound = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   650
            for e in self.ignoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   651
                try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   652
                    while 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   653
                        loc,dummy = e._parse( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   654
                        exprsFound = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   655
                except ParseException:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   656
                    pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   657
        return loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   658
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   659
    def preParse( self, instring, loc ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   660
        if self.ignoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   661
            loc = self.skipIgnorables( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   662
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   663
        if self.skipWhitespace:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   664
            wt = self.whiteChars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   665
            instrlen = len(instring)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   666
            while loc < instrlen and instring[loc] in wt:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   667
                loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   668
                
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   669
        return loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   670
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   671
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   672
        return loc, []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   673
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   674
    def postParse( self, instring, loc, tokenlist ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   675
        return tokenlist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   676
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   677
    #~ @profile
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   678
    def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   679
        debugging = ( self.debug ) #and doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   680
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   681
        if debugging or self.failAction:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   682
            #~ print "Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   683
            if (self.debugActions[0] ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   684
                self.debugActions[0]( instring, loc, self )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   685
            if callPreParse:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   686
                preloc = self.preParse( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   687
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   688
                preloc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   689
            tokensStart = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   690
            try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   691
                try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   692
                    loc,tokens = self.parseImpl( instring, preloc, doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   693
                except IndexError:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   694
                    raise ParseException( instring, len(instring), self.errmsg, self )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   695
            #~ except ReparseException, retryEx:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   696
                #~ pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   697
            except ParseException, err:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   698
                #~ print "Exception raised:", err
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   699
                if self.debugActions[2]:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   700
                    self.debugActions[2]( instring, tokensStart, self, err )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   701
                if self.failAction:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   702
                    self.failAction( instring, tokensStart, self, err )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   703
                raise
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   704
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   705
            if callPreParse:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   706
                preloc = self.preParse( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   707
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   708
                preloc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   709
            tokensStart = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   710
            if self.mayIndexError or loc >= len(instring):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   711
                try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   712
                    loc,tokens = self.parseImpl( instring, preloc, doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   713
                except IndexError:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   714
                    raise ParseException( instring, len(instring), self.errmsg, self )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   715
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   716
                loc,tokens = self.parseImpl( instring, preloc, doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   717
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   718
        tokens = self.postParse( instring, loc, tokens )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   719
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   720
        retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   721
        if self.parseAction and doActions:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   722
            if debugging:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   723
                try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   724
                    for fn in self.parseAction:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   725
                        tokens = fn( instring, tokensStart, retTokens )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   726
                        if tokens is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   727
                            retTokens = ParseResults( tokens, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   728
                                                      self.resultsName, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   729
                                                      asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   730
                                                      modal=self.modalResults )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   731
                except ParseException, err:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   732
                    #~ print "Exception raised in user parse action:", err
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   733
                    if (self.debugActions[2] ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   734
                        self.debugActions[2]( instring, tokensStart, self, err )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   735
                    raise
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   736
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   737
                for fn in self.parseAction:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   738
                    tokens = fn( instring, tokensStart, retTokens )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   739
                    if tokens is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   740
                        retTokens = ParseResults( tokens, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   741
                                                  self.resultsName, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   742
                                                  asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   743
                                                  modal=self.modalResults )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   744
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   745
        if debugging:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   746
            #~ print "Matched",self,"->",retTokens.asList()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   747
            if (self.debugActions[1] ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   748
                self.debugActions[1]( instring, tokensStart, loc, self, retTokens )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   749
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   750
        return loc, retTokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   751
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   752
    def tryParse( self, instring, loc ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   753
        return self._parse( instring, loc, doActions=False )[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   754
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   755
    # this method gets repeatedly called during backtracking with the same arguments -
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   756
    # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   757
    def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   758
        if doActions and self.parseAction:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   759
            return self._parseNoCache( instring, loc, doActions, callPreParse )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   760
        lookup = (self,instring,loc,callPreParse)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   761
        if lookup in ParserElement._exprArgCache:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   762
            value = ParserElement._exprArgCache[ lookup ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   763
            if isinstance(value,Exception):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   764
                if isinstance(value,ParseBaseException):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   765
                    value.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   766
                raise value
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   767
            return value
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   768
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   769
            try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   770
                ParserElement._exprArgCache[ lookup ] = \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   771
                    value = self._parseNoCache( instring, loc, doActions, callPreParse )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   772
                return value
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   773
            except ParseBaseException, pe:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   774
                ParserElement._exprArgCache[ lookup ] = pe
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   775
                raise
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   776
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   777
    _parse = _parseNoCache
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   778
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   779
    # argument cache for optimizing repeated calls when backtracking through recursive expressions
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   780
    _exprArgCache = {}
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   781
    def resetCache():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   782
        ParserElement._exprArgCache.clear()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   783
    resetCache = staticmethod(resetCache)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   784
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   785
    _packratEnabled = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   786
    def enablePackrat():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   787
        """Enables "packrat" parsing, which adds memoizing to the parsing logic.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   788
           Repeated parse attempts at the same string location (which happens 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   789
           often in many complex grammars) can immediately return a cached value, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   790
           instead of re-executing parsing/validating code.  Memoizing is done of
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   791
           both valid results and parsing exceptions.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   792
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   793
           This speedup may break existing programs that use parse actions that 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   794
           have side-effects.  For this reason, packrat parsing is disabled when
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   795
           you first import pyparsing.  To activate the packrat feature, your
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   796
           program must call the class method ParserElement.enablePackrat().  If
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   797
           your program uses psyco to "compile as you go", you must call 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   798
           enablePackrat before calling psyco.full().  If you do not do this,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   799
           Python will crash.  For best results, call enablePackrat() immediately
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   800
           after importing pyparsing.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   801
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   802
        if not ParserElement._packratEnabled:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   803
            ParserElement._packratEnabled = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   804
            ParserElement._parse = ParserElement._parseCache
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   805
    enablePackrat = staticmethod(enablePackrat)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   806
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   807
    def parseString( self, instring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   808
        """Execute the parse expression with the given string.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   809
           This is the main interface to the client code, once the complete 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   810
           expression has been built.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   811
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   812
        ParserElement.resetCache()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   813
        if not self.streamlined:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   814
            self.streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   815
            #~ self.saveAsList = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   816
        for e in self.ignoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   817
            e.streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   818
        if self.keepTabs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   819
            loc, tokens = self._parse( instring, 0 )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   820
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   821
            loc, tokens = self._parse( instring.expandtabs(), 0 )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   822
        return tokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   823
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   824
    def scanString( self, instring, maxMatches=sys.maxint ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   825
        """Scan the input string for expression matches.  Each match will return the 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   826
           matching tokens, start location, and end location.  May be called with optional
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   827
           maxMatches argument, to clip scanning after 'n' matches are found."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   828
        if not self.streamlined:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   829
            self.streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   830
        for e in self.ignoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   831
            e.streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   832
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   833
        if not self.keepTabs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   834
            instring = instring.expandtabs()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   835
        instrlen = len(instring)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   836
        loc = 0
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   837
        preparseFn = self.preParse
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   838
        parseFn = self._parse
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   839
        ParserElement.resetCache()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   840
        matches = 0
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   841
        while loc <= instrlen and matches < maxMatches:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   842
            try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   843
                preloc = preparseFn( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   844
                nextLoc,tokens = parseFn( instring, preloc, callPreParse=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   845
            except ParseException:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   846
                loc = preloc+1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   847
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   848
                matches += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   849
                yield tokens, preloc, nextLoc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   850
                loc = nextLoc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   851
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   852
    def transformString( self, instring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   853
        """Extension to scanString, to modify matching text with modified tokens that may
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   854
           be returned from a parse action.  To use transformString, define a grammar and 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   855
           attach a parse action to it that modifies the returned token list.  
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   856
           Invoking transformString() on a target string will then scan for matches, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   857
           and replace the matched text patterns according to the logic in the parse 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   858
           action.  transformString() returns the resulting transformed string."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   859
        out = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   860
        lastE = 0
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   861
        # force preservation of <TAB>s, to minimize unwanted transformation of string, and to
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   862
        # keep string locs straight between transformString and scanString
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   863
        self.keepTabs = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   864
        for t,s,e in self.scanString( instring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   865
            out.append( instring[lastE:s] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   866
            if t:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   867
                if isinstance(t,ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   868
                    out += t.asList()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   869
                elif isinstance(t,list):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   870
                    out += t
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   871
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   872
                    out.append(t)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   873
            lastE = e
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   874
        out.append(instring[lastE:])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   875
        return "".join(out)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   876
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   877
    def searchString( self, instring, maxMatches=sys.maxint ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   878
        """Another extension to scanString, simplifying the access to the tokens found
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   879
           to match the given parse expression.  May be called with optional
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   880
           maxMatches argument, to clip searching after 'n' matches are found.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   881
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   882
        return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   883
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   884
    def __add__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   885
        """Implementation of + operator - returns And"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   886
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   887
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   888
        if not isinstance( other, ParserElement ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   889
            warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   890
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   891
        return And( [ self, other ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   892
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   893
    def __radd__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   894
        """Implementation of += operator"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   895
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   896
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   897
        if not isinstance( other, ParserElement ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   898
            warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   899
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   900
        return other + self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   901
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   902
    def __or__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   903
        """Implementation of | operator - returns MatchFirst"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   904
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   905
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   906
        if not isinstance( other, ParserElement ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   907
            warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   908
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   909
        return MatchFirst( [ self, other ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   910
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   911
    def __ror__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   912
        """Implementation of |= operator"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   913
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   914
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   915
        if not isinstance( other, ParserElement ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   916
            warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   917
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   918
        return other | self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   919
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   920
    def __xor__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   921
        """Implementation of ^ operator - returns Or"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   922
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   923
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   924
        if not isinstance( other, ParserElement ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   925
            warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   926
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   927
        return Or( [ self, other ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   928
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   929
    def __rxor__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   930
        """Implementation of ^= operator"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   931
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   932
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   933
        if not isinstance( other, ParserElement ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   934
            warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   935
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   936
        return other ^ self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   937
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   938
    def __and__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   939
        """Implementation of & operator - returns Each"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   940
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   941
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   942
        if not isinstance( other, ParserElement ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   943
            warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   944
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   945
        return Each( [ self, other ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   946
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   947
    def __rand__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   948
        """Implementation of right-& operator"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   949
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   950
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   951
        if not isinstance( other, ParserElement ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   952
            warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   953
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   954
        return other & self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   955
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   956
    def __invert__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   957
        """Implementation of ~ operator - returns NotAny"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   958
        return NotAny( self )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   959
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   960
    def suppress( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   961
        """Suppresses the output of this ParserElement; useful to keep punctuation from
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   962
           cluttering up returned output.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   963
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   964
        return Suppress( self )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   965
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   966
    def leaveWhitespace( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   967
        """Disables the skipping of whitespace before matching the characters in the 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   968
           ParserElement's defined pattern.  This is normally only used internally by
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   969
           the pyparsing module, but may be needed in some whitespace-sensitive grammars.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   970
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   971
        self.skipWhitespace = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   972
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   973
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   974
    def setWhitespaceChars( self, chars ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   975
        """Overrides the default whitespace chars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   976
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   977
        self.skipWhitespace = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   978
        self.whiteChars = chars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   979
        self.copyDefaultWhiteChars = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   980
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   981
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   982
    def parseWithTabs( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   983
        """Overrides default behavior to expand <TAB>s to spaces before parsing the input string.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   984
           Must be called before parseString when the input grammar contains elements that 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   985
           match <TAB> characters."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   986
        self.keepTabs = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   987
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   988
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   989
    def ignore( self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   990
        """Define expression to be ignored (e.g., comments) while doing pattern 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   991
           matching; may be called repeatedly, to define multiple comment or other
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   992
           ignorable patterns.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   993
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   994
        if isinstance( other, Suppress ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   995
            if other not in self.ignoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   996
                self.ignoreExprs.append( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   997
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   998
            self.ignoreExprs.append( Suppress( other ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
   999
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1000
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1001
    def setDebugActions( self, startAction, successAction, exceptionAction ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1002
        """Enable display of debugging messages while doing pattern matching."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1003
        self.debugActions = (startAction or _defaultStartDebugAction, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1004
                             successAction or _defaultSuccessDebugAction, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1005
                             exceptionAction or _defaultExceptionDebugAction)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1006
        self.debug = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1007
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1008
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1009
    def setDebug( self, flag=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1010
        """Enable display of debugging messages while doing pattern matching."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1011
        if flag:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1012
            self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1013
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1014
            self.debug = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1015
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1016
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1017
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1018
        return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1019
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1020
    def __repr__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1021
        return _ustr(self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1022
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1023
    def streamline( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1024
        self.streamlined = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1025
        self.strRepr = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1026
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1027
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1028
    def checkRecursion( self, parseElementList ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1029
        pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1030
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1031
    def validate( self, validateTrace=[] ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1032
        """Check defined expressions for valid structure, check for infinite recursive definitions."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1033
        self.checkRecursion( [] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1034
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1035
    def parseFile( self, file_or_filename ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1036
        """Execute the parse expression on the given file or filename.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1037
           If a filename is specified (instead of a file object),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1038
           the entire file is opened, read, and closed before parsing.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1039
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1040
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1041
            file_contents = file_or_filename.read()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1042
        except AttributeError:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1043
            f = open(file_or_filename, "rb")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1044
            file_contents = f.read()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1045
            f.close()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1046
        return self.parseString(file_contents)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1047
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1048
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1049
class Token(ParserElement):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1050
    """Abstract ParserElement subclass, for defining atomic matching patterns."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1051
    def __init__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1052
        super(Token,self).__init__( savelist=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1053
        self.myException = ParseException("",0,"",self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1054
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1055
    def setName(self, name):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1056
        s = super(Token,self).setName(name)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1057
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1058
        s.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1059
        return s
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1060
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1061
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1062
class Empty(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1063
    """An empty token, will always match."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1064
    def __init__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1065
        super(Empty,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1066
        self.name = "Empty"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1067
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1068
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1069
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1070
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1071
class NoMatch(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1072
    """A token that will never match."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1073
    def __init__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1074
        super(NoMatch,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1075
        self.name = "NoMatch"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1076
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1077
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1078
        self.errmsg = "Unmatchable token"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1079
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1080
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1081
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1082
        exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1083
        exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1084
        exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1085
        raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1086
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1087
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1088
class Literal(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1089
    """Token to exactly match a specified string."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1090
    def __init__( self, matchString ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1091
        super(Literal,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1092
        self.match = matchString
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1093
        self.matchLen = len(matchString)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1094
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1095
            self.firstMatchChar = matchString[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1096
        except IndexError:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1097
            warnings.warn("null string passed to Literal; use Empty() instead", 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1098
                            SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1099
            self.__class__ = Empty
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1100
        self.name = '"%s"' % self.match
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1101
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1102
        self.mayReturnEmpty = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1103
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1104
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1105
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1106
    # Performance tuning: this routine gets called a *lot*
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1107
    # if this is a single character match string  and the first character matches,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1108
    # short-circuit as quickly as possible, and avoid calling startswith
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1109
    #~ @profile
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1110
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1111
        if (instring[loc] == self.firstMatchChar and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1112
            (self.matchLen==1 or instring.startswith(self.match,loc)) ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1113
            return loc+self.matchLen, self.match
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1114
        #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1115
        exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1116
        exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1117
        exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1118
        raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1119
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1120
class Keyword(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1121
    """Token to exactly match a specified string as a keyword, that is, it must be 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1122
       immediately followed by a non-keyword character.  Compare with Literal::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1123
         Literal("if") will match the leading 'if' in 'ifAndOnlyIf'.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1124
         Keyword("if") will not; it will only match the leading 'if in 'if x=1', or 'if(y==2)'
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1125
       Accepts two optional constructor arguments in addition to the keyword string:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1126
       identChars is a string of characters that would be valid identifier characters,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1127
       defaulting to all alphanumerics + "_" and "$"; caseless allows case-insensitive
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1128
       matching, default is False.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1129
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1130
    DEFAULT_KEYWORD_CHARS = alphanums+"_$"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1131
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1132
    def __init__( self, matchString, identChars=DEFAULT_KEYWORD_CHARS, caseless=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1133
        super(Keyword,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1134
        self.match = matchString
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1135
        self.matchLen = len(matchString)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1136
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1137
            self.firstMatchChar = matchString[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1138
        except IndexError:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1139
            warnings.warn("null string passed to Keyword; use Empty() instead", 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1140
                            SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1141
        self.name = '"%s"' % self.match
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1142
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1143
        self.mayReturnEmpty = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1144
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1145
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1146
        self.caseless = caseless
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1147
        if caseless:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1148
            self.caselessmatch = matchString.upper()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1149
            identChars = identChars.upper()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1150
        self.identChars = _str2dict(identChars)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1151
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1152
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1153
        if self.caseless:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1154
            if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1155
                 (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1156
                 (loc == 0 or instring[loc-1].upper() not in self.identChars) ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1157
                return loc+self.matchLen, self.match
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1158
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1159
            if (instring[loc] == self.firstMatchChar and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1160
                (self.matchLen==1 or instring.startswith(self.match,loc)) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1161
                (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1162
                (loc == 0 or instring[loc-1] not in self.identChars) ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1163
                return loc+self.matchLen, self.match
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1164
        #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1165
        exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1166
        exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1167
        exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1168
        raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1169
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1170
    def copy(self):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1171
        c = super(Keyword,self).copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1172
        c.identChars = Keyword.DEFAULT_KEYWORD_CHARS
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1173
        return c
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1174
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1175
    def setDefaultKeywordChars( chars ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1176
        """Overrides the default Keyword chars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1177
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1178
        Keyword.DEFAULT_KEYWORD_CHARS = chars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1179
    setDefaultKeywordChars = staticmethod(setDefaultKeywordChars)        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1180
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1181
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1182
class CaselessLiteral(Literal):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1183
    """Token to match a specified string, ignoring case of letters.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1184
       Note: the matched results will always be in the case of the given
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1185
       match string, NOT the case of the input text.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1186
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1187
    def __init__( self, matchString ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1188
        super(CaselessLiteral,self).__init__( matchString.upper() )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1189
        # Preserve the defining literal.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1190
        self.returnString = matchString
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1191
        self.name = "'%s'" % self.returnString
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1192
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1193
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1194
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1195
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1196
        if instring[ loc:loc+self.matchLen ].upper() == self.match:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1197
            return loc+self.matchLen, self.returnString
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1198
        #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1199
        exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1200
        exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1201
        exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1202
        raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1203
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1204
class CaselessKeyword(Keyword):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1205
    def __init__( self, matchString, identChars=Keyword.DEFAULT_KEYWORD_CHARS ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1206
        super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1207
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1208
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1209
        if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1210
             (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1211
            return loc+self.matchLen, self.match
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1212
        #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1213
        exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1214
        exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1215
        exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1216
        raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1217
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1218
class Word(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1219
    """Token for matching words composed of allowed character sets.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1220
       Defined with string containing all allowed initial characters,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1221
       an optional string containing allowed body characters (if omitted,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1222
       defaults to the initial character set), and an optional minimum,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1223
       maximum, and/or exact length.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1224
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1225
    def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0 ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1226
        super(Word,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1227
        self.initCharsOrig = initChars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1228
        self.initChars = _str2dict(initChars)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1229
        if bodyChars :
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1230
            self.bodyCharsOrig = bodyChars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1231
            self.bodyChars = _str2dict(bodyChars)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1232
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1233
            self.bodyCharsOrig = initChars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1234
            self.bodyChars = _str2dict(initChars)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1235
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1236
        self.maxSpecified = max > 0
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1237
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1238
        self.minLen = min
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1239
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1240
        if max > 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1241
            self.maxLen = max
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1242
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1243
            self.maxLen = sys.maxint
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1244
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1245
        if exact > 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1246
            self.maxLen = exact
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1247
            self.minLen = exact
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1248
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1249
        self.name = _ustr(self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1250
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1251
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1252
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1253
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1254
        if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1255
            if self.bodyCharsOrig == self.initCharsOrig:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1256
                self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1257
            elif len(self.bodyCharsOrig) == 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1258
                self.reString = "%s[%s]*" % \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1259
                                      (re.escape(self.initCharsOrig),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1260
                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1261
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1262
                self.reString = "[%s][%s]*" % \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1263
                                      (_escapeRegexRangeChars(self.initCharsOrig),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1264
                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1265
            try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1266
                self.re = re.compile( self.reString )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1267
            except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1268
                self.re = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1269
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1270
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1271
        if self.re:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1272
            result = self.re.match(instring,loc)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1273
            if not result:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1274
                exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1275
                exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1276
                exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1277
                raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1278
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1279
            loc = result.end()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1280
            return loc,result.group()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1281
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1282
        if not(instring[ loc ] in self.initChars):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1283
            #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1284
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1285
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1286
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1287
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1288
        start = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1289
        loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1290
        instrlen = len(instring)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1291
        bodychars = self.bodyChars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1292
        maxloc = start + self.maxLen
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1293
        maxloc = min( maxloc, instrlen )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1294
        while loc < maxloc and instring[loc] in bodychars:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1295
            loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1296
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1297
        throwException = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1298
        if loc - start < self.minLen:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1299
            throwException = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1300
        if self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1301
            throwException = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1302
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1303
        if throwException:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1304
            #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1305
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1306
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1307
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1308
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1309
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1310
        return loc, instring[start:loc]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1311
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1312
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1313
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1314
            return super(Word,self).__str__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1315
        except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1316
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1317
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1318
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1319
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1320
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1321
            def charsAsStr(s):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1322
                if len(s)>4:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1323
                    return s[:4]+"..."
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1324
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1325
                    return s
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1326
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1327
            if ( self.initCharsOrig != self.bodyCharsOrig ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1328
                self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1329
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1330
                self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1331
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1332
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1333
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1334
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1335
class Regex(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1336
    """Token for matching strings that match a given regular expression.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1337
       Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1338
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1339
    def __init__( self, pattern, flags=0):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1340
        """The parameters pattern and flags are passed to the re.compile() function as-is. See the Python re module for an explanation of the acceptable patterns and flags."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1341
        super(Regex,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1342
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1343
        if len(pattern) == 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1344
            warnings.warn("null string passed to Regex; use Empty() instead", 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1345
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1346
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1347
        self.pattern = pattern
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1348
        self.flags = flags
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1349
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1350
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1351
            self.re = re.compile(self.pattern, self.flags)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1352
            self.reString = self.pattern
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1353
        except sre_constants.error,e:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1354
            warnings.warn("invalid pattern (%s) passed to Regex" % pattern, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1355
                SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1356
            raise
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1357
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1358
        self.name = _ustr(self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1359
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1360
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1361
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1362
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1363
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1364
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1365
        result = self.re.match(instring,loc)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1366
        if not result:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1367
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1368
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1369
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1370
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1371
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1372
        loc = result.end()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1373
        d = result.groupdict()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1374
        ret = ParseResults(result.group())
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1375
        if d:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1376
            for k in d.keys():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1377
                ret[k] = d[k]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1378
        return loc,ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1379
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1380
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1381
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1382
            return super(Regex,self).__str__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1383
        except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1384
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1385
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1386
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1387
            self.strRepr = "Re:(%s)" % repr(self.pattern)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1388
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1389
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1390
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1391
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1392
class QuotedString(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1393
    """Token for matching strings that are delimited by quoting characters.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1394
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1395
    def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1396
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1397
           Defined with the following parameters:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1398
           - quoteChar - string of one or more characters defining the quote delimiting string
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1399
           - escChar - character to escape quotes, typically backslash (default=None)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1400
           - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=None)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1401
           - multiline - boolean indicating whether quotes can span multiple lines (default=False)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1402
           - unquoteResults - boolean indicating whether the matched text should be unquoted (default=True)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1403
           - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=None => same as quoteChar)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1404
        """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1405
        super(QuotedString,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1406
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1407
        # remove white space from quote chars - wont work anyway
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1408
        quoteChar = quoteChar.strip()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1409
        if len(quoteChar) == 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1410
            warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1411
            raise SyntaxError()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1412
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1413
        if endQuoteChar is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1414
            endQuoteChar = quoteChar
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1415
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1416
            endQuoteChar = endQuoteChar.strip()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1417
            if len(endQuoteChar) == 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1418
                warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1419
                raise SyntaxError()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1420
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1421
        self.quoteChar = quoteChar
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1422
        self.quoteCharLen = len(quoteChar)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1423
        self.firstQuoteChar = quoteChar[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1424
        self.endQuoteChar = endQuoteChar
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1425
        self.endQuoteCharLen = len(endQuoteChar)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1426
        self.escChar = escChar
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1427
        self.escQuote = escQuote
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1428
        self.unquoteResults = unquoteResults
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1429
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1430
        if multiline:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1431
            self.flags = re.MULTILINE | re.DOTALL
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1432
            self.pattern = r'%s(?:[^%s%s]' % \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1433
                ( re.escape(self.quoteChar),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1434
                  _escapeRegexRangeChars(self.endQuoteChar[0]),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1435
                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1436
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1437
            self.flags = 0
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1438
            self.pattern = r'%s(?:[^%s\n\r%s]' % \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1439
                ( re.escape(self.quoteChar),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1440
                  _escapeRegexRangeChars(self.endQuoteChar[0]),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1441
                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1442
        if len(self.endQuoteChar) > 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1443
            self.pattern += (
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1444
                '|(?:' + ')|(?:'.join(["%s[^%s]" % (re.escape(self.endQuoteChar[:i]),
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1445
                                               _escapeRegexRangeChars(self.endQuoteChar[i])) 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1446
                                    for i in range(len(self.endQuoteChar)-1,0,-1)]) + ')'
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1447
                )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1448
        if escQuote:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1449
            self.pattern += (r'|(?:%s)' % re.escape(escQuote))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1450
        if escChar:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1451
            self.pattern += (r'|(?:%s.)' % re.escape(escChar))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1452
            self.escCharReplacePattern = re.escape(self.escChar)+"(.)"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1453
        self.pattern += (r')*%s' % re.escape(self.endQuoteChar))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1454
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1455
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1456
            self.re = re.compile(self.pattern, self.flags)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1457
            self.reString = self.pattern
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1458
        except sre_constants.error,e:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1459
            warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1460
                SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1461
            raise
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1462
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1463
        self.name = _ustr(self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1464
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1465
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1466
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1467
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1468
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1469
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1470
        result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1471
        if not result:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1472
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1473
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1474
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1475
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1476
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1477
        loc = result.end()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1478
        ret = result.group()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1479
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1480
        if self.unquoteResults:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1481
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1482
            # strip off quotes
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1483
            ret = ret[self.quoteCharLen:-self.endQuoteCharLen]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1484
                
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1485
            if isinstance(ret,basestring):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1486
                # replace escaped characters
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1487
                if self.escChar:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1488
                    ret = re.sub(self.escCharReplacePattern,"\g<1>",ret)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1489
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1490
                # replace escaped quotes
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1491
                if self.escQuote:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1492
                    ret = ret.replace(self.escQuote, self.endQuoteChar)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1493
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1494
        return loc, ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1495
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1496
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1497
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1498
            return super(QuotedString,self).__str__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1499
        except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1500
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1501
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1502
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1503
            self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1504
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1505
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1506
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1507
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1508
class CharsNotIn(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1509
    """Token for matching words composed of characters *not* in a given set.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1510
       Defined with string containing all disallowed characters, and an optional 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1511
       minimum, maximum, and/or exact length.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1512
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1513
    def __init__( self, notChars, min=1, max=0, exact=0 ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1514
        super(CharsNotIn,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1515
        self.skipWhitespace = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1516
        self.notChars = notChars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1517
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1518
        self.minLen = min
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1519
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1520
        if max > 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1521
            self.maxLen = max
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1522
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1523
            self.maxLen = sys.maxint
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1524
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1525
        if exact > 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1526
            self.maxLen = exact
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1527
            self.minLen = exact
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1528
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1529
        self.name = _ustr(self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1530
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1531
        self.mayReturnEmpty = ( self.minLen == 0 )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1532
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1533
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1534
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1535
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1536
        if instring[loc] in self.notChars:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1537
            #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1538
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1539
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1540
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1541
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1542
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1543
        start = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1544
        loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1545
        notchars = self.notChars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1546
        maxlen = min( start+self.maxLen, len(instring) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1547
        while loc < maxlen and (instring[loc] not in notchars):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1548
            loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1549
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1550
        if loc - start < self.minLen:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1551
            #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1552
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1553
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1554
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1555
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1556
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1557
        return loc, instring[start:loc]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1558
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1559
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1560
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1561
            return super(CharsNotIn, self).__str__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1562
        except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1563
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1564
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1565
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1566
            if len(self.notChars) > 4:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1567
                self.strRepr = "!W:(%s...)" % self.notChars[:4]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1568
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1569
                self.strRepr = "!W:(%s)" % self.notChars
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1570
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1571
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1572
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1573
class White(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1574
    """Special matching class for matching whitespace.  Normally, whitespace is ignored
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1575
       by pyparsing grammars.  This class is included when some whitespace structures
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1576
       are significant.  Define with a string containing the whitespace characters to be
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1577
       matched; default is " \\t\\n".  Also takes optional min, max, and exact arguments,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1578
       as defined for the Word class."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1579
    whiteStrs = {
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1580
        " " : "<SPC>",
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1581
        "\t": "<TAB>",
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1582
        "\n": "<LF>",
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1583
        "\r": "<CR>",
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1584
        "\f": "<FF>",
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1585
        }
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1586
    def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1587
        super(White,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1588
        self.matchWhite = ws
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1589
        self.setWhitespaceChars( "".join([c for c in self.whiteChars if c not in self.matchWhite]) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1590
        #~ self.leaveWhitespace()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1591
        self.name = ("".join([White.whiteStrs[c] for c in self.matchWhite]))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1592
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1593
        self.errmsg = "Expected " + self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1594
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1595
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1596
        self.minLen = min
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1597
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1598
        if max > 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1599
            self.maxLen = max
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1600
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1601
            self.maxLen = sys.maxint
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1602
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1603
        if exact > 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1604
            self.maxLen = exact
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1605
            self.minLen = exact
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1606
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1607
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1608
        if not(instring[ loc ] in self.matchWhite):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1609
            #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1610
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1611
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1612
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1613
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1614
        start = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1615
        loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1616
        maxloc = start + self.maxLen
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1617
        maxloc = min( maxloc, len(instring) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1618
        while loc < maxloc and instring[loc] in self.matchWhite:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1619
            loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1620
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1621
        if loc - start < self.minLen:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1622
            #~ raise ParseException( instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1623
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1624
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1625
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1626
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1627
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1628
        return loc, instring[start:loc]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1629
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1630
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1631
class PositionToken(Token):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1632
    def __init__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1633
        super(PositionToken,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1634
        self.name=self.__class__.__name__
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1635
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1636
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1637
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1638
class GoToColumn(PositionToken):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1639
    """Token to advance to a specific column of input text; useful for tabular report scraping."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1640
    def __init__( self, colno ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1641
        super(GoToColumn,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1642
        self.col = colno
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1643
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1644
    def preParse( self, instring, loc ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1645
        if col(loc,instring) != self.col:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1646
            instrlen = len(instring)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1647
            if self.ignoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1648
                loc = self.skipIgnorables( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1649
            while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col :
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1650
                loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1651
        return loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1652
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1653
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1654
        thiscol = col( loc, instring )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1655
        if thiscol > self.col:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1656
            raise ParseException( instring, loc, "Text not in expected column", self )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1657
        newloc = loc + self.col - thiscol
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1658
        ret = instring[ loc: newloc ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1659
        return newloc, ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1660
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1661
class LineStart(PositionToken):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1662
    """Matches if current position is at the beginning of a line within the parse string"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1663
    def __init__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1664
        super(LineStart,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1665
        self.setWhitespaceChars( " \t" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1666
        self.errmsg = "Expected start of line"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1667
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1668
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1669
    def preParse( self, instring, loc ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1670
        preloc = super(LineStart,self).preParse(instring,loc)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1671
        if instring[preloc] == "\n":
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1672
            loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1673
        return loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1674
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1675
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1676
        if not( loc==0 or
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1677
            (loc == self.preParse( instring, 0 )) or
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1678
            (instring[loc-1] == "\n") ): #col(loc, instring) != 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1679
            #~ raise ParseException( instring, loc, "Expected start of line" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1680
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1681
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1682
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1683
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1684
        return loc, []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1685
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1686
class LineEnd(PositionToken):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1687
    """Matches if current position is at the end of a line within the parse string"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1688
    def __init__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1689
        super(LineEnd,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1690
        self.setWhitespaceChars( " \t" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1691
        self.errmsg = "Expected end of line"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1692
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1693
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1694
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1695
        if loc<len(instring):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1696
            if instring[loc] == "\n":
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1697
                return loc+1, "\n"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1698
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1699
                #~ raise ParseException( instring, loc, "Expected end of line" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1700
                exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1701
                exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1702
                exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1703
                raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1704
        elif loc == len(instring):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1705
            return loc+1, []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1706
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1707
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1708
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1709
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1710
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1711
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1712
class StringStart(PositionToken):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1713
    """Matches if current position is at the beginning of the parse string"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1714
    def __init__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1715
        super(StringStart,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1716
        self.errmsg = "Expected start of text"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1717
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1718
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1719
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1720
        if loc != 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1721
            # see if entire string up to here is just whitespace and ignoreables
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1722
            if loc != self.preParse( instring, 0 ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1723
                #~ raise ParseException( instring, loc, "Expected start of text" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1724
                exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1725
                exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1726
                exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1727
                raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1728
        return loc, []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1729
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1730
class StringEnd(PositionToken):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1731
    """Matches if current position is at the end of the parse string"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1732
    def __init__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1733
        super(StringEnd,self).__init__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1734
        self.errmsg = "Expected end of text"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1735
        self.myException.msg = self.errmsg
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1736
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1737
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1738
        if loc < len(instring):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1739
            #~ raise ParseException( instring, loc, "Expected end of text" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1740
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1741
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1742
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1743
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1744
        elif loc == len(instring):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1745
            return loc+1, []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1746
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1747
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1748
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1749
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1750
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1751
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1752
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1753
class ParseExpression(ParserElement):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1754
    """Abstract subclass of ParserElement, for combining and post-processing parsed tokens."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1755
    def __init__( self, exprs, savelist = False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1756
        super(ParseExpression,self).__init__(savelist)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1757
        if isinstance( exprs, list ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1758
            self.exprs = exprs
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1759
        elif isinstance( exprs, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1760
            self.exprs = [ Literal( exprs ) ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1761
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1762
            self.exprs = [ exprs ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1763
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1764
    def __getitem__( self, i ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1765
        return self.exprs[i]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1766
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1767
    def append( self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1768
        self.exprs.append( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1769
        self.strRepr = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1770
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1771
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1772
    def leaveWhitespace( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1773
        """Extends leaveWhitespace defined in base class, and also invokes leaveWhitespace on
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1774
           all contained expressions."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1775
        self.skipWhitespace = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1776
        self.exprs = [ e.copy() for e in self.exprs ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1777
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1778
            e.leaveWhitespace()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1779
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1780
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1781
    def ignore( self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1782
        if isinstance( other, Suppress ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1783
            if other not in self.ignoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1784
                super( ParseExpression, self).ignore( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1785
                for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1786
                    e.ignore( self.ignoreExprs[-1] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1787
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1788
            super( ParseExpression, self).ignore( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1789
            for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1790
                e.ignore( self.ignoreExprs[-1] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1791
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1792
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1793
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1794
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1795
            return super(ParseExpression,self).__str__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1796
        except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1797
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1798
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1799
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1800
            self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1801
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1802
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1803
    def streamline( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1804
        super(ParseExpression,self).streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1805
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1806
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1807
            e.streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1808
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1809
        # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1810
        # but only if there are no parse actions or resultsNames on the nested And's
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1811
        # (likewise for Or's and MatchFirst's)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1812
        if ( len(self.exprs) == 2 ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1813
            other = self.exprs[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1814
            if ( isinstance( other, self.__class__ ) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1815
                  not(other.parseAction) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1816
                  other.resultsName is None and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1817
                  not other.debug ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1818
                self.exprs = other.exprs[:] + [ self.exprs[1] ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1819
                self.strRepr = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1820
                self.mayReturnEmpty |= other.mayReturnEmpty
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1821
                self.mayIndexError  |= other.mayIndexError
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1822
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1823
            other = self.exprs[-1]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1824
            if ( isinstance( other, self.__class__ ) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1825
                  not(other.parseAction) and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1826
                  other.resultsName is None and
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1827
                  not other.debug ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1828
                self.exprs = self.exprs[:-1] + other.exprs[:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1829
                self.strRepr = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1830
                self.mayReturnEmpty |= other.mayReturnEmpty
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1831
                self.mayIndexError  |= other.mayIndexError
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1832
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1833
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1834
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1835
    def setResultsName( self, name, listAllMatches=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1836
        ret = super(ParseExpression,self).setResultsName(name,listAllMatches)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1837
        return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1838
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1839
    def validate( self, validateTrace=[] ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1840
        tmp = validateTrace[:]+[self]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1841
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1842
            e.validate(tmp)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1843
        self.checkRecursion( [] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1844
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1845
class And(ParseExpression):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1846
    """Requires all given ParseExpressions to be found in the given order.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1847
       Expressions may be separated by whitespace.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1848
       May be constructed using the '+' operator.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1849
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1850
    def __init__( self, exprs, savelist = True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1851
        super(And,self).__init__(exprs, savelist)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1852
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1853
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1854
            if not e.mayReturnEmpty:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1855
                self.mayReturnEmpty = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1856
                break
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1857
        self.setWhitespaceChars( exprs[0].whiteChars )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1858
        self.skipWhitespace = exprs[0].skipWhitespace
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1859
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1860
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1861
        # pass False as last arg to _parse for first element, since we already
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1862
        # pre-parsed the string as part of our And pre-parsing
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1863
        loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1864
        for e in self.exprs[1:]:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1865
            loc, exprtokens = e._parse( instring, loc, doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1866
            if exprtokens or exprtokens.keys():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1867
                resultlist += exprtokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1868
        return loc, resultlist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1869
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1870
    def __iadd__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1871
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1872
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1873
        return self.append( other ) #And( [ self, other ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1874
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1875
    def checkRecursion( self, parseElementList ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1876
        subRecCheckList = parseElementList[:] + [ self ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1877
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1878
            e.checkRecursion( subRecCheckList )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1879
            if not e.mayReturnEmpty:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1880
                break
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1881
                
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1882
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1883
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1884
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1885
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1886
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1887
            self.strRepr = "{" + " ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1888
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1889
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1890
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1891
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1892
class Or(ParseExpression):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1893
    """Requires that at least one ParseExpression is found.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1894
       If two expressions match, the expression that matches the longest string will be used.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1895
       May be constructed using the '^' operator.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1896
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1897
    def __init__( self, exprs, savelist = False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1898
        super(Or,self).__init__(exprs, savelist)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1899
        self.mayReturnEmpty = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1900
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1901
            if e.mayReturnEmpty:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1902
                self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1903
                break
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1904
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1905
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1906
        maxExcLoc = -1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1907
        maxMatchLoc = -1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1908
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1909
            try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1910
                loc2 = e.tryParse( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1911
            except ParseException, err:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1912
                if err.loc > maxExcLoc:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1913
                    maxException = err
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1914
                    maxExcLoc = err.loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1915
            except IndexError, err:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1916
                if len(instring) > maxExcLoc:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1917
                    maxException = ParseException(instring,len(instring),e.errmsg,self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1918
                    maxExcLoc = len(instring)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1919
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1920
                if loc2 > maxMatchLoc:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1921
                    maxMatchLoc = loc2
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1922
                    maxMatchExp = e
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1923
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1924
        if maxMatchLoc < 0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1925
            if self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1926
                raise maxException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1927
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1928
                raise ParseException(instring, loc, "no defined alternatives to match", self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1929
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1930
        return maxMatchExp._parse( instring, loc, doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1931
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1932
    def __ixor__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1933
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1934
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1935
        return self.append( other ) #Or( [ self, other ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1936
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1937
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1938
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1939
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1940
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1941
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1942
            self.strRepr = "{" + " ^ ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1943
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1944
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1945
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1946
    def checkRecursion( self, parseElementList ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1947
        subRecCheckList = parseElementList[:] + [ self ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1948
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1949
            e.checkRecursion( subRecCheckList )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1950
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1951
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1952
class MatchFirst(ParseExpression):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1953
    """Requires that at least one ParseExpression is found.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1954
       If two expressions match, the first one listed is the one that will match.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1955
       May be constructed using the '|' operator.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1956
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1957
    def __init__( self, exprs, savelist = False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1958
        super(MatchFirst,self).__init__(exprs, savelist)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1959
        if exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1960
            self.mayReturnEmpty = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1961
            for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1962
                if e.mayReturnEmpty:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1963
                    self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1964
                    break
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1965
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1966
            self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1967
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1968
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1969
        maxExcLoc = -1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1970
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1971
            try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1972
                ret = e._parse( instring, loc, doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1973
                return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1974
            except ParseException, err:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1975
                if err.loc > maxExcLoc:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1976
                    maxException = err
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1977
                    maxExcLoc = err.loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1978
            except IndexError, err:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1979
                if len(instring) > maxExcLoc:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1980
                    maxException = ParseException(instring,len(instring),e.errmsg,self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1981
                    maxExcLoc = len(instring)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1982
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1983
        # only got here if no expression matched, raise exception for match that made it the furthest
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1984
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1985
            if self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1986
                raise maxException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1987
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1988
                raise ParseException(instring, loc, "no defined alternatives to match", self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1989
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1990
    def __ior__(self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1991
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1992
            other = Literal( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1993
        return self.append( other ) #MatchFirst( [ self, other ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1994
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1995
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1996
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1997
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1998
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  1999
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2000
            self.strRepr = "{" + " | ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2001
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2002
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2003
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2004
    def checkRecursion( self, parseElementList ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2005
        subRecCheckList = parseElementList[:] + [ self ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2006
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2007
            e.checkRecursion( subRecCheckList )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2008
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2009
class Each(ParseExpression):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2010
    """Requires all given ParseExpressions to be found, but in any order.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2011
       Expressions may be separated by whitespace.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2012
       May be constructed using the '&' operator.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2013
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2014
    def __init__( self, exprs, savelist = True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2015
        super(Each,self).__init__(exprs, savelist)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2016
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2017
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2018
            if not e.mayReturnEmpty:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2019
                self.mayReturnEmpty = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2020
                break
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2021
        self.skipWhitespace = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2022
        self.optionals = [ e.expr for e in exprs if isinstance(e,Optional) ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2023
        self.multioptionals = [ e.expr for e in exprs if isinstance(e,ZeroOrMore) ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2024
        self.multirequired = [ e.expr for e in exprs if isinstance(e,OneOrMore) ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2025
        self.required = [ e for e in exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2026
        self.required += self.multirequired
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2027
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2028
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2029
        tmpLoc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2030
        tmpReqd = self.required[:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2031
        tmpOpt  = self.optionals[:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2032
        matchOrder = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2033
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2034
        keepMatching = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2035
        while keepMatching:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2036
            tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2037
            failed = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2038
            for e in tmpExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2039
                try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2040
                    tmpLoc = e.tryParse( instring, tmpLoc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2041
                except ParseException:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2042
                    failed.append(e)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2043
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2044
                    matchOrder.append(e)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2045
                    if e in tmpReqd:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2046
                        tmpReqd.remove(e)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2047
                    elif e in tmpOpt:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2048
                        tmpOpt.remove(e)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2049
            if len(failed) == len(tmpExprs):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2050
                keepMatching = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2051
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2052
        if tmpReqd:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2053
            missing = ", ".join( [ _ustr(e) for e in tmpReqd ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2054
            raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2055
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2056
        resultlist = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2057
        for e in matchOrder:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2058
            loc,results = e._parse(instring,loc,doActions)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2059
            resultlist.append(results)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2060
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2061
        finalResults = ParseResults([])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2062
        for r in resultlist:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2063
            dups = {}
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2064
            for k in r.keys():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2065
                if k in finalResults.keys():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2066
                    tmp = ParseResults(finalResults[k])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2067
                    tmp += ParseResults(r[k])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2068
                    dups[k] = tmp
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2069
            finalResults += ParseResults(r)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2070
            for k,v in dups.items():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2071
                finalResults[k] = v
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2072
        return loc, finalResults
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2073
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2074
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2075
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2076
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2077
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2078
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2079
            self.strRepr = "{" + " & ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2080
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2081
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2082
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2083
    def checkRecursion( self, parseElementList ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2084
        subRecCheckList = parseElementList[:] + [ self ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2085
        for e in self.exprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2086
            e.checkRecursion( subRecCheckList )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2087
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2088
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2089
class ParseElementEnhance(ParserElement):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2090
    """Abstract subclass of ParserElement, for combining and post-processing parsed tokens."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2091
    def __init__( self, expr, savelist=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2092
        super(ParseElementEnhance,self).__init__(savelist)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2093
        if isinstance( expr, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2094
            expr = Literal(expr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2095
        self.expr = expr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2096
        self.strRepr = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2097
        if expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2098
            self.mayIndexError = expr.mayIndexError
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2099
            self.setWhitespaceChars( expr.whiteChars )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2100
            self.skipWhitespace = expr.skipWhitespace
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2101
            self.saveAsList = expr.saveAsList
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2102
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2103
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2104
        if self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2105
            return self.expr._parse( instring, loc, doActions, callPreParse=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2106
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2107
            raise ParseException("",loc,self.errmsg,self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2108
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2109
    def leaveWhitespace( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2110
        self.skipWhitespace = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2111
        self.expr = self.expr.copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2112
        if self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2113
            self.expr.leaveWhitespace()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2114
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2115
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2116
    def ignore( self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2117
        if isinstance( other, Suppress ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2118
            if other not in self.ignoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2119
                super( ParseElementEnhance, self).ignore( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2120
                if self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2121
                    self.expr.ignore( self.ignoreExprs[-1] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2122
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2123
            super( ParseElementEnhance, self).ignore( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2124
            if self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2125
                self.expr.ignore( self.ignoreExprs[-1] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2126
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2127
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2128
    def streamline( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2129
        super(ParseElementEnhance,self).streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2130
        if self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2131
            self.expr.streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2132
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2133
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2134
    def checkRecursion( self, parseElementList ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2135
        if self in parseElementList:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2136
            raise RecursiveGrammarException( parseElementList+[self] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2137
        subRecCheckList = parseElementList[:] + [ self ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2138
        if self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2139
            self.expr.checkRecursion( subRecCheckList )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2140
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2141
    def validate( self, validateTrace=[] ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2142
        tmp = validateTrace[:]+[self]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2143
        if self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2144
            self.expr.validate(tmp)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2145
        self.checkRecursion( [] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2146
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2147
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2148
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2149
            return super(ParseElementEnhance,self).__str__()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2150
        except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2151
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2152
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2153
        if self.strRepr is None and self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2154
            self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2155
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2156
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2157
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2158
class FollowedBy(ParseElementEnhance):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2159
    """Lookahead matching of the given parse expression.  FollowedBy
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2160
    does *not* advance the parsing position within the input string, it only 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2161
    verifies that the specified parse expression matches at the current 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2162
    position.  FollowedBy always returns a null token list."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2163
    def __init__( self, expr ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2164
        super(FollowedBy,self).__init__(expr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2165
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2166
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2167
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2168
        self.expr.tryParse( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2169
        return loc, []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2170
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2171
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2172
class NotAny(ParseElementEnhance):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2173
    """Lookahead to disallow matching with the given parse expression.  NotAny
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2174
    does *not* advance the parsing position within the input string, it only 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2175
    verifies that the specified parse expression does *not* match at the current 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2176
    position.  Also, NotAny does *not* skip over leading whitespace. NotAny 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2177
    always returns a null token list.  May be constructed using the '~' operator."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2178
    def __init__( self, expr ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2179
        super(NotAny,self).__init__(expr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2180
        #~ self.leaveWhitespace()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2181
        self.skipWhitespace = False  # do NOT use self.leaveWhitespace(), don't want to propagate to exprs
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2182
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2183
        self.errmsg = "Found unwanted token, "+_ustr(self.expr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2184
        self.myException = ParseException("",0,self.errmsg,self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2185
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2186
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2187
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2188
            self.expr.tryParse( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2189
        except (ParseException,IndexError):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2190
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2191
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2192
            #~ raise ParseException(instring, loc, self.errmsg )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2193
            exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2194
            exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2195
            exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2196
            raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2197
        return loc, []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2198
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2199
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2200
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2201
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2202
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2203
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2204
            self.strRepr = "~{" + _ustr(self.expr) + "}"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2205
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2206
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2207
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2208
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2209
class ZeroOrMore(ParseElementEnhance):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2210
    """Optional repetition of zero or more of the given expression."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2211
    def __init__( self, expr ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2212
        super(ZeroOrMore,self).__init__(expr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2213
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2214
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2215
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2216
        tokens = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2217
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2218
            loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2219
            hasIgnoreExprs = ( len(self.ignoreExprs) > 0 )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2220
            while 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2221
                if hasIgnoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2222
                    preloc = self.skipIgnorables( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2223
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2224
                    preloc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2225
                loc, tmptokens = self.expr._parse( instring, preloc, doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2226
                if tmptokens or tmptokens.keys():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2227
                    tokens += tmptokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2228
        except (ParseException,IndexError):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2229
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2230
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2231
        return loc, tokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2232
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2233
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2234
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2235
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2236
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2237
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2238
            self.strRepr = "[" + _ustr(self.expr) + "]..."
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2239
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2240
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2241
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2242
    def setResultsName( self, name, listAllMatches=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2243
        ret = super(ZeroOrMore,self).setResultsName(name,listAllMatches)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2244
        ret.saveAsList = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2245
        return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2246
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2247
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2248
class OneOrMore(ParseElementEnhance):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2249
    """Repetition of one or more of the given expression."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2250
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2251
        # must be at least one
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2252
        loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2253
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2254
            hasIgnoreExprs = ( len(self.ignoreExprs) > 0 )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2255
            while 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2256
                if hasIgnoreExprs:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2257
                    preloc = self.skipIgnorables( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2258
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2259
                    preloc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2260
                loc, tmptokens = self.expr._parse( instring, preloc, doActions )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2261
                if tmptokens or tmptokens.keys():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2262
                    tokens += tmptokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2263
        except (ParseException,IndexError):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2264
            pass
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2265
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2266
        return loc, tokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2267
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2268
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2269
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2270
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2271
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2272
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2273
            self.strRepr = "{" + _ustr(self.expr) + "}..."
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2274
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2275
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2276
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2277
    def setResultsName( self, name, listAllMatches=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2278
        ret = super(OneOrMore,self).setResultsName(name,listAllMatches)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2279
        ret.saveAsList = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2280
        return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2281
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2282
class _NullToken(object):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2283
    def __bool__(self):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2284
        return False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2285
    def __str__(self):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2286
        return ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2287
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2288
_optionalNotMatched = _NullToken()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2289
class Optional(ParseElementEnhance):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2290
    """Optional matching of the given expression.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2291
       A default return string can also be specified, if the optional expression
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2292
       is not found.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2293
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2294
    def __init__( self, exprs, default=_optionalNotMatched ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2295
        super(Optional,self).__init__( exprs, savelist=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2296
        self.defaultValue = default
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2297
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2298
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2299
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2300
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2301
            loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2302
        except (ParseException,IndexError):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2303
            if self.defaultValue is not _optionalNotMatched:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2304
                tokens = [ self.defaultValue ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2305
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2306
                tokens = []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2307
        return loc, tokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2308
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2309
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2310
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2311
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2312
            
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2313
        if self.strRepr is None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2314
            self.strRepr = "[" + _ustr(self.expr) + "]"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2315
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2316
        return self.strRepr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2317
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2318
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2319
class SkipTo(ParseElementEnhance):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2320
    """Token for skipping over all undefined text until the matched expression is found.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2321
       If include is set to true, the matched expression is also consumed.  The ignore
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2322
       argument is used to define grammars (typically quoted strings and comments) that 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2323
       might contain false matches.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2324
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2325
    def __init__( self, other, include=False, ignore=None ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2326
        super( SkipTo, self ).__init__( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2327
        if ignore is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2328
            self.expr = self.expr.copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2329
            self.expr.ignore(ignore)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2330
        self.mayReturnEmpty = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2331
        self.mayIndexError = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2332
        self.includeMatch = include
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2333
        self.asList = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2334
        self.errmsg = "No match found for "+_ustr(self.expr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2335
        self.myException = ParseException("",0,self.errmsg,self)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2336
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2337
    def parseImpl( self, instring, loc, doActions=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2338
        startLoc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2339
        instrlen = len(instring)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2340
        expr = self.expr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2341
        while loc <= instrlen:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2342
            try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2343
                loc = expr.skipIgnorables( instring, loc )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2344
                expr._parse( instring, loc, doActions=False, callPreParse=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2345
                if self.includeMatch:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2346
                    skipText = instring[startLoc:loc]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2347
                    loc,mat = expr._parse(instring,loc)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2348
                    if mat:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2349
                        return loc, [ skipText, mat ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2350
                    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2351
                        return loc, [ skipText ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2352
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2353
                    return loc, [ instring[startLoc:loc] ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2354
            except (ParseException,IndexError):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2355
                loc += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2356
        exc = self.myException
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2357
        exc.loc = loc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2358
        exc.pstr = instring
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2359
        raise exc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2360
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2361
class Forward(ParseElementEnhance):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2362
    """Forward declaration of an expression to be defined later -
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2363
       used for recursive grammars, such as algebraic infix notation.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2364
       When the expression is known, it is assigned to the Forward variable using the '<<' operator.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2365
       
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2366
       Note: take care when assigning to Forward not to overlook precedence of operators.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2367
       Specifically, '|' has a lower precedence than '<<', so that::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2368
          fwdExpr << a | b | c
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2369
       will actually be evaluated as::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2370
          (fwdExpr << a) | b | c
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2371
       thereby leaving b and c out as parseable alternatives.  It is recommended that you
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2372
       explicitly group the values inserted into the Forward::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2373
          fwdExpr << (a | b | c)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2374
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2375
    def __init__( self, other=None ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2376
        super(Forward,self).__init__( other, savelist=False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2377
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2378
    def __lshift__( self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2379
        if isinstance( other, basestring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2380
            other = Literal(other)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2381
        self.expr = other
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2382
        self.mayReturnEmpty = other.mayReturnEmpty
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2383
        self.strRepr = None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2384
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2385
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2386
    def leaveWhitespace( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2387
        self.skipWhitespace = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2388
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2389
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2390
    def streamline( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2391
        if not self.streamlined:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2392
            self.streamlined = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2393
            if self.expr is not None: 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2394
                self.expr.streamline()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2395
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2396
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2397
    def validate( self, validateTrace=[] ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2398
        if self not in validateTrace:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2399
            tmp = validateTrace[:]+[self]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2400
            if self.expr is not None: 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2401
                self.expr.validate(tmp)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2402
        self.checkRecursion([])        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2403
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2404
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2405
        if hasattr(self,"name"):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2406
            return self.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2407
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2408
        self.__class__ = _ForwardNoRecurse
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2409
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2410
            if self.expr is not None: 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2411
                retString = _ustr(self.expr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2412
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2413
                retString = "None"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2414
        finally:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2415
            self.__class__ = Forward
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2416
        return "Forward: "+retString
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2417
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2418
    def copy(self):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2419
        if self.expr is not None:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2420
            return super(Forward,self).copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2421
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2422
            ret = Forward()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2423
            ret << self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2424
            return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2425
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2426
class _ForwardNoRecurse(Forward):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2427
    def __str__( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2428
        return "..."
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2429
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2430
class TokenConverter(ParseElementEnhance):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2431
    """Abstract subclass of ParseExpression, for converting parsed results."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2432
    def __init__( self, expr, savelist=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2433
        super(TokenConverter,self).__init__( expr )#, savelist )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2434
        self.saveAsList = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2435
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2436
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2437
class Upcase(TokenConverter):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2438
    """Converter to upper case all matching tokens."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2439
    def __init__(self, *args):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2440
        super(Upcase,self).__init__(*args)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2441
        warnings.warn("Upcase class is deprecated, use upcaseTokens parse action instead", 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2442
                       DeprecationWarning,stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2443
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2444
    def postParse( self, instring, loc, tokenlist ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2445
        return map( string.upper, tokenlist )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2446
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2447
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2448
class Combine(TokenConverter):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2449
    """Converter to concatenate all matching tokens to a single string.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2450
       By default, the matching patterns must also be contiguous in the input string;
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2451
       this can be disabled by specifying 'adjacent=False' in the constructor.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2452
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2453
    def __init__( self, expr, joinString="", adjacent=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2454
        super(Combine,self).__init__( expr )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2455
        # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2456
        if adjacent:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2457
            self.leaveWhitespace()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2458
        self.adjacent = adjacent
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2459
        self.skipWhitespace = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2460
        self.joinString = joinString
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2461
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2462
    def ignore( self, other ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2463
        if self.adjacent:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2464
            ParserElement.ignore(self, other)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2465
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2466
            super( Combine, self).ignore( other )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2467
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2468
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2469
    def postParse( self, instring, loc, tokenlist ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2470
        retToks = tokenlist.copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2471
        del retToks[:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2472
        retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2473
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2474
        if self.resultsName and len(retToks.keys())>0:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2475
            return [ retToks ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2476
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2477
            return retToks
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2478
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2479
class Group(TokenConverter):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2480
    """Converter to return the matched tokens as a list - useful for returning tokens of ZeroOrMore and OneOrMore expressions."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2481
    def __init__( self, expr ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2482
        super(Group,self).__init__( expr )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2483
        self.saveAsList = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2484
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2485
    def postParse( self, instring, loc, tokenlist ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2486
        return [ tokenlist ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2487
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2488
class Dict(TokenConverter):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2489
    """Converter to return a repetitive expression as a list, but also as a dictionary.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2490
       Each element can also be referenced using the first token in the expression as its key.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2491
       Useful for tabular report scraping when the first column can be used as a item key.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2492
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2493
    def __init__( self, exprs ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2494
        super(Dict,self).__init__( exprs )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2495
        self.saveAsList = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2496
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2497
    def postParse( self, instring, loc, tokenlist ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2498
        for i,tok in enumerate(tokenlist):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2499
            ikey = _ustr(tok[0]).strip()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2500
            if len(tok)==1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2501
                tokenlist[ikey] = ("",i)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2502
            elif len(tok)==2 and not isinstance(tok[1],ParseResults):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2503
                tokenlist[ikey] = (tok[1],i)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2504
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2505
                dictvalue = tok.copy() #ParseResults(i)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2506
                del dictvalue[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2507
                if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.keys()):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2508
                    tokenlist[ikey] = (dictvalue,i)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2509
                else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2510
                    tokenlist[ikey] = (dictvalue[0],i)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2511
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2512
        if self.resultsName:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2513
            return [ tokenlist ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2514
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2515
            return tokenlist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2516
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2517
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2518
class Suppress(TokenConverter):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2519
    """Converter for ignoring the results of a parsed expression."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2520
    def postParse( self, instring, loc, tokenlist ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2521
        return []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2522
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2523
    def suppress( self ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2524
        return self
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2525
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2526
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2527
class OnlyOnce(object):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2528
    """Wrapper for parse actions, to ensure they are only called once."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2529
    def __init__(self, methodCall):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2530
        self.callable = ParserElement.normalizeParseActionArgs(methodCall)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2531
        self.called = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2532
    def __call__(self,s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2533
        if not self.called:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2534
            results = self.callable(s,l,t)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2535
            self.called = True
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2536
            return results
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2537
        raise ParseException(s,l,"")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2538
    def reset():
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2539
        self.called = False
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2540
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2541
def traceParseAction(f):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2542
    """Decorator for debugging parse actions."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2543
    f = ParserElement.normalizeParseActionArgs(f)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2544
    def z(*paArgs):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2545
        thisFunc = f.func_name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2546
        s,l,t = paArgs[-3:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2547
        if len(paArgs)>3:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2548
            thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2549
        sys.stderr.write( ">>entering %s(line: '%s', %d, %s)\n" % (thisFunc,line(l,s),l,t) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2550
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2551
            ret = f(*paArgs)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2552
        except Exception, exc:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2553
            sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2554
            raise
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2555
        sys.stderr.write( "<<leaving %s (ret: %s)\n" % (thisFunc,ret) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2556
        return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2557
    return z
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2558
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2559
#
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2560
# global helpers
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2561
#
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2562
def delimitedList( expr, delim=",", combine=False ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2563
    """Helper to define a delimited list of expressions - the delimiter defaults to ','.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2564
       By default, the list elements and delimiters can have intervening whitespace, and 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2565
       comments, but this can be overridden by passing 'combine=True' in the constructor.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2566
       If combine is set to True, the matching tokens are returned as a single token
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2567
       string, with the delimiters included; otherwise, the matching tokens are returned
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2568
       as a list of tokens, with the delimiters suppressed.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2569
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2570
    dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..."
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2571
    if combine:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2572
        return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2573
    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2574
        return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2575
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2576
def countedArray( expr ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2577
    """Helper to define a counted list of expressions.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2578
       This helper defines a pattern of the form::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2579
           integer expr expr expr...
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2580
       where the leading integer tells how many expr expressions follow.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2581
       The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2582
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2583
    arrayExpr = Forward()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2584
    def countFieldParseAction(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2585
        n = int(t[0])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2586
        arrayExpr << (n and Group(And([expr]*n)) or Group(empty))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2587
        return []
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2588
    return ( Word(nums).setParseAction(countFieldParseAction) + arrayExpr )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2589
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2590
def _flatten(L):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2591
    if type(L) is not list: return [L]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2592
    if L == []: return L
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2593
    return _flatten(L[0]) + _flatten(L[1:])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2594
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2595
def matchPreviousLiteral(expr):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2596
    """Helper to define an expression that is indirectly defined from
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2597
       the tokens matched in a previous expression, that is, it looks
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2598
       for a 'repeat' of a previous expression.  For example::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2599
           first = Word(nums)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2600
           second = matchPreviousLiteral(first)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2601
           matchExpr = first + ":" + second
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2602
       will match "1:1", but not "1:2".  Because this matches a 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2603
       previous literal, will also match the leading "1:1" in "1:10".  
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2604
       If this is not desired, use matchPreviousExpr.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2605
       Do *not* use with packrat parsing enabled.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2606
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2607
    rep = Forward()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2608
    def copyTokenToRepeater(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2609
        if t:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2610
            if len(t) == 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2611
                rep << t[0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2612
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2613
                # flatten t tokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2614
                tflat = _flatten(t.asList())
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2615
                rep << And( [ Literal(tt) for tt in tflat ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2616
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2617
            rep << Empty()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2618
    expr.addParseAction(copyTokenToRepeater)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2619
    return rep
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2620
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2621
def matchPreviousExpr(expr):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2622
    """Helper to define an expression that is indirectly defined from
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2623
       the tokens matched in a previous expression, that is, it looks
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2624
       for a 'repeat' of a previous expression.  For example::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2625
           first = Word(nums)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2626
           second = matchPreviousExpr(first)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2627
           matchExpr = first + ":" + second
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2628
       will match "1:1", but not "1:2".  Because this matches by
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2629
       expressions, will *not* match the leading "1:1" in "1:10";
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2630
       the expressions are evaluated first, and then compared, so
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2631
       "1" is compared with "10".
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2632
       Do *not* use with packrat parsing enabled.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2633
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2634
    rep = Forward()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2635
    e2 = expr.copy()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2636
    rep << e2
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2637
    def copyTokenToRepeater(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2638
        matchTokens = _flatten(t.asList())
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2639
        def mustMatchTheseTokens(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2640
            theseTokens = _flatten(t.asList())
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2641
            if  theseTokens != matchTokens:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2642
                raise ParseException("",0,"")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2643
        rep.setParseAction( mustMatchTheseTokens )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2644
    expr.addParseAction(copyTokenToRepeater)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2645
    return rep
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2646
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2647
def _escapeRegexRangeChars(s):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2648
    #~  escape these chars: ^-]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2649
    for c in r"\^-]":
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2650
        s = s.replace(c,"\\"+c)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2651
    s = s.replace("\n",r"\n")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2652
    s = s.replace("\t",r"\t")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2653
    return _ustr(s)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2654
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2655
def oneOf( strs, caseless=False, useRegex=True ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2656
    """Helper to quickly define a set of alternative Literals, and makes sure to do 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2657
       longest-first testing when there is a conflict, regardless of the input order, 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2658
       but returns a MatchFirst for best performance.  
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2659
       
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2660
       Parameters:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2661
        - strs - a string of space-delimited literals, or a list of string literals
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2662
        - caseless - (default=False) - treat all literals as caseless
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2663
        - useRegex - (default=True) - as an optimization, will generate a Regex
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2664
          object; otherwise, will generate a MatchFirst object (if caseless=True, or
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2665
          if creating a Regex raises an exception)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2666
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2667
    if caseless:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2668
        isequal = ( lambda a,b: a.upper() == b.upper() )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2669
        masks = ( lambda a,b: b.upper().startswith(a.upper()) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2670
        parseElementClass = CaselessLiteral
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2671
    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2672
        isequal = ( lambda a,b: a == b )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2673
        masks = ( lambda a,b: b.startswith(a) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2674
        parseElementClass = Literal
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2675
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2676
    if isinstance(strs,(list,tuple)):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2677
        symbols = strs[:]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2678
    elif isinstance(strs,basestring):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2679
        symbols = strs.split()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2680
    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2681
        warnings.warn("Invalid argument to oneOf, expected string or list",
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2682
                SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2683
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2684
    i = 0
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2685
    while i < len(symbols)-1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2686
        cur = symbols[i]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2687
        for j,other in enumerate(symbols[i+1:]):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2688
            if ( isequal(other, cur) ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2689
                del symbols[i+j+1]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2690
                break
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2691
            elif ( masks(cur, other) ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2692
                del symbols[i+j+1]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2693
                symbols.insert(i,other)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2694
                cur = other
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2695
                break
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2696
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2697
            i += 1
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2698
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2699
    if not caseless and useRegex:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2700
        #~ print strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2701
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2702
            if len(symbols)==len("".join(symbols)):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2703
                return Regex( "[%s]" % "".join( [ _escapeRegexRangeChars(sym) for sym in symbols] ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2704
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2705
                return Regex( "|".join( [ re.escape(sym) for sym in symbols] ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2706
        except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2707
            warnings.warn("Exception creating Regex for oneOf, building MatchFirst",
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2708
                    SyntaxWarning, stacklevel=2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2709
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2710
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2711
    # last resort, just use MatchFirst
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2712
    return MatchFirst( [ parseElementClass(sym) for sym in symbols ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2713
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2714
def dictOf( key, value ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2715
    """Helper to easily and clearly define a dictionary by specifying the respective patterns
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2716
       for the key and value.  Takes care of defining the Dict, ZeroOrMore, and Group tokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2717
       in the proper order.  The key pattern can include delimiting markers or punctuation,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2718
       as long as they are suppressed, thereby leaving the significant key text.  The value
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2719
       pattern can include named results, so that the Dict results can include named token 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2720
       fields.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2721
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2722
    return Dict( ZeroOrMore( Group ( key + value ) ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2723
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2724
_bslash = "\\"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2725
printables = "".join( [ c for c in string.printable if c not in string.whitespace ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2726
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2727
# convenience constants for positional expressions
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2728
empty       = Empty().setName("empty")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2729
lineStart   = LineStart().setName("lineStart")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2730
lineEnd     = LineEnd().setName("lineEnd")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2731
stringStart = StringStart().setName("stringStart")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2732
stringEnd   = StringEnd().setName("stringEnd")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2733
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2734
_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2735
_printables_less_backslash = "".join([ c for c in printables if c not in  r"\]" ])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2736
_escapedHexChar = Combine( Suppress(_bslash + "0x") + Word(hexnums) ).setParseAction(lambda s,l,t:unichr(int(t[0],16)))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2737
_escapedOctChar = Combine( Suppress(_bslash) + Word("0","01234567") ).setParseAction(lambda s,l,t:unichr(int(t[0],8)))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2738
_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(_printables_less_backslash,exact=1)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2739
_charRange = Group(_singleChar + Suppress("-") + _singleChar)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2740
_reBracketExpr = "[" + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2741
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2742
_expanded = lambda p: (isinstance(p,ParseResults) and ''.join([ unichr(c) for c in range(ord(p[0]),ord(p[1])+1) ]) or p)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2743
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2744
def srange(s):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2745
    r"""Helper to easily define string ranges for use in Word construction.  Borrows
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2746
       syntax from regexp '[]' string range definitions::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2747
          srange("[0-9]")   -> "0123456789"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2748
          srange("[a-z]")   -> "abcdefghijklmnopqrstuvwxyz"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2749
          srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2750
       The input string must be enclosed in []'s, and the returned string is the expanded 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2751
       character set joined into a single string.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2752
       The values enclosed in the []'s may be::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2753
          a single character
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2754
          an escaped character with a leading backslash (such as \- or \])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2755
          an escaped hex character with a leading '\0x' (\0x21, which is a '!' character)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2756
          an escaped octal character with a leading '\0' (\041, which is a '!' character)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2757
          a range of any of the above, separated by a dash ('a-z', etc.)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2758
          any combination of the above ('aeiouy', 'a-zA-Z0-9_$', etc.)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2759
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2760
    try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2761
        return "".join([_expanded(part) for part in _reBracketExpr.parseString(s).body])
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2762
    except:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2763
        return ""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2764
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2765
def replaceWith(replStr):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2766
    """Helper method for common parse actions that simply return a literal value.  Especially 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2767
       useful when used with transformString().
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2768
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2769
    def _replFunc(*args):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2770
        return [replStr]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2771
    return _replFunc
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2772
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2773
def removeQuotes(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2774
    """Helper parse action for removing quotation marks from parsed quoted strings.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2775
       To use, add this parse action to quoted string using::
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2776
         quotedString.setParseAction( removeQuotes )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2777
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2778
    return t[0][1:-1]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2779
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2780
def upcaseTokens(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2781
    """Helper parse action to convert tokens to upper case."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2782
    return [ str(tt).upper() for tt in t ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2783
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2784
def downcaseTokens(s,l,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2785
    """Helper parse action to convert tokens to lower case."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2786
    return [ str(tt).lower() for tt in t ]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2787
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2788
def keepOriginalText(s,startLoc,t):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2789
    import inspect
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2790
    """Helper parse action to preserve original parsed text,
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2791
       overriding any nested parse actions."""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2792
    f = inspect.stack()[1][0]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2793
    try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2794
        endloc = f.f_locals["loc"]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2795
    finally:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2796
        del f
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2797
    return s[startLoc:endloc]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2798
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2799
def _makeTags(tagStr, xml):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2800
    """Internal helper to construct opening and closing tag expressions, given a tag name"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2801
    if isinstance(tagStr,basestring):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2802
        resname = tagStr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2803
        tagStr = Keyword(tagStr, caseless=not xml)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2804
    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2805
        resname = tagStr.name
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2806
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2807
    tagAttrName = Word(alphas,alphanums+"_-")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2808
    if (xml):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2809
        tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2810
        openTag = Suppress("<") + tagStr + \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2811
                Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2812
                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2813
    else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2814
        printablesLessRAbrack = "".join( [ c for c in printables if c not in ">" ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2815
        tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2816
        openTag = Suppress("<") + tagStr + \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2817
                Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2818
                Suppress("=") + tagAttrValue ))) + \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2819
                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2820
    closeTag = Combine("</" + tagStr + ">")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2821
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2822
    openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % tagStr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2823
    closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % tagStr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2824
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2825
    return openTag, closeTag
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2826
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2827
def makeHTMLTags(tagStr):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2828
    """Helper to construct opening and closing tag expressions for HTML, given a tag name"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2829
    return _makeTags( tagStr, False )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2830
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2831
def makeXMLTags(tagStr):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2832
    """Helper to construct opening and closing tag expressions for XML, given a tag name"""
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2833
    return _makeTags( tagStr, True )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2834
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2835
opAssoc = _Constants()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2836
opAssoc.LEFT = object()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2837
opAssoc.RIGHT = object()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2838
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2839
def operatorPrecedence( baseExpr, opList ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2840
    """Helper method for constructing grammars of expressions made up of 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2841
       operators working in a precedence hierarchy.  Operators may be unary or
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2842
       binary, left- or right-associative.  Parse actions can also be attached
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2843
       to operator expressions.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2844
        
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2845
       Parameters:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2846
        - baseExpr - expression representing the most basic element for the nested 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2847
        - opList - list of tuples, one for each operator precedence level in the expression grammar; each tuple is of the form
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2848
          (opExpr, numTerms, rightLeftAssoc, parseAction), where:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2849
           - opExpr is the pyparsing expression for the operator;
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2850
              may also be a string, which will be converted to a Literal
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2851
           - numTerms is the number of terms for this operator (must
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2852
              be 1 or 2)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2853
           - rightLeftAssoc is the indicator whether the operator is
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2854
              right or left associative, using the pyparsing-defined
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2855
              constants opAssoc.RIGHT and opAssoc.LEFT.
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2856
           - parseAction is the parse action to be associated with 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2857
              expressions matching this operator expression (the
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2858
              parse action tuple member may be omitted)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2859
    """
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2860
    ret = Forward()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2861
    lastExpr = baseExpr | ( Suppress('(') + ret + Suppress(')') )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2862
    for i,operDef in enumerate(opList):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2863
        opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4]
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2864
        thisExpr = Forward().setName("expr%d" % i)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2865
        if rightLeftAssoc == opAssoc.LEFT:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2866
            if arity == 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2867
                matchExpr = Group( lastExpr + opExpr )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2868
            elif arity == 2:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2869
                matchExpr = Group( lastExpr + OneOrMore( opExpr + lastExpr ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2870
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2871
                raise ValueError, "operator must be unary (1) or binary (2)"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2872
        elif rightLeftAssoc == opAssoc.RIGHT:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2873
            if arity == 1:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2874
                # try to avoid LR with this extra test
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2875
                if not isinstance(opExpr, Optional):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2876
                    opExpr = Optional(opExpr)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2877
                matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2878
            elif arity == 2:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2879
                matchExpr = Group( lastExpr + OneOrMore( opExpr + thisExpr ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2880
            else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2881
                raise ValueError, "operator must be unary (1) or binary (2)"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2882
        else:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2883
            raise ValueError, "operator must indicate right or left associativity"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2884
        if pa:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2885
            matchExpr.setParseAction( pa )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2886
        thisExpr << ( matchExpr | lastExpr )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2887
        lastExpr = thisExpr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2888
    ret << lastExpr
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2889
    return ret
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2890
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2891
alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2892
punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2893
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2894
dblQuotedString = Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\.))*"').setName("string enclosed in double quotes")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2895
sglQuotedString = Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\.))*'").setName("string enclosed in single quotes")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2896
quotedString = Regex(r'''(?:"(?:[^"\n\r\\]|(?:"")|(?:\\.))*")|(?:'(?:[^'\n\r\\]|(?:'')|(?:\\.))*')''').setName("quotedString using single or double quotes")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2897
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2898
anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_"))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2899
commonHTMLEntity = Combine("&" + oneOf("gt lt amp nbsp quot").setResultsName("entity") +";")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2900
_htmlEntityMap = dict(zip("gt lt amp nbsp quot".split(),"><& '"))
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2901
replaceHTMLEntity = lambda t : t.entity in _htmlEntityMap and _htmlEntityMap[t.entity] or None
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2902
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2903
# it's easy to get these comment structures wrong - they're very common, so may as well make them available
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2904
cStyleComment = Regex(r"/\*(?:[^*]*\*+)+?/").setName("C style comment")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2905
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2906
htmlComment = Regex(r"<!--[\s\S]*?-->")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2907
restOfLine = Regex(r".*").leaveWhitespace()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2908
dblSlashComment = Regex(r"\/\/(\\\n|.)*").setName("// comment")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2909
cppStyleComment = Regex(r"/(?:\*(?:[^*]*\*+)+?/|/[^\n]*(?:\n[^\n]*)*?(?:(?<!\\)|\Z))").setName("C++ style comment")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2910
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2911
javaStyleComment = cppStyleComment
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2912
pythonStyleComment = Regex(r"#.*").setName("Python style comment")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2913
_noncomma = "".join( [ c for c in printables if c != "," ] )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2914
_commasepitem = Combine(OneOrMore(Word(_noncomma) + 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2915
                                  Optional( Word(" \t") + 
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2916
                                            ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2917
commaSeparatedList = delimitedList( Optional( quotedString | _commasepitem, default="") ).setName("commaSeparatedList")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2918
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2919
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2920
if __name__ == "__main__":
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2921
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2922
    def test( teststring ):
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2923
        print teststring,"->",
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2924
        try:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2925
            tokens = simpleSQL.parseString( teststring )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2926
            tokenlist = tokens.asList()
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2927
            print tokenlist
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2928
            print "tokens = ",        tokens
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2929
            print "tokens.columns =", tokens.columns
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2930
            print "tokens.tables =",  tokens.tables
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2931
            print tokens.asXML("SQL",True)
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2932
        except ParseException, err:
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2933
            print err.line
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2934
            print " "*(err.column-1) + "^"
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2935
            print err
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2936
        print
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2937
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2938
    selectToken    = CaselessLiteral( "select" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2939
    fromToken      = CaselessLiteral( "from" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2940
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2941
    ident          = Word( alphas, alphanums + "_$" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2942
    columnName     = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2943
    columnNameList = Group( delimitedList( columnName ) )#.setName("columns")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2944
    tableName      = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2945
    tableNameList  = Group( delimitedList( tableName ) )#.setName("tables")
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2946
    simpleSQL      = ( selectToken + \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2947
                     ( '*' | columnNameList ).setResultsName( "columns" ) + \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2948
                     fromToken + \
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2949
                     tableNameList.setResultsName( "tables" ) )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2950
    
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2951
    test( "SELECT * from XYZZY, ABC" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2952
    test( "select * from SYS.XYZZY" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2953
    test( "Select A from Sys.dual" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2954
    test( "Select AA,BB,CC from Sys.dual" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2955
    test( "Select A, B, C from Sys.dual" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2956
    test( "Select A, B, C from Sys.dual" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2957
    test( "Xelect A, B, C from Sys.dual" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2958
    test( "Select A, B, C frox Sys.dual" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2959
    test( "Select" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2960
    test( "Select ^^^ frox Sys.dual" )
e1eecf4d390d Team sf branch.
tnmurphy@4GBL06592.nokia.com
parents: 0
diff changeset
  2961
    test( "Select A, B, C from Sys.dual, Table2   " )