Skip to content

Commit

Permalink
base_parser.py: Update precedence of == and != (#684)
Browse files Browse the repository at this point in the history
To align with industry standard order of operations, and with EDKII parsers, equals (`==`) and not equals (`!=`) should have a higher precedence than logical OR (`||`) and logical AND (`&&`) operators.

Prior to this commit, they shared the same precedence level which would lead to evaluations similar to `!if RACECAR == RACECAR || RACECAR == STREETCAR` being completed in the wrong order as compared to EDKII parsers. Additionally, this removes the parentheses that were inserted at the beginning and end of tokens as they appear to serve no further purpose.
  • Loading branch information
ponchofigueroa authored Jan 3, 2025
1 parent 55350f3 commit c4a8dd5
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 c4a8dd5

Please sign in to comment.