[Python-modules-commits] r25005 - in packages/pyexcelerator/trunk (34 files)

dktrkranz at users.alioth.debian.org dktrkranz at users.alioth.debian.org
Thu Jun 27 21:58:45 UTC 2013


    Date: Thursday, June 27, 2013 @ 21:58:43
  Author: dktrkranz
Revision: 25005

Apply changes included in 0.6.4.1-1 upload

Added:
  packages/pyexcelerator/trunk/.cvsignore
  packages/pyexcelerator/trunk/examples/xls2csv.py
  packages/pyexcelerator/trunk/examples/xls2html.py
  packages/pyexcelerator/trunk/examples/xls2txt.py
  packages/pyexcelerator/trunk/pyExcelerator/antlr.py
Modified:
  packages/pyexcelerator/trunk/CHANGES.txt
  packages/pyexcelerator/trunk/TODO.txt
  packages/pyexcelerator/trunk/debian/changelog
  packages/pyexcelerator/trunk/debian/compat
  packages/pyexcelerator/trunk/debian/control
  packages/pyexcelerator/trunk/debian/docs
  packages/pyexcelerator/trunk/debian/patches/01-write_datetime.dpatch
  packages/pyexcelerator/trunk/examples/format.py
  packages/pyexcelerator/trunk/examples/formula_names.py
  packages/pyexcelerator/trunk/examples/formulas.py
  packages/pyexcelerator/trunk/examples/hyperlinks.py
  packages/pyexcelerator/trunk/examples/parse-fmla.py
  packages/pyexcelerator/trunk/museum/mini-mini.xls
  packages/pyexcelerator/trunk/museum/mini.xls
  packages/pyexcelerator/trunk/pyExcelerator/BIFFRecords.py
  packages/pyexcelerator/trunk/pyExcelerator/Cell.py
  packages/pyexcelerator/trunk/pyExcelerator/Column.py
  packages/pyexcelerator/trunk/pyExcelerator/CompoundDoc.py
  packages/pyexcelerator/trunk/pyExcelerator/ExcelFormula.py
  packages/pyexcelerator/trunk/pyExcelerator/ExcelFormulaLexer.py
  packages/pyexcelerator/trunk/pyExcelerator/ExcelFormulaParser.py
  packages/pyexcelerator/trunk/pyExcelerator/Formatting.py
  packages/pyexcelerator/trunk/pyExcelerator/Row.py
  packages/pyexcelerator/trunk/pyExcelerator/Style.py
  packages/pyexcelerator/trunk/pyExcelerator/Utils.py
  packages/pyexcelerator/trunk/pyExcelerator/Workbook.py
  packages/pyexcelerator/trunk/pyExcelerator/Worksheet.py
  packages/pyexcelerator/trunk/pyExcelerator/excel-formula.g
  packages/pyexcelerator/trunk/setup.py

Added: packages/pyexcelerator/trunk/.cvsignore
===================================================================
--- packages/pyexcelerator/trunk/.cvsignore	                        (rev 0)
+++ packages/pyexcelerator/trunk/.cvsignore	2013-06-27 21:58:43 UTC (rev 25005)
@@ -0,0 +1 @@
+build
\ No newline at end of file

Modified: packages/pyexcelerator/trunk/CHANGES.txt
===================================================================
--- packages/pyexcelerator/trunk/CHANGES.txt	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/CHANGES.txt	2013-06-27 21:58:43 UTC (rev 25005)
@@ -66,3 +66,26 @@
       20-30% faster)
     * updated THANKS file
     * xls2csv, xls2txt, xls2html now resides in ./tools
+
+0.6.4.1 (11.04.2009)
+---------
+    * support writing to file-like objects
+    * add support for setting formula cell options
+    * add support for using color name strings to set the Font color
+      properties
+    * add support for setting default row height records
+    * add set_column, set_columns, and write_cols which are similar
+      to the perl counter parts and allow setting/writing to multiple columns
+    * allow page breaks to be intergers in the page break list
+    * add support for setting print area, and beginnings of other macros
+      and builtin functions
+    * allow None to be given to add_style to set default style
+    * Accepted patch for some bugs in the RK conversion routine from
+      John Machin
+    * add support for setting default results for formulas
+    * fix bug in lexer where symbols of more than one character are
+      not recognized
+    * Fix #1621199: typo causes DIMENSIONS record to have wrong number
+      of columns
+    * add support hyperlinks
+    * FIX #1618833: XFStyle defaults are now copies of the default properties.

Modified: packages/pyexcelerator/trunk/TODO.txt
===================================================================
--- packages/pyexcelerator/trunk/TODO.txt	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/TODO.txt	2013-06-27 21:58:43 UTC (rev 25005)
@@ -1,2 +1,4 @@
 *Write documentation
 *BSE container for Esher layer
+*Fully implement Name Records (for macros and functions)
+*Support Asian phonetic and rich-text settings
\ No newline at end of file

Modified: packages/pyexcelerator/trunk/debian/changelog
===================================================================
--- packages/pyexcelerator/trunk/debian/changelog	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/debian/changelog	2013-06-27 21:58:43 UTC (rev 25005)
@@ -1,3 +1,16 @@
+pyexcelerator (0.6.4.1-1) unstable; urgency=low
+
+  * New upstream version independent of the xlwt project. Closes: #500185.
+  * debian/control:
+    + Bumped Standards Version to 3.8.3. No changes.
+    + Bumped debhelper version to 7.4~.
+  * Bumped debian/compat from 5 to 7.
+  * Updated 01-write_datetime.dpatch in debian/patches since upstream changed
+    the file.
+  * Added debian/README.source to debian/docs.
+
+ -- Kevin Coyner <kcoyner at debian.org>  Mon, 19 Oct 2009 08:58:31 -0400
+
 pyexcelerator (0.6.3a-4) unstable; urgency=medium
 
   [ Piotr Ożarowski, Sandro Tosi ]

Modified: packages/pyexcelerator/trunk/debian/compat
===================================================================
--- packages/pyexcelerator/trunk/debian/compat	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/debian/compat	2013-06-27 21:58:43 UTC (rev 25005)
@@ -1 +1 @@
-5
+7

Modified: packages/pyexcelerator/trunk/debian/control
===================================================================
--- packages/pyexcelerator/trunk/debian/control	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/debian/control	2013-06-27 21:58:43 UTC (rev 25005)
@@ -3,9 +3,9 @@
 Priority: optional
 Maintainer: Kevin Coyner <kcoyner at debian.org>
 Uploaders: Debian Python Modules Team <python-modules-team at lists.alioth.debian.org>
-Build-Depends: cdbs (>=0.4.43), debhelper (>= 5.0.37.2), python-dev, python-central (>= 0.5), dpatch
+Build-Depends: cdbs (>=0.4.43), debhelper (>= 7.4~), python-dev, python-central (>= 0.5), dpatch
 XS-Python-Version: >= 2.4
-Standards-Version: 3.8.0
+Standards-Version: 3.8.3
 Homepage: http://sourceforge.net/projects/pyexcelerator
 Vcs-Svn: svn://svn.debian.org/python-modules/packages/pyexcelerator/trunk/
 Vcs-Browser: http://svn.debian.org/viewsvn/python-modules/packages/pyexcelerator/trunk/

Modified: packages/pyexcelerator/trunk/debian/docs
===================================================================
--- packages/pyexcelerator/trunk/debian/docs	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/debian/docs	2013-06-27 21:58:43 UTC (rev 25005)
@@ -1,4 +1,5 @@
 debian/README.Debian-source
+debian/README.source
 README.txt
 THANKS.txt
 examples/

Modified: packages/pyexcelerator/trunk/debian/patches/01-write_datetime.dpatch
===================================================================
--- packages/pyexcelerator/trunk/debian/patches/01-write_datetime.dpatch	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/debian/patches/01-write_datetime.dpatch	2013-06-27 21:58:43 UTC (rev 25005)
@@ -1,23 +1,22 @@
 #! /bin/sh /usr/share/dpatch/dpatch-run
 ## 01-write_datetime.dpatch by Kevin Coyner <kcoyner at debian.org>
 ##
-## All lines beginning with `## DP:' are a description of the patch.
 ## DP: Fixed inability to write datetime.date to a cell.
 
 @DPATCH@
-diff -urNad pyexcelerator-0.6.3a~/pyExcelerator/Row.py pyexcelerator-0.6.3a/pyExcelerator/Row.py
---- pyexcelerator-0.6.3a~/pyExcelerator/Row.py	2005-08-11 12:53:48.000000000 -0400
-+++ pyexcelerator-0.6.3a/pyExcelerator/Row.py	2008-03-04 10:39:11.000000000 -0500
-@@ -216,7 +216,7 @@
+diff -urNad pyexcelerator-0.6.4.1~/pyExcelerator/Row.py pyexcelerator-0.6.4.1/pyExcelerator/Row.py
+--- pyexcelerator-0.6.4.1~/pyExcelerator/Row.py	2007-02-14 02:00:44.000000000 -0500
++++ pyexcelerator-0.6.4.1/pyExcelerator/Row.py	2009-10-19 08:34:46.000000000 -0400
+@@ -240,7 +240,7 @@
                  self.__cells.extend([ Cell.BlankCell(self, col, self.__parent_wb.add_style(style)) ])
-         elif isinstance(label, (int, float)):
+         elif isinstance(label, (int, long, float)):
              self.__cells.extend([ Cell.NumberCell(self, col, self.__parent_wb.add_style(style), label) ])            
 -        elif isinstance(label, (dt.datetime, dt.time)):
 +        elif isinstance(label, (dt.datetime, dt.date, dt.time)):
              self.__cells.extend([ Cell.NumberCell(self, col, self.__parent_wb.add_style(style), self.__excel_date_dt(label)) ])
          else:
              self.__cells.extend([ Cell.FormulaCell(self, col, self.__parent_wb.add_style(style), label) ])
-@@ -228,4 +228,4 @@
+@@ -252,4 +252,4 @@
          self.__cells.extend([ Cell.MulBlankCell(self, c1, c2, self.__parent_wb.add_style(style)) ])
  
          

Modified: packages/pyexcelerator/trunk/examples/format.py
===================================================================
--- packages/pyexcelerator/trunk/examples/format.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/examples/format.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -7,13 +7,10 @@
 
 from pyExcelerator import *
 
-font0 = Font()
-font0.name = 'Times New Roman'
-font0.struck_out = True
-font0.bold = True
-
 style0 = XFStyle()
-style0.font = font0
+style0.font.name = 'Times New Roman'
+style0.font.struck_out = True
+style0.font.bold = True
 
 
 wb = Workbook()
@@ -22,17 +19,11 @@
 ws0.write(1, 1, 'Test', style0)
 
 for i in range(0, 0x53):
-    fnt = Font()
-    fnt.name = 'Arial'
-    fnt.colour_index = i
-    fnt.outline = True
-
-    borders = Borders()
-    borders.left = i
-
     style = XFStyle()
-    style.font = fnt
-    style.borders = borders
+    style.font.name = 'Arial'
+    style.font.colour_index = i
+    style.font.outline = True
+    style.borders.left = i
 
     ws0.write(i, 2, 'colour', style)
     ws0.write(i, 3, hex(i), style0)

Modified: packages/pyexcelerator/trunk/examples/formula_names.py
===================================================================
--- packages/pyexcelerator/trunk/examples/formula_names.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/examples/formula_names.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -1,18 +1,18 @@
-#!/usr/bin/env python
-# -*- coding: windows-1251 -*-
-# Copyright (C) 2005 Kiseliov Roman
-__rev_id__ = """$Id: formula_names.py,v 1.1 2005/08/11 08:53:48 rvk Exp $"""
-
-
-from pyExcelerator import *
-
-w = Workbook()
-ws = w.add_sheet('F')
-
-i = 0
-for n in sorted(ExcelMagic.std_func_by_name):
-    ws.write(i, 0, n)
-    ws.write(i, 3, Formula(n + "($A$1)"))
-    i += 1
-
+#!/usr/bin/env python
+# -*- coding: windows-1251 -*-
+# Copyright (C) 2005 Kiseliov Roman
+__rev_id__ = """$Id: formula_names.py,v 1.1 2005/08/11 08:53:48 rvk Exp $"""
+
+
+from pyExcelerator import *
+
+w = Workbook()
+ws = w.add_sheet('F')
+
+i = 0
+for n in sorted(ExcelMagic.std_func_by_name):
+    ws.write(i, 0, n)
+    ws.write(i, 3, Formula(n + "($A$1)"))
+    i += 1
+
 w.save('formula_names.xls')
\ No newline at end of file

Modified: packages/pyexcelerator/trunk/examples/formulas.py
===================================================================
--- packages/pyexcelerator/trunk/examples/formulas.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/examples/formulas.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -5,19 +5,21 @@
 
 
 from pyExcelerator import *
+from pyExcelerator.Worksheet import *
 
 w = Workbook()
 ws = w.add_sheet('F')
+ws.frmla_opts=NoCalcs
 
-ws.write(0, 0, Formula("-(1+1)"))
-ws.write(1, 0, Formula("-(1+1)/(-2-2)"))
-ws.write(2, 0, Formula("-(134.8780789+1)"))
-ws.write(3, 0, Formula("-(134.8780789e-10+1)"))
-ws.write(4, 0, Formula("-1/(1+1)+9344"))
+ws.write(0, 0, Formula("-(1+1)", None))
+ws.write(1, 0, Formula("-(1+1)/(-2-2)", 3.14))
+ws.write(2, 0, Formula("-(134.8780789+1)", ErrorCode("#NULL!"), CalcOnOpen))
+ws.write(3, 0, Formula("-(134.8780789e-10+1)", ErrorCode("#NAME?")))
+ws.write(4, 0, Formula("-1/(1+1)+9344", 12345))
 
-ws.write(0, 1, Formula("-(1+1)"))
-ws.write(1, 1, Formula("-(1+1)/(-2-2)"))
-ws.write(2, 1, Formula("-(134.8780789+1)"))
+ws.write(0, 1, Formula("-(1+1)", "this is 2", CalcOnOpen))
+ws.write(1, 1, Formula("-(1+1)/(-2-2)", u"this is 0.5"))
+ws.write(2, 1, Formula("-(134.8780789+1)", ""))
 ws.write(3, 1, Formula("-(134.8780789e-10+1)"))
 ws.write(4, 1, Formula("-1/(1+1)+9344"))
 

Modified: packages/pyexcelerator/trunk/examples/hyperlinks.py
===================================================================
--- packages/pyexcelerator/trunk/examples/hyperlinks.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/examples/hyperlinks.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -18,6 +18,7 @@
 
 w = Workbook()
 ws = w.add_sheet('F')
+ws_A = w.add_sheet('A')
 
 ##############
 ## NOTE: parameters are separated by semicolon!!!
@@ -27,4 +28,9 @@
 ws.write_merge(1, 1, 1, 10, Formula(n + '("http://www.irs.gov/pub/irs-pdf/f1000.pdf";"f1000.pdf")'), h_style)
 ws.write_merge(2, 2, 2, 25, Formula(n + '("mailto:roman.kiseliov at gmail.com?subject=pyExcelerator-feedback&Body=Hello,%20Roman!";"pyExcelerator-feedback")'), h_style)
 
+ws.write(3, 0, "Goto Google")
+ws.set_link(3, 0, "http://www.google.com", description="Google")
+ws.write(4, 0, "Goto Next Page")
+ws.set_link(4, 0, "#A!A2", description="page A")
+
 w.save("hyperlinks.xls")
\ No newline at end of file

Modified: packages/pyexcelerator/trunk/examples/parse-fmla.py
===================================================================
--- packages/pyexcelerator/trunk/examples/parse-fmla.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/examples/parse-fmla.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -1,12 +1,12 @@
-from pyExcelerator import ExcelFormulaParser, ExcelFormula
-import sys
-
-f = ExcelFormula.Formula(
-""" -((1.80 + 2.898 * 1)/(1.80 + 2.898))*
-AVERAGE((1.80 + 2.898 * 1)/(1.80 + 2.898); 
-        (1.80 + 2.898 * 1)/(1.80 + 2.898); 
-        (1.80 + 2.898 * 1)/(1.80 + 2.898)) + 
-SIN(PI()/4)""")
-
-#for t in f.rpn():
-#    print "%15s %15s" % (ExcelFormulaParser.PtgNames[t[0]], t[1])
+from pyExcelerator import ExcelFormulaParser, ExcelFormula
+import sys
+
+f = ExcelFormula.Formula(
+""" -((1.80 + 2.898 * 1)/(1.80 + 2.898))*
+AVERAGE((1.80 + 2.898 * 1)/(1.80 + 2.898); 
+        (1.80 + 2.898 * 1)/(1.80 + 2.898); 
+        (1.80 + 2.898 * 1)/(1.80 + 2.898)) + 
+SIN(PI()/4)""")
+
+#for t in f.rpn():
+#    print "%15s %15s" % (ExcelFormulaParser.PtgNames[t[0]], t[1])

