Fix wrong output leading to incorrect tokenization of minus signs

When the tree has a unary minus node (NEG) whose child is a product node (*), and the left operand of the product node starts with a minus sign but is not a NEG node, this produced at least two minus signs in sequence without any spaces.

Normally, OptSigns hides this problem, but when it is disabled, or when the left factor is a pre-decrement (--V) node, the problem is visible.

Fix by creating a function that detects all kinds of leading minus signs, and use it in place of the comparison with NEG.

Fixes #31. Reported by @KrsityKu, who also provided a repro.
This commit is contained in:
Sei Lisa 2024-05-24 23:55:23 +02:00
parent 0083da6b01
commit d70c914738
4 changed files with 61 additions and 4 deletions

View file

@ -194,6 +194,20 @@ class outscript(object):
return self.symtab[scope][node]['NewName']
return node
def LeadMinus(self, node):
"""Tells whether a node starts with a minus sign"""
# TODO: This may add redundant parentheses around --V.
# More exactly, the line marked "!!!".
# They are necessary to prevent wrong output (---v instead of -(--v))
# but not always are they actually necessary. See regr/issue-31.lsl
return (node.nt == 'NEG'
or node.nt == '--V' # !!!
or not self.optsigns
and node.nt == 'CONST'
and node.t in {'integer', 'float'}
and copysign(1, node.value) == -1
)
def OutIndented(self, node):
if node.nt != '{}':
self.indentlevel += 1
@ -235,7 +249,9 @@ class outscript(object):
if lnt in self.op_priority:
if self.op_priority[lnt] < base_pri:
lparen = True
elif lnt == 'NEG' and base_pri > self.op_priority['-']:
elif (self.LeadMinus(child[0]) and base_pri >
self.op_priority['-']
):
lparen = True
# This situation has ugly cases due to the strange precedence
@ -261,13 +277,17 @@ class outscript(object):
and lnode.nt not in ('~', '!')
):
break
if lnode.nt == 'NEG' and base_pri > self.op_priority['-']:
if (self.LeadMinus(lnode) and base_pri >
self.op_priority['-']
):
lparen = True
if rnt in self.op_priority:
if self.op_priority[rnt] <= base_pri:
rparen = True
elif rnt == 'NEG' and self.op_priority['-'] < base_pri:
elif (self.LeadMinus(child[1]) and self.op_priority['-'] <
base_pri
):
rparen = True
# see above
elif rnt in ('~', '!'):
@ -278,7 +298,9 @@ class outscript(object):
lnode = lnode.ch[0]
if lnode.nt not in self.op_priority and lnode.nt not in ('~', '!'):
break
if lnode.nt == 'NEG' and base_pri > self.op_priority['-']:
if (self.LeadMinus(lnode) and base_pri >
self.op_priority['-']
):
# TODO: Improve right operand parenthesis removal
# for minus signs.
# Shouldn't this look into the RHS node?