Skip to content

Commit

Permalink
Update operator precedence for post fix evaluation
Browse files Browse the repository at this point in the history
Equals '==' operator should have a higher precedence than OR and AND.
This fixes a bug where a conditional like
"!if RACECAR == RACECAR ||  RACECAR == STREETCAR" would evaluate the last two
operators in the wrong order, returning False when it should be True.
Removing extra parenthesis at the end of the tokens as it is modifying the
input object and is only needed because an opening one is added to the stack.
  • Loading branch information
ponchofigueroa committed Jan 3, 2025
1 parent 55350f3 commit b828b1f
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 3 deletions.
5 changes: 2 additions & 3 deletions edk2toollib/uefi/edk2/parsers/base_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,8 +638,7 @@ def _TokenizeConditional(cls: "BaseParser", text: str) -> str:
@classmethod
def _ConvertTokensToPostFix(cls: "BaseParser", tokens: list[str]) -> list[str]:
# convert infix into post fix
stack = ["("]
tokens.append(")") # add an extra parathesis
stack = []
expression = []
for token in tokens:
# If the incoming symbol is a left parenthesis, push it on the stack.
Expand Down Expand Up @@ -699,7 +698,7 @@ def _GetOperatorPrecedence(cls: "BaseParser", token: str) -> int:
return 100
if token == "NOT": # not is the lowest
return -2
if token == "IN":
if token == "IN" or token == "==" or token == "!=":
return 1
return 0

Expand Down
85 changes: 85 additions & 0 deletions tests.unit/parsers/test_base_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,91 @@ def test_process_and_operation_conditional(self):
self.assertFalse(parser.EvaluateConditional("!if FALSE AND FALSE"))
self.assertFalse(parser.EvaluateConditional("!if FALSE && FALSE"))

def test_process_equal_or_equal_operation_conditional(self):
parser = BaseParser("")
self.assertTrue(parser.EvaluateConditional("!if RACECAR == RACECAR || RACECAR == STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == RACECAR OR RACECAR == STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == RACECAR || RACECAR != STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == RACECAR OR RACECAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR || RACECAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR OR RACECAR == STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != RACECAR || RACECAR != STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != RACECAR OR RACECAR != STREETCAR"))

self.assertTrue(parser.EvaluateConditional("!if RACECAR == STREETCAR || RACECAR == RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == STREETCAR OR RACECAR == RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR || RACECAR != RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR OR RACECAR != RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR || RACECAR == RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR OR RACECAR == RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR || RACECAR != RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR OR RACECAR != RACECAR"))

self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR || STREETCAR == RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR OR STREETCAR == RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == STREETCAR || STREETCAR != RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == STREETCAR OR STREETCAR != RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR || STREETCAR == RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR OR STREETCAR == RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR || STREETCAR != RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR OR STREETCAR != RACECAR"))

self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR || RACECAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR OR RACECAR == STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == STREETCAR || RACECAR != STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == STREETCAR OR RACECAR != STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR || RACECAR == STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR OR RACECAR == STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR || RACECAR != STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR OR RACECAR != STREETCAR"))

def test_process_equal_and_equal_operation_conditional(self):
parser = BaseParser("")
self.assertTrue(parser.EvaluateConditional("!if RACECAR == RACECAR && RACECAR != STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == RACECAR AND RACECAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == RACECAR && RACECAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == RACECAR AND RACECAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR && RACECAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR AND RACECAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR && RACECAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR AND RACECAR == STREETCAR"))

self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR && RACECAR == RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR AND RACECAR == RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR && RACECAR != RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR AND RACECAR != RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR && RACECAR == RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR AND RACECAR == RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != STREETCAR && RACECAR != RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != STREETCAR AND RACECAR != RACECAR"))

self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR && STREETCAR == RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR AND STREETCAR == RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR && STREETCAR != RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR AND STREETCAR != RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != STREETCAR && STREETCAR == RACECAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != STREETCAR AND STREETCAR == RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR && STREETCAR != RACECAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR AND STREETCAR != RACECAR"))

self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR && RACECAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR AND RACECAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR && RACECAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == STREETCAR AND RACECAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != STREETCAR && RACECAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != STREETCAR AND RACECAR == STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR && RACECAR != STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR != STREETCAR AND RACECAR != STREETCAR"))

self.assertTrue(parser.EvaluateConditional("!if RACECAR == RACECAR && STREETCAR == STREETCAR"))
self.assertTrue(parser.EvaluateConditional("!if RACECAR == RACECAR AND STREETCAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == RACECAR && STREETCAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR == RACECAR AND STREETCAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR && STREETCAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR AND STREETCAR == STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR && STREETCAR != STREETCAR"))
self.assertFalse(parser.EvaluateConditional("!if RACECAR != RACECAR AND STREETCAR != STREETCAR"))

def test_process_invalid_conditional(self):
parser = BaseParser("")
with self.assertRaises(RuntimeError):
Expand Down

0 comments on commit b828b1f

Please sign in to comment.