Added: packages/pyexcelerator/trunk/examples/xls2csv.py
===================================================================
--- packages/pyexcelerator/trunk/examples/xls2csv.py	                        (rev 0)
+++ packages/pyexcelerator/trunk/examples/xls2csv.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# -*- coding: windows-1251 -*-
+# Copyright (C) 2005 Kiseliov Roman
+
+__rev_id__ = """$Id: xls2csv.py,v 1.1 2005/05/19 09:27:42 rvk Exp $"""
+
+
+from pyExcelerator import *
+import sys
+
+me, args = sys.argv[0], sys.argv[1:]
+
+
+if args:
+    for arg in args:
+        print >>sys.stderr, 'extracting data from', arg
+        for sheet_name, values in parse_xls(arg, 'cp1251'): # parse_xls(arg) -- default encoding
+            matrix = [[]]
+            print 'Sheet = "%s"' % sheet_name.encode('cp866', 'backslashreplace')
+            print '----------------'
+            for row_idx, col_idx in sorted(values.keys()):
+                v = values[(row_idx, col_idx)]
+                if isinstance(v, unicode):
+                    v = v.encode('cp866', 'backslashreplace')
+                else:
+                    v = str(v)
+                last_row, last_col = len(matrix), len(matrix[-1])
+                while last_row < row_idx:
+                    matrix.extend([[]])
+                    last_row = len(matrix)
+
+                while last_col < col_idx:
+                    matrix[-1].extend([''])
+                    last_col = len(matrix[-1])
+
+                matrix[-1].extend([v])
+                    
+            for row in matrix:
+                csv_row = ','.join(row)
+                print csv_row
+
+else:
+    print 'usage: %s (inputfile)+' % me
+

Added: packages/pyexcelerator/trunk/examples/xls2html.py
===================================================================
--- packages/pyexcelerator/trunk/examples/xls2html.py	                        (rev 0)
+++ packages/pyexcelerator/trunk/examples/xls2html.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# -*- coding: windows-1251 -*-
+# Copyright (C) 2005 Kiseliov Roman
+
+__rev_id__ = """$Id: xls2html.py,v 1.1 2005/05/19 09:27:42 rvk Exp $"""
+
+
+from pyExcelerator import *
+import sys
+
+me, args = sys.argv[0], sys.argv[1:]
+
+
+if args:
+    for arg in args:
+        print >>sys.stderr, 'extracting data from', arg
+        print '<html>'
+        for sheet_name, values in parse_xls(arg, 'cp1251'): # parse_xls(arg) -- default encoding
+            matrix = [[]]
+            print 'Sheet = "%s"' % sheet_name.encode('cp1251', 'backslashreplace')
+            print '<table border="2" cellpadding="1" cellspacing="1" >'
+
+            for row_idx, col_idx in sorted(values.keys()):
+                v = values[(row_idx, col_idx)]
+                if isinstance(v, unicode):
+                    v = v.encode('cp1251', 'backslashreplace')
+                else:
+                    v = str(v)
+                last_row, last_col = len(matrix), len(matrix[-1])
+                while last_row < row_idx:
+                    matrix.extend([[]])
+                    last_row = len(matrix)
+
+                while last_col < col_idx:
+                    matrix[-1].extend([''])
+                    last_col = len(matrix[-1])
+
+                matrix[-1].extend([v])
+                    
+            for row in matrix:
+                print '<tr>'
+                for col in row:
+                    print '<td> %s </td>' % col
+                print '</tr>'
+
+            print '</table>'
+        print '</html>'
+
+else:
+    print 'usage: %s (inputfile)+' % me
+

Added: packages/pyexcelerator/trunk/examples/xls2txt.py
===================================================================
--- packages/pyexcelerator/trunk/examples/xls2txt.py	                        (rev 0)
+++ packages/pyexcelerator/trunk/examples/xls2txt.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# -*- coding: windows-1251 -*-
+# Copyright (C) 2005 Kiseliov Roman
+
+__rev_id__ = """$Id: xls2txt.py,v 1.3 2005/05/19 09:27:42 rvk Exp $"""
+
+
+from pyExcelerator import *
+import sys
+
+me, args = sys.argv[0], sys.argv[1:]
+
+if args:
+    for arg in args:
+        print >>sys.stderr, 'extracting data from', arg
+        for sheet_name, values in parse_xls(arg, 'cp1251'): # parse_xls(arg) -- default encoding
+            print 'Sheet = "%s"' % sheet_name.encode('cp866', 'backslashreplace')
+            print '----------------'
+            for row_idx, col_idx in sorted(values.keys()):
+                v = values[(row_idx, col_idx)]
+                if isinstance(v, unicode):
+                    v = v.encode('cp866', 'backslashreplace')
+                print '(%d, %d) =' % (row_idx, col_idx), v
+            print '----------------'
+else:
+    print 'usage: %s (inputfile)+' % me
+

Modified: packages/pyexcelerator/trunk/museum/mini-mini.xls
===================================================================
(Binary files differ)

Modified: packages/pyexcelerator/trunk/museum/mini.xls
===================================================================
(Binary files differ)

Modified: packages/pyexcelerator/trunk/pyExcelerator/BIFFRecords.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/BIFFRecords.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/BIFFRecords.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -1556,6 +1556,50 @@
         self._rec_data = struct.pack('<3Hd', row, col, xf_index, number)
 
 
+class StringRecord(BiffRecord):
+    """
+    Offset     Size   Contents
+    0       1 or 2  Length of the string (character count, ln)
+    1 or 2      1     Option flags:
+                     Bit       Mask Contents
+                                01H
+                      0                  Character compression (ccompr):
+                                         02 = Compressed (8-bit characters)
+                                         12 = Uncompressed (16-bit characters)
+                                04H
+                      2                  Asian phonetic settings (phonetic):
+                                         02 = Does not contain Asian phonetic settings
+                                         12 = Contains Asian phonetic settings
+                                08H
+                      3                  Rich-Text settings (richtext):
+                                         02 = Does not contain Rich-Text settings
+                                         12 = Contains Rich-Text settings
+    [2 or 3]     2     (optional, only if richtext=1) Number of Rich-Text formatting runs (rt)
+    [var.]      4     (optional, only if phonetic=1) Size of Asian phonetic settings block (in bytes, sz)
+    var.   ln or 2ln Character array (8-bit characters or 16-bit characters, dependent on ccompr)
+    [var.]    4rt     (optional, only if richtext=1) List of rt formatting runs (3.2)
+            sz
+    [var.]            (optional, only if phonetic=1) Asian Phonetic Settings Block (3.4.2)
+    """
+    _REC_ID = 0x0207
+
+    def __init__(self, s):
+        BiffRecord.__init__(self)
+        uncompressed = 0x01
+        asian_phonetic_settings = 0x04
+        rich_text_settings = 0x08
+        
+        s = s.encode('UTF-16le')
+        slen = len(s)/2
+        options = uncompressed
+        if not s[1::2].strip(chr(0x00)):
+            # if high bytes are all zero, do string compression
+            s = s[::2]
+            slen = len(s)
+            options &= ~uncompressed
+        self._rec_data = struct.pack('<HB%ds'%len(s), slen, options, s)
+
+
 class FormulaRecord(BiffRecord):
     """
     Offset Size Contents
@@ -1574,11 +1618,138 @@
     """
     _REC_ID = 0x0006
 
-    def __init__(self, row, col, xf_index, rpn):
+    def __init__(self, row, col, xf_index, result, opts, rpn):
         BiffRecord.__init__(self)
