mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Parse_unary_postfix_expression shouldn't accept the token (i.e. advance to the next) if it's not processed. This caused a mismatch between the reported syntax error and the position where it should have been detected. Fixed.
Added corresponding regression test.
This commit is contained in:
parent
ceb442e931
commit
cfb9dee941
2 changed files with 28 additions and 5 deletions
|
@ -642,18 +642,22 @@ class parser(object):
|
||||||
"""
|
"""
|
||||||
tok0 = self.tok[0]
|
tok0 = self.tok[0]
|
||||||
val = self.tok[1] if len(self.tok) > 1 else None
|
val = self.tok[1] if len(self.tok) > 1 else None
|
||||||
self.NextToken()
|
|
||||||
CONST = 'CONST'
|
CONST = 'CONST'
|
||||||
if tok0 == '-' and self.tok[0] in ('INTEGER_VALUE', 'FLOAT_VALUE'):
|
if tok0 == '-':
|
||||||
tok0 = self.tok[0]
|
|
||||||
val = self.tok[1]
|
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
return {'nt':CONST, 't':'integer' if type(val) == int else 'float', 'value':-val}
|
if self.tok[0] in ('INTEGER_VALUE', 'FLOAT_VALUE'):
|
||||||
|
tok0 = self.tok[0]
|
||||||
|
val = self.tok[1]
|
||||||
|
self.NextToken()
|
||||||
|
return {'nt':CONST, 't':'integer' if type(val) == int else 'float', 'value':-val}
|
||||||
if tok0 == 'INTEGER_VALUE':
|
if tok0 == 'INTEGER_VALUE':
|
||||||
|
self.NextToken()
|
||||||
return {'nt':CONST, 't':'integer', 'value':val}
|
return {'nt':CONST, 't':'integer', 'value':val}
|
||||||
if tok0 == 'FLOAT_VALUE':
|
if tok0 == 'FLOAT_VALUE':
|
||||||
|
self.NextToken()
|
||||||
return {'nt':CONST, 't':'float', 'value':val}
|
return {'nt':CONST, 't':'float', 'value':val}
|
||||||
if tok0 == 'STRING_VALUE':
|
if tok0 == 'STRING_VALUE':
|
||||||
|
self.NextToken()
|
||||||
if self.allowmultistrings:
|
if self.allowmultistrings:
|
||||||
while self.tok[0] == 'STRING_VALUE':
|
while self.tok[0] == 'STRING_VALUE':
|
||||||
val += self.tok[1]
|
val += self.tok[1]
|
||||||
|
@ -663,14 +667,19 @@ class parser(object):
|
||||||
#if tok0 == 'KEY_VALUE':
|
#if tok0 == 'KEY_VALUE':
|
||||||
# return [CONST, 'key', val]
|
# return [CONST, 'key', val]
|
||||||
if tok0 == 'VECTOR_VALUE':
|
if tok0 == 'VECTOR_VALUE':
|
||||||
|
self.NextToken()
|
||||||
return {'nt':CONST, 't':'vector', 'value':val}
|
return {'nt':CONST, 't':'vector', 'value':val}
|
||||||
if tok0 == 'ROTATION_VALUE':
|
if tok0 == 'ROTATION_VALUE':
|
||||||
|
self.NextToken()
|
||||||
return {'nt':CONST, 't':'rotation', 'value':val}
|
return {'nt':CONST, 't':'rotation', 'value':val}
|
||||||
if tok0 == 'LIST_VALUE':
|
if tok0 == 'LIST_VALUE':
|
||||||
|
self.NextToken()
|
||||||
return {'nt':CONST, 't':'list', 'value':val}
|
return {'nt':CONST, 't':'list', 'value':val}
|
||||||
if tok0 in ('TRUE', 'FALSE'):
|
if tok0 in ('TRUE', 'FALSE'):
|
||||||
|
self.NextToken()
|
||||||
return {'nt':CONST, 't':'integer', 'value':int(tok0 == 'TRUE')}
|
return {'nt':CONST, 't':'integer', 'value':int(tok0 == 'TRUE')}
|
||||||
if tok0 == '<':
|
if tok0 == '<':
|
||||||
|
self.NextToken()
|
||||||
val = [self.Parse_expression()]
|
val = [self.Parse_expression()]
|
||||||
self.expect(',')
|
self.expect(',')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
|
@ -709,11 +718,13 @@ class parser(object):
|
||||||
return {'nt':'ROTATION', 't':'rotation', 'ch':val}
|
return {'nt':'ROTATION', 't':'rotation', 'ch':val}
|
||||||
|
|
||||||
if tok0 == '[':
|
if tok0 == '[':
|
||||||
|
self.NextToken()
|
||||||
val = self.Parse_optional_expression_list()
|
val = self.Parse_optional_expression_list()
|
||||||
self.expect(']')
|
self.expect(']')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
return {'nt':'LIST', 't':'list', 'ch':val}
|
return {'nt':'LIST', 't':'list', 'ch':val}
|
||||||
if tok0 == 'PRINT':
|
if tok0 == 'PRINT':
|
||||||
|
self.NextToken()
|
||||||
self.expect('(')
|
self.expect('(')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
expr = self.Parse_expression()
|
expr = self.Parse_expression()
|
||||||
|
@ -728,6 +739,7 @@ class parser(object):
|
||||||
raise EParseUEOF(self)
|
raise EParseUEOF(self)
|
||||||
raise EParseSyntax(self)
|
raise EParseSyntax(self)
|
||||||
name = val
|
name = val
|
||||||
|
self.NextToken()
|
||||||
|
|
||||||
# Course of action decided here.
|
# Course of action decided here.
|
||||||
tok0 = self.tok[0]
|
tok0 = self.tok[0]
|
||||||
|
|
|
@ -467,6 +467,17 @@ class Test03_Optimizer(UnitTestCase):
|
||||||
self.assertRaises(EParseAlreadyDefined, self.parser.parse,
|
self.assertRaises(EParseAlreadyDefined, self.parser.parse,
|
||||||
'default { timer() {} timer() {} }')
|
'default { timer() {} timer() {} }')
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.parser.parse('default { timer() { return } }')
|
||||||
|
# should raise EParseSyntax, so it should never get here
|
||||||
|
self.assertFalse(True)
|
||||||
|
except EParseSyntax as e:
|
||||||
|
# should err before first closing brace
|
||||||
|
self.assertEqual(e.cno, 27)
|
||||||
|
except:
|
||||||
|
# should raise no other exception
|
||||||
|
self.assertFalse(True)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
del self.parser
|
del self.parser
|
||||||
del self.opt
|
del self.opt
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue