pyparsing: match empty line

Marek Kubica marek at xivilization.net
Wed Sep 3 10:08:50 EDT 2008


On Wed, 03 Sep 2008 06:12:47 -0700, Paul McGuire wrote:

> On Sep 3, 4:26 am, Marek Kubica <ma... at xivilization.net> wrote:

>> I could set the whitespace
>> on every element, but that is as you surely agree quite ugly. Do you
>> accept patches? I'm thinking about some kind of factory-class which
>> would automatically set the whitespaces:
>>
>> >>> factory = TokenFactory(' \t\r')
>> >>> word = Factory.Word(alphas)
>>
>> That way, one wouldn't need to set a grobal value which might interfere
>> with other pyparsers running in the same process.
> 
> I tried to prototype up your TokenFactory class, but once I got as far
> as implementing __getattribute__ to return the corresponding pyparsing
> class, I couldn't see how to grab the object generated for that class,
> and modify its whitespace values.

I have had the same problem, until I remembered that I can fake __init__ 
using a function closure.

I have imported pyparsing.py into a hg repository with a patchstack, here 
is my first patch:

diff -r 12e2bbff259e pyparsing.py
--- a/pyparsing.py      Wed Sep 03 09:40:09 2008 +0000
+++ b/pyparsing.py      Wed Sep 03 14:08:15 2008 +0000
@@ -1400,9 +1400,38 @@
     def __req__(self,other):
         return self == other
 
+class TokenFinder(type):
+    """Collects all classes that are derived from Token"""
+    token_classes = dict()
+    def __init__(cls, name, bases, dict):
+        # save the class
+        TokenFinder.token_classes[cls.__name__] = cls
+
+class WhitespaceTokenFactory(object):
+    def __init__(self, whitespace):
+        self._whitespace = whitespace
+
+    def __getattr__(self, name):
+        """Get an attribute of this class"""
+        # check whether there is such a Token
+        if name in TokenFinder.token_classes:
+            token = TokenFinder.token_classes[name]
+            # construct a closure which fakes the constructor
+            def _callable(*args, **kwargs):
+                obj = token(*args, **kwargs)
+                # set the whitespace on the token
+                obj.setWhitespaceChars(self._whitespace)
+                return obj
+            # return the function which returns an instance of the Token
+            return _callable
+        else:
+            raise AttributeError("'%s' object has no attribute '%s'" % (
+                WhitespaceTokenFactory.__name__, name))
 
 class Token(ParserElement):
     """Abstract ParserElement subclass, for defining atomic matching 
patterns."""
+    __metaclass__ = TokenFinder
+
     def __init__( self ):

I used metaclasses for getting all Token-subclasses so new classes that 
are created are automatically accessible via the factory, without any 
additional registration.

Oh and yes, more patches will follow. I'm currently editing the second 
patch, but I better mail it directly to you as it is not really 
interesting for this list.

regards,
Marek



More information about the Python-list mailing list