-        self._rec_data = struct.pack('<3HQHL', row, col, xf_index, 0xFFFF000000000003, 0, 0) + rpn
+        # for an empty cell
+        self._rec_data = struct.pack('<3HQHL', row, col, xf_index, result, opts, 0) + rpn
 
 
+class HyperlinkRecord(BiffRecord):
+    """
+    Each HLINK record starts with the same data items and continues with
+    special data related to the current type of hyperlink. It starts with a
+    cell range. Each cell of this range will contain the same hyperlink.
+
+    Record HLINK, BIFF8:
+   Offset            Size        Contents
+       0               8         Cell range address of all cells containing this hyperlink (3.13.1)
+       8              16         GUID of StdLink:
+                                 D0H C9H EAH 79H F9H BAH CEH 11H 8CH 82H 00H AAH 00H 4BH A9H 0BH
+                                 (79EAC9D0-BAF9-11CE-8C82-00AA004BA90B)
+      24               4         Unknown value: 00000002H
+      28               4        Option flags (see below)
+     [32]              4        (optional, see option flags) Character count of description text, including trailing zero word
+                                (dl)
+     [36]            2dl        (optional, see option flags) Character array of description text, no Unicode string header,
+                                always 16-bit characters, zero-terminated
+    [var.]             4        (optional, see option flags) Character count of target frame, including trailing zero word
+                                (fl)
+    [var.]           2fl         (optional, see option flags) Character array of target frame, no Unicode string header,
+                                 always 16-bit characters, zero-terminated
+     var.            var.        Special data (6.53.2 and following)
+    [var.]             4         (optional, see option flags) Character count of the text mark, including trailing zero word
+                                 (tl)
+    [var.]           2tl         (optional, see option flags) Character array of the text mark without "#" sign, no Unicode
+                                 string header, always 16-bit characters, zero-terminated
+
+    """
+    _REC_ID = 0x01B8
+
+    def __init__(self, frow, lrow, fcol, lcol, url, target=None, description=None):
+        BiffRecord.__init__(self)
+        options = 0x00
+        special=None
+        textmark=None
+        
+        #~ assert url is not None or textmark is not None, 'must specify either url or textmark arguments'
+        
+        if description is not None:
+            options |= 0x14
+            description = description.encode('UTF-16le') + '\x00\x00'
+        
+        if target is not None:
+            options |= 0x80
+            target = target.encode('UTF-16le') + '\x00\x00'
+        
+        u16url = url.encode('UTF-16le') + '\x00\x00'
+        if url[0].isalpha() and url.find(':') > 3:
+            # hyperlink containing a URL (6.53.2)
+            assert url[:url.find(':')].isalpha(), 'not valid URL'%url
+            options |= 0x03
+            special  = pack('<4L', 0x79eac9e0, 0x11cebaf9, 0xaa00828c, 0x0ba94b00)
+            special += pack('<L%ds'%len(u16url), len(u16url), u16url)
+        elif url[0].isalnum() or url[0] in ('.',):
+            # hyperlink to the current workbook (6.53.3)
+            options |= 0x01
+            
+            uplvl_cnt=0
+            if url[0].isalpha() and url[1:].startswith(':\\'):
+                # this is an absolute path
+                options |= 0x02
+            else:
+                uplvl_cnt += 1
+                while url.startswith('..\\'):
+                    url = url[3:]
+            url += '\x00'
+            
+            special  = pack('<4L', 0x00000303, 0x00000000, 0x000000C0, 0x46000000)
+            special += pack('<HL%ds'%len(url), uplvl_cnt, len(url), url)
+            special += pack('<4s20x', '\xff\xff\xad\xde')
+            # I don't understand the first field here, setting to zero is safe
+            # till I figure out what it is
+            special += pack('<LL2s%ds'%len(u16url[:-2]), 0, len(u16url[:-2]), 
+                            '\x03\x00', u16url[:-2])
+        elif url.startswith('\\\\'):
+            # hyperlink to a File with UNC Path (6.53.4)
+            options |= 0x103
+            special  = pack('<L%ds'%len(u16url), len(u16url), u16url)
+        elif url.startswith('#'):
+            # hyperlink to the current workbook (6.53.5)
+            options |= 0x08
+            textmark = url[1:]
+        
+        if textmark is not None:
+            textmark = textmark.encode('UTF-16le') + '\x00\x00'
+        
+        self._rec_data  = pack('<4H', frow, lrow, fcol, lcol)
+        # GUID of StdLink
+        self._rec_data += pack('<4L', 0x79eac9d0, 0x11cebaf9, 0xaa00828c, 0x0ba94b00)
+        #~ self._rec_data += '\xd0\xc9\xea\x79\xf9\xba\xce\x11\x8c\x82\x00\xaa\x00\x4b\xa9\x0b'
+        self._rec_data += pack('<LL',   0x2, options)
+        if description is not None:
+            self._rec_data += pack('<L%ds'%len(description), len(description)/2, description)
+        if target is not None:
+            self._rec_data += pack('<L%ds'%len(target), len(target)/2, target)
+        if special is not None:
+            self._rec_data += pack('<%ds'%len(special), special)
+        if textmark is not None:
+            self._rec_data += pack('<L%ds'%len(textmark), len(textmark)/2, textmark)
+
+
+class QuicktipRecord(BiffRecord):
+    """
+    This record contains the cell range and text for a tool tip. It occurs in
+    conjunction with the HLINK record for hyperlinks (6.53) in the Hyperlink
+    Table (5.13). This record is only available in Excel 9.0 (Excel 2000) and
+    later.
+
+    Record QUICKTIP, BIFF8:
+
+    Offset Size Contents
+    0      2   0800H (repeated record identifier)
+    2      8   Cell range address of all cells containing the tool tip (3.13.1)
+    10    var. Character array of the tool tip, no Unicode string header, always 16-bit characters, zero-
+            terminated
+
+    """
+    _REC_ID = 0x0800
+
+    def __init__(self, frow, lrow, fcol, lcol, hint):
+        BiffRecord.__init__(self)
+        hint = hint.encode('UTF-16le')
+        self._rec_data = pack('<5H%dsx'%len(hint), self._REC_ID, frow, lrow, fcol, lcol, hint)
+
+
 class GutsRecord(BiffRecord):
     """
     This record contains information about the layout of outline symbols.
@@ -2294,3 +2465,120 @@
                                         header_margin, footer_margin,
                                         num_copies)
 
+class NameRecord(BiffRecord):
+    """
+    This record is part of a Link Table. It contains the name and the token
+    array of an internal defined name. Token arrays of defined names
+    contain tokens with aberrant token classes.
+
+    Record NAME, BIFF5/BIFF7:
+    Offset      Size    Contents
+       0          2     Option flags, see below
+       2          1     Keyboard shortcut (only for command macro names, see below)
+       3          1     Length of the name (character count, ln)
+       4          2     Size of the formula data (sz)
+       6          2     0 = Global name, otherwise index to EXTERNSHEET record (one-based)
+       8          2     0 = Global name, otherwise index to sheet (one-based)
+      10          1     Length of menu text (character count, lm)
+      11          1     Length of description text (character count, ld)
+      12          1     Length of help topic text (character count, lh)
+      13          1     Length of status bar text (character count, ls)
+      14         ln     Character array of the name
+    14+ln        sz     Formula data (RPN token array without size field, 4)
+  14+ln+sz       lm     Character array of menu text
+     var.        ld     Character array of description text
+     var.        lh     Character array of help topic text
+     var.        ls     Character array of status bar text
+
+    Record NAME, BIFF8:
+    Offset      Size Contents
+       0          2  Option flags, see below
+       2          1  Keyboard shortcut (only for command macro names, see below)
+       3          1  Length of the name (character count, ln)
+       4          2  Size of the formula data (sz)
+       6          2  Not used
+       8          2  0 = Global name, otherwise index to sheet (one-based)
+      10          1  Length of menu text (character count, lm)
+      11          1  Length of description text (character count, ld)
+      12          1  Length of help topic text (character count, lh)
+      13          1  Length of status bar text (character count, ls)
+      14        var. Name (Unicode string without length field, 3.4)
+     var.        sz  Formula data (RPN token array without size field, 4)
+    [var.]      var. (optional, only if lm > 0) Menu text (Unicode string without length field, 3.4)
+    [var.]      var. (optional, only if ld > 0) Description text (Unicode string without length field, 3.4)
+    [var.]      var. (optional, only if lh > 0) Help topic text (Unicode string without length field, 3.4)
+    [var.]      var. (optional, only if ls > 0) Status bar text (Unicode string without length field, 3.4)
+    """
+    _REC_ID = 0x0018
+
+    def __init__(self, options, keyboard_shortcut, name, sheet_index, rpn, menu_text='', desc_text='', help_text='', status_text=''):
+        BiffRecord.__init__(self)
+        if type(name) == int:
+            uname = chr(name)
+        else:
+            uname = upack1(name)[1:]
+        uname_len = len(uname)
+        
+        #~ self._rec_data = struct.pack('<HBBHHHBBBB%ds%ds' % (uname_len, len(rpn)), options, keyboard_shortcut, uname_len, len(rpn), 0x0000, sheet_index, len(menu_text), len(desc_text), len(help_text), len(status_text), uname, rpn) + menu_text + desc_text + help_text + status_text
+        self._rec_data = struct.pack('<HBBHHHBBBBB%ds%ds' % (uname_len, len(rpn)), options, keyboard_shortcut, uname_len, len(rpn), 0x0000, sheet_index, 0x00, len(menu_text), len(desc_text), len(help_text), len(status_text), uname, rpn) + menu_text + desc_text + help_text + status_text
+        
+        #~ print repr(self.get())
+        #~ print repr(self._rec_data)
+        #~ print len(self._rec_data)
+
+class ExternSheetRecord(BiffRecord):
+    """
+    In BIFF8 the record stores a list with indexes to SUPBOOK
+    records (list of REF structures, 6.100). See 5.10.3 for 
+    details about external references in BIFF8.
+    
+    Record EXTERNSHEET, BIFF8:
+    Offset          Size      Contents
+       0             2        Number of following REF structures (nm)
+       2           6nm        List of nm REF structures. Each REF contains the following data:
+                              Offset     Size     Contents
+                                 0         2      Index to SUPBOOK record
+                                 2         2      Index to first SUPBOOK sheet
+                                 4         2      Index to last SUPBOOK sheet
+    """
+    _REC_ID = 0x0017
+
+    def __init__(self, refs=[]):
+        BiffRecord.__init__(self)
+        
+        # do we always need this ref? or only if there are no refs?
+        refs.insert(0, (0,0,0))
+        #~ ref_data = ''.join([ref.get() for r in refs])
+        ref_data = ''.join([struct.pack('<HHH', *r) for r in refs])
+        self._rec_data = struct.pack('<H%ds' % (len(refs)*6), len(refs), ref_data)
+
+class SupBookRecord(BiffRecord):
+    """
+    This record mainly stores the URL of an external document
+    and a list of sheet names inside this document. Furthermore
+    it is used to store DDE and OLE object links, or to indicate
+    an internal 3D reference or an add-in function. See 5.10.3
+    for details about external references in BIFF8.
+    
+    """
+    _REC_ID = 0x01AE
+
+    def __init__(self):
+        BiffRecord.__init__(self)
+
+class InternalReferenceSupBookRecord(SupBookRecord):
+    """
+    In each file occurs a SUPBOOK that is used for internal 3D
+    references. It stores the number of sheets of the own document.
+    
+    Record SUPBOOK for 3D references, BIFF8:
+    Offset         Size   Contents
+      0             2     Number of sheets in this document
+      2             2     01H 04H (relict of BIFF5/BIFF7, the byte string "<04H>", see 3.9.1)
+
+    """
+
+    def __init__(self, num_sheets):
+        SupBookRecord.__init__(self)
+        
+        self._rec_data = struct.pack('<HBB', num_sheets, 0x01, 0x04)

Modified: packages/pyexcelerator/trunk/pyExcelerator/Cell.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/Cell.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/Cell.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -45,8 +45,8 @@
 
 import struct
 import BIFFRecords
+from ExcelFormula import ErrorCode
 
-
 class StrCell(object):
     __slots__ = ["__init__", "get_biff_data",
                 "__parent", "__idx", "__xf_idx", "__sst_idx"]
@@ -79,6 +79,7 @@
                 "__parent", "__col1", "__col2", "__xf_idx"]
 
     def __init__(self, parent, col1, col2, xf_idx):
+        assert col1 < col2, '%d < %d is false'%(col1, col2)
         self.__parent = parent
         self.__col1 = col1
         self.__col2 = col2
@@ -113,9 +114,9 @@
             rk_encoded = (w3 << 16) | w2
             return BIFFRecords.RKRecord(self.__parent.get_index(), self.__idx, self.__xf_idx, rk_encoded).get()
 
-        if abs(self.__number) < 0x40000000 and int(self.__number) == self.__number:
+        if abs(self.__number) < 0x20000000 and int(self.__number) == self.__number:
             #print "30-bit integer RK"
-            rk_encoded = 2 | (int(self.__number) << 2)
+            rk_encoded = (2 | (int(self.__number) << 2)) & 0xffffffffL
             return BIFFRecords.RKRecord(self.__parent.get_index(), self.__idx, self.__xf_idx, rk_encoded).get()
 
         temp = self.__number*100
@@ -127,9 +128,9 @@
             rk_encoded = 1 | (w3 << 16) | w2
             return BIFFRecords.RKRecord(self.__parent.get_index(), self.__idx, self.__xf_idx, rk_encoded).get()
 
-        if abs(temp) < 0x40000000 and int(temp) == temp:
+        if abs(temp) < 0x20000000 and int(temp) == temp:
             #print "30-bit integer RK*100"
-            rk_encoded = 3 | (int(temp) << 2)
+            rk_encoded = (3 | (int(temp) << 2)) & 0xffffffffL
             return BIFFRecords.RKRecord(self.__parent.get_index(), self.__idx, self.__xf_idx, rk_encoded).get()
 
         #print "Number" 
@@ -152,18 +153,48 @@
 
 
 class FormulaCell(object):
-    __slots__ = ["__init__", "get_biff_data",
-                "__parent", "__idx", "__xf_idx", "__frmla"]
+    __slots__ = ["__init__", "get_biff_data", "result",
+                "__parent", "__idx", "__xf_idx", "__result", "__opts", "__frmla", "__str"]
 
     def __init__(self, parent, idx, xf_idx, frmla):
+        self.__str = None
         self.__parent = parent
         self.__idx = idx
         self.__xf_idx = xf_idx
+        self.result = frmla.default
+        self.__opts = frmla.opts != None and frmla.opts or self.__parent.frmla_opts
         self.__frmla = frmla
 
 
     def get_biff_data(self):
-        return BIFFRecords.FormulaRecord(self.__parent.get_index(), self.__idx, self.__xf_idx, self.__frmla.rpn()).get()
+        frmla_block_data = BIFFRecords.FormulaRecord(self.__parent.get_index(), self.__idx, self.__xf_idx, self.__result, self.__opts, self.__frmla.rpn()).get()
+        if self.__str:
+            frmla_block_data += BIFFRecords.StringRecord(self.__str).get()
+        return frmla_block_data
 
+    def set_result(self, value):
+        self.__result = self._convertToResult(value)
 
+    def get_result(self):
+        return self.__result
 
+    result = property(get_result, set_result)
+
+    def _convertToResult(self, val):
+        ret = 0
+        self.__str = ''
+        if isinstance(val, (int, float)):
+            ret = struct.pack('<d', val)
+        else:
+            if isinstance(val, bool):
+                ret = struct.pack('BxB3x', 0x01, val and 0x01 or 0x00)
+            elif isinstance(val, ErrorCode):
+                ret = struct.pack('BxB3x', 0x02, val.int())
+            elif (isinstance(val, (unicode, str)) and val) or bool(val):
+                ret = struct.pack('B5x', 0x00)
+                self.__str = unicode(val)
+            elif not val:
+                ret = struct.pack('B5x', 0x03)
+            ret += struct.pack('<H', 0xFFFF)
+        return struct.unpack('<Q', ret)[0]
+

Modified: packages/pyexcelerator/trunk/pyExcelerator/Column.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/Column.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/Column.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -43,6 +43,7 @@
 __rev_id__ = """$Id: Column.py,v 1.4 2005/07/20 07:24:11 rvk Exp $"""
 
 
+import Style
 from BIFFRecords import ColInfoRecord
 from Deco import *
 from Worksheet import Worksheet
@@ -51,10 +52,10 @@
 class Column(object):
     @accepts(object, int, Worksheet)
     def __init__(self, indx, parent_sheet):
-        self._index = indx
-        self._parent = parent_sheet
-        self._parent_wb = parent_sheet.get_parent()
-        self._xf_index = 0x0F
+        self.__index = indx
+        self.__parent = parent_sheet
+        self.__parent_wb = parent_sheet.get_parent()
+        self.__xf_index = 0x0F
         
         self.width = 0x0B92
         self.hidden = 0
@@ -67,7 +68,15 @@
         options |= (self.level & 0x07) << 8
         options |= (self.collapse & 0x01) << 12
         
-        return ColInfoRecord(self._index, self._index, self.width, self._xf_index, options).get()
+        return ColInfoRecord(self.__index, self.__index, self.width, self.__xf_index, options).get()
         
         
+    @accepts(object, Style.XFStyle)
+    def set_style(self, style):
+        # self.__adjust_height(style)
+        self.__xf_index = self.__parent_wb.add_style(style)        
         
+
+    def get_index(self):
+        return self.__index
+        

Modified: packages/pyexcelerator/trunk/pyExcelerator/CompoundDoc.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/CompoundDoc.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/CompoundDoc.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -53,7 +53,10 @@
         self.dump = dump
         self.STREAMS = {}
 
-        doc = file(filename, 'rb').read()
+        f = filename
+        if not hasattr(filename, 'read'):
+            f = file(filename, 'rb')
+        doc = f.read()
         self.header, self.data = doc[0:512], doc[512:]
         del doc
 
@@ -546,7 +549,9 @@
         self.__build_sat()
         self.__build_header()
         
-        f = file(filename, 'wb')
+        f = filename
+        if not hasattr(filename, 'write'):
+            f = file(filename, 'wb')
         f.write(self.header)
         f.write(self.packed_MSAT_1st)
         f.write(stream)
@@ -554,7 +559,6 @@
         f.write(self.packed_MSAT_2nd)
         f.write(self.packed_SAT)
         f.write(self.dir_stream)
-        f.close()
 
 
 if __name__ == '__main__':

Modified: packages/pyexcelerator/trunk/pyExcelerator/ExcelFormula.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/ExcelFormula.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/ExcelFormula.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -43,16 +43,31 @@
 __rev_id__ = """$Id: ExcelFormula.py,v 1.3 2005/08/11 08:53:48 rvk Exp $"""
 
 
-import ExcelFormulaParser, ExcelFormulaLexer
+import ExcelFormulaParser, ExcelFormulaLexer, ExcelMagic
 import struct
+from Deco import *
 from antlr import ANTLRException
 
+NoCalcs=0x00
+RecalcAlways=0x01
+CalcOnOpen=0x02
+PartOfShareFormula=0x08
 
+class ErrorCode(object):
+    error_msg = dict([(i[1], i[0]) for i in ExcelMagic.error_msg_by_code.items()])
+    
+    def __init__(self, s):
+        self.val = self.error_msg[s]
+    
+    def int(self): return self.val
+
 class Formula(object):
-    __slots__ = ["__init__", "text", "rpn", "__s", "__parser"]
+    __slots__ = ["__init__", "text", "rpn", "default", "opts", "__s", "__parser", "__default", "__opts"]
 
 
-    def __init__(self, s):
+    def __init__(self, s, default=None, opts=None):
+        self.__default = default
+        self.__opts = opts
         try:
             self.__s = s
             lexer = ExcelFormulaLexer.Lexer(s)
@@ -61,6 +76,24 @@
         except ANTLRException:
             raise Exception, "can't parse formula " + s
 
+    def set_default(self, val):
+        self.__default = val
+
+    def get_default(self):
+        return self.__default
+
+    default = property(get_default, set_default)
+
+    @accepts(object, int)
+    def set_opts(self, value):
+        assert (int(value) & ~(0x0b)) == 0, "Invalid bits set for opts (%s)"%hex(int(value))
+        self.__opts = int(value)
+
+    def get_opts(self):
+        return self.__opts
+
+    opts = property(get_opts, set_opts)
+
     def text(self):
         return self.__s
 

Modified: packages/pyexcelerator/trunk/pyExcelerator/ExcelFormulaLexer.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/ExcelFormulaLexer.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/ExcelFormulaLexer.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -104,6 +104,10 @@
         return len(self._text) <= self._pos
 
 
+    def rest(self):
+        return self._text[self._pos:]
+
+
     def curr_ch(self):
         return self._text[self._pos]
 
@@ -141,8 +145,8 @@
                 return t
         # second, we want find short tokens
         for ty, te in type_text_tuples:
-            if self.curr_ch() == te:
-                self.next_ch()
+            if self.rest().startswith(te):
+                self.next_ch(len(te))
                 return Tok(type = ty, text = te, col = self._pos)
         # at this point, smth strange is happened
         raise TokenStreamException("Unknown char %s at %u col." % (self.curr_ch(), self._pos))

Modified: packages/pyexcelerator/trunk/pyExcelerator/ExcelFormulaParser.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/ExcelFormulaParser.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/ExcelFormulaParser.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -96,7 +96,7 @@
                 elif la1 and la1 in [GT]:
                     pass
                     self.match(GT)
-                    op = struct.pack('B', ptgGE)
+                    op = struct.pack('B', ptgGT)
                 elif la1 and la1 in [LT]:
                     pass
                     self.match(LT)

Modified: packages/pyexcelerator/trunk/pyExcelerator/Formatting.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/Formatting.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/Formatting.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -75,7 +75,42 @@
 
 import BIFFRecords
 
-class Font(object):
+colours = {
+        'aqua'    : 0x0F,
+        'cyan'    : 0x0F,
+        'black'   : 0x08,
+        'blue'    : 0x0C,
+        'brown'   : 0x10,
+        'magenta' : 0x0E,
+        'fuchsia' : 0x0E,
+        'gray'    : 0x17,
+        'grey'    : 0x17,
+        'green'   : 0x11,
+        'lime'    : 0x0B,
+        'navy'    : 0x12,
+        'orange'  : 0x35,
+        'pink'    : 0x21,
+        'purple'  : 0x14,
+        'red'     : 0x0A,
+        'silver'  : 0x16,
+        'white'   : 0x09,
+        'yellow'  : 0x0D,
+}
+
+def get_colour_val(c):
+    if c in colours:
+        return colours[c]
+    return c
+
+class CopyableObject(object):
+    # make sure to override this in the derived class if
+    # copying needs to be more complex
+    def copy(self):
+        cobj = self.__class__()
+        cobj.__dict__.update(self.__dict__)
+        return cobj
+
+class Font(CopyableObject):
     ESCAPEMENT_NONE         = 0x00
     ESCAPEMENT_SUPERSCRIPT  = 0x01
     ESCAPEMENT_SUBSCRIPT    = 0x02
@@ -150,7 +185,7 @@
         if self.shadow:
             options |= 0x020
             
-        colour_index = self.colour_index 
+        colour_index = get_colour_val(self.colour_index)
         weight = self._weight
         escapement = self.escapement
         underline = self.underline 
@@ -162,7 +197,7 @@
                     underline, family, charset, 
                     name)
 
-class Alignment(object):
+class Alignment(CopyableObject):
     HORZ_GENERAL                = 0x00
     HORZ_LEFT                   = 0x01
     HORZ_CENTER                 = 0x02
@@ -207,7 +242,7 @@
         self.inde = 0
         self.merg = 0
 
-class Borders(object):
+class Borders(CopyableObject):
     NO_LINE = 0x00
     THIN    = 0x01
     MEDIUM  = 0x02
@@ -245,17 +280,25 @@
         self.need_diag1 = self.NO_NEED_DIAG1
         self.need_diag2 = self.NO_NEED_DIAG2
 
-class Pattern(object):
+class Pattern(CopyableObject):
     # patterns 0x00 - 0x12
     NO_PATTERN      = 0x00 
     SOLID_PATTERN   = 0x01 
     
     def __init__(self):
         self.pattern = self.NO_PATTERN
-        self.pattern_fore_colour = 0x40
-        self.pattern_back_colour = 0x41
-        
-class Protection(object):
+        self._pattern_fore_colour = 0x40
+        self._pattern_back_colour = 0x41
+    
+    def get_pattern_fore_colour(self): return self._pattern_fore_colour
+    def set_pattern_fore_colour(self, c): self._pattern_fore_colour = get_colour_val(c)
+    pattern_fore_colour = property(get_pattern_fore_colour, set_pattern_fore_colour)
+    
+    def get_pattern_back_colour(self): return self._pattern_back_colour
+    def set_pattern_back_colour(self, c): self._pattern_back_colour = get_colour_val(c)
+    pattern_back_colour = property(get_pattern_back_colour, set_pattern_back_colour)
+
+class Protection(CopyableObject):
     def __init__(self):
         self.cell_locked = 1
         self.formula_hidden = 0
@@ -275,4 +318,3 @@
         f = file(filename, 'wb')
         f.write(font.get_biff_record().get_data())
         f.close
-        
\ No newline at end of file

Modified: packages/pyexcelerator/trunk/pyExcelerator/Row.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/Row.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/Row.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -79,15 +79,18 @@
                  "__total_str",
                  "__xf_index",
                  "__has_default_format",
+                 "__has_default_height",
+                 "__height",
                  "__height_in_pixels",
+                 "__frmla_opts",
                  # public variables
-                 "height",
-                 "has_default_height",
                  "level",
                  "collapse",
                  "hidden",
                  "space_above",
-                 "space_below"]
+                 "space_below",
+                 "height",
+                 "frmla_opts",]
 
     #################################################################
     ## Constructor
@@ -102,10 +105,11 @@
         self.__total_str = 0
         self.__xf_index = 0x0F
         self.__has_default_format = 0
+        self.__has_default_height = 0x01
+        self.__height = 0x00FF
         self.__height_in_pixels = 0x11
+        self.__frmla_opts = self.__parent.frmla_opts
         
-        self.height = 0x00FF
-        self.has_default_height = 0x00
         self.level = 0
         self.collapse = 0
         self.hidden = 0
@@ -169,7 +173,7 @@
 
         
     def get_max_col(self):
-        return self.__min_col_idx
+        return self.__max_col_idx
 
         
     def get_str_count(self):
@@ -177,8 +181,8 @@
 
 
     def get_row_biff_data(self):
-        height_options = (self.height & 0x07FFF) 
-        height_options |= (self.has_default_height & 0x01) << 15
+        height_options = (self.__height & 0x07FFF) 
+        height_options |= (self.__has_default_height & 0x01) << 15
 
         options =  (self.level & 0x07) << 0
         options |= (self.collapse & 0x01) << 4
@@ -204,7 +208,27 @@
         return self.__idx
 
 
-    @accepts(object, int, (str, unicode, int, float, dt.datetime, dt.time, dt.date, ExcelFormula.Formula), Style.XFStyle)
+    def get_height(self):
+        return self.__height
+
+    def set_height(self, h):
+        if h == None:
+            self.__has_default_height = 0x01
+        else: self.__height = h
+    
+    height = property(get_height, set_height)
+
+    @accepts(object, int)
+    def set_frmla_opts(self, value):
+        assert (int(value) & ~(0x0b)) == 0, "Invalid bits set for frmla_opts (%s)"%hex(int(value))
+        self.__frmla_opts = int(value)
+
+    def get_frmla_opts(self):
+        return self.__frmla_opts
+
+    frmla_opts = property(get_frmla_opts, set_frmla_opts)
+
+    @accepts(object, int, (str, unicode, int, long, float, dt.datetime, dt.time, dt.date, ExcelFormula.Formula), (Style.XFStyle, type(None)))
     def write(self, col, label, style):
         self.__adjust_height(style)
         self.__adjust_bound_col_idx(col)
@@ -214,7 +238,7 @@
                 self.__total_str += 1
             else:
                 self.__cells.extend([ Cell.BlankCell(self, col, self.__parent_wb.add_style(style)) ])
-        elif isinstance(label, (int, float)):
+        elif isinstance(label, (int, long, float)):
             self.__cells.extend([ Cell.NumberCell(self, col, self.__parent_wb.add_style(style), label) ])            
         elif isinstance(label, (dt.datetime, dt.time)):
             self.__cells.extend([ Cell.NumberCell(self, col, self.__parent_wb.add_style(style), self.__excel_date_dt(label)) ])

Modified: packages/pyexcelerator/trunk/pyExcelerator/Style.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/Style.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/Style.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -58,11 +58,11 @@
     
     def __init__(self):
         self.num_format_str  = _default_num_format
-        self.font            = _default_font 
-        self.alignment       = _default_alignment
-        self.borders         = _default_borders
-        self.pattern         = _default_pattern 
-        self.protection      = _default_protection
+        self.font            = _default_font.copy()
+        self.alignment       = _default_alignment.copy()
+        self.borders         = _default_borders.copy()
+        self.pattern         = _default_pattern.copy()
+        self.protection      = _default_protection.copy()
 
 class StyleCollection(object):
     _std_num_fmt_list = [

Modified: packages/pyexcelerator/trunk/pyExcelerator/Utils.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/Utils.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/Utils.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -163,3 +163,8 @@
     col |= int(not row_abs) << 15
     col |= int(not col_abs) << 14
     return row, col
+
+def pts_to_px(pts): return pts*(4.0/3)
+def px_to_pts(px): return px*(3.0/4)
+def tw_to_px(tw): return tw/15.0
+def px_to_tw(px): return px*15

Modified: packages/pyexcelerator/trunk/pyExcelerator/Workbook.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/Workbook.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/Workbook.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -92,6 +92,23 @@
 
 class Workbook(object):
 
+    macros = {
+        'Consolidate_Area' : 0x00,
+        'Auto_Open' : 0x01,
+        'Auto_Close' : 0x02,
+        'Extract' : 0x03,
+        'Database' : 0x04,
+        'Criteria' : 0x05,
+        'Print_Area' : 0x06,
+        'Print_Titles' : 0x07, # in the docs it says Pint_Titles, I think its a mistake
+        'Recorder' : 0x08,
+        'Data_Form' : 0x09,
+        'Auto_Activate' : 0x0A,
+        'Auto_Deactivate' : 0x0B,
+        'Sheet_Title' : 0x0C,
+        '_FilterDatabase' : 0x0D,
+    }
+
     #################################################################
     ## Constructor
     #################################################################
@@ -128,6 +145,8 @@
         self.__sst = BIFFRecords.SharedStringTable()
         
         self.__worksheets = []
+        self.__names = []
+        self.__refs = []
 
     #################################################################
     ## Properties, "getters", "setters"
@@ -352,7 +371,7 @@
     ## Methods
     ##################################################################
 
-    @accepts(object, Style.XFStyle)
+    @accepts(object, (Style.XFStyle, type(None)))
     def add_style(self, style):
         return self.__styles.add(style)
 
@@ -374,6 +393,22 @@
     def get_sheet(self, sheetnum):
         return self.__worksheets[sheetnum]
         
+    @accepts(object, (int, unicode, str), int, int, int, int)    
+    def print_area(self, sheetnum, rstart, rend, cstart, cend):
+        import ExcelFormula
+        from struct import pack
+        if type(sheetnum) != int:
+            for i, ws in enumerate(self.__worksheets):
+                if ws.name == sheetnum: sheetnum = i+1
+        
+        options = 0x0020 # see Options Flags for Name record
+        
+        # FIXME: this is just a bad hack, need to use Formula to make the rpn
+        #~ rpn = ExcelFormula.Formula('').rpn()[2:] # minus the size field
+        rpn = pack('<BHHHHH', 0x3B, 0x0000, rstart, rend, cstart, cend)
+        
+        return self.__names.append(BIFFRecords.NameRecord(options, 0x00, self.macros['Print_Area'], sheetnum, rpn))
+
     ##################################################################
     ## BIFF records generation
     ##################################################################
@@ -471,6 +506,12 @@
     def __useselfs_rec(self):
         return BIFFRecords.UseSelfsRecord().get()
         
+    def __names_rec(self):
+        name_records = ''
+        for n in self.__names:
+            name_records += n.get()
+        return name_records
+        
     def __boundsheets_rec(self, data_len_before, data_len_after, sheet_biff_lens):
         #  .................................  
         # BOUNDSEHEET0
@@ -493,8 +534,12 @@
         return result
 
     def __all_links_rec(self):
-        result = ''
-        return result
+        supbook_records = ''
+        #~ supbook_records += BIFFRecords.AddInFunctionSupBookRecord(len(self.__worksheets)).get()
+        supbook_records += BIFFRecords.InternalReferenceSupBookRecord(len(self.__worksheets)).get()
+        #~ supbook_records += BIFFRecords.ExternalReferenceSupBookRecord(len(self.__worksheets)).get()
+        externsheet_record = BIFFRecords.ExternSheetRecord(self.__refs).get()
+        return supbook_records + externsheet_record
         
     def __sst_rec(self):
         return self.__sst.get_biff_record()
@@ -515,6 +560,7 @@
         before += self.__dsf_rec() 
         before += self.__tabid_rec() 
         before += self.__fngroupcount_rec()
+        #~ before += self.__names_rec()
         before += self.__wnd_protect_rec()
         before += self.__protect_rec()
         before += self.__obj_protect_rec()
@@ -534,9 +580,10 @@
         
         country            = self.__country_rec()
         all_links          = self.__all_links_rec()
+        names              = self.__names_rec()
         
         shared_str_table   = self.__sst_rec()        
-        after = country + all_links + shared_str_table
+        after = country + all_links + names + shared_str_table
         
         ext_sst = self.__ext_sst_rec(0) # need fake cause we need calc stream pos
         eof = self.__eof_rec()
@@ -551,7 +598,7 @@
             
         bundlesheets = self.__boundsheets_rec(len(before), len(after)+len(ext_sst)+len(eof), sheet_biff_lens)       
        
-        sst_stream_pos = len(before) + len(bundlesheets) + len(country)  + len(all_links)
+        sst_stream_pos = len(before) + len(bundlesheets) + len(country)  + len(all_links) +  len(names)
         ext_sst = self.__ext_sst_rec(sst_stream_pos)           
         
         return before + bundlesheets + after + ext_sst + eof + sheets

Modified: packages/pyexcelerator/trunk/pyExcelerator/Worksheet.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/Worksheet.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/Worksheet.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -82,9 +82,10 @@
 import Bitmap
 import Formatting
 import Style
+import Utils
+import ExcelFormula
 from Deco import *
 
-
 class Worksheet(object):
     from Workbook import Workbook
 
@@ -105,6 +106,7 @@
         self.__rows = {}
         self.__cols = {}
         self.__merged_ranges = []
+        self.__links = {}
         self.__bmp_rec = ''
 
         self.__show_formulas = 0
@@ -149,12 +151,17 @@
         self.__row_default_height = 0x00FF
         self.__col_default_width = 0x0008
 
+        self.__default_row_hidden = 0
+        self.__default_row_space_above = 0
+        self.__default_row_space_below = 0
+
         self.__calc_mode = 1
         self.__calc_count = 0x0064
         self.__RC_ref_mode = 1
         self.__iterations_on = 0
         self.__delta = 0.001
         self.__save_recalc = 0
+        self.__frmla_opts = ExcelFormula.RecalcAlways | ExcelFormula.CalcOnOpen
 
         self.__print_headers = 0
         self.__print_grid = 0
@@ -619,10 +626,11 @@
 
     @accepts(object, int)
     def set_row_default_height(self, value):
-        self.__row_default_height = value
+        ''' set default row height in pixels '''
+        self.__row_default_height = Utils.px_to_tw(value)
 
     def get_row_default_height(self):
-        return self.__row_default_height
+        return Utils.tw_to_px(self.__row_default_height)
 
     row_default_height = property(get_row_default_height, set_row_default_height)
 
@@ -641,7 +649,7 @@
 
     @accepts(object, int)
     def set_calc_mode(self, value):
-        self.__calc_mode = value & 0x03
+        self.__calc_mode = (value == 0xFFFF and value) or value & 0x01
 
     def get_calc_mode(self):
         return self.__calc_mode
@@ -705,6 +713,18 @@
 
     #################################################################
 
+    @accepts(object, int)
+    def set_frmla_opts(self, value):
+        assert (int(value) & ~(0x0b)) == 0, "Invalid bits set for frmla_opts (%s)"%hex(int(value))
+        self.__frmla_opts = int(value)
+
+    def get_frmla_opts(self):
+        return self.__frmla_opts
+
+    frmla_opts = property(get_frmla_opts, set_frmla_opts)
+
+    #################################################################
+
     @accepts(object, bool)
     def set_print_headers(self, value):
         self.__print_headers = int(value)
@@ -1142,6 +1162,36 @@
             result += self.__rows[r].get_str_count()
         return result
 
+    def set_column(self, col_range, width=None, format=Style.XFStyle()):
+        col_by_name = Utils.col_by_name
+        # width is in pixels
+        if col_range.find(':') > -1:
+            start_col, end_col = col_range.split(':')
+            scol_ind, ecol_ind = col_by_name(start_col), col_by_name(end_col)
+            col_range = range(scol_ind, ecol_ind+1)
+        else: col_range = [col_by_name(col_range)]
+        for i in col_range:
+            #~ if width: worksheet.col_default_width = width
+            if width:
+                self.col(i).width = (width*(2962/81.0))
+                #~ print 'setting col %i to width %i'%(i,width*(2962/81.0))
+            #~ if format: worksheet.col(i)._xf_index = worksheet.parent.add_style(format)
+            self.col(i).set_style(format)
+
+    def set_columns(self, col_range, width=None, format=Style.XFStyle()):
+        for r in col_range.split(','):
+            self.set_column(r, width, format)
+
+    def  write_cols(self, r, cstart, cdata, style=Style.XFStyle()):
+        for i, c in enumerate(cdata):
+            self.write(r, cstart+i, c, style)
+
+    def  print_area(self, rstart, rend, cstart, cend):
+        self.__parent.print_area(self.__name, rstart, rend, cstart, cend)
+
+    def set_link(self, x, y, url, target=None, description=None):
+        self.__links[(x,y)] = (url, target, description)
+
     ##################################################################
     ## BIFF records generation
     ##################################################################
@@ -1160,6 +1210,14 @@
 
         return BIFFRecords.GutsRecord(self.__row_gut_width, self.__col_gut_height, row_visible_levels, col_visible_levels).get()
 
+    def __default_row_height_rec(self):
+        options = 0x00
+        options = (0x00 & 0x01) << 0
+        options = (self.__default_row_hidden & 0x01) << 1
+        options = (self.__default_row_space_above & 0x01) << 2
+        options = (self.__default_row_space_below & 0x01) << 3
+        return BIFFRecords.DefaultRowHeight(options, self.__row_default_height).get()
+
     def __wsbool_rec(self):
         options = 0x00
         options |= (self.__show_auto_page_breaks & 0x01) << 0
@@ -1287,8 +1345,8 @@
 
     def __calc_settings_rec(self):
         result = ''
-        result += BIFFRecords.CalcModeRecord(self.__calc_mode & 0x01).get()
         result += BIFFRecords.CalcCountRecord(self.__calc_count & 0xFFFF).get()
+        result += BIFFRecords.CalcModeRecord(self.__calc_mode).get()
         result += BIFFRecords.RefModeRecord(self.__RC_ref_mode & 0x01).get()
         result += BIFFRecords.IterationRecord(self.__iterations_on & 0x01).get()
         result += BIFFRecords.DeltaRecord(self.__delta).get()
@@ -1300,8 +1358,8 @@
         result += BIFFRecords.PrintHeadersRecord(self.__print_headers).get()
         result += BIFFRecords.PrintGridLinesRecord(self.__print_grid).get()
         result += BIFFRecords.GridSetRecord(self.__grid_set).get()
-        result += BIFFRecords.HorizontalPageBreaksRecord(self.__horz_page_breaks).get()
-        result += BIFFRecords.VerticalPageBreaksRecord(self.__vert_page_breaks).get()
+        result += BIFFRecords.HorizontalPageBreaksRecord([type(b) == int and (b, 0, -1) or b for b in self.__horz_page_breaks]).get()
+        result += BIFFRecords.VerticalPageBreaksRecord([type(b) == int and (b, 0, -1) or b for b in self.__vert_page_breaks]).get()
         result += BIFFRecords.HeaderRecord(self.__header_str).get()
         result += BIFFRecords.FooterRecord(self.__footer_str).get()
         result += BIFFRecords.HCenterRecord(self.__print_centered_horz).get()
@@ -1344,11 +1402,20 @@
         result += BIFFRecords.PasswordRecord(self.__password).get()
         return result
 
+    def __hyperlink_table_rec(self):
+        result = ''
+        for (x, y), (url, target, description) in self.__links.items():
+            result += BIFFRecords.HyperlinkRecord(x, x, y, y, url, target=target, description=description).get()
+            if description is not None:
+                result += BIFFRecords.QuicktipRecord(x, x, y, y, description).get()
+        return result
+
     def get_biff_data(self):
         result = ''
         result += self.__bof_rec()
         result += self.__calc_settings_rec()
         result += self.__guts_rec()
+        result += self.__default_row_height_rec()
         result += self.__wsbool_rec()
         result += self.__colinfo_rec()
         result += self.__dimensions_rec()
@@ -1359,6 +1426,7 @@
         result += self.__bitmaps_rec()
         result += self.__window2_rec()
         result += self.__panes_rec()
+        result += self.__hyperlink_table_rec()
         result += self.__eof_rec()
 
         return result

Added: packages/pyexcelerator/trunk/pyExcelerator/antlr.py
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/antlr.py	                        (rev 0)
+++ packages/pyexcelerator/trunk/pyExcelerator/antlr.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -0,0 +1,2800 @@
+## This file is part of PyANTLR. See LICENSE.txt for license
+## details..........Copyright (C) Wolfgang Haefelinger, 2004.
+
+## get sys module
+import sys
+
+version = sys.version.split()[0]
+if version < '2.2.1':
+    False = 0
+if version < '2.3':
+    True = not False
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                     global symbols                             ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+### ANTLR Standard Tokens
+SKIP                = -1
+INVALID_TYPE        = 0
+EOF_TYPE            = 1
+EOF                 = 1
+NULL_TREE_LOOKAHEAD = 3
+MIN_USER_TYPE       = 4
+
+### ANTLR's EOF Symbol
+EOF_CHAR            = ''
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                    general functions                           ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+def error(fmt,*args):
+    if fmt:
+        print "error: ", fmt % tuple(args)
+
+def ifelse(cond,_then,_else):
+    if cond :
+        r = _then
+    else:
+        r = _else
+    return r
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                     ANTLR Exceptions                           ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class ANTLRException(Exception):
+
+    def __init__(self, *args):
+        Exception.__init__(self, *args)
+
+
+class RecognitionException(ANTLRException):
+
+    def __init__(self, *args):
+        ANTLRException.__init__(self, *args)
+        self.fileName = None
+        self.line = -1
+        self.column = -1
+        if len(args) >= 2:
+            self.fileName = args[1]
+        if len(args) >= 3:
+            self.line = args[2]
+        if len(args) >= 4:
+            self.column = args[3]
+
+    def __str__(self):
+        buf = ['']
+        if self.fileName:
+            buf.append(self.fileName + ":")
+        if self.line != -1:
+            if not self.fileName:
+                buf.append("line ")
+            buf.append(str(self.line))
+            if self.column != -1:
+                buf.append(":" + str(self.column))
+            buf.append(":")
+        buf.append(" ")
+        return str('').join(buf)
+
+    __repr__ = __str__
+
+
+class NoViableAltException(RecognitionException):
+
+    def __init__(self, *args):
+        RecognitionException.__init__(self, *args)
+        self.token = None
+        self.node  = None
+        if isinstance(args[0],AST):
+            self.node = args[0]
+        elif isinstance(args[0],Token):
+            self.token = args[0]
+        else:
+            raise TypeError("NoViableAltException requires Token or AST argument")
+
+    def __str__(self):
+        if self.token:
+            line = self.token.getLine()
+            col  = self.token.getColumn()
+            text = self.token.getText()
+            return "unexpected symbol at line %s (column %s): \"%s\"" % (line,col,text)
+        if self.node == ASTNULL:
+            return "unexpected end of subtree"
+        assert self.node
+        ### hackish, we assume that an AST contains method getText
+        return "unexpected node: %s" % (self.node.getText())
+
+    __repr__ = __str__
+
+
+class NoViableAltForCharException(RecognitionException):
+
+    def __init__(self, *args):
+        self.foundChar = None
+        if len(args) == 2:
+            self.foundChar = args[0]
+            scanner = args[1]
+            RecognitionException.__init__(self, "NoViableAlt",
+                                          scanner.getFilename(),
+                                          scanner.getLine(),
+                                          scanner.getColumn())
+        elif len(args) == 4:
+            self.foundChar = args[0]
+            fileName = args[1]
+            line = args[2]
+            column = args[3]
+            RecognitionException.__init__(self, "NoViableAlt",
+                                          fileName, line, column)
+        else:
+            RecognitionException.__init__(self, "NoViableAlt",
+                                          '', -1, -1)
+
+    def __str__(self):
+        mesg = "unexpected char: "
+        if self.foundChar >= ' ' and self.foundChar <= '~':
+            mesg += "'" + self.foundChar + "'"
+        elif self.foundChar:
+            mesg += "0x" + hex(ord(self.foundChar)).upper()[2:]
+        else:
+            mesg += "<None>"
+        return mesg
+
+    __repr__ = __str__
+
+
+class SemanticException(RecognitionException):
+
+    def __init__(self, *args):
+        RecognitionException.__init__(self, *args)
+
+
+class MismatchedCharException(RecognitionException):
+
+    NONE = 0
+    CHAR = 1
+    NOT_CHAR = 2
+    RANGE = 3
+    NOT_RANGE = 4
+    SET = 5
+    NOT_SET = 6
+
+    def __init__(self, *args):
+        self.args = args
+        if len(args) == 5:
+            # Expected range / not range
+            if args[3]:
+                self.mismatchType = MismatchedCharException.NOT_RANGE
+            else:
+                self.mismatchType = MismatchedCharException.RANGE
+            self.foundChar = args[0]
+            self.expecting = args[1]
+            self.upper = args[2]
+            self.scanner = args[4]
+            RecognitionException.__init__(self, "Mismatched char range",
+                                          self.scanner.getFilename(),
+                                          self.scanner.getLine(),
+                                          self.scanner.getColumn())
+        elif len(args) == 4 and isinstance(args[1], str):
+            # Expected char / not char
+            if args[2]:
+                self.mismatchType = MismatchedCharException.NOT_CHAR
+            else:
+                self.mismatchType = MismatchedCharException.CHAR
+            self.foundChar = args[0]
+            self.expecting = args[1]
+            self.scanner = args[3]
+            RecognitionException.__init__(self, "Mismatched char",
+                                          self.scanner.getFilename(),
+                                          self.scanner.getLine(),
+                                          self.scanner.getColumn())
+        elif len(args) == 4 and isinstance(args[1], BitSet):
+            # Expected BitSet / not BitSet
+            if args[2]:
+                self.mismatchType = MismatchedCharException.NOT_SET
+            else:
+                self.mismatchType = MismatchedCharException.SET
+            self.foundChar = args[0]
+            self.set = args[1]
+            self.scanner = args[3]
+            RecognitionException.__init__(self, "Mismatched char set",
+                                          self.scanner.getFilename(),
+                                          self.scanner.getLine(),
+                                          self.scanner.getColumn())
+        else:
+            self.mismatchType = MismatchedCharException.NONE
+            RecognitionException.__init__(self, "Mismatched char")
+
+    ## Append a char to the msg buffer.  If special,
+    #  then show escaped version
+    #
+    def appendCharName(self, sb, c):
+        if not c or c == 65535:
+            # 65535 = (char) -1 = EOF
+            sb.append("'<EOF>'")
+        elif c == '\n':
+            sb.append("'\\n'")
+        elif c == '\r':
+            sb.append("'\\r'");
+        elif c == '\t':
+            sb.append("'\\t'")
+        else:
+            sb.append('\'' + c + '\'')
+
+    ##
+    # Returns an error message with line number/column information
+    #
+    def __str__(self):
+        sb = ['']
+        sb.append(RecognitionException.__str__(self))
+
+        if self.mismatchType == MismatchedCharException.CHAR:
+            sb.append("expecting ")
+            self.appendCharName(sb, self.expecting)
+            sb.append(", found ")
+            self.appendCharName(sb, self.foundChar)
+        elif self.mismatchType == MismatchedCharException.NOT_CHAR:
+            sb.append("expecting anything but '")
+            self.appendCharName(sb, self.expecting)
+            sb.append("'; got it anyway")
+        elif self.mismatchType in [MismatchedCharException.RANGE, MismatchedCharException.NOT_RANGE]:
+            sb.append("expecting char ")
+            if self.mismatchType == MismatchedCharException.NOT_RANGE:
+                sb.append("NOT ")
+            sb.append("in range: ")
+            appendCharName(sb, self.expecting)
+            sb.append("..")
+            appendCharName(sb, self.upper)
+            sb.append(", found ")
+            appendCharName(sb, self.foundChar)
+        elif self.mismatchType in [MismatchedCharException.SET, MismatchedCharException.NOT_SET]:
+            sb.append("expecting ")
+            if self.mismatchType == MismatchedCharException.NOT_SET:
+                sb.append("NOT ")
+            sb.append("one of (")
+            for i in range(len(self.set)):
+                self.appendCharName(sb, self.set[i])
+            sb.append("), found ")
+            self.appendCharName(sb, self.foundChar)
+
+        return str().join(sb).strip()
+
+    __repr__ = __str__
+
+
+class MismatchedTokenException(RecognitionException):
+
+    NONE = 0
+    TOKEN = 1
+    NOT_TOKEN = 2
+    RANGE = 3
+    NOT_RANGE = 4
+    SET = 5
+    NOT_SET = 6
+
+    def __init__(self, *args):
+        self.args =  args
+        self.tokenNames = []
+        self.token = None
+        self.tokenText = ''
+        self.node =  None
+        if len(args) == 6:
+            # Expected range / not range
+            if args[3]:
+                self.mismatchType = MismatchedTokenException.NOT_RANGE
+            else:
+                self.mismatchType = MismatchedTokenException.RANGE
+            self.tokenNames = args[0]
+            self.expecting = args[2]
+            self.upper = args[3]
+            self.fileName = args[5]
+
+        elif len(args) == 4 and isinstance(args[2], int):
+            # Expected token / not token
+            if args[3]:
+                self.mismatchType = MismatchedTokenException.NOT_TOKEN
+            else:
+                self.mismatchType = MismatchedTokenException.TOKEN
+            self.tokenNames = args[0]
+            self.expecting = args[2]
+
+        elif len(args) == 4 and isinstance(args[2], BitSet):
+            # Expected BitSet / not BitSet
+            if args[3]:
+                self.mismatchType = MismatchedTokenException.NOT_SET
+            else:
+                self.mismatchType = MismatchedTokenException.SET
+            self.tokenNames = args[0]
+            self.set = args[2]
+
+        else:
+            self.mismatchType = MismatchedTokenException.NONE
+            RecognitionException.__init__(self, "Mismatched Token: expecting any AST node", "<AST>", -1, -1)
+
+        if len(args) >= 2:
+            if isinstance(args[1],Token):
+                self.token = args[1]
+                self.tokenText = self.token.getText()
+                RecognitionException.__init__(self, "Mismatched Token",
+                                              self.fileName,
+                                              self.token.getLine(),
+                                              self.token.getColumn())
+            elif isinstance(args[1],AST):
+                self.node = args[1]
+                self.tokenText = str(self.node)
+                RecognitionException.__init__(self, "Mismatched Token",
+                                              "<AST>",
+                                              self.node.getLine(),
+                                              self.node.getColumn())
+            else:
+                self.tokenText = "<empty tree>"
+                RecognitionException.__init__(self, "Mismatched Token",
+                                              "<AST>", -1, -1)
+
+    def appendTokenName(self, sb, tokenType):
+        if tokenType == INVALID_TYPE:
+            sb.append("<Set of tokens>")
+        elif tokenType < 0 or tokenType >= len(self.tokenNames):
+            sb.append("<" + str(tokenType) + ">")
+        else:
+            sb.append(self.tokenNames[tokenType])
+
+    ##
+    # Returns an error message with line number/column information
+    #
+    def __str__(self):
+        sb = ['']
+        sb.append(RecognitionException.__str__(self))
+
+        if self.mismatchType == MismatchedTokenException.TOKEN:
+            sb.append("expecting ")
+            self.appendTokenName(sb, self.expecting)
+            sb.append(", found " + self.tokenText)
+        elif self.mismatchType == MismatchedTokenException.NOT_TOKEN:
+            sb.append("expecting anything but '")
+            self.appendTokenName(sb, self.expecting)
+            sb.append("'; got it anyway")
+        elif self.mismatchType in [MismatchedTokenException.RANGE, MismatchedTokenException.NOT_RANGE]:
+            sb.append("expecting token ")
+            if self.mismatchType == MismatchedTokenException.NOT_RANGE:
+                sb.append("NOT ")
+            sb.append("in range: ")
+            appendTokenName(sb, self.expecting)
+            sb.append("..")
+            appendTokenName(sb, self.upper)
+            sb.append(", found " + self.tokenText)
+        elif self.mismatchType in [MismatchedTokenException.SET, MismatchedTokenException.NOT_SET]:
+            sb.append("expecting ")
+            if self.mismatchType == MismatchedTokenException.NOT_SET:
+                sb.append("NOT ")
+            sb.append("one of (")
+            for i in range(len(self.set)):
+                self.appendTokenName(sb, self.set[i])
+            sb.append("), found " + self.tokenText)
+
+        return str().join(sb).strip()
+
+    __repr__ = __str__
+
+
+class TokenStreamException(ANTLRException):
+
+    def __init__(self, *args):
+        ANTLRException.__init__(self, *args)
+
+
+# Wraps an Exception in a TokenStreamException
+class TokenStreamIOException(TokenStreamException):
+
+    def __init__(self, *args):
+        if args and isinstance(args[0], Exception):
+            io = args[0]
+            TokenStreamException.__init__(self, str(io))
+            self.io = io
+        else:
+            TokenStreamException.__init__(self, *args)
+            self.io = self
+
+
+# Wraps a RecognitionException in a TokenStreamException
+class TokenStreamRecognitionException(TokenStreamException):
+
+    def __init__(self, *args):
+        if args and isinstance(args[0], RecognitionException):
+            recog = args[0]
+            TokenStreamException.__init__(self, str(recog))
+            self.recog = recog
+        else:
+            raise TypeError("TokenStreamRecognitionException requires RecognitionException argument")
+
+    def __str__(self):
+        return str(self.recog)
+
+    __repr__ = __str__
+
+
+class TokenStreamRetryException(TokenStreamException):
+
+    def __init__(self, *args):
+        TokenStreamException.__init__(self, *args)
+
+
+class CharStreamException(ANTLRException):
+
+    def __init__(self, *args):
+        ANTLRException.__init__(self, *args)
+
+
+# Wraps an Exception in a CharStreamException
+class CharStreamIOException(CharStreamException):
+
+    def __init__(self, *args):
+        if args and isinstance(args[0], Exception):
+            io = args[0]
+            CharStreamException.__init__(self, str(io))
+            self.io = io
+        else:
+            CharStreamException.__init__(self, *args)
+            self.io = self
+
+
+class TryAgain(Exception):
+    pass
+
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       Token                                    ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class Token(object):
+    SKIP                = -1
+    INVALID_TYPE        = 0
+    EOF_TYPE            = 1
+    EOF                 = 1
+    NULL_TREE_LOOKAHEAD = 3
+    MIN_USER_TYPE       = 4
+
+    def __init__(self,**argv):
+        try:
+            self.type = argv['type']
+        except:
+            self.type = INVALID_TYPE
+        try:
+            self.text = argv['text']
+        except:
+            self.text = "<no text>"
+
+    def isEOF(self):
+        return (self.type == EOF_TYPE)
+
+    def getColumn(self):
+        return 0
+
+    def getLine(self):
+        return 0
+
+    def getFilename(self):
+        return None
+
+    def setFilename(self,name):
+        return self
+
+    def getText(self):
+        return "<no text>"
+
+    def setText(self,text):
+        if isinstance(text,str):
+            pass
+        else:
+            raise TypeError("Token.setText requires string argument")
+        return self
+
+    def setColumn(self,column):
+        return self
+
+    def setLine(self,line):
+        return self
+
+    def getType(self):
+        return self.type
+
+    def setType(self,type):
+        if isinstance(type,int):
+            self.type = type
+        else:
+            raise TypeError("Token.setType requires integer argument")
+        return self
+
+    def toString(self):
+        ## not optimal
+        type_ = self.type
+        if type_ == 3:
+            tval = 'NULL_TREE_LOOKAHEAD'
+        elif type_ == 1:
+            tval = 'EOF_TYPE'
+        elif type_ == 0:
+            tval = 'INVALID_TYPE'
+        elif type_ == -1:
+            tval = 'SKIP'
+        else:
+            tval = type_
+        return '["%s",<%s>]' % (self.getText(),tval)
+
+    __str__ = toString
+    __repr__ = toString
+
+### static attribute ..
+Token.badToken = Token( type=INVALID_TYPE, text="<no text>")
+
+if __name__ == "__main__":
+    print "testing .."
+    T = Token.badToken
+    print T
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       CommonToken                              ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class CommonToken(Token):
+
+    def __init__(self,**argv):
+        Token.__init__(self,**argv)
+        self.line = 0
+        self.col  = 0
+        try:
+            self.line = argv['line']
+        except:
+            pass
+        try:
+            self.col = argv['col']
+        except:
+            pass
+
+    def getLine(self):
+        return self.line
+
+    def getText(self):
+        return self.text
+
+    def getColumn(self):
+        return self.col
+
+    def setLine(self,line):
+        self.line = line
+        return self
+
+    def setText(self,text):
+        self.text = text
+        return self
+
+    def setColumn(self,col):
+        self.col = col
+        return self
+
+    def toString(self):
+        ## not optimal
+        type_ = self.type
+        if type_ == 3:
+            tval = 'NULL_TREE_LOOKAHEAD'
+        elif type_ == 1:
+            tval = 'EOF_TYPE'
+        elif type_ == 0:
+            tval = 'INVALID_TYPE'
+        elif type_ == -1:
+            tval = 'SKIP'
+        else:
+            tval = type_
+        d = {
+           'text' : self.text,
+           'type' : tval,
+           'line' : self.line,
+           'colm' : self.col
+           }
+
+        fmt = '["%(text)s",<%(type)s>,line=%(line)s,col=%(colm)s]'
+        return fmt % d
+
+    __str__ = toString
+    __repr__ = toString
+
+
+if __name__ == '__main__' :
+    T = CommonToken()
+    print T
+    T = CommonToken(col=15,line=1,text="some text", type=5)
+    print T
+    T = CommonToken()
+    T.setLine(1).setColumn(15).setText("some text").setType(5)
+    print T
+    print T.getLine()
+    print T.getColumn()
+    print T.getText()
+    print T.getType()
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                    CommonHiddenStreamToken                     ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class CommonHiddenStreamToken(CommonToken):
+    def __init__(self,*args):
+        CommonToken.__init__(self,*args)
+        self.hiddenBefore = None
+        self.hiddenAfter  = None
+
+    def getHiddenAfter(self):
+        return self.hiddenAfter
+
+    def getHiddenBefore(self):
+        return self.hiddenBefore
+
+    def setHiddenAfter(self,t):
+        self.hiddenAfter = t
+
+    def setHiddenBefore(self, t):
+        self.hiddenBefore = t
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       Queue                                    ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+## Shall be a circular buffer on tokens ..
+class Queue(object):
+
+    def __init__(self):
+        self.buffer = [] # empty list
+
+    def append(self,item):
+        self.buffer.append(item)
+
+    def elementAt(self,index):
+        return self.buffer[index]
+
+    def reset(self):
+        self.buffer = []
+
+    def removeFirst(self):
+        self.buffer.pop(0)
+
+    def length(self):
+        return len(self.buffer)
+
+    def __str__(self):
+        return str(self.buffer)
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       InputBuffer                              ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class InputBuffer(object):
+    def __init__(self):
+        self.nMarkers = 0
+        self.markerOffset = 0
+        self.numToConsume = 0
+        self.queue = Queue()
+
+    def __str__(self):
+        return "(%s,%s,%s,%s)" % (
+           self.nMarkers,
+           self.markerOffset,
+           self.numToConsume,
+           self.queue)
+
+    def __repr__(self):
+        return str(self)
+
+    def commit(self):
+        self.nMarkers -= 1
+
+    def consume(self) :
+        self.numToConsume += 1
+
+    ## probably better to return a list of items
+    ## because of unicode. Or return a unicode
+    ## string ..
+    def getLAChars(self) :
+        i = self.markerOffset
+        n = self.queue.length()
+        s = ''
+        while i<n:
+            s += self.queue.elementAt(i)
+        return s
+
+    ## probably better to return a list of items
+    ## because of unicode chars
+    def getMarkedChars(self) :
+        s = ''
+        i = 0
+        n = self.markerOffset
+        while i<n:
+            s += self.queue.elementAt(i)
+        return s
+
+    def isMarked(self) :
+        return self.nMarkers != 0
+
+    def fill(self,k):
+        ### abstract method
+        raise NotImplementedError()
+
+    def LA(self,k) :
+        self.fill(k)
+        return self.queue.elementAt(self.markerOffset + k - 1)
+
+    def mark(self) :
+        self.syncConsume()
+        self.nMarkers += 1
+        return self.markerOffset
+
+    def rewind(self,mark) :
+        self.syncConsume()
+        self.markerOffset = mark
+        self.nMarkers -= 1
+
+    def reset(self) :
+        self.nMarkers = 0
+        self.markerOffset = 0
+        self.numToConsume = 0
+        self.queue.reset()
+
+    def syncConsume(self) :
+        while self.numToConsume > 0:
+            if self.nMarkers > 0:
+                # guess mode -- leave leading characters and bump offset.
+                self.markerOffset += 1
+            else:
+                # normal mode -- remove first character
+                self.queue.removeFirst()
+            self.numToConsume -= 1
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       CharBuffer                               ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class CharBuffer(InputBuffer):
+    def __init__(self,reader):
+        ##assert isinstance(reader,file)
+        super(CharBuffer,self).__init__()
+        ## a reader is supposed to be anything that has
+        ## a method 'read(int)'.
+        self.input = reader
+
+    def __str__(self):
+        base = super(CharBuffer,self).__str__()
+        return "CharBuffer{%s,%s" % (base,str(input))
+
+    def fill(self,amount):
+        try:
+            self.syncConsume()
+            while self.queue.length() < (amount + self.markerOffset) :
+                ## retrieve just one char - what happend at end
+                ## of input?
+                c = self.input.read(1)
+                ### python's behaviour is to return the empty string  on
+                ### EOF, ie. no exception whatsoever is thrown. An empty
+                ### python  string  has  the  nice feature that it is of
+                ### type 'str' and  "not ''" would return true. Contrary,
+                ### one can't  do  this: '' in 'abc'. This should return
+                ### false,  but all we  get  is  then  a TypeError as an
+                ### empty string is not a character.
+
+                ### Let's assure then that we have either seen a
+                ### character or an empty string (EOF).
+                assert len(c) == 0 or len(c) == 1
+
+                ### And it shall be of type string (ASCII or UNICODE).
+                assert isinstance(c,str) or isinstance(c,unicode)
+
+                ### Just append EOF char to buffer. Note that buffer may
+                ### contain then just more than one EOF char ..
+
+                ### use unicode chars instead of ASCII ..
+                self.queue.append(c)
+        except Exception,e:
+            raise CharStreamIOException(e)
+        ##except: # (mk) Cannot happen ...
+            ##error ("unexpected exception caught ..")
+            ##assert 0
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       LexerSharedInputState                    ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class LexerSharedInputState(object):
+    def __init__(self,ibuf):
+        assert isinstance(ibuf,InputBuffer)
+        self.input = ibuf
+        self.column = 1
+        self.line = 1
+        self.tokenStartColumn = 1
+        self.tokenStartLine = 1
+        self.guessing = 0
+        self.filename = None
+
+    def reset(self):
+        self.column = 1
+        self.line = 1
+        self.tokenStartColumn = 1
+        self.tokenStartLine = 1
+        self.guessing = 0
+        self.filename = None
+        self.input.reset()
+
+    def LA(self,k):
+        return self.input.LA(k)
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                    TokenStream                                 ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class TokenStream(object):
+    def nextToken(self):
+        pass
+
+    def __iter__(self):
+        return TokenStreamIterator(self)
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                    TokenStreamIterator                                 ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class TokenStreamIterator(object):
+    def __init__(self,inst):
+        if isinstance(inst,TokenStream):
+            self.inst = inst
+            return
+        raise TypeError("TokenStreamIterator requires TokenStream object")
+
+    def next(self):
+        assert self.inst
+        item = self.inst.nextToken()
+        if not item or item.isEOF():
+            raise StopIteration()
+        return item
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                    TokenStreamSelector                        ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class TokenStreamSelector(TokenStream):
+
+    def __init__(self):
+        self._input = None
+        self._stmap = {}
+        self._stack = []
+
+    def addInputStream(self,stream,key):
+        self._stmap[key] = stream
+
+    def getCurrentStream(self):
+        return self._input
+
+    def getStream(self,sname):
+        try:
+            stream = self._stmap[sname]
+        except:
+            raise ValueError("TokenStream " + sname + " not found");
+        return stream;
+
+    def nextToken(self):
+        while 1:
+            try:
+                return self._input.nextToken()
+            except TokenStreamRetryException,r:
+                ### just retry "forever"
+                pass
+
+    def pop(self):
+        stream = self._stack.pop();
+        self.select(stream);
+        return stream;
+
+    def push(self,arg):
+        self._stack.append(self._input);
+        self.select(arg)
+
+    def retry(self):
+        raise TokenStreamRetryException()
+
+    def select(self,arg):
+        if isinstance(arg,TokenStream):
+            self._input = arg
+            return
+        if isinstance(arg,str):
+            self._input = self.getStream(arg)
+            return
+        raise TypeError("TokenStreamSelector.select requires " +
+                        "TokenStream or string argument")
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                      TokenStreamBasicFilter                    ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class TokenStreamBasicFilter(TokenStream):
+
+    def __init__(self,input):
+
+        self.input = input;
+        self.discardMask = BitSet()
+
+    def discard(self,arg):
+        if isinstance(arg,int):
+            self.discardMask.add(arg)
+            return
+        if isinstance(arg,BitSet):
+            self.discardMark = arg
+            return
+        raise TypeError("TokenStreamBasicFilter.discard requires" +
+                        "integer or BitSet argument")
+
+    def nextToken(self):
+        tok = self.input.nextToken()
+        while tok and self.discardMask.member(tok.getType()):
+            tok = self.input.nextToken()
+        return tok
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                      TokenStreamHiddenTokenFilter              ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class TokenStreamHiddenTokenFilter(TokenStreamBasicFilter):
+
+    def __init__(self,input):
+        TokenStreamBasicFilter.__init__(self,input)
+        self.hideMask = BitSet()
+        self.nextMonitoredToken = None
+        self.lastHiddenToken = None
+        self.firstHidden = None
+
+    def consume(self):
+        self.nextMonitoredToken = self.input.nextToken()
+
+    def consumeFirst(self):
+        self.consume()
+
+        p = None;
+        while self.hideMask.member(self.LA(1).getType()) or \
+              self.discardMask.member(self.LA(1).getType()):
+            if self.hideMask.member(self.LA(1).getType()):
+                if not p:
+                    p = self.LA(1)
+                else:
+                    p.setHiddenAfter(self.LA(1))
+                    self.LA(1).setHiddenBefore(p)
+                    p = self.LA(1)
+                self.lastHiddenToken = p
+                if not self.firstHidden:
+                    self.firstHidden = p
+            self.consume()
+
+    def getDiscardMask(self):
+        return self.discardMask
+
+    def getHiddenAfter(self,t):
+        return t.getHiddenAfter()
+
+    def getHiddenBefore(self,t):
+        return t.getHiddenBefore()
+
+    def getHideMask(self):
+        return self.hideMask
+
+    def getInitialHiddenToken(self):
+        return self.firstHidden
+
+    def hide(self,m):
+        if isinstance(m,int):
+            self.hideMask.add(m)
+            return
+        if isinstance(m.BitMask):
+            self.hideMask = m
+            return
+
+    def LA(self,i):
+        return self.nextMonitoredToken
+
+    def nextToken(self):
+        if not self.LA(1):
+            self.consumeFirst()
+
+        monitored = self.LA(1)
+
+        monitored.setHiddenBefore(self.lastHiddenToken)
+        self.lastHiddenToken = None
+
+        self.consume()
+        p = monitored
+
+        while self.hideMask.member(self.LA(1).getType()) or \
+              self.discardMask.member(self.LA(1).getType()):
+            if self.hideMask.member(self.LA(1).getType()):
+                p.setHiddenAfter(self.LA(1))
+                if p != monitored:
+                    self.LA(1).setHiddenBefore(p)
+                p = self.lastHiddenToken = self.LA(1)
+            self.consume()
+        return monitored
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       StringBuffer                             ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class StringBuffer:
+    def __init__(self,string=None):
+        if string:
+            self.text = list(string)
+        else:
+            self.text = []
+
+    def setLength(self,sz):
+        if not sz :
+            self.text = []
+            return
+        assert sz>0
+        if sz >= self.length():
+            return
+        ### just reset to empty buffer
+        self.text = self.text[0:sz]
+
+    def length(self):
+        return len(self.text)
+
+    def append(self,c):
+        self.text.append(c)
+
+    ### return buffer as string. Arg 'a' is  used  as index
+    ## into the buffer and 2nd argument shall be the length.
+    ## If 2nd args is absent, we return chars till end of
+    ## buffer starting with 'a'.
+    def getString(self,a=None,length=None):
+        if not a :
+            a = 0
+        assert a>=0
+        if a>= len(self.text) :
+            return ""
+
+        if not length:
+            ## no second argument
+            L = self.text[a:]
+        else:
+            assert (a+length) <= len(self.text)
+            b = a + length
+            L = self.text[a:b]
+        s = ""
+        for x in L : s += x
+        return s
+
+    toString = getString ## alias
+
+    def __str__(self):
+        return str(self.text)
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       Reader                                   ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+## When reading Japanese chars, it happens that a stream returns a
+## 'char' of length 2. This looks like  a  bug  in the appropriate
+## codecs - but I'm  rather  unsure about this. Anyway, if this is
+## the case, I'm going to  split  this string into a list of chars
+## and put them  on  hold, ie. on a  buffer. Next time when called
+## we read from buffer until buffer is empty.
+## wh: nov, 25th -> problem does not appear in Python 2.4.0.c1.
+
+class Reader(object):
+    def __init__(self,stream):
+        self.cin = stream
+        self.buf = []
+
+    def read(self,num):
+        assert num==1
+
+        if len(self.buf):
+            return self.buf.pop()
+
+        ## Read a char - this may return a string.
+        ## Is this a bug in codecs/Python?
+        c = self.cin.read(1)
+
+        if not c or len(c)==1:
+            return c
+
+        L = list(c)
+        L.reverse()
+        for x in L:
+            self.buf.append(x)
+
+        ## read one char ..
+        return self.read(1)
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       CharScanner                              ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class CharScanner(TokenStream):
+    ## class members
+    NO_CHAR = 0
+    EOF_CHAR = ''  ### EOF shall be the empty string.
+
+    def __init__(self, *argv, **kwargs):
+        super(CharScanner, self).__init__()
+        self.saveConsumedInput = True
+        self.tokenClass = None
+        self.caseSensitive = True
+        self.caseSensitiveLiterals = True
+        self.literals = None
+        self.tabsize = 8
+        self._returnToken = None
+        self.commitToPath = False
+        self.traceDepth = 0
+        self.text = StringBuffer()
+        self.hashString = hash(self)
+        self.setTokenObjectClass(CommonToken)
+        self.setInput(*argv)
+
+    def __iter__(self):
+        return CharScannerIterator(self)
+
+    def setInput(self,*argv):
+        ## case 1:
+        ## if there's no arg we default to read from
+        ## standard input
+        if not argv:
+            import sys
+            self.setInput(sys.stdin)
+            return
+
+        ## get 1st argument
+        arg1 = argv[0]
+
+        ## case 2:
+        ## if arg1 is a string,  we assume it's a file name
+        ## and  open  a  stream  using 2nd argument as open
+        ## mode. If there's no 2nd argument we fall back to
+        ## mode '+rb'.
+        if isinstance(arg1,str):
+            f = open(arg1,"rb")
+            self.setInput(f)
+            self.setFilename(arg1)
+            return
+
+        ## case 3:
+        ## if arg1 is a file we wrap it by a char buffer (
+        ## some additional checks?? No, can't do this in
+        ## general).
+        if isinstance(arg1,file):
+            self.setInput(CharBuffer(arg1))
+            return
+
+        ## case 4:
+        ## if arg1 is of type SharedLexerInputState we use
+        ## argument as is.
+        if isinstance(arg1,LexerSharedInputState):
+            self.inputState = arg1
+            return
+
+        ## case 5:
+        ## check whether argument type is of type input
+        ## buffer. If so create a SharedLexerInputState and
+        ## go ahead.
+        if isinstance(arg1,InputBuffer):
+            self.setInput(LexerSharedInputState(arg1))
+            return
+
+        ## case 6:
+        ## check whether argument type has a method read(int)
+        ## If so create CharBuffer ...
+        try:
+            if arg1.read:
+                rd = Reader(arg1)
+                cb = CharBuffer(rd)
+                ss = LexerSharedInputState(cb)
+                self.inputState = ss
+            return
+        except:
+            pass
+
+        ## case 7:
+        ## raise wrong argument exception
+        raise TypeError(argv)
+
+    def setTabSize(self,size) :
+        self.tabsize = size
+
+    def getTabSize(self) :
+        return self.tabsize
+
+    def setCaseSensitive(self,t) :
+        self.caseSensitive = t
+
+    def setCommitToPath(self,commit) :
+        self.commitToPath = commit
+
+    def setFilename(self,f) :
+        self.inputState.filename = f
+
+    def setLine(self,line) :
+        self.inputState.line = line
+
+    def setText(self,s) :
+        self.resetText()
+        self.text.append(s)
+
+    def getCaseSensitive(self) :
+        return self.caseSensitive
+
+    def getCaseSensitiveLiterals(self) :
+        return self.caseSensitiveLiterals
+
+    def getColumn(self) :
+        return self.inputState.column
+
+    def setColumn(self,c) :
+        self.inputState.column = c
+
+    def getCommitToPath(self) :
+        return self.commitToPath
+
+    def getFilename(self) :
+        return self.inputState.filename
+
+    def getInputBuffer(self) :
+        return self.inputState.input
+
+    def getInputState(self) :
+        return self.inputState
+
+    def setInputState(self,state) :
+        assert isinstance(state,LexerSharedInputState)
+        self.inputState = state
+
+    def getLine(self) :
+        return self.inputState.line
+
+    def getText(self) :
+        return str(self.text)
+
+    def getTokenObject(self) :
+        return self._returnToken
+
+    def LA(self,i) :
+        c = self.inputState.input.LA(i)
+        if not self.caseSensitive:
+            ### E0006
+            c = c.__class__.lower(c)
+        return c
+
+    def makeToken(self,type) :
+        try:
+            ## dynamically load a class
+            assert self.tokenClass
+            tok = self.tokenClass()
+            tok.setType(type)
+            tok.setColumn(self.inputState.tokenStartColumn)
+            tok.setLine(self.inputState.tokenStartLine)
+            return tok
+        except:
+            self.panic("unable to create new token")
+        return Token.badToken
+
+    def mark(self) :
+        return self.inputState.input.mark()
+
+    def _match_bitset(self,b) :
+        if b.member(self.LA(1)):
+            self.consume()
+        else:
+            raise MismatchedCharException(self.LA(1), b, False, self)
+
+    def _match_string(self,s) :
+        for c in s:
+            if self.LA(1) == c:
+                self.consume()
+            else:
+                raise MismatchedCharException(self.LA(1), c, False, self)
+
+    def match(self,item):
+        if isinstance(item,str) or isinstance(item,unicode):
+            return self._match_string(item)
+        else:
+            return self._match_bitset(item)
+
+    def matchNot(self,c) :
+        if self.LA(1) != c:
+            self.consume()
+        else:
+            raise MismatchedCharException(self.LA(1), c, True, self)
+
+    def matchRange(self,c1,c2) :
+        if self.LA(1) < c1 or self.LA(1) > c2 :
+            raise MismatchedCharException(self.LA(1), c1, c2, False, self)
+        else:
+            self.consume()
+
+    def newline(self) :
+        self.inputState.line += 1
+        self.inputState.column = 1
+
+    def tab(self) :
+        c = self.getColumn()
+        nc = ( ((c-1)/self.tabsize) + 1) * self.tabsize + 1
+        self.setColumn(nc)
+
+    def panic(self,s='') :
+        print "CharScanner: panic: " + s
+        sys.exit(1)
+
+    def reportError(self,ex) :
+        print ex
+
+    def reportError(self,s) :
+        if not self.getFilename():
+            print "error: " + str(s)
+        else:
+            print self.getFilename() + ": error: " + str(s)
+
+    def reportWarning(self,s) :
+        if not self.getFilename():
+            print "warning: " + str(s)
+        else:
+            print self.getFilename() + ": warning: " + str(s)
+
+    def resetText(self) :
+        self.text.setLength(0)
+        self.inputState.tokenStartColumn = self.inputState.column
+        self.inputState.tokenStartLine = self.inputState.line
+
+    def rewind(self,pos) :
+        self.inputState.input.rewind(pos)
+
+    def setTokenObjectClass(self,cl):
+        self.tokenClass = cl
+
+    def testForLiteral(self,token):
+        if not token:
+            return
+        assert isinstance(token,Token)
+
+        _type = token.getType()
+
+        ## special tokens can't be literals
+        if _type in [SKIP,INVALID_TYPE,EOF_TYPE,NULL_TREE_LOOKAHEAD] :
+            return
+
+        _text = token.getText()
+        if not _text:
+            return
+
+        assert isinstance(_text,str) or isinstance(_text,unicode)
+        _type = self.testLiteralsTable(_text,_type)
+        token.setType(_type)
+        return _type
+
+    def testLiteralsTable(self,*args):
+        if isinstance(args[0],str) or isinstance(args[0],unicode):
+            s = args[0]
+            i = args[1]
+        else:
+            s = self.text.getString()
+            i = args[0]
+
+        ## check whether integer has been given
+        if not isinstance(i,int):
+            assert isinstance(i,int)
+
+        ## check whether we have a dict
+        assert isinstance(self.literals,dict)
+        try:
+            ## E0010
+            if not self.caseSensitiveLiterals:
+                s = s.__class__.lower(s)
+            i = self.literals[s]
+        except:
+            pass
+        return i
+
+    def toLower(self,c):
+        return c.__class__.lower()
+
+    def traceIndent(self):
+        print ' ' * self.traceDepth
+
+    def traceIn(self,rname):
+        self.traceDepth += 1
+        self.traceIndent()
+        print "> lexer %s c== %s" % (rname,self.LA(1))
+
+    def traceOut(self,rname):
+        self.traceIndent()
+        print "< lexer %s c== %s" % (rname,self.LA(1))
+        self.traceDepth -= 1
+
+    def uponEOF(self):
+        pass
+
+    def append(self,c):
+        if self.saveConsumedInput :
+            self.text.append(c)
+
+    def commit(self):
+        self.inputState.input.commit()
+
+    def consume(self):
+        if not self.inputState.guessing:
+            c = self.LA(1)
+            if self.caseSensitive:
+                self.append(c)
+            else:
+                # use input.LA(), not LA(), to get original case
+                # CharScanner.LA() would toLower it.
+                c =  self.inputState.input.LA(1)
+                self.append(c)
+
+            if c and c in "\t":
+                self.tab()
+            else:
+                self.inputState.column += 1
+        self.inputState.input.consume()
+
+    ## Consume chars until one matches the given char
+    def consumeUntil_char(self,c):
+        while self.LA(1) != EOF_CHAR and self.LA(1) != c:
+            self.consume()
+
+    ## Consume chars until one matches the given set
+    def consumeUntil_bitset(self,bitset):
+        while self.LA(1) != EOF_CHAR and not self.set.member(self.LA(1)):
+            self.consume()
+
+    ### If symbol seen is EOF then generate and set token, otherwise
+    ### throw exception.
+    def default(self,la1):
+        if not la1 :
+            self.uponEOF()
+            self._returnToken = self.makeToken(EOF_TYPE)
+        else:
+            self.raise_NoViableAlt(la1)
+
+    def filterdefault(self,la1,*args):
+        if not la1:
+            self.uponEOF()
+            self._returnToken = self.makeToken(EOF_TYPE)
+            return
+
+        if not args:
+            self.consume()
+            raise TryAgain()
+        else:
+            ### apply filter object
+            self.commit();
+            try:
+                func=args[0]
+                args=args[1:]
+                apply(func,args)
+            except RecognitionException, e:
+                ## catastrophic failure
+                self.reportError(e);
+                self.consume();
+            raise TryAgain()
+
+    def raise_NoViableAlt(self,la1=None):
+        if not la1: la1 = self.LA(1)
+        fname = self.getFilename()
+        line  = self.getLine()
+        col   = self.getColumn()
+        raise NoViableAltForCharException(la1,fname,line,col)
+
+    def set_return_token(self,_create,_token,_ttype,_offset):
+        if _create and not _token and (not _ttype == SKIP):
+            string = self.text.getString(_offset)
+            _token = self.makeToken(_ttype)
+            _token.setText(string)
+        self._returnToken = _token
+        return _token
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                   CharScannerIterator                          ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class CharScannerIterator:
+
+    def __init__(self,inst):
+        if isinstance(inst,CharScanner):
+            self.inst = inst
+            return
+        raise TypeError("CharScannerIterator requires CharScanner object")
+
+    def next(self):
+        assert self.inst
+        item = self.inst.nextToken()
+        if not item or item.isEOF():
+            raise StopIteration()
+        return item
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       BitSet                                   ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+### I'm assuming here that a long is 64bits. It appears however, that
+### a long is of any size. That means we can use a single long as the
+### bitset (!), ie. Python would do almost all the work (TBD).
+
+class BitSet(object):
+    BITS     = 64
+    NIBBLE   = 4
+    LOG_BITS = 6
+    MOD_MASK = BITS -1
+
+    def __init__(self,data=None):
+        if not data:
+            BitSet.__init__(self,[long(0)])
+            return
+        if isinstance(data,int):
+            BitSet.__init__(self,[long(data)])
+            return
+        if isinstance(data,long):
+            BitSet.__init__(self,[data])
+            return
+        if not isinstance(data,list):
+            raise TypeError("BitSet requires integer, long, or " +
+                            "list argument")
+        for x in data:
+            if not isinstance(x,long):
+                raise TypeError(self,"List argument item is " +
+                                "not a long: %s" % (x))
+        self.data = data
+
+    def __str__(self):
+        bits = len(self.data) * BitSet.BITS
+        s = ""
+        for i in xrange(0,bits):
+            if self.at(i):
+                s += "1"
+            else:
+                s += "o"
+            if not ((i+1) % 10):
+                s += '|%s|' % (i+1)
+        return s
+
+    def __repr__(self):
+        return str(self)
+
+    def member(self,item):
+        if not item:
+            return False
+
+        if isinstance(item,int):
+            return self.at(item)
+
+        if not (isinstance(item,str) or isinstance(item,unicode)):
+            raise TypeError(self,"char or unichar expected: %s" % (item))
+
+        ## char is a (unicode) string with at most lenght 1, ie.
+        ## a char.
+
+        if len(item) != 1:
+            raise TypeError(self,"char expected: %s" % (item))
+
+        ### handle ASCII/UNICODE char
+        num = ord(item)
+
+        ### check whether position num is in bitset
+        return self.at(num)
+
+    def wordNumber(self,bit):
+        return bit >> BitSet.LOG_BITS
+
+    def bitMask(self,bit):
+        pos = bit & BitSet.MOD_MASK  ## bit mod BITS
+        return (1L << pos)
+
+    def set(self,bit,on=True):
+        # grow bitset as required (use with care!)
+        i = self.wordNumber(bit)
+        mask = self.bitMask(bit)
+        if i>=len(self.data):
+            d = i - len(self.data) + 1
+            for x in xrange(0,d):
+                self.data.append(0L)
+            assert len(self.data) == i+1
+        if on:
+            self.data[i] |=  mask
+        else:
+            self.data[i] &= (~mask)
+
+    ### make add an alias for set
+    add = set
+
+    def off(self,bit,off=True):
+        self.set(bit,not off)
+
+    def at(self,bit):
+        i = self.wordNumber(bit)
+        v = self.data[i]
+        m = self.bitMask(bit)
+        return v & m
+
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                      some further funcs                        ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+def illegalarg_ex(func):
+    raise ValueError(
+       "%s is only valid if parser is built for debugging" %
+       (func.func_name))
+
+def runtime_ex(func):
+    raise RuntimeException(
+       "%s is only valid if parser is built for debugging" %
+       (func.func_name))
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       TokenBuffer                              ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class TokenBuffer(object):
+    def __init__(self,stream):
+        self.input = stream
+        self.nMarkers = 0
+        self.markerOffset = 0
+        self.numToConsume = 0
+        self.queue = Queue()
+
+    def reset(self) :
+        self.nMarkers = 0
+        self.markerOffset = 0
+        self.numToConsume = 0
+        self.queue.reset()
+
+    def consume(self) :
+        self.numToConsume += 1
+
+    def fill(self, amount):
+        self.syncConsume()
+        while self.queue.length() < (amount + self.markerOffset):
+            self.queue.append(self.input.nextToken())
+
+    def getInput(self):
+        return self.input
+
+    def LA(self,k) :
+        self.fill(k)
+        return self.queue.elementAt(self.markerOffset + k - 1).type
+
+    def LT(self,k) :
+        self.fill(k)
+        return self.queue.elementAt(self.markerOffset + k - 1)
+
+    def mark(self) :
+        self.syncConsume()
+        self.nMarkers += 1
+        return self.markerOffset
+
+    def rewind(self,mark) :
+        self.syncConsume()
+        self.markerOffset = mark
+        self.nMarkers -= 1
+
+    def syncConsume(self) :
+        while self.numToConsume > 0:
+            if self.nMarkers > 0:
+                # guess mode -- leave leading characters and bump offset.
+                self.markerOffset += 1
+            else:
+                # normal mode -- remove first character
+                self.queue.removeFirst()
+            self.numToConsume -= 1
+
+    def __str__(self):
+        return "(%s,%s,%s,%s,%s)" % (
+           self.input,
+           self.nMarkers,
+           self.markerOffset,
+           self.numToConsume,
+           self.queue)
+
+    def __repr__(self):
+        return str(self)
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       ParserSharedInputState                   ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class ParserSharedInputState(object):
+
+    def __init__(self):
+        self.input = None
+        self.reset()
+
+    def reset(self):
+        self.guessing = 0
+        self.filename = None
+        if self.input:
+            self.input.reset()
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       Parser                                   ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class Parser(object):
+
+    def __init__(self, *args, **kwargs):
+        self.tokenNames = None
+        self.returnAST  = None
+        self.astFactory = None
+        self.tokenTypeToASTClassMap = {}
+        self.ignoreInvalidDebugCalls = False
+        self.traceDepth = 0
+        if not args:
+            self.inputState = ParserSharedInputState()
+            return
+        arg0 = args[0]
+        assert isinstance(arg0,ParserSharedInputState)
+        self.inputState = arg0
+        return
+
+    def getTokenTypeToASTClassMap(self):
+        return self.tokenTypeToASTClassMap
+
+
+    def addMessageListener(self, l):
+        if not self.ignoreInvalidDebugCalls:
+            illegalarg_ex(addMessageListener)
+
+    def addParserListener(self,l) :
+        if (not self.ignoreInvalidDebugCalls) :
+            illegalarg_ex(addParserListener)
+
+    def addParserMatchListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls) :
+            illegalarg_ex(addParserMatchListener)
+
+    def addParserTokenListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            illegalarg_ex(addParserTokenListener)
+
+    def addSemanticPredicateListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            illegalarg_ex(addSemanticPredicateListener)
+
+    def addSyntacticPredicateListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            illegalarg_ex(addSyntacticPredicateListener)
+
+    def addTraceListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            illegalarg_ex(addTraceListener)
+
+    def consume(self):
+        raise NotImplementedError()
+
+    def _consumeUntil_type(self,tokenType):
+        while self.LA(1) != EOF_TYPE and self.LA(1) != tokenType:
+            self.consume()
+
+    def _consumeUntil_bitset(self, set):
+        while self.LA(1) != EOF_TYPE and not set.member(self.LA(1)):
+            self.consume()
+
+    def consumeUntil(self,arg):
+        if isinstance(arg,int):
+            self._consumeUntil_type(arg)
+        else:
+            self._consumeUntil_bitset(arg)
+
+    def defaultDebuggingSetup(self):
+        pass
+
+    def getAST(self) :
+        return self.returnAST
+
+    def getASTFactory(self) :
+        return self.astFactory
+
+    def getFilename(self) :
+        return self.inputState.filename
+
+    def getInputState(self) :
+        return self.inputState
+
+    def setInputState(self, state) :
+        self.inputState = state
+
+    def getTokenName(self,num) :
+        return self.tokenNames[num]
+
+    def getTokenNames(self) :
+        return self.tokenNames
+
+    def isDebugMode(self) :
+        return self.false
+
+    def LA(self, i):
+        raise NotImplementedError()
+
+    def LT(self, i):
+        raise NotImplementedError()
+
+    def mark(self):
+        return self.inputState.input.mark()
+
+    def _match_int(self,t):
+        if (self.LA(1) != t):
+            raise MismatchedTokenException(
+               self.tokenNames, self.LT(1), t, False, self.getFilename())
+        else:
+            self.consume()
+
+    def _match_set(self, b):
+        if (not b.member(self.LA(1))):
+            raise MismatchedTokenException(
+               self.tokenNames,self.LT(1), b, False, self.getFilename())
+        else:
+            self.consume()
+
+    def match(self,set) :
+        if isinstance(set,int):
+            self._match_int(set)
+            return
+        if isinstance(set,BitSet):
+            self._match_set(set)
+            return
+        raise TypeError("Parser.match requires integer ot BitSet argument")
+
+    def matchNot(self,t):
+        if self.LA(1) == t:
+            raise MismatchedTokenException(
+               tokenNames, self.LT(1), t, True, self.getFilename())
+        else:
+            self.consume()
+
+    def removeMessageListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            runtime_ex(removeMessageListener)
+
+    def removeParserListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            runtime_ex(removeParserListener)
+
+    def removeParserMatchListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            runtime_ex(removeParserMatchListener)
+
+    def removeParserTokenListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            runtime_ex(removeParserTokenListener)
+
+    def removeSemanticPredicateListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            runtime_ex(removeSemanticPredicateListener)
+
+    def removeSyntacticPredicateListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            runtime_ex(removeSyntacticPredicateListener)
+
+    def removeTraceListener(self, l) :
+        if (not self.ignoreInvalidDebugCalls):
+            runtime_ex(removeTraceListener)
+
+    def reportError(self,x) :
+        fmt = "syntax error:"
+        f = self.getFilename()
+        if f:
+            fmt = ("%s:" % f) + fmt
+        if isinstance(x,Token):
+            line = x.getColumn()
+            col  = x.getLine()
+            text = x.getText()
+            fmt  = fmt + 'unexpected symbol at line %s (column %s) : "%s"'
+            print >>sys.stderr, fmt % (line,col,text)
+        else:
+            print >>sys.stderr, fmt,str(x)
+
+    def reportWarning(self,s):
+        f = self.getFilename()
+        if f:
+            print "%s:warning: %s" % (f,str(x))
+        else:
+            print "warning: %s" % (str(x))
+
+    def rewind(self, pos) :
+        self.inputState.input.rewind(pos)
+
+    def setASTFactory(self, f) :
+        self.astFactory = f
+
+    def setASTNodeClass(self, cl) :
+        self.astFactory.setASTNodeType(cl)
+
+    def setASTNodeType(self, nodeType) :
+        self.setASTNodeClass(nodeType)
+
+    def setDebugMode(self, debugMode) :
+        if (not self.ignoreInvalidDebugCalls):
+            runtime_ex(setDebugMode)
+
+    def setFilename(self, f) :
+        self.inputState.filename = f
+
+    def setIgnoreInvalidDebugCalls(self, value) :
+        self.ignoreInvalidDebugCalls = value
+
+    def setTokenBuffer(self, t) :
+        self.inputState.input = t
+
+    def traceIndent(self):
+        print " " * self.traceDepth
+
+    def traceIn(self,rname):
+        self.traceDepth += 1
+        self.trace("> ", rname)
+
+    def traceOut(self,rname):
+        self.trace("< ", rname)
+        self.traceDepth -= 1
+
+    ### wh: moved from ASTFactory to Parser
+    def addASTChild(self,currentAST, child):
+        if not child:
+            return
+        if not currentAST.root:
+            currentAST.root = child
+        elif not currentAST.child:
+            currentAST.root.setFirstChild(child)
+        else:
+            currentAST.child.setNextSibling(child)
+        currentAST.child = child
+        currentAST.advanceChildToEnd()
+
+    ### wh: moved from ASTFactory to Parser
+    def makeASTRoot(self,currentAST,root) :
+        if root:
+            ### Add the current root as a child of new root
+            root.addChild(currentAST.root)
+            ### The new current child is the last sibling of the old root
+            currentAST.child = currentAST.root
+            currentAST.advanceChildToEnd()
+            ### Set the new root
+            currentAST.root = root
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       LLkParser                                ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class LLkParser(Parser):
+
+    def __init__(self, *args, **kwargs):
+        try:
+            arg1 = args[0]
+        except:
+            arg1 = 1
+
+        if isinstance(arg1,int):
+            super(LLkParser,self).__init__()
+            self.k = arg1
+            return
+
+        if isinstance(arg1,ParserSharedInputState):
+            super(LLkParser,self).__init__(arg1)
+            self.set_k(1,*args)
+            return
+
+        if isinstance(arg1,TokenBuffer):
+            super(LLkParser,self).__init__()
+            self.setTokenBuffer(arg1)
+            self.set_k(1,*args)
+            return
+
+        if isinstance(arg1,TokenStream):
+            super(LLkParser,self).__init__()
+            tokenBuf = TokenBuffer(arg1)
+            self.setTokenBuffer(tokenBuf)
+            self.set_k(1,*args)
+            return
+
+        ### unknown argument
+        raise TypeError("LLkParser requires integer, " +
+                        "ParserSharedInputStream or TokenStream argument")
+
+    def consume(self):
+        self.inputState.input.consume()
+
+    def LA(self,i):
+        return self.inputState.input.LA(i)
+
+    def LT(self,i):
+        return self.inputState.input.LT(i)
+
+    def set_k(self,index,*args):
+        try:
+            self.k = args[index]
+        except:
+            self.k = 1
+
+    def trace(self,ee,rname):
+        print type(self)
+        self.traceIndent()
+        guess = ""
+        if self.inputState.guessing > 0:
+            guess = " [guessing]"
+        print(ee + rname + guess)
+        for i in xrange(1,self.k+1):
+            if i != 1:
+                print(", ")
+            if self.LT(i) :
+                v = self.LT(i).getText()
+            else:
+                v = "null"
+            print "LA(%s) == %s" % (i,v)
+        print("\n")
+
+    def traceIn(self,rname):
+        self.traceDepth += 1;
+        self.trace("> ", rname);
+
+    def traceOut(self,rname):
+        self.trace("< ", rname);
+        self.traceDepth -= 1;
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                    TreeParserSharedInputState                  ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class TreeParserSharedInputState(object):
+    def __init__(self):
+        self.guessing = 0
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       TreeParser                               ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class TreeParser(object):
+
+    def __init__(self, *args, **kwargs):
+        self.inputState = TreeParserSharedInputState()
+        self._retTree   = None
+        self.tokenNames = []
+        self.returnAST  = None
+        self.astFactory = ASTFactory()
+        self.traceDepth = 0
+
+    def getAST(self):
+        return self.returnAST
+
+    def getASTFactory(self):
+        return self.astFactory
+
+    def getTokenName(self,num) :
+        return self.tokenNames[num]
+
+    def getTokenNames(self):
+        return self.tokenNames
+
+    def match(self,t,set) :
+        assert isinstance(set,int) or isinstance(set,BitSet)
+        if not t or t == ASTNULL:
+            raise MismatchedTokenException(self.getTokenNames(), t,set, False)
+
+        if isinstance(set,int) and t.getType() != set:
+            raise MismatchedTokenException(self.getTokenNames(), t,set, False)
+
+        if isinstance(set,BitSet) and not set.member(t.getType):
+            raise MismatchedTokenException(self.getTokenNames(), t,set, False)
+
+    def matchNot(self,t, ttype) :
+        if not t or (t == ASTNULL) or (t.getType() == ttype):
+            raise MismatchedTokenException(getTokenNames(), t, ttype, True)
+
+    def reportError(self,ex):
+        print >>sys.stderr,"error:",ex
+
+    def  reportWarning(self, s):
+        print "warning:",s
+
+    def setASTFactory(self,f):
+        self.astFactory = f
+
+    def setASTNodeType(self,nodeType):
+        self.setASTNodeClass(nodeType)
+
+    def setASTNodeClass(self,nodeType):
+        self.astFactory.setASTNodeType(nodeType)
+
+    def traceIndent(self):
+        print " " * self.traceDepth
+
+    def traceIn(self,rname,t):
+        self.traceDepth += 1
+        self.traceIndent()
+        print("> " + rname + "(" +
+              ifelse(t,str(t),"null") + ")" +
+              ifelse(self.inputState.guessing>0,"[guessing]",""))
+
+    def traceOut(self,rname,t):
+        self.traceIndent()
+        print("< " + rname + "(" +
+              ifelse(t,str(t),"null") + ")" +
+              ifelse(self.inputState.guessing>0,"[guessing]",""))
+        self.traceDepth -= 1
+
+    ### wh: moved from ASTFactory to TreeParser
+    def addASTChild(self,currentAST, child):
+        if not child:
+            return
+        if not currentAST.root:
+            currentAST.root = child
+        elif not currentAST.child:
+            currentAST.root.setFirstChild(child)
+        else:
+            currentAST.child.setNextSibling(child)
+        currentAST.child = child
+        currentAST.advanceChildToEnd()
+
+    ### wh: moved from ASTFactory to TreeParser
+    def makeASTRoot(self,currentAST,root):
+        if root:
+            ### Add the current root as a child of new root
+            root.addChild(currentAST.root)
+            ### The new current child is the last sibling of the old root
+            currentAST.child = currentAST.root
+            currentAST.advanceChildToEnd()
+            ### Set the new root
+            currentAST.root = root
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###               funcs to work on trees                           ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+def rightmost(ast):
+    if ast:
+        while(ast.right):
+            ast = ast.right
+    return ast
+
+def cmptree(s,t,partial):
+    while(s and t):
+        ### as a quick optimization, check roots first.
+        if not s.equals(t):
+            return False
+
+        ### if roots match, do full list match test on children.
+        if not cmptree(s.getFirstChild(),t.getFirstChild(),partial):
+            return False
+
+        s = s.getNextSibling()
+        t = t.getNextSibling()
+
+    r = ifelse(partial,not t,not s and not t)
+    return r
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                          AST                                   ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class AST(object):
+    def __init__(self):
+        pass
+
+    def addChild(self, c):
+        pass
+
+    def equals(self, t):
+        return False
+
+    def equalsList(self, t):
+        return False
+
+    def equalsListPartial(self, t):
+        return False
+
+    def equalsTree(self, t):
+        return False
+
+    def equalsTreePartial(self, t):
+        return False
+
+    def findAll(self, tree):
+        return None
+
+    def findAllPartial(self, subtree):
+        return None
+
+    def getFirstChild(self):
+        return self
+
+    def getNextSibling(self):
+        return self
+
+    def getText(self):
+        return ""
+
+    def getType(self):
+        return INVALID_TYPE
+
+    def getLine(self):
+        return 0
+
+    def getColumn(self):
+        return 0
+
+    def getNumberOfChildren(self):
+        return 0
+
+    def initialize(self, t, txt):
+        pass
+
+    def initialize(self, t):
+        pass
+
+    def setFirstChild(self, c):
+        pass
+
+    def setNextSibling(self, n):
+        pass
+
+    def setText(self, text):
+        pass
+
+    def setType(self, ttype):
+        pass
+
+    def toString(self):
+        self.getText()
+
+    __str__ = toString
+
+    def toStringList(self):
+        return self.getText()
+
+    def toStringTree(self):
+        return self.getText()
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       ASTNULLType                              ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+### There is only one instance of this class **/
+class ASTNULLType(AST):
+    def __init__(self):
+        AST.__init__(self)
+        pass
+
+    def getText(self):
+        return "<ASTNULL>"
+
+    def getType(self):
+        return NULL_TREE_LOOKAHEAD
+
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       BaseAST                                  ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class BaseAST(AST):
+
+    verboseStringConversion = False
+    tokenNames = None
+
+    def __init__(self):
+        self.down  = None ## kid
+        self.right = None ## sibling
+
+    def addChild(self,node):
+        if node:
+            t = rightmost(self.down)
+            if t:
+                t.right = node
+            else:
+                assert not self.down
+                self.down = node
+
+    def getNumberOfChildren(self):
+        t = self.down
+        n = 0
+        while t:
+            n += 1
+            t = t.right
+        return n
+
+    def doWorkForFindAll(self,v,target,partialMatch):
+        sibling = self
+
+        while sibling:
+            c1 = partialMatch and sibling.equalsTreePartial(target)
+            if c1:
+                v.append(sibling)
+            else:
+                c2 = not partialMatch and sibling.equalsTree(target)
+                if c2:
+                    v.append(sibling)
+
+            ### regardless of match or not, check any children for matches
+            if sibling.getFirstChild():
+                sibling.getFirstChild().doWorkForFindAll(v,target,partialMatch)
+
+            sibling = sibling.getNextSibling()
+
+    ### Is node t equal to 'self' in terms of token type and text?
+    def equals(self,t):
+        if not t:
+            return False
+        return self.getText() == t.getText() and self.getType() == t.getType()
+
+    ### Is t an exact structural and equals() match of this tree.  The
+    ### 'self' reference is considered the start of a sibling list.
+    ###
+    def equalsList(self, t):
+        return cmptree(self, t, partial=False)
+
+    ### Is 't' a subtree of this list?
+    ### The siblings of the root are NOT ignored.
+    ###
+    def equalsListPartial(self,t):
+        return cmptree(self,t,partial=True)
+
+    ### Is tree rooted at 'self' equal to 't'?  The siblings
+    ### of 'self' are ignored.
+    ###
+    def equalsTree(self, t):
+        return self.equals(t) and \
+               cmptree(self.getFirstChild(), t.getFirstChild(), partial=False)
+
+    ### Is 't' a subtree of the tree rooted at 'self'?  The siblings
+    ### of 'self' are ignored.
+    ###
+    def equalsTreePartial(self, t):
+        if not t:
+            return True
+        return self.equals(t) and cmptree(
+           self.getFirstChild(), t.getFirstChild(), partial=True)
+
+    ### Walk the tree looking for all exact subtree matches.  Return
+    ### an ASTEnumerator that lets the caller walk the list
+    ### of subtree roots found herein.
+    def findAll(self,target):
+        roots = []
+
+        ### the empty tree cannot result in an enumeration
+        if not target:
+            return None
+        # find all matches recursively
+        self.doWorkForFindAll(roots, target, False)
+        return roots
+
+    ### Walk the tree looking for all subtrees.  Return
+    ###  an ASTEnumerator that lets the caller walk the list
+    ###  of subtree roots found herein.
+    def findAllPartial(self,sub):
+        roots = []
+
+        ### the empty tree cannot result in an enumeration
+        if not sub:
+            return None
+
+        self.doWorkForFindAll(roots, sub, True)  ### find all matches recursively
+        return roots
+
+    ### Get the first child of this node None if not children
+    def getFirstChild(self):
+        return self.down
+
+    ### Get the next sibling in line after this one
+    def getNextSibling(self):
+        return self.right
+
+    ### Get the token text for this node
+    def getText(self):
+        return ""
+
+    ### Get the token type for this node
+    def getType(self):
+        return 0
+
+    def getLine(self):
+        return 0
+
+    def getColumn(self):
+        return 0
+
+    ### Remove all children */
+    def removeChildren(self):
+        self.down = None
+
+    def setFirstChild(self,c):
+        self.down = c
+
+    def setNextSibling(self, n):
+        self.right = n
+
+    ### Set the token text for this node
+    def setText(self, text):
+        pass
+
+    ### Set the token type for this node
+    def setType(self, ttype):
+        pass
+
+    ### static
+    def setVerboseStringConversion(verbose,names):
+        verboseStringConversion = verbose
+        tokenNames = names
+    setVerboseStringConversion = staticmethod(setVerboseStringConversion)
+
+    ### Return an array of strings that maps token ID to it's text.
+    ##  @since 2.7.3
+    def getTokenNames():
+        return tokenNames
+
+    def toString(self):
+        return self.getText()
+
+    ### return tree as lisp string - sibling included
+    def toStringList(self):
+        ts = self.toStringTree()
+        sib = self.getNextSibling()
+        if sib:
+            ts += sib.toStringList()
+        return ts
+
+    __str__ = toStringList
+
+    ### return tree as string - siblings ignored
+    def toStringTree(self):
+        ts = ""
+        kid = self.getFirstChild()
+        if kid:
+            ts += " ("
+        ts += " " + self.toString()
+        if kid:
+            ts += kid.toStringList()
+            ts += " )"
+        return ts
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       CommonAST                                ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+### Common AST node implementation
+class CommonAST(BaseAST):
+    def __init__(self,token=None):
+        super(CommonAST,self).__init__()
+        self.ttype = INVALID_TYPE
+        self.text  = "<no text>"
+        self.initialize(token)
+        #assert self.text
+
+    ### Get the token text for this node
+    def getText(self):
+        return self.text
+
+    ### Get the token type for this node
+    def getType(self):
+        return self.ttype
+
+    def initialize(self,*args):
+        if not args:
+            return
+
+        arg0 = args[0]
+
+        if isinstance(arg0,int):
+            arg1 = args[1]
+            self.setType(arg0)
+            self.setText(arg1)
+            return
+
+        if isinstance(arg0,AST) or isinstance(arg0,Token):
+            self.setText(arg0.getText())
+            self.setType(arg0.getType())
+            return
+
+    ### Set the token text for this node
+    def setText(self,text_):
+        assert isinstance(text_,str)
+        self.text = text_
+
+    ### Set the token type for this node
+    def setType(self,ttype_):
+        assert isinstance(ttype_,int)
+        self.ttype = ttype_
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                     CommonASTWithHiddenTokens                  ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class CommonASTWithHiddenTokens(CommonAST):
+
+    def __init__(self,*args):
+        CommonAST.__init__(self,*args)
+        self.hiddenBefore = None
+        self.hiddenAfter  = None
+
+    def getHiddenAfter(self):
+        return self.hiddenAfter
+
+    def getHiddenBefore(self):
+        return self.hiddenBefore
+
+    def initialize(self,*args):
+        CommonAST.initialize(self,*args)
+        if args and isinstance(args[0],Token):
+            assert isinstance(args[0],CommonHiddenStreamToken)
+            self.hideenBefore = args[0].getHiddenBefore()
+            self.hiddenAfter  = args[0].getHiddenAfter()
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       ASTPair                                  ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class ASTPair(object):
+    def __init__(self):
+        self.root = None          ### current root of tree
+        self.child = None         ### current child to which siblings are added
+
+    ### Make sure that child is the last sibling */
+    def advanceChildToEnd(self):
+        if self.child:
+            while self.child.getNextSibling():
+                self.child = self.child.getNextSibling()
+
+    ### Copy an ASTPair.  Don't call it clone() because we want type-safety */
+    def copy(self):
+        tmp = ASTPair()
+        tmp.root = self.root
+        tmp.child = self.child
+        return tmp
+
+    def toString(self):
+        r = ifelse(not root,"null",self.root.getText())
+        c = ifelse(not child,"null",self.child.getText())
+        return "[%s,%s]" % (r,c)
+
+    __str__ = toString
+    __repr__ = toString
+
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       ASTFactory                               ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class ASTFactory(object):
+    def __init__(self,table=None):
+        self._class = None
+        self._classmap = ifelse(table,table,None)
+
+    def create(self,*args):
+        if not args:
+            return self.create(INVALID_TYPE)
+
+        arg0 = args[0]
+        arg1 = None
+        arg2 = None
+
+        try:
+            arg1 = args[1]
+            arg2 = args[2]
+        except:
+            pass
+
+        # ctor(int)
+        if isinstance(arg0,int) and not arg2:
+            ### get class for 'self' type
+            c = self.getASTNodeType(arg0)
+            t = self.create(c)
+            if t:
+                t.initialize(arg0, ifelse(arg1,arg1,""))
+            return t
+
+        # ctor(int,something)
+        if isinstance(arg0,int) and arg2:
+            t = self.create(arg2)
+            if t:
+                t.initialize(arg0,arg1)
+            return t
+
+        # ctor(AST)
+        if isinstance(arg0,AST):
+            t = self.create(arg0.getType())
+            if t:
+                t.initialize(arg0)
+            return t
+
+        # ctor(token)
+        if isinstance(arg0,Token) and not arg1:
+            ttype = arg0.getType()
+            assert isinstance(ttype,int)
+            t = self.create(ttype)
+            if t:
+                t.initialize(arg0)
+            return t
+
+        # ctor(token,class)
+        if isinstance(arg0,Token) and arg1:
+            assert isinstance(arg1,type)
+            assert issubclass(arg1,AST)
+            # this creates instance of 'arg1' using 'arg0' as
+            # argument. Wow, that's magic!
+            t = arg1(arg0)
+            assert t and isinstance(t,AST)
+            return t
+
+        # ctor(class)
+        if isinstance(arg0,type):
+            ### next statement creates instance of type (!)
+            t = arg0()
+            assert isinstance(t,AST)
+            return t
+
+
+    def setASTNodeClass(self,className=None):
+        if not className:
+            return
+        assert isinstance(className,type)
+        assert issubclass(className,AST)
+        self._class = className
+
+    ### kind of misnomer - use setASTNodeClass instead.
+    setASTNodeType = setASTNodeClass
+
+    def getASTNodeClass(self):
+        return self._class
+
+
+
+    def getTokenTypeToASTClassMap(self):
+        return self._classmap
+
+    def setTokenTypeToASTClassMap(self,amap):
+        self._classmap = amap
+
+    def error(self, e):
+        import sys
+        print >> sys.stderr, e
+
+    def setTokenTypeASTNodeType(self, tokenType, className):
+        """
+        Specify a mapping between a token type and a (AST) class.
+        """
+        if not self._classmap:
+            self._classmap = {}
+
+        if not className:
+            try:
+                del self._classmap[tokenType]
+            except:
+                pass
+        else:
+            ### here we should also perform actions to ensure that
+            ### a. class can be loaded
+            ### b. class is a subclass of AST
+            ###
+            assert isinstance(className,type)
+            assert issubclass(className,AST)  ## a & b
+            ### enter the class
+            self._classmap[tokenType] = className
+
+    def getASTNodeType(self,tokenType):
+        """
+        For a given token type return the AST node type. First we
+        lookup a mapping table, second we try _class
+        and finally we resolve to "antlr.CommonAST".
+        """
+
+        # first
+        if self._classmap:
+            try:
+                c = self._classmap[tokenType]
+                if c:
+                    return c
+            except:
+                pass
+        # second
+        if self._class:
+            return self._class
+
+        # default
+        return CommonAST
+
+    ### methods that have been moved to file scope - just listed
+    ### here to be somewhat consistent with original API
+    def dup(self,t):
+        return antlr.dup(t,self)
+
+    def dupList(self,t):
+        return antlr.dupList(t,self)
+
+    def dupTree(self,t):
+        return antlr.dupTree(t,self)
+
+    ### methods moved to other classes
+    ### 1. makeASTRoot  -> Parser
+    ### 2. addASTChild  -> Parser
+
+    ### non-standard: create alias for longish method name
+    maptype = setTokenTypeASTNodeType
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###                       ASTVisitor                               ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+class ASTVisitor(object):
+    def __init__(self,*args):
+        pass
+
+    def visit(self,ast):
+        pass
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+###               static methods and variables                     ###
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx###
+
+ASTNULL = ASTNULLType()
+
+### wh: moved from ASTFactory as there's nothing ASTFactory-specific
+### in this method.
+def make(*nodes):
+    if not nodes:
+        return None
+
+    for i in xrange(0,len(nodes)):
+        node = nodes[i]
+        if node:
+            assert isinstance(node,AST)
+
+    root = nodes[0]
+    tail = None
+    if root:
+        root.setFirstChild(None)
+
+    for i in xrange(1,len(nodes)):
+        if not nodes[i]:
+            continue
+        if not root:
+            root = tail = nodes[i]
+        elif not tail:
+            root.setFirstChild(nodes[i])
+            tail = root.getFirstChild()
+        else:
+            tail.setNextSibling(nodes[i])
+            tail = tail.getNextSibling()
+
+        ### Chase tail to last sibling
+        while tail.getNextSibling():
+            tail = tail.getNextSibling()
+    return root
+
+def dup(t,factory):
+    if not t:
+        return None
+
+    if factory:
+        dup_t = factory.create(t.__class__)
+    else:
+        raise TypeError("dup function requires ASTFactory argument")
+    dup_t.initialize(t)
+    return dup_t
+
+def dupList(t,factory):
+    result = dupTree(t,factory)
+    nt = result
+    while t:
+        ## for each sibling of the root
+        t = t.getNextSibling()
+        nt.setNextSibling(dupTree(t,factory))
+        nt = nt.getNextSibling()
+    return result
+
+def dupTree(t,factory):
+    result = dup(t,factory)
+    if t:
+        result.setFirstChild(dupList(t.getFirstChild(),factory))
+    return result
+
+###xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+### $Id: antlr.py,v 1.2 2005/10/26 07:44:24 rvk Exp $
+
+# Local Variables:    ***
+# mode: python        ***
+# py-indent-offset: 4 ***
+# End:                ***

Modified: packages/pyexcelerator/trunk/pyExcelerator/excel-formula.g
===================================================================
--- packages/pyexcelerator/trunk/pyExcelerator/excel-formula.g	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/pyExcelerator/excel-formula.g	2013-06-27 21:58:43 UTC (rev 25005)
@@ -72,7 +72,7 @@
             (
                   EQ { op = struct.pack('B', ptgEQ) }
                 | NE { op = struct.pack('B', ptgNE) }
-                | GT { op = struct.pack('B', ptgGE) }
+                | GT { op = struct.pack('B', ptgGT) }
                 | LT { op = struct.pack('B', ptgLT) }
                 | GE { op = struct.pack('B', ptgGE) }
                 | LE { op = struct.pack('B', ptgLE) }

Modified: packages/pyexcelerator/trunk/setup.py
===================================================================
--- packages/pyexcelerator/trunk/setup.py	2013-06-27 21:54:40 UTC (rev 25004)
+++ packages/pyexcelerator/trunk/setup.py	2013-06-27 21:58:43 UTC (rev 25005)
@@ -75,7 +75,7 @@
 'xls openoffice excel spreadsheet workbook database table unicode'
 
 setup(name = 'pyExcelerator',
-      version = '0.6.3a',
+      version = '0.6.4.1',
       author = 'Roman V. Kiseliov',
       author_email = 'roman at kiseliov.ru',
       url = 'http://sourceforge.net/projects/pyexcelerator/',




More information about the Python-modules-commits mailing list