ePolyglot: Examination and development of multilanguage programming using Eiffel, Python, and Haskell | ||
---|---|---|
Prev | Chapter 10. User Modules | Next |
Since we're now able to export entire Python modules with relative ease, let's put one to work. One of the often-touted features of the Python language is its ability to manipulate text easily, and one of the keys to this is its powerful abilities to use and manipulate Unix-style regular expressions. Its main tool for this is the simple but powerful re module, which makes use of the extremely complex but powerful regular expression language. Using re from within Python is extremely easy:
Example 10-6. Using re from within Python
Python 1.5.2 (#1, Sep 17 1999, 20:15:36) [GCC egcs-2.91.66 19990314/Linux (egcs- on linux-i386 Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam >>> import re >>> r = re.compile( r"^\D*(\d*)" ) >>> m = r.match( "blahblah42blahblah" ) >>> m.groups(0) ('42',) >>> re.split( "--", "this--is a simple--test" ) ['this', 'is a simple', 'test'] |
It would be nice to have something even close to that expressive power under Eiffel. Using the make targets listed in the previous section, the make_all_eiffel_stubs.py script was able to export the re module and its enclosed classes, allowing us to write the single source program below. If you remove the many std_output.put_string lines which exist to produce output illustrating what's happening, the actual lines of code doing the job are remarkably similar; for example, the Python line
r = re.compile( r"^\D*(\d*)" ) |
Maps pretty directly into the equivalent Eiffel program line
create r.make_from_python_object( re.compile( << "^\D(\d*)" >> ) ) |
...which is a little more verbose but still extremely handy. Complete source for the re_test program is below:
Example 10-7. The re_test sample application
class RE_TEST inherit PYTHON_CLIENT creation make feature make is local r : RE_REGEXOBJECT s : STRING m : RE_MATCHOBJECT o : PYTHON_OBJECT re : RE do std_output.put_string( "%Nre_test : uses Python 're' module to % %manipulate Eiffel strings%N%N" ) py_initialize create re.make --create a simple regex that should find the first number in a string... create r.make_from_python_object( re.compile( << "^\D*(\d*)" >> ) ) std_output.put_string( r.to_string + "%N" ) std_output.put_string( "Regex object created from pattern " + r.get_attr_string( "pattern" ).to_string + "%N" ) --now search in a string for the regex s := "blahblah42blahblah" std_output.put_string( "Searching in " + s + "%N" ) create m.make_from_python_object( r.match( << s >> ) ) std_output.put_string( "Found group: " + m.groups(<<0>>).to_string + "%N" ) std_output.put_new_line --now use the module's "split" command to split a string std_output.put_string( "Splitting 'this--is a simple--test' % %on '--'%N" ) std_output.put_string( "Result: " + re.split( << "--", "this--is a simple--test" >> ).to_string ) std_output.put_new_line rescue if not py_err_occurred.is_null then py_err_print end end end |
...which, when executed, produces the following output, strikingly similar to that produced by the Python interpreter above:
Example 10-8. Output from the re_test program
[vputz@yak_prime re]$ ./re_test re_test : uses Python 're' module to manipulate Eiffel strings <re.RegexObject instance at 80f3f08> Regex object created from pattern '^\\D*(\\d*)' Searching in blahblah42blahblah Found group: ('42',) Splitting 'this--is a simple--test' on '--' Result: ['this', 'is a simple', 'test'] |