mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Make parentheses no longer explicit in the AST (Beta).
The output module adds parentheses where necessary, depending on the evaluation order in the tree. Or that's the idea. Prone to bugs, let's see how it bodes.
This commit is contained in:
parent
59451b90e5
commit
1dea1bd12c
5 changed files with 75 additions and 113 deletions
|
@ -384,12 +384,8 @@ class deadcode(object):
|
||||||
else: # assumed VECTOR or ROTATION per SymbolReplacedOrDeleted
|
else: # assumed VECTOR or ROTATION per SymbolReplacedOrDeleted
|
||||||
SEF = 'SEF' in value
|
SEF = 'SEF' in value
|
||||||
value = self.Cast(value['ch'][fieldidx], 'float')
|
value = self.Cast(value['ch'][fieldidx], 'float')
|
||||||
# Replace it, in parentheses
|
# Replace it
|
||||||
if value['nt'] not in ('CONST','()','FLD','IDENT','FNCALL'):
|
node = curnode['ch'][index] = value
|
||||||
node = curnode['ch'][index] = \
|
|
||||||
{'nt':'()', 'X':True, 't':value['t'], 'ch':[value]}
|
|
||||||
else:
|
|
||||||
node = curnode['ch'][index] = value
|
|
||||||
if SEF:
|
if SEF:
|
||||||
node['SEF'] = True
|
node['SEF'] = True
|
||||||
|
|
||||||
|
@ -400,18 +396,11 @@ class deadcode(object):
|
||||||
new = sym['W']
|
new = sym['W']
|
||||||
new['X'] = True
|
new['X'] = True
|
||||||
|
|
||||||
if new['nt'] not in ('CONST','()','FLD','IDENT','FNCALL'):
|
|
||||||
new = {'nt':'()', 'X':True, 't':sym['W']['t'],
|
|
||||||
'ch':[new]}
|
|
||||||
SEF = 'SEF' in sym['W']
|
SEF = 'SEF' in sym['W']
|
||||||
if SEF:
|
if SEF:
|
||||||
new['SEF'] = True
|
new['SEF'] = True
|
||||||
if new['t'] != node['t']:
|
if new['t'] != node['t']:
|
||||||
new = self.Cast(new, node['t'])
|
new = self.Cast(new, node['t'])
|
||||||
if new['nt'] not in ('CONST','()','FLD','IDENT','FNCALL'):
|
|
||||||
new = {'nt':'()', 'X':True, 't':node['t'], 'ch':[new]}
|
|
||||||
if SEF:
|
|
||||||
new['SEF'] = True
|
|
||||||
curnode['ch'][index] = node = new
|
curnode['ch'][index] = node = new
|
||||||
# Delete orig if present, as we've eliminated the original
|
# Delete orig if present, as we've eliminated the original
|
||||||
#if 'orig' in sym['W']:
|
#if 'orig' in sym['W']:
|
||||||
|
|
|
@ -96,9 +96,6 @@ class foldconst(object):
|
||||||
|
|
||||||
if nt == 'NEG':
|
if nt == 'NEG':
|
||||||
self.FoldTree(child, 0)
|
self.FoldTree(child, 0)
|
||||||
while child[0]['nt'] == '()' and child[0]['ch'][0]['nt'] == 'NEG':
|
|
||||||
# Remove parentheses: - ( - expr ) --> - - expr
|
|
||||||
child[0] = child[0]['ch'][0]
|
|
||||||
if child[0]['nt'] == 'NEG':
|
if child[0]['nt'] == 'NEG':
|
||||||
# Double negation: - - expr --> expr
|
# Double negation: - - expr --> expr
|
||||||
# NOTE: Not 100% sure this doesn't need parentheses around expr.
|
# NOTE: Not 100% sure this doesn't need parentheses around expr.
|
||||||
|
@ -120,12 +117,11 @@ class foldconst(object):
|
||||||
track = track['ch'][0]['ch'][0]
|
track = track['ch'][0]['ch'][0]
|
||||||
if const > 2:
|
if const > 2:
|
||||||
# -~-~-~expr -> expr+3
|
# -~-~-~expr -> expr+3
|
||||||
SEF = 'SEF' in track
|
|
||||||
node = {'nt':'CONST', 't':'integer', 'SEF':True, 'value':const}
|
node = {'nt':'CONST', 't':'integer', 'SEF':True, 'value':const}
|
||||||
node = {'nt':'+', 't':'integer', 'ch':[node, track]}
|
node = {'nt':'+', 't':'integer', 'ch':[node, track]}
|
||||||
parent[index] = node = {'nt':'()', 't':'integer', 'ch':[node]}
|
if 'SEF' in track:
|
||||||
if SEF:
|
node['SEF'] = True
|
||||||
node['SEF'] = node['ch'][0]['SEF'] = True
|
parent[index] = node
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -136,8 +132,6 @@ class foldconst(object):
|
||||||
subexpr = child[0]
|
subexpr = child[0]
|
||||||
if 'SEF' in subexpr:
|
if 'SEF' in subexpr:
|
||||||
node['SEF'] = True
|
node['SEF'] = True
|
||||||
while subexpr['nt'] == '()' and subexpr['ch'][0]['nt'] in ('()', '~', '!', '++V', '--V'):
|
|
||||||
subexpr = child[0] = subexpr['ch'][0] # Remove parentheses
|
|
||||||
if subexpr['nt'] == '!' and subexpr['ch'][0]['nt'] == '!':
|
if subexpr['nt'] == '!' and subexpr['ch'][0]['nt'] == '!':
|
||||||
# Simplify !!! to !
|
# Simplify !!! to !
|
||||||
subexpr = child[0] = subexpr['ch'][0]['ch'][0]
|
subexpr = child[0] = subexpr['ch'][0]['ch'][0]
|
||||||
|
@ -151,9 +145,6 @@ class foldconst(object):
|
||||||
subexpr = child[0]
|
subexpr = child[0]
|
||||||
if 'SEF' in subexpr:
|
if 'SEF' in subexpr:
|
||||||
node['SEF'] = True
|
node['SEF'] = True
|
||||||
while subexpr['nt'] == '()' and subexpr['ch'][0]['nt'] in ('()',
|
|
||||||
'~', '!', '++V', '--V'):
|
|
||||||
subexpr = child[0] = subexpr['ch'][0] # Remove parentheses
|
|
||||||
if subexpr['nt'] == '~':
|
if subexpr['nt'] == '~':
|
||||||
# Double negation: ~~expr
|
# Double negation: ~~expr
|
||||||
parent[index] = subexpr['ch'][0]
|
parent[index] = subexpr['ch'][0]
|
||||||
|
@ -162,22 +153,6 @@ class foldconst(object):
|
||||||
node['value'] = ~node['value']
|
node['value'] = ~node['value']
|
||||||
return
|
return
|
||||||
|
|
||||||
if nt == '()':
|
|
||||||
self.FoldTree(child, 0)
|
|
||||||
if 'SEF' in child[0]:
|
|
||||||
node['SEF'] = True
|
|
||||||
if child[0]['nt'] in ('()', 'CONST', 'VECTOR', 'ROTATION', 'LIST',
|
|
||||||
'IDENT', 'FIELD', 'V++', 'V--', 'FUNCTION', 'PRINT'):
|
|
||||||
# Child is an unary postfix expression (highest priority);
|
|
||||||
# parentheses are redundant and can be removed safely. Not
|
|
||||||
# strictly an optimization but it helps keeping the output
|
|
||||||
# tidy-ish a bit, and helps the optimizer do its work. It's not
|
|
||||||
# done in general (e.g. (a * b) + c does not need parentheses
|
|
||||||
# but these are not eliminated). Only cases like (3) or
|
|
||||||
# (myvar++) are simplified.
|
|
||||||
parent[index] = child[0]
|
|
||||||
return
|
|
||||||
|
|
||||||
if nt in self.binary_ops:
|
if nt in self.binary_ops:
|
||||||
# RTL evaluation
|
# RTL evaluation
|
||||||
self.FoldTree(child, 1)
|
self.FoldTree(child, 1)
|
||||||
|
@ -272,14 +247,6 @@ class foldconst(object):
|
||||||
# Tough one. Remove neutral elements for the diverse types,
|
# Tough one. Remove neutral elements for the diverse types,
|
||||||
# and more.
|
# and more.
|
||||||
|
|
||||||
# Remove redundant parentheses
|
|
||||||
if lnt == '()' and lval['ch'][0]['nt'] in ('+', '-', '*', '/', '%', '~', '!', 'NEG', 'CAST', 'V++', 'V--', '++V', '--V'):
|
|
||||||
# (a op b) + c -> a op b + c
|
|
||||||
# (op b) + c -> op b + c
|
|
||||||
# where op's priority is that of + or greater
|
|
||||||
lval = child[0] = lval['ch'][0]
|
|
||||||
lnt = lval['nt']
|
|
||||||
|
|
||||||
# Addition of integers, strings, and lists is associative
|
# Addition of integers, strings, and lists is associative
|
||||||
# Addition of floats, vectors and rotations would be, except
|
# Addition of floats, vectors and rotations would be, except
|
||||||
# for FP precision.
|
# for FP precision.
|
||||||
|
@ -343,15 +310,6 @@ class foldconst(object):
|
||||||
parent[index] = lval
|
parent[index] = lval
|
||||||
return
|
return
|
||||||
|
|
||||||
# Remove parentheses if they enclose a NEG, to unhide their
|
|
||||||
# operators. Precedence rules allow us.
|
|
||||||
if lnt == '()' and lval['ch'][0]['nt'] == 'NEG':
|
|
||||||
# (-expr) + expr -> -expr + expr
|
|
||||||
lval = child[0] = lval['ch'][0]
|
|
||||||
if rnt == '()' and rval['ch'][0]['nt'] == 'NEG':
|
|
||||||
# expr + (-expr) -> expr + -expr
|
|
||||||
rval = child[1] = rval['ch'][0]
|
|
||||||
|
|
||||||
if lnt != 'CONST' != rnt:
|
if lnt != 'CONST' != rnt:
|
||||||
# Neither is const. Two chances to optimize.
|
# Neither is const. Two chances to optimize.
|
||||||
# 1. -expr + -expr -> -(expr + expr) (saves 1 byte)
|
# 1. -expr + -expr -> -(expr + expr) (saves 1 byte)
|
||||||
|
@ -364,9 +322,6 @@ class foldconst(object):
|
||||||
if lnt == rnt == 'NEG':
|
if lnt == rnt == 'NEG':
|
||||||
node = {'nt':'+', 't':optype, 'ch':[lval['ch'][0], rval['ch'][0]]}
|
node = {'nt':'+', 't':optype, 'ch':[lval['ch'][0], rval['ch'][0]]}
|
||||||
SEF = 'SEF' in lval['ch'][0] and 'SEF' in rval['ch'][0]
|
SEF = 'SEF' in lval['ch'][0] and 'SEF' in rval['ch'][0]
|
||||||
if SEF:
|
|
||||||
node['SEF'] = True
|
|
||||||
node = {'nt':'()', 't':optype, 'ch':[node]}
|
|
||||||
if SEF:
|
if SEF:
|
||||||
node['SEF'] = True
|
node['SEF'] = True
|
||||||
node = {'nt':'NEG', 't':optype, 'ch':[node]}
|
node = {'nt':'NEG', 't':optype, 'ch':[node]}
|
||||||
|
@ -398,9 +353,8 @@ class foldconst(object):
|
||||||
lval = child[0] = lval['ch'][0]
|
lval = child[0] = lval['ch'][0]
|
||||||
lnt = lval['nt']
|
lnt = lval['nt']
|
||||||
|
|
||||||
if rnt == '+' and rval['ch'][0]['nt'] == '()' and rval['ch'][0]['ch'][0]['nt'] == '+' \
|
if rnt == '+' and (rval['ch'][0]['nt'] == 'CONST'
|
||||||
and (rval['ch'][0]['ch'][0]['nt'] == 'CONST'
|
or rval['ch'][1]['nt'] == 'CONST'):
|
||||||
or rval['ch'][0]['ch'][1]['nt'] == 'CONST'):
|
|
||||||
# const + (expr + const) or const + (const + expr)
|
# const + (expr + const) or const + (const + expr)
|
||||||
# same as above, join them
|
# same as above, join them
|
||||||
|
|
||||||
|
@ -416,17 +370,10 @@ class foldconst(object):
|
||||||
# output rather than introducing the parens in the tree.
|
# output rather than introducing the parens in the tree.
|
||||||
if lval['value'] == -1 or lval['value'] == -2:
|
if lval['value'] == -1 or lval['value'] == -2:
|
||||||
if rnt == 'NEG': # Cancel the NEG
|
if rnt == 'NEG': # Cancel the NEG
|
||||||
node = {'nt':'()', 't':optype, 'ch':rval['ch']}
|
node = {'nt':'~', 't':optype, 'ch':rval['ch']}
|
||||||
if RSEF:
|
|
||||||
node['SEF'] = True
|
|
||||||
node = {'nt':'~', 't':optype, 'ch':[node]}
|
|
||||||
if RSEF:
|
if RSEF:
|
||||||
node['SEF'] = True
|
node['SEF'] = True
|
||||||
else: # Add the NEG
|
else: # Add the NEG
|
||||||
#node = {'nt':'()', 't':optype, 'ch':[rval]}
|
|
||||||
#if RSEF:
|
|
||||||
# node['SEF'] = True
|
|
||||||
#node = {'nt':'NEG', 't':optype, 'ch':[node]}
|
|
||||||
node = {'nt':'NEG', 't':optype, 'ch':[rval]}
|
node = {'nt':'NEG', 't':optype, 'ch':[rval]}
|
||||||
if RSEF:
|
if RSEF:
|
||||||
node['SEF'] = True
|
node['SEF'] = True
|
||||||
|
@ -445,18 +392,11 @@ class foldconst(object):
|
||||||
|
|
||||||
if lval['value'] == 1 or lval['value'] == 2:
|
if lval['value'] == 1 or lval['value'] == 2:
|
||||||
if rnt == '~': # Cancel the ~
|
if rnt == '~': # Cancel the ~
|
||||||
#node = {'nt':'()', 't':optype, 'ch':rval['ch']}
|
|
||||||
#if RSEF:
|
|
||||||
# node['SEF'] = True
|
|
||||||
#node = {'nt':'NEG', 't':optype, 'ch':[node]}
|
|
||||||
node = {'nt':'NEG', 't':optype, 'ch':rval['ch']}
|
node = {'nt':'NEG', 't':optype, 'ch':rval['ch']}
|
||||||
if RSEF:
|
if RSEF:
|
||||||
node['SEF'] = True
|
node['SEF'] = True
|
||||||
else:
|
else:
|
||||||
node = {'nt':'()', 't':optype, 'ch':[rval]}
|
node = {'nt':'~', 't':optype, 'ch':[rval]}
|
||||||
if RSEF:
|
|
||||||
node['SEF'] = True
|
|
||||||
node = {'nt':'~', 't':optype, 'ch':[node]}
|
|
||||||
if RSEF:
|
if RSEF:
|
||||||
node['SEF'] = True
|
node['SEF'] = True
|
||||||
node = {'nt':'NEG', 't':optype, 'ch':[node]}
|
node = {'nt':'NEG', 't':optype, 'ch':[node]}
|
||||||
|
@ -486,13 +426,6 @@ class foldconst(object):
|
||||||
# have e.g. {<< {& x y} 3}; there will be explicit
|
# have e.g. {<< {& x y} 3}; there will be explicit
|
||||||
# parentheses here always, so we don't need to worry.
|
# parentheses here always, so we don't need to worry.
|
||||||
|
|
||||||
# Operands with priority between * (not included) and <<
|
|
||||||
# (included).
|
|
||||||
if child[0]['nt'] in ('+', '-', 'NEG', '<<', '>>'):
|
|
||||||
SEF = 'SEF' in child[0]
|
|
||||||
child[0] = {'nt':'()', 't':child[0]['t'], 'ch':[child[0]]}
|
|
||||||
if SEF:
|
|
||||||
child[0]['SEF'] = True
|
|
||||||
# we have {<<, something, {CONST n}}, transform into {*, something, {CONST n}}
|
# we have {<<, something, {CONST n}}, transform into {*, something, {CONST n}}
|
||||||
node['nt'] = '*'
|
node['nt'] = '*'
|
||||||
child[1]['value'] = 1 << (child[1]['value'] & 31)
|
child[1]['value'] = 1 << (child[1]['value'] & 31)
|
||||||
|
@ -515,13 +448,14 @@ class foldconst(object):
|
||||||
|
|
||||||
if nt != '=':
|
if nt != '=':
|
||||||
# Replace the node with the expression alone
|
# Replace the node with the expression alone
|
||||||
child[1] = {'nt':'()', 't':child[1]['t'], 'ch':[child[1]]}
|
# e.g. a += b -> a + b
|
||||||
node['nt'] = nt[:-1]
|
node['nt'] = nt[:-1]
|
||||||
|
|
||||||
# Linden Craziness: i *= f; is valid (but no other i op= f is).
|
# Linden Craziness: int *= float; is valid (but no other
|
||||||
# It's actually performed as i = (integer)(i + (f)). This breaks
|
# int op= float is). It's actually performed as
|
||||||
# regular equivalence of x op= y as x = x op (y) so we add
|
# i = (integer)(i + (f));
|
||||||
# the type cast here.
|
# This breaks equivalence of x op= y as x = x op (y) so we add
|
||||||
|
# the explicit type cast here.
|
||||||
if nt == '*=' and child[0]['t'] == 'integer' and child[1]['t'] == 'float':
|
if nt == '*=' and child[0]['t'] == 'integer' and child[1]['t'] == 'float':
|
||||||
node['t'] = 'float' # Addition shall return float.
|
node['t'] = 'float' # Addition shall return float.
|
||||||
node = self.Cast(node, 'integer')
|
node = self.Cast(node, 'integer')
|
||||||
|
@ -605,8 +539,7 @@ class foldconst(object):
|
||||||
elif node['name'] == 'llGetListLength' and child[0]['nt'] == 'IDENT':
|
elif node['name'] == 'llGetListLength' and child[0]['nt'] == 'IDENT':
|
||||||
# Convert llGetListLength(ident) to (ident != [])
|
# Convert llGetListLength(ident) to (ident != [])
|
||||||
node = {'nt':'CONST', 't':'list', 'value':[]}
|
node = {'nt':'CONST', 't':'list', 'value':[]}
|
||||||
node = {'nt':'!=', 't':'list', 'ch':[child[0], node]}
|
parent[index] = node = {'nt':'!=', 't':'list', 'ch':[child[0], node]}
|
||||||
parent[index] = {'nt':'()', 't':'list', 'ch':[node]}
|
|
||||||
elif SEFargs and 'SEF' in self.symtab[0][node['name']]:
|
elif SEFargs and 'SEF' in self.symtab[0][node['name']]:
|
||||||
# The function is marked as SEF in the symbol table, and the
|
# The function is marked as SEF in the symbol table, and the
|
||||||
# arguments are all side-effect-free. The result is SEF.
|
# arguments are all side-effect-free. The result is SEF.
|
||||||
|
|
|
@ -31,13 +31,6 @@ class optimizer(foldconst, renamer, deadcode):
|
||||||
# value unchanged
|
# value unchanged
|
||||||
if value['t'] == newtype:
|
if value['t'] == newtype:
|
||||||
return value
|
return value
|
||||||
if value not in ('CONST','()','FLD','IDENT','FNCALL','V++','V--',
|
|
||||||
'VECTOR','ROTATION','LIST'):
|
|
||||||
value = {'nt':'()', 't':newtype, 'ch':[value]}
|
|
||||||
if 'SEF' in value['ch'][0]:
|
|
||||||
value['SEF'] = True
|
|
||||||
if 'X' in value['ch'][0]:
|
|
||||||
value['X'] = value['ch'][0]['X']
|
|
||||||
ret = {'nt':'CAST', 't':newtype, 'ch':[value]}
|
ret = {'nt':'CAST', 't':newtype, 'ch':[value]}
|
||||||
if 'SEF' in value:
|
if 'SEF' in value:
|
||||||
ret['SEF'] = True
|
ret['SEF'] = True
|
||||||
|
|
|
@ -10,6 +10,11 @@ class outscript(object):
|
||||||
))
|
))
|
||||||
extended_assignments = frozenset(('&=', '|=', '^=', '<<=', '>>='))
|
extended_assignments = frozenset(('&=', '|=', '^=', '<<=', '>>='))
|
||||||
unary_operands = frozenset(('NEG', '!', '~'))
|
unary_operands = frozenset(('NEG', '!', '~'))
|
||||||
|
op_priority = {'=':0, '+=':0, '-=':0, '*=':0, '/=':0, '%=':0, '&=':0,
|
||||||
|
'|=':0, '^=':0, '<<=':0, '>>=':0,
|
||||||
|
'||':1, '&&':1, '|':2, '^':3, '&':4, '==':5, '!=':5,
|
||||||
|
'<':6, '<=':6, '>':6, '>=':6, '<<':7, '>>':7, '+':8, '-':8,# 'NEG':8,
|
||||||
|
'*':9, '/':9, '%':9}#, '!':10, '~':10, '++':10, '--':10, }
|
||||||
|
|
||||||
def Value2LSL(self, value):
|
def Value2LSL(self, value):
|
||||||
tvalue = type(value)
|
tvalue = type(value)
|
||||||
|
@ -174,11 +179,33 @@ class outscript(object):
|
||||||
if 'ch' in expr:
|
if 'ch' in expr:
|
||||||
child = expr['ch']
|
child = expr['ch']
|
||||||
|
|
||||||
if nt == '()':
|
|
||||||
return '(' + self.OutExpr(child[0]) + ')'
|
|
||||||
|
|
||||||
if nt in self.binary_operands:
|
if nt in self.binary_operands:
|
||||||
return self.OutExpr(child[0]) + ' ' + nt + ' ' + self.OutExpr(child[1])
|
lnt = child[0]['nt']
|
||||||
|
lparen = False
|
||||||
|
rnt = child[1]['nt']
|
||||||
|
rparen = False
|
||||||
|
if nt in self.op_priority:
|
||||||
|
base_pri = self.op_priority[nt]
|
||||||
|
if lnt in self.op_priority:
|
||||||
|
if self.op_priority[lnt] < base_pri:
|
||||||
|
lparen = True
|
||||||
|
elif lnt == 'NEG' and base_pri > self.op_priority['-']:
|
||||||
|
lparen = True
|
||||||
|
|
||||||
|
if rnt in self.op_priority:
|
||||||
|
if self.op_priority[rnt] <= base_pri:
|
||||||
|
rparen = True
|
||||||
|
|
||||||
|
if lparen:
|
||||||
|
ret = '(' + self.OutExpr(child[0]) + ')'
|
||||||
|
else:
|
||||||
|
ret = self.OutExpr(child[0])
|
||||||
|
ret += ' ' + nt + ' '
|
||||||
|
if rparen:
|
||||||
|
ret += '(' + self.OutExpr(child[1]) + ')'
|
||||||
|
else:
|
||||||
|
ret += self.OutExpr(child[1])
|
||||||
|
return ret
|
||||||
|
|
||||||
if nt == 'IDENT':
|
if nt == 'IDENT':
|
||||||
return self.FindName(expr)
|
return self.FindName(expr)
|
||||||
|
@ -190,7 +217,7 @@ class outscript(object):
|
||||||
ret = '(' + expr['t'] + ')'
|
ret = '(' + expr['t'] + ')'
|
||||||
expr = child[0]
|
expr = child[0]
|
||||||
if expr['nt'] in ('CONST', 'IDENT', 'V++', 'V--', 'VECTOR',
|
if expr['nt'] in ('CONST', 'IDENT', 'V++', 'V--', 'VECTOR',
|
||||||
'ROTATION', 'LIST', 'FIELD', 'PRINT', 'FUNCTION', '()'):
|
'ROTATION', 'LIST', 'FIELD', 'PRINT', 'FUNCTION'):
|
||||||
return ret + self.OutExpr(expr)
|
return ret + self.OutExpr(expr)
|
||||||
return ret + '(' + self.OutExpr(expr) + ')'
|
return ret + '(' + self.OutExpr(expr) + ')'
|
||||||
|
|
||||||
|
@ -201,7 +228,17 @@ class outscript(object):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
if nt in ('VECTOR', 'ROTATION'):
|
if nt in ('VECTOR', 'ROTATION'):
|
||||||
return '<' + self.OutExprList(child) + '>'
|
ret = ('<' + self.OutExpr(child[0]) + ','
|
||||||
|
+ self.OutExpr(child[1]) + ',')
|
||||||
|
if nt == 'ROTATION':
|
||||||
|
ret += self.OutExpr(child[2]) + ','
|
||||||
|
lnt = child[-1]['nt']
|
||||||
|
if lnt in self.op_priority \
|
||||||
|
and self.op_priority[lnt] <= self.op_priority['>']:
|
||||||
|
ret += '(' + self.OutExpr(child[-1]) + ')'
|
||||||
|
else:
|
||||||
|
ret += self.OutExpr(child[-1])
|
||||||
|
return ret + '>'
|
||||||
|
|
||||||
if nt == 'FNCALL':
|
if nt == 'FNCALL':
|
||||||
return self.FindName(expr) + '(' + self.OutExprList(child) + ')'
|
return self.FindName(expr) + '(' + self.OutExprList(child) + ')'
|
||||||
|
@ -210,9 +247,22 @@ class outscript(object):
|
||||||
return 'print(' + self.OutExpr(child[0]) + ')'
|
return 'print(' + self.OutExpr(child[0]) + ')'
|
||||||
|
|
||||||
if nt in self.unary_operands:
|
if nt in self.unary_operands:
|
||||||
|
ret = nt
|
||||||
|
lnt = child[0]['nt']
|
||||||
|
paren = False
|
||||||
if nt == 'NEG':
|
if nt == 'NEG':
|
||||||
nt = '- '
|
ret = '- '
|
||||||
return nt + self.OutExpr(child[0])
|
if lnt in self.op_priority:
|
||||||
|
paren = self.op_priority[lnt] <= self.op_priority['-']
|
||||||
|
else:
|
||||||
|
if lnt in self.op_priority:
|
||||||
|
paren = True
|
||||||
|
|
||||||
|
if paren:
|
||||||
|
ret += '(' + self.OutExpr(child[0]) + ')'
|
||||||
|
else:
|
||||||
|
ret += self.OutExpr(child[0])
|
||||||
|
return ret
|
||||||
|
|
||||||
if nt == 'FLD':
|
if nt == 'FLD':
|
||||||
return self.OutExpr(child[0]) + '.' + expr['fld']
|
return self.OutExpr(child[0]) + '.' + expr['fld']
|
||||||
|
|
|
@ -798,8 +798,6 @@ class parser(object):
|
||||||
|
|
||||||
if tok0 == '(':
|
if tok0 == '(':
|
||||||
# Parenthesized expression or typecast
|
# Parenthesized expression or typecast
|
||||||
# TODO: Don't include parentheses in the tree, defer to the output
|
|
||||||
# module to add them where necessary.
|
|
||||||
|
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
if self.tok[0] != 'TYPE':
|
if self.tok[0] != 'TYPE':
|
||||||
|
@ -807,7 +805,7 @@ class parser(object):
|
||||||
expr = self.Parse_expression()
|
expr = self.Parse_expression()
|
||||||
self.expect(')')
|
self.expect(')')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
return {'nt':'()', 't':expr['t'], 'ch':[expr]}
|
return expr
|
||||||
|
|
||||||
# Typecast
|
# Typecast
|
||||||
typ = self.tok[1]
|
typ = self.tok[1]
|
||||||
|
@ -825,7 +823,6 @@ class parser(object):
|
||||||
expr = self.Parse_expression()
|
expr = self.Parse_expression()
|
||||||
self.expect(')')
|
self.expect(')')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
expr = {'nt':'()', 't':expr['t'], 'ch':[expr]}
|
|
||||||
else:
|
else:
|
||||||
expr = self.Parse_unary_postfix_expression(AllowAssignment = False)
|
expr = self.Parse_unary_postfix_expression(AllowAssignment = False)
|
||||||
basetype = expr['t']
|
basetype = expr['t']
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue