forked from ScoDoc/ScoDoc
458 lines
13 KiB
Python
Executable File
458 lines
13 KiB
Python
Executable File
### $ANTLR 2.7.5 (20050128): "excel-formula.g" -> "ExcelFormulaParser.py"$
|
|
### import antlr and other modules ..
|
|
import sys
|
|
import antlr
|
|
|
|
version = sys.version.split()[0]
|
|
if version < '2.2.1':
|
|
False = 0
|
|
if version < '2.3':
|
|
True = not False
|
|
### header action >>>
|
|
__rev_id__ = """$Id: ExcelFormulaParser.py,v 1.4 2005/08/14 06:40:23 rvk Exp $"""
|
|
|
|
import struct
|
|
import Utils
|
|
from UnicodeUtils import upack1
|
|
from ExcelMagic import *
|
|
### header action <<<
|
|
### preamble action>>>
|
|
|
|
### preamble action <<<
|
|
|
|
### import antlr.Token
|
|
from antlr import Token
|
|
### >>>The Known Token Types <<<
|
|
SKIP = antlr.SKIP
|
|
INVALID_TYPE = antlr.INVALID_TYPE
|
|
EOF_TYPE = antlr.EOF_TYPE
|
|
EOF = antlr.EOF
|
|
NULL_TREE_LOOKAHEAD = antlr.NULL_TREE_LOOKAHEAD
|
|
MIN_USER_TYPE = antlr.MIN_USER_TYPE
|
|
TRUE_CONST = 4
|
|
FALSE_CONST = 5
|
|
STR_CONST = 6
|
|
NUM_CONST = 7
|
|
INT_CONST = 8
|
|
NAME = 9
|
|
EQ = 10
|
|
NE = 11
|
|
GT = 12
|
|
LT = 13
|
|
GE = 14
|
|
LE = 15
|
|
ADD = 16
|
|
SUB = 17
|
|
MUL = 18
|
|
DIV = 19
|
|
POWER = 20
|
|
PERCENT = 21
|
|
LP = 22
|
|
RP = 23
|
|
LB = 24
|
|
RB = 25
|
|
COLON = 26
|
|
COMMA = 27
|
|
SEMICOLON = 28
|
|
CONCAT = 29
|
|
REF2D = 30
|
|
|
|
class Parser(antlr.LLkParser):
|
|
### user action >>>
|
|
### user action <<<
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
antlr.LLkParser.__init__(self, *args, **kwargs)
|
|
self.tokenNames = _tokenNames
|
|
### __init__ header action >>>
|
|
self.rpn = ""
|
|
### __init__ header action <<<
|
|
|
|
def formula(self):
|
|
|
|
pass
|
|
self.expr("V")
|
|
|
|
def expr(self,
|
|
arg_type
|
|
):
|
|
|
|
pass
|
|
self.prec0_expr(arg_type)
|
|
while True:
|
|
if ((self.LA(1) >= EQ and self.LA(1) <= LE)):
|
|
pass
|
|
la1 = self.LA(1)
|
|
if False:
|
|
pass
|
|
elif la1 and la1 in [EQ]:
|
|
pass
|
|
self.match(EQ)
|
|
op = struct.pack('B', ptgEQ)
|
|
elif la1 and la1 in [NE]:
|
|
pass
|
|
self.match(NE)
|
|
op = struct.pack('B', ptgNE)
|
|
elif la1 and la1 in [GT]:
|
|
pass
|
|
self.match(GT)
|
|
op = struct.pack('B', ptgGE)
|
|
elif la1 and la1 in [LT]:
|
|
pass
|
|
self.match(LT)
|
|
op = struct.pack('B', ptgLT)
|
|
elif la1 and la1 in [GE]:
|
|
pass
|
|
self.match(GE)
|
|
op = struct.pack('B', ptgGE)
|
|
elif la1 and la1 in [LE]:
|
|
pass
|
|
self.match(LE)
|
|
op = struct.pack('B', ptgLE)
|
|
else:
|
|
raise antlr.NoViableAltException(self.LT(1), self.getFilename())
|
|
|
|
self.prec0_expr(arg_type)
|
|
self.rpn += op
|
|
else:
|
|
break
|
|
|
|
|
|
def prec0_expr(self,
|
|
arg_type
|
|
):
|
|
|
|
pass
|
|
self.prec1_expr(arg_type)
|
|
while True:
|
|
if (self.LA(1)==CONCAT):
|
|
pass
|
|
pass
|
|
self.match(CONCAT)
|
|
op = struct.pack('B', ptgConcat)
|
|
self.prec1_expr(arg_type)
|
|
self.rpn += op
|
|
else:
|
|
break
|
|
|
|
|
|
def prec1_expr(self,
|
|
arg_type
|
|
):
|
|
|
|
pass
|
|
self.prec2_expr(arg_type)
|
|
while True:
|
|
if (self.LA(1)==ADD or self.LA(1)==SUB):
|
|
pass
|
|
la1 = self.LA(1)
|
|
if False:
|
|
pass
|
|
elif la1 and la1 in [ADD]:
|
|
pass
|
|
self.match(ADD)
|
|
op = struct.pack('B', ptgAdd)
|
|
elif la1 and la1 in [SUB]:
|
|
pass
|
|
self.match(SUB)
|
|
op = struct.pack('B', ptgSub)
|
|
else:
|
|
raise antlr.NoViableAltException(self.LT(1), self.getFilename())
|
|
|
|
self.prec2_expr(arg_type)
|
|
self.rpn += op
|
|
else:
|
|
break
|
|
|
|
|
|
def prec2_expr(self,
|
|
arg_type
|
|
):
|
|
|
|
pass
|
|
self.prec3_expr(arg_type)
|
|
while True:
|
|
if (self.LA(1)==MUL or self.LA(1)==DIV):
|
|
pass
|
|
la1 = self.LA(1)
|
|
if False:
|
|
pass
|
|
elif la1 and la1 in [MUL]:
|
|
pass
|
|
self.match(MUL)
|
|
op = struct.pack('B', ptgMul)
|
|
elif la1 and la1 in [DIV]:
|
|
pass
|
|
self.match(DIV)
|
|
op = struct.pack('B', ptgDiv)
|
|
else:
|
|
raise antlr.NoViableAltException(self.LT(1), self.getFilename())
|
|
|
|
self.prec3_expr(arg_type)
|
|
self.rpn += op
|
|
else:
|
|
break
|
|
|
|
|
|
def prec3_expr(self,
|
|
arg_type
|
|
):
|
|
|
|
pass
|
|
self.prec4_expr(arg_type)
|
|
while True:
|
|
if (self.LA(1)==POWER):
|
|
pass
|
|
pass
|
|
self.match(POWER)
|
|
op = struct.pack('B', ptgPower)
|
|
self.prec4_expr(arg_type)
|
|
self.rpn += op
|
|
else:
|
|
break
|
|
|
|
|
|
def prec4_expr(self,
|
|
arg_type
|
|
):
|
|
|
|
pass
|
|
self.prec5_expr(arg_type)
|
|
la1 = self.LA(1)
|
|
if False:
|
|
pass
|
|
elif la1 and la1 in [PERCENT]:
|
|
pass
|
|
self.match(PERCENT)
|
|
self.rpn += struct.pack('B', ptgPercent)
|
|
elif la1 and la1 in [EOF,EQ,NE,GT,LT,GE,LE,ADD,SUB,MUL,DIV,POWER,RP,SEMICOLON,CONCAT]:
|
|
pass
|
|
else:
|
|
raise antlr.NoViableAltException(self.LT(1), self.getFilename())
|
|
|
|
|
|
def prec5_expr(self,
|
|
arg_type
|
|
):
|
|
|
|
la1 = self.LA(1)
|
|
if False:
|
|
pass
|
|
elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,NAME,LP,REF2D]:
|
|
pass
|
|
self.primary(arg_type)
|
|
elif la1 and la1 in [SUB]:
|
|
pass
|
|
self.match(SUB)
|
|
self.primary(arg_type)
|
|
self.rpn += struct.pack('B', ptgUminus)
|
|
else:
|
|
raise antlr.NoViableAltException(self.LT(1), self.getFilename())
|
|
|
|
|
|
def primary(self,
|
|
arg_type
|
|
):
|
|
|
|
str_tok = None
|
|
int_tok = None
|
|
num_tok = None
|
|
ref2d_tok = None
|
|
ref2d1_tok = None
|
|
ref2d2_tok = None
|
|
name_tok = None
|
|
func_tok = None
|
|
la1 = self.LA(1)
|
|
if False:
|
|
pass
|
|
elif la1 and la1 in [TRUE_CONST]:
|
|
pass
|
|
self.match(TRUE_CONST)
|
|
self.rpn += struct.pack("2B", ptgBool, 1)
|
|
elif la1 and la1 in [FALSE_CONST]:
|
|
pass
|
|
self.match(FALSE_CONST)
|
|
self.rpn += struct.pack("2B", ptgBool, 0)
|
|
elif la1 and la1 in [STR_CONST]:
|
|
pass
|
|
str_tok = self.LT(1)
|
|
self.match(STR_CONST)
|
|
self.rpn += struct.pack("B", ptgStr) + upack1(str_tok.text[1:-1])
|
|
elif la1 and la1 in [INT_CONST]:
|
|
pass
|
|
int_tok = self.LT(1)
|
|
self.match(INT_CONST)
|
|
self.rpn += struct.pack("<BH", ptgInt, int(int_tok.text))
|
|
elif la1 and la1 in [NUM_CONST]:
|
|
pass
|
|
num_tok = self.LT(1)
|
|
self.match(NUM_CONST)
|
|
self.rpn += struct.pack("<Bd", ptgNum, float(num_tok.text))
|
|
elif la1 and la1 in [LP]:
|
|
pass
|
|
self.match(LP)
|
|
self.expr(arg_type)
|
|
self.match(RP)
|
|
self.rpn += struct.pack("B", ptgParen)
|
|
else:
|
|
if (self.LA(1)==REF2D) and (_tokenSet_0.member(self.LA(2))):
|
|
pass
|
|
ref2d_tok = self.LT(1)
|
|
self.match(REF2D)
|
|
r, c = Utils.cell_to_packed_rowcol(ref2d_tok.text)
|
|
if arg_type == "R":
|
|
self.rpn += struct.pack("<B2H", ptgRefR, r, c)
|
|
else:
|
|
self.rpn += struct.pack("<B2H", ptgRefV, r, c)
|
|
elif (self.LA(1)==REF2D) and (self.LA(2)==COLON):
|
|
pass
|
|
ref2d1_tok = self.LT(1)
|
|
self.match(REF2D)
|
|
self.match(COLON)
|
|
ref2d2_tok = self.LT(1)
|
|
self.match(REF2D)
|
|
r1, c1 = Utils.cell_to_packed_rowcol(ref2d1_tok.text)
|
|
r2, c2 = Utils.cell_to_packed_rowcol(ref2d2_tok.text)
|
|
if arg_type == "R":
|
|
self.rpn += struct.pack("<B4H", ptgAreaR, r1, r2, c1, c2)
|
|
else:
|
|
self.rpn += struct.pack("<B4H", ptgAreaV, r1, r2, c1, c2)
|
|
elif (self.LA(1)==NAME) and (_tokenSet_0.member(self.LA(2))):
|
|
pass
|
|
name_tok = self.LT(1)
|
|
self.match(NAME)
|
|
self.rpn += ""
|
|
elif (self.LA(1)==NAME) and (self.LA(2)==LP):
|
|
pass
|
|
func_tok = self.LT(1)
|
|
self.match(NAME)
|
|
if func_tok.text.upper() in std_func_by_name:
|
|
(opcode,
|
|
min_argc,
|
|
max_argc,
|
|
func_type,
|
|
arg_type_list,
|
|
volatile_func) = std_func_by_name[func_tok.text.upper()]
|
|
else:
|
|
raise Exception, "unknown function: %s" % func_tok.text
|
|
self.match(LP)
|
|
arg_count=self.expr_list(arg_type_list, min_argc, max_argc)
|
|
self.match(RP)
|
|
if arg_count > max_argc or arg_count < min_argc:
|
|
raise Exception, "%d parameters for function: %s" % (arg_count, func_tok.text)
|
|
if min_argc == max_argc:
|
|
if func_type == "V":
|
|
func_ptg = ptgFuncV
|
|
elif func_type == "R":
|
|
func_ptg = ptgFuncR
|
|
elif func_type == "A":
|
|
func_ptg = ptgFuncA
|
|
else:
|
|
raise Exception, "wrong function type"
|
|
self.rpn += struct.pack("<BH", func_ptg, opcode)
|
|
else:
|
|
if func_type == "V":
|
|
func_ptg = ptgFuncVarV
|
|
elif func_type == "R":
|
|
func_ptg = ptgFuncVarR
|
|
elif func_type == "A":
|
|
func_ptg = ptgFuncVarA
|
|
else:
|
|
raise Exception, "wrong function type"
|
|
self.rpn += struct.pack("<2BH", func_ptg, arg_count, opcode)
|
|
else:
|
|
raise antlr.NoViableAltException(self.LT(1), self.getFilename())
|
|
|
|
|
|
def expr_list(self,
|
|
arg_type_list, min_argc, max_argc
|
|
):
|
|
arg_cnt = None
|
|
|
|
arg_cnt = 0
|
|
arg_type_list = arg_type_list.split()
|
|
arg_type = arg_type_list[arg_cnt]
|
|
la1 = self.LA(1)
|
|
if False:
|
|
pass
|
|
elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,NAME,SUB,LP,REF2D]:
|
|
pass
|
|
self.expr(arg_type)
|
|
arg_cnt += 1
|
|
while True:
|
|
if (self.LA(1)==SEMICOLON):
|
|
pass
|
|
if arg_cnt < len(arg_type_list):
|
|
arg_type = arg_type_list[arg_cnt]
|
|
else:
|
|
arg_type = arg_type_list[-1]
|
|
if arg_type == "...":
|
|
arg_type = arg_type_list[-2]
|
|
self.match(SEMICOLON)
|
|
la1 = self.LA(1)
|
|
if False:
|
|
pass
|
|
elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,NAME,SUB,LP,REF2D]:
|
|
pass
|
|
self.expr(arg_type)
|
|
elif la1 and la1 in [RP,SEMICOLON]:
|
|
pass
|
|
self.rpn += struct.pack("B", ptgMissArg)
|
|
else:
|
|
raise antlr.NoViableAltException(self.LT(1), self.getFilename())
|
|
|
|
arg_cnt += 1
|
|
else:
|
|
break
|
|
|
|
elif la1 and la1 in [RP]:
|
|
pass
|
|
else:
|
|
raise antlr.NoViableAltException(self.LT(1), self.getFilename())
|
|
|
|
return arg_cnt
|
|
|
|
|
|
_tokenNames = [
|
|
"<0>",
|
|
"EOF",
|
|
"<2>",
|
|
"NULL_TREE_LOOKAHEAD",
|
|
"TRUE_CONST",
|
|
"FALSE_CONST",
|
|
"STR_CONST",
|
|
"NUM_CONST",
|
|
"INT_CONST",
|
|
"NAME",
|
|
"EQ",
|
|
"NE",
|
|
"GT",
|
|
"LT",
|
|
"GE",
|
|
"LE",
|
|
"ADD",
|
|
"SUB",
|
|
"MUL",
|
|
"DIV",
|
|
"POWER",
|
|
"PERCENT",
|
|
"LP",
|
|
"RP",
|
|
"LB",
|
|
"RB",
|
|
"COLON",
|
|
"COMMA",
|
|
"SEMICOLON",
|
|
"CONCAT",
|
|
"REF2D"
|
|
]
|
|
|
|
|
|
### generate bit set
|
|
def mk_tokenSet_0():
|
|
### var1
|
|
data = [ 817888258L, 0L]
|
|
return data
|
|
_tokenSet_0 = antlr.BitSet(mk_tokenSet_0())
|
|
|