[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