This library provides a simple parser that can be used to evaluate the value of an expression which aligns EDK II Meta-Data Expression Syntax Specification revision 1.3.
This library requires Python 3.10 or later, and Pygments.
This library is intended to be used as part of another project, and I will not make it available on PyPI.
You can use the pip
to install it from source:
pip install git+https://github.com/tzing/edk2-expression.git
or simply copy the source code into your project.
First, parse the expression text into abstract syntax tree (AST):
>>> import edk2_expression
>>> expr = edk2_expression.parse("$(FOO) +2")
Then, evaluate the expression with a dictionary of variables:
>>> print(expr.evaluate({"FOO": 1}))
3
For nested expression, one can set nest
to evaluate
to evaluate it:
>>> expr1 = edk2_expression.parse("True ? $(BAR) + 3 : 0")
>>> print(expr1.evaluate({"FOO": 1, "BAR": expr}, nest="evaluate"))
6
See example/ directory for more examples.
EDK II Data Field Name | Supported | Evaluate |
---|---|---|
<Array> |
No1 | No |
<CName> |
Yes | No |
<Function> |
No2 | No |
<GuidValue> |
Partial3 | Yes; Returns uuid.UUID |
<MacroVal> |
Yes | Yes; Returns the macro value |
<Number> |
Yes | Yes; Returns the number |
<PcdName> |
Yes | No |
<StringLiteral> |
Yes | Yes; Returns the string |
<TrueFalse> |
Yes | Yes; Returns True /False |
EDK II Expression Name | Operator | Supported | Precedence4 |
---|---|---|---|
<UnaryExpression> |
! , NOT , not , ~ |
Yes | 2 |
<MultiplicativeExpress> |
* , / , % |
Yes | 3 |
<AdditiveExpress> |
+ , - |
Yes | 4 |
<ShiftExpression> |
<< , >> |
Yes | 5 |
<RelationalExpress> |
< , LT , <= , LE , > , GT , >= , GE |
Yes | 6 |
<EqualityExpression> |
== , EQ , != , NE |
Yes | 7 |
<BitwiseAndExpression> |
& |
Yes | 8 |
<BitwiseXorExpress> |
^ |
Yes | 9 |
<BitwiseOrExpress> |
| |
Yes | 10 |
<LogicalAndExpress> |
&& , AND , and |
Yes | 11 |
<LogicalXorExpress> |
XOR , xor |
Yes | 12 |
<LogicalOrExpress> |
|| , OR , or |
Yes | 13 |
<CondExpress> |
?: (ternary conditional) |
Yes | 15 |
This parser utilizes Pygments for expression text tokenization and, as a result, it comes packaged with a lexer.
If you are using Pygments, you can use the lexer directly:
import edk2_expression.lex
lexer = edk2_expression.lex.Edk2ExpressionLexer()
A function that returns True
if the macro is defined, otherwise False
.
The syntax is defined as follows in EBNF:
<MacroDefined> ::= "DEFINED(" <CName> ")"
<CName> ::= (a-zA-Z_) [(a-zA-Z0-9_)]*
This function is not defined in EDK II specification therefore it is disabled by default.
To enable it, uncomment the lines for <MacroDefined>
in lexer:
patch
diff --git a/edk2_expression/lex.py b/edk2_expression/lex.py
index ac66120..e87340b 100644
--- a/edk2_expression/lex.py
+++ b/edk2_expression/lex.py
@@ -64,10 +64,10 @@ class Edk2ExpressionLexer(RegexLexer):
r"(\$\()([A-Z][A-Z0-9_]*)(\))",
bygroups(Keyword.Declaration, Name.Variable, Keyword.Declaration),
),
- # ( # <MacroDefined>
- # rf"\b(DEFINED)(\()({CName})(\))",
- # bygroups(Keyword.Type, Punctuation, Name.Variable, Punctuation),
- # ),
+ ( # <MacroDefined>
+ rf"\b(DEFINED)(\()({CName})(\))",
+ bygroups(Keyword.Type, Punctuation, Name.Variable, Punctuation),
+ ),
(rf"\b{CName}\b", Name.Variable), # <CName>
],
"array": [
See Changelog.md.
This project is licensed under the terms of the MIT license.
Footnotes
-
This library currently reads the array as a string, and does not support any operations or evaluation. ↩
-
Per addressed by EDK II:
Functions should only be used if all tools that process the entry in the meta-data file comprehend the function syntax.
Since this library is designed for general purpose, it does not parse functions. ↩
-
GUID in
<CformatGuid>
format is currently not parsed. ↩ -
The lower the number, the higher the precedence. ↩