[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Python-based regular expression parser that allows patterns to call functions?

Andrew Warkentin

3/2/2008 2:41:00 PM

I am writing a filtering HTTP proxy (the site is
http://xuproxy.source...). I want it to be compatible with
Proxomitron (http://proxomi...) filters. I need a regular
expression parser that allows patterns to call functions (or more
likely, class methods), to implement "matching commands" (look at the
Proxmitron documentation to see what I mean). Does anyone know if such a
library exists for Python, or do I have to write my own parser?
3 Answers

Aaron Brady

3/2/2008 4:01:00 PM

0

On Mar 2, 8:41 am, Andrew Warkentin <andr...@datanet.ab.ca> wrote:
> I am writing a filtering HTTP proxy (the site ishttp://xuproxy.sourcef...). I want it to be compatible with
> Proxomitron (http://proxomi...) filters. I need a regular
> expression parser that allows patterns to call functions (or more
> likely, class methods), to implement "matching commands" (look at the
> Proxmitron documentation to see what I mean). Does anyone know if such a
> library exists for Python, or do I have to write my own parser?

To make a list of commands available:

class C:
def behavior( self ): pass
def behavior2( self ): pass
cmds= [ behavior, behavior2 ]

Then search C.cmds for a match to the regular expression.
C.behavior.func_name contains the string 'behavior' for checking. You
might need to "bind" the contents of C.cmds before you call them too.
More info available, just ask.

You can also do:

class C:
@string_callable
def behavior( self ): pass
@string_callable
def behavior2( self ): pass

and

class C:
def behavior( self ): pass
def behavior2( self ): pass
cmds= [ 'behavior', 'behavior2' ]

(strings this time), and use getattr( C, 'behavior' ) or for c= C(),
getattr( c, 'behavior' ).

class C:
def behavior( self ): pass
def behavior2( self ): pass
cmds= [ 'behavior', 'behavior2' ]
C.cmds= commandmap( C, C.cmds )

can generate a dictionary of strings to methods. And there's always

getattr( c, strA ), for your choice of strA, which throws an exception
if strA is not an attribute (method or property) of c, and hasattr( c,
strA ) can test if it is.

You less often want to generate distinct functions based on parameters
only, but you can.

c= C()
def behavior3( self ): pass
c.behavior3= behavior3

so c.behavior3() is legal.

Where does that get you?

Paul McGuire

3/2/2008 4:54:00 PM

0

On Mar 2, 8:41 am, Andrew Warkentin <andr...@datanet.ab.ca> wrote:
> I am writing a filtering HTTP proxy (the site ishttp://xuproxy.sourcef...). I want it to be compatible with
> Proxomitron (http://proxomi...) filters. I need a regular
> expression parser that allows patterns to call functions (or more
> likely, class methods), to implement "matching commands" (look at the
> Proxmitron documentation to see what I mean). Does anyone know if such a
> library exists for Python, or do I have to write my own parser?

Andrew -

Pyparsing allows you to define parse actions that get called when
element within a grammar are matched. These actions can update
external data structures, modify the matched text, or can be used to
provide additional semantic validation. Here's an example:

from pyparsing import *

integer = Regex(r"\b\d+\b")
# could also be written as
#~ integer = WordStart() + Word(nums) + WordEnd()

# convert matched text to actual integer
def cvt_to_int (tokens):
return int(tokens[0])

# only accept integers < 100
def must_be_less_than_100(tokens):
if (tokens[0]) >= 100:
raise ParseException("only integers < 100 are allowed")

# add value to running tally of matches
def increment_tally(tokens):
global running_total
running_total += tokens[0]

integer.setParseAction( cvt_to_int)
integer.addParseAction( must_be_less_than_100 )
integer.addParseAction( increment_tally )

# could also be written as
#~ integer.setParseAction( cvt_to_int,
#~ must_be_less_than_100,
#~ increment_tally )

running_total = 0
print integer.searchString("absdlkj 1 5 12 121 78 22")
print running_total

Prints:

[[1], [5], [12], [78], [22]]
118

More info about pyparsing at http://pyparsing.wiki..., plus
more examples, and links to other doc sources.

-- Paul

Paul McGuire

3/3/2008 4:22:00 AM

0

pyparsing also includes a decorator function, traceParseAction, which
will list out calls to parse actions, the tokens passed in, and the
value returned or exception raised. If you add "@traceParseAction"
before each of the parse actions in my example, you can see the token
processing being done in the parse actions.

-- Paul