summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/Python/UPT/Library/ExpressionValidate.py')
-rw-r--r--BaseTools/Source/Python/UPT/Library/ExpressionValidate.py1134
1 files changed, 567 insertions, 567 deletions
diff --git a/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py b/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py
index 7718ca12e5..ae5f835bae 100644
--- a/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py
+++ b/BaseTools/Source/Python/UPT/Library/ExpressionValidate.py
@@ -1,567 +1,567 @@
-## @file
-# This file is used to check PCD logical expression
-#
-# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-
-'''
-ExpressionValidate
-'''
-from __future__ import print_function
-
-##
-# Import Modules
-#
-import re
-from Logger import StringTable as ST
-
-## IsValidBareCString
-#
-# Check if String is comprised by whitespace(0x20), !(0x21), 0x23 - 0x7E
-# or '\n', '\t', '\f', '\r', '\b', '\0', '\\'
-#
-# @param String: string to be checked
-#
-def IsValidBareCString(String):
- EscapeList = ['n', 't', 'f', 'r', 'b', '0', '\\', '"']
- PreChar = ''
- LastChar = ''
- for Char in String:
- LastChar = Char
- if PreChar == '\\':
- if Char not in EscapeList:
- return False
- if Char == '\\':
- PreChar = ''
- continue
- else:
- IntChar = ord(Char)
- if IntChar != 0x20 and IntChar != 0x09 and IntChar != 0x21 \
- and (IntChar < 0x23 or IntChar > 0x7e):
- return False
- PreChar = Char
-
- # Last char cannot be \ if PreChar is not \
- if LastChar == '\\' and PreChar == LastChar:
- return False
- return True
-
-def _ValidateToken(Token):
- Token = Token.strip()
- Index = Token.find("\"")
- if Index != -1:
- return IsValidBareCString(Token[Index+1:-1])
- return True
-
-## _ExprError
-#
-# @param Exception: Exception
-#
-class _ExprError(Exception):
- def __init__(self, Error = ''):
- Exception.__init__(self)
- self.Error = Error
-
-## _ExprBase
-#
-class _ExprBase:
- HEX_PATTERN = '[\t\s]*0[xX][a-fA-F0-9]+'
- INT_PATTERN = '[\t\s]*[0-9]+'
- MACRO_PATTERN = '[\t\s]*\$\(([A-Z][_A-Z0-9]*)\)'
- PCD_PATTERN = \
- '[\t\s]*[_a-zA-Z][a-zA-Z0-9_]*[\t\s]*\.[\t\s]*[_a-zA-Z][a-zA-Z0-9_]*'
- QUOTED_PATTERN = '[\t\s]*L?"[^"]*"'
- BOOL_PATTERN = '[\t\s]*(true|True|TRUE|false|False|FALSE)'
- def __init__(self, Token):
- self.Token = Token
- self.Index = 0
- self.Len = len(Token)
-
- ## SkipWhitespace
- #
- def SkipWhitespace(self):
- for Char in self.Token[self.Index:]:
- if Char not in ' \t':
- break
- self.Index += 1
-
- ## IsCurrentOp
- #
- # @param OpList: option list
- #
- def IsCurrentOp(self, OpList):
- self.SkipWhitespace()
- LetterOp = ["EQ", "NE", "GE", "LE", "GT", "LT", "NOT", "and", "AND",
- "or", "OR", "XOR"]
- OpMap = {
- '|' : '|',
- '&' : '&',
- '!' : '=',
- '>' : '=',
- '<' : '='
- }
-
- for Operator in OpList:
- if not self.Token[self.Index:].startswith(Operator):
- continue
-
- self.Index += len(Operator)
- Char = self.Token[self.Index : self.Index + 1]
-
- if (Operator in LetterOp and (Char == '_' or Char.isalnum())) \
- or (Operator in OpMap and OpMap[Operator] == Char):
- self.Index -= len(Operator)
- break
-
- return True
-
- return False
-
-## _LogicalExpressionParser
-#
-# @param _ExprBase: _ExprBase object
-#
-class _LogicalExpressionParser(_ExprBase):
- #
- # STRINGITEM can only be logical field according to spec
- #
- STRINGITEM = -1
-
- #
- # Evaluate to True or False
- #
- LOGICAL = 0
- REALLOGICAL = 2
-
- #
- # Just arithmetic expression
- #
- ARITH = 1
-
- def __init__(self, Token):
- _ExprBase.__init__(self, Token)
- self.Parens = 0
-
- def _CheckToken(self, MatchList):
- for Match in MatchList:
- if Match and Match.start() == 0:
- if not _ValidateToken(
- self.Token[self.Index:self.Index+Match.end()]
- ):
- return False
-
- self.Index += Match.end()
- if self.Token[self.Index - 1] == '"':
- return True
- if self.Token[self.Index:self.Index+1] == '_' or \
- self.Token[self.Index:self.Index+1].isalnum():
- self.Index -= Match.end()
- return False
-
- Token = self.Token[self.Index - Match.end():self.Index]
- if Token.strip() in ["EQ", "NE", "GE", "LE", "GT", "LT",
- "NOT", "and", "AND", "or", "OR", "XOR"]:
- self.Index -= Match.end()
- return False
-
- return True
-
- return False
-
- def IsAtomicNumVal(self):
- #
- # Hex number
- #
- Match1 = re.compile(self.HEX_PATTERN).match(self.Token[self.Index:])
-
- #
- # Number
- #
- Match2 = re.compile(self.INT_PATTERN).match(self.Token[self.Index:])
-
- #
- # Macro
- #
- Match3 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:])
-
- #
- # PcdName
- #
- Match4 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:])
-
- return self._CheckToken([Match1, Match2, Match3, Match4])
-
-
- def IsAtomicItem(self):
- #
- # Macro
- #
- Match1 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:])
-
- #
- # PcdName
- #
- Match2 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:])
-
- #
- # Quoted string
- #
- Match3 = re.compile(self.QUOTED_PATTERN).\
- match(self.Token[self.Index:].replace('\\\\', '//').\
- replace('\\\"', '\\\''))
-
- return self._CheckToken([Match1, Match2, Match3])
-
- ## A || B
- #
- def LogicalExpression(self):
- Ret = self.SpecNot()
- while self.IsCurrentOp(['||', 'OR', 'or', '&&', 'AND', 'and', 'XOR', 'xor', '^']):
- if self.Token[self.Index-1] == '|' and self.Parens <= 0:
- raise _ExprError(ST.ERR_EXPR_OR % self.Token)
- if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
- raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
- Ret = self.SpecNot()
- if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
- raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
- Ret = self.REALLOGICAL
- return Ret
-
- def SpecNot(self):
- if self.IsCurrentOp(["NOT", "!", "not"]):
- return self.SpecNot()
- return self.Rel()
-
- ## A < B, A > B, A <= B, A >= B
- #
- def Rel(self):
- Ret = self.Expr()
- if self.IsCurrentOp(["<=", ">=", ">", "<", "GT", "LT", "GE", "LE",
- "==", "EQ", "!=", "NE"]):
- if Ret == self.STRINGITEM:
- raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
- Ret = self.Expr()
- if Ret == self.REALLOGICAL:
- raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
- Ret = self.REALLOGICAL
- return Ret
-
- ## A + B, A - B
- #
- def Expr(self):
- Ret = self.Factor()
- while self.IsCurrentOp(["+", "-", "&", "|", "^", "XOR", "xor"]):
- if self.Token[self.Index-1] == '|' and self.Parens <= 0:
- raise _ExprError(ST.ERR_EXPR_OR)
- if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:
- raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
- Ret = self.Factor()
- if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:
- raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
- Ret = self.ARITH
- return Ret
-
- ## Factor
- #
- def Factor(self):
- if self.IsCurrentOp(["("]):
- self.Parens += 1
- Ret = self.LogicalExpression()
- if not self.IsCurrentOp([")"]):
- raise _ExprError(ST.ERR_EXPR_RIGHT_PAREN % \
- (self.Token, self.Token[self.Index:]))
- self.Parens -= 1
- return Ret
-
- if self.IsAtomicItem():
- if self.Token[self.Index - 1] == '"':
- return self.STRINGITEM
- return self.LOGICAL
- elif self.IsAtomicNumVal():
- return self.ARITH
- else:
- raise _ExprError(ST.ERR_EXPR_FACTOR % \
- (self.Token[self.Index:], self.Token))
-
- ## IsValidLogicalExpression
- #
- def IsValidLogicalExpression(self):
- if self.Len == 0:
- return False, ST.ERR_EXPRESS_EMPTY
- try:
- if self.LogicalExpression() not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
- return False, ST.ERR_EXPR_LOGICAL % self.Token
- except _ExprError as XExcept:
- return False, XExcept.Error
- self.SkipWhitespace()
- if self.Index != self.Len:
- return False, (ST.ERR_EXPR_BOOLEAN % \
- (self.Token[self.Index:], self.Token))
- return True, ''
-
-## _ValidRangeExpressionParser
-#
-class _ValidRangeExpressionParser(_ExprBase):
- INT_RANGE_PATTERN = '[\t\s]*[0-9]+[\t\s]*-[\t\s]*[0-9]+'
- HEX_RANGE_PATTERN = \
- '[\t\s]*0[xX][a-fA-F0-9]+[\t\s]*-[\t\s]*0[xX][a-fA-F0-9]+'
- def __init__(self, Token):
- _ExprBase.__init__(self, Token)
- self.Parens = 0
- self.HEX = 1
- self.INT = 2
- self.IsParenHappen = False
- self.IsLogicalOpHappen = False
-
- ## IsValidRangeExpression
- #
- def IsValidRangeExpression(self):
- if self.Len == 0:
- return False, ST.ERR_EXPR_RANGE_EMPTY
- try:
- if self.RangeExpression() not in [self.HEX, self.INT]:
- return False, ST.ERR_EXPR_RANGE % self.Token
- except _ExprError as XExcept:
- return False, XExcept.Error
-
- self.SkipWhitespace()
- if self.Index != self.Len:
- return False, (ST.ERR_EXPR_RANGE % self.Token)
- return True, ''
-
- ## RangeExpression
- #
- def RangeExpression(self):
- Ret = self.Unary()
- while self.IsCurrentOp(['OR', 'AND', 'and', 'or']):
- self.IsLogicalOpHappen = True
- if not self.IsParenHappen:
- raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token)
- self.IsParenHappen = False
- Ret = self.Unary()
-
- if self.IsCurrentOp(['XOR']):
- Ret = self.Unary()
-
- return Ret
-
- ## Unary
- #
- def Unary(self):
- if self.IsCurrentOp(["NOT"]):
- return self.Unary()
-
- return self.ValidRange()
-
- ## ValidRange
- #
- def ValidRange(self):
- Ret = -1
- if self.IsCurrentOp(["("]):
- self.IsLogicalOpHappen = False
- self.IsParenHappen = True
- self.Parens += 1
- if self.Parens > 1:
- raise _ExprError(ST.ERR_EXPR_RANGE_DOUBLE_PAREN_NESTED % self.Token)
- Ret = self.RangeExpression()
- if not self.IsCurrentOp([")"]):
- raise _ExprError(ST.ERR_EXPR_RIGHT_PAREN % self.Token)
- self.Parens -= 1
- return Ret
-
- if self.IsLogicalOpHappen:
- raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token)
-
- if self.IsCurrentOp(["LT", "GT", "LE", "GE", "EQ", "XOR"]):
- IntMatch = \
- re.compile(self.INT_PATTERN).match(self.Token[self.Index:])
- HexMatch = \
- re.compile(self.HEX_PATTERN).match(self.Token[self.Index:])
- if HexMatch and HexMatch.start() == 0:
- self.Index += HexMatch.end()
- Ret = self.HEX
- elif IntMatch and IntMatch.start() == 0:
- self.Index += IntMatch.end()
- Ret = self.INT
- else:
- raise _ExprError(ST.ERR_EXPR_RANGE_FACTOR % (self.Token[self.Index:], self.Token))
- else:
- IntRangeMatch = re.compile(
- self.INT_RANGE_PATTERN).match(self.Token[self.Index:]
- )
- HexRangeMatch = re.compile(
- self.HEX_RANGE_PATTERN).match(self.Token[self.Index:]
- )
- if HexRangeMatch and HexRangeMatch.start() == 0:
- self.Index += HexRangeMatch.end()
- Ret = self.HEX
- elif IntRangeMatch and IntRangeMatch.start() == 0:
- self.Index += IntRangeMatch.end()
- Ret = self.INT
- else:
- raise _ExprError(ST.ERR_EXPR_RANGE % self.Token)
-
- return Ret
-
-## _ValidListExpressionParser
-#
-class _ValidListExpressionParser(_ExprBase):
- VALID_LIST_PATTERN = '(0[xX][0-9a-fA-F]+|[0-9]+)([\t\s]*,[\t\s]*(0[xX][0-9a-fA-F]+|[0-9]+))*'
- def __init__(self, Token):
- _ExprBase.__init__(self, Token)
- self.NUM = 1
-
- def IsValidListExpression(self):
- if self.Len == 0:
- return False, ST.ERR_EXPR_LIST_EMPTY
- try:
- if self.ListExpression() not in [self.NUM]:
- return False, ST.ERR_EXPR_LIST % self.Token
- except _ExprError as XExcept:
- return False, XExcept.Error
-
- self.SkipWhitespace()
- if self.Index != self.Len:
- return False, (ST.ERR_EXPR_LIST % self.Token)
-
- return True, ''
-
- def ListExpression(self):
- Ret = -1
- self.SkipWhitespace()
- ListMatch = re.compile(self.VALID_LIST_PATTERN).match(self.Token[self.Index:])
- if ListMatch and ListMatch.start() == 0:
- self.Index += ListMatch.end()
- Ret = self.NUM
- else:
- raise _ExprError(ST.ERR_EXPR_LIST % self.Token)
-
- return Ret
-
-## _StringTestParser
-#
-class _StringTestParser(_ExprBase):
- def __init__(self, Token):
- _ExprBase.__init__(self, Token)
-
- ## IsValidStringTest
- #
- def IsValidStringTest(self):
- if self.Len == 0:
- return False, ST.ERR_EXPR_EMPTY
- try:
- self.StringTest()
- except _ExprError as XExcept:
- return False, XExcept.Error
- return True, ''
-
- ## StringItem
- #
- def StringItem(self):
- Match1 = re.compile(self.QUOTED_PATTERN)\
- .match(self.Token[self.Index:].replace('\\\\', '//')\
- .replace('\\\"', '\\\''))
- Match2 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:])
- Match3 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:])
- MatchList = [Match1, Match2, Match3]
- for Match in MatchList:
- if Match and Match.start() == 0:
- if not _ValidateToken(
- self.Token[self.Index:self.Index+Match.end()]
- ):
- raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \
- (self.Token, self.Token[self.Index:]))
- self.Index += Match.end()
- Token = self.Token[self.Index - Match.end():self.Index]
- if Token.strip() in ["EQ", "NE"]:
- raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \
- (self.Token, self.Token[self.Index:]))
- return
- else:
- raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \
- (self.Token, self.Token[self.Index:]))
-
- ## StringTest
- #
- def StringTest(self):
- self.StringItem()
- if not self.IsCurrentOp(["==", "EQ", "!=", "NE"]):
- raise _ExprError(ST.ERR_EXPR_EQUALITY % \
- (self.Token[self.Index:], self.Token))
- self.StringItem()
- if self.Index != self.Len:
- raise _ExprError(ST.ERR_EXPR_BOOLEAN % \
- (self.Token[self.Index:], self.Token))
-
-##
-# Check syntax of string test
-#
-# @param Token: string test token
-#
-def IsValidStringTest(Token, Flag=False):
- #
- # Not do the check right now, keep the implementation for future enhancement.
- #
- if not Flag:
- return True, ""
- return _StringTestParser(Token).IsValidStringTest()
-
-
-##
-# Check syntax of logical expression
-#
-# @param Token: expression token
-#
-def IsValidLogicalExpr(Token, Flag=False):
- #
- # Not do the check right now, keep the implementation for future enhancement.
- #
- if not Flag:
- return True, ""
- return _LogicalExpressionParser(Token).IsValidLogicalExpression()
-
-##
-# Check syntax of range expression
-#
-# @param Token: range expression token
-#
-def IsValidRangeExpr(Token):
- return _ValidRangeExpressionParser(Token).IsValidRangeExpression()
-
-##
-# Check syntax of value list expression token
-#
-# @param Token: value list expression token
-#
-def IsValidListExpr(Token):
- return _ValidListExpressionParser(Token).IsValidListExpression()
-
-##
-# Check whether the feature flag expression is valid or not
-#
-# @param Token: feature flag expression
-#
-def IsValidFeatureFlagExp(Token, Flag=False):
- #
- # Not do the check right now, keep the implementation for future enhancement.
- #
- if not Flag:
- return True, "", Token
- else:
- if Token in ['TRUE', 'FALSE', 'true', 'false', 'True', 'False',
- '0x1', '0x01', '0x0', '0x00']:
- return True, ""
- Valid, Cause = IsValidStringTest(Token, Flag)
- if not Valid:
- Valid, Cause = IsValidLogicalExpr(Token, Flag)
- if not Valid:
- return False, Cause
- return True, ""
-
-if __name__ == '__main__':
-# print IsValidRangeExpr('LT 9')
- print(_LogicalExpressionParser('gCrownBayTokenSpaceGuid.PcdPciDevice1BridgeAddressLE0').IsValidLogicalExpression())
-
-
-
+## @file
+# This file is used to check PCD logical expression
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+
+'''
+ExpressionValidate
+'''
+from __future__ import print_function
+
+##
+# Import Modules
+#
+import re
+from Logger import StringTable as ST
+
+## IsValidBareCString
+#
+# Check if String is comprised by whitespace(0x20), !(0x21), 0x23 - 0x7E
+# or '\n', '\t', '\f', '\r', '\b', '\0', '\\'
+#
+# @param String: string to be checked
+#
+def IsValidBareCString(String):
+ EscapeList = ['n', 't', 'f', 'r', 'b', '0', '\\', '"']
+ PreChar = ''
+ LastChar = ''
+ for Char in String:
+ LastChar = Char
+ if PreChar == '\\':
+ if Char not in EscapeList:
+ return False
+ if Char == '\\':
+ PreChar = ''
+ continue
+ else:
+ IntChar = ord(Char)
+ if IntChar != 0x20 and IntChar != 0x09 and IntChar != 0x21 \
+ and (IntChar < 0x23 or IntChar > 0x7e):
+ return False
+ PreChar = Char
+
+ # Last char cannot be \ if PreChar is not \
+ if LastChar == '\\' and PreChar == LastChar:
+ return False
+ return True
+
+def _ValidateToken(Token):
+ Token = Token.strip()
+ Index = Token.find("\"")
+ if Index != -1:
+ return IsValidBareCString(Token[Index+1:-1])
+ return True
+
+## _ExprError
+#
+# @param Exception: Exception
+#
+class _ExprError(Exception):
+ def __init__(self, Error = ''):
+ Exception.__init__(self)
+ self.Error = Error
+
+## _ExprBase
+#
+class _ExprBase:
+ HEX_PATTERN = '[\t\s]*0[xX][a-fA-F0-9]+'
+ INT_PATTERN = '[\t\s]*[0-9]+'
+ MACRO_PATTERN = '[\t\s]*\$\(([A-Z][_A-Z0-9]*)\)'
+ PCD_PATTERN = \
+ '[\t\s]*[_a-zA-Z][a-zA-Z0-9_]*[\t\s]*\.[\t\s]*[_a-zA-Z][a-zA-Z0-9_]*'
+ QUOTED_PATTERN = '[\t\s]*L?"[^"]*"'
+ BOOL_PATTERN = '[\t\s]*(true|True|TRUE|false|False|FALSE)'
+ def __init__(self, Token):
+ self.Token = Token
+ self.Index = 0
+ self.Len = len(Token)
+
+ ## SkipWhitespace
+ #
+ def SkipWhitespace(self):
+ for Char in self.Token[self.Index:]:
+ if Char not in ' \t':
+ break
+ self.Index += 1
+
+ ## IsCurrentOp
+ #
+ # @param OpList: option list
+ #
+ def IsCurrentOp(self, OpList):
+ self.SkipWhitespace()
+ LetterOp = ["EQ", "NE", "GE", "LE", "GT", "LT", "NOT", "and", "AND",
+ "or", "OR", "XOR"]
+ OpMap = {
+ '|' : '|',
+ '&' : '&',
+ '!' : '=',
+ '>' : '=',
+ '<' : '='
+ }
+
+ for Operator in OpList:
+ if not self.Token[self.Index:].startswith(Operator):
+ continue
+
+ self.Index += len(Operator)
+ Char = self.Token[self.Index : self.Index + 1]
+
+ if (Operator in LetterOp and (Char == '_' or Char.isalnum())) \
+ or (Operator in OpMap and OpMap[Operator] == Char):
+ self.Index -= len(Operator)
+ break
+
+ return True
+
+ return False
+
+## _LogicalExpressionParser
+#
+# @param _ExprBase: _ExprBase object
+#
+class _LogicalExpressionParser(_ExprBase):
+ #
+ # STRINGITEM can only be logical field according to spec
+ #
+ STRINGITEM = -1
+
+ #
+ # Evaluate to True or False
+ #
+ LOGICAL = 0
+ REALLOGICAL = 2
+
+ #
+ # Just arithmetic expression
+ #
+ ARITH = 1
+
+ def __init__(self, Token):
+ _ExprBase.__init__(self, Token)
+ self.Parens = 0
+
+ def _CheckToken(self, MatchList):
+ for Match in MatchList:
+ if Match and Match.start() == 0:
+ if not _ValidateToken(
+ self.Token[self.Index:self.Index+Match.end()]
+ ):
+ return False
+
+ self.Index += Match.end()
+ if self.Token[self.Index - 1] == '"':
+ return True
+ if self.Token[self.Index:self.Index+1] == '_' or \
+ self.Token[self.Index:self.Index+1].isalnum():
+ self.Index -= Match.end()
+ return False
+
+ Token = self.Token[self.Index - Match.end():self.Index]
+ if Token.strip() in ["EQ", "NE", "GE", "LE", "GT", "LT",
+ "NOT", "and", "AND", "or", "OR", "XOR"]:
+ self.Index -= Match.end()
+ return False
+
+ return True
+
+ return False
+
+ def IsAtomicNumVal(self):
+ #
+ # Hex number
+ #
+ Match1 = re.compile(self.HEX_PATTERN).match(self.Token[self.Index:])
+
+ #
+ # Number
+ #
+ Match2 = re.compile(self.INT_PATTERN).match(self.Token[self.Index:])
+
+ #
+ # Macro
+ #
+ Match3 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:])
+
+ #
+ # PcdName
+ #
+ Match4 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:])
+
+ return self._CheckToken([Match1, Match2, Match3, Match4])
+
+
+ def IsAtomicItem(self):
+ #
+ # Macro
+ #
+ Match1 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:])
+
+ #
+ # PcdName
+ #
+ Match2 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:])
+
+ #
+ # Quoted string
+ #
+ Match3 = re.compile(self.QUOTED_PATTERN).\
+ match(self.Token[self.Index:].replace('\\\\', '//').\
+ replace('\\\"', '\\\''))
+
+ return self._CheckToken([Match1, Match2, Match3])
+
+ ## A || B
+ #
+ def LogicalExpression(self):
+ Ret = self.SpecNot()
+ while self.IsCurrentOp(['||', 'OR', 'or', '&&', 'AND', 'and', 'XOR', 'xor', '^']):
+ if self.Token[self.Index-1] == '|' and self.Parens <= 0:
+ raise _ExprError(ST.ERR_EXPR_OR % self.Token)
+ if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
+ raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
+ Ret = self.SpecNot()
+ if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
+ raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
+ Ret = self.REALLOGICAL
+ return Ret
+
+ def SpecNot(self):
+ if self.IsCurrentOp(["NOT", "!", "not"]):
+ return self.SpecNot()
+ return self.Rel()
+
+ ## A < B, A > B, A <= B, A >= B
+ #
+ def Rel(self):
+ Ret = self.Expr()
+ if self.IsCurrentOp(["<=", ">=", ">", "<", "GT", "LT", "GE", "LE",
+ "==", "EQ", "!=", "NE"]):
+ if Ret == self.STRINGITEM:
+ raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
+ Ret = self.Expr()
+ if Ret == self.REALLOGICAL:
+ raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
+ Ret = self.REALLOGICAL
+ return Ret
+
+ ## A + B, A - B
+ #
+ def Expr(self):
+ Ret = self.Factor()
+ while self.IsCurrentOp(["+", "-", "&", "|", "^", "XOR", "xor"]):
+ if self.Token[self.Index-1] == '|' and self.Parens <= 0:
+ raise _ExprError(ST.ERR_EXPR_OR)
+ if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:
+ raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
+ Ret = self.Factor()
+ if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:
+ raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)
+ Ret = self.ARITH
+ return Ret
+
+ ## Factor
+ #
+ def Factor(self):
+ if self.IsCurrentOp(["("]):
+ self.Parens += 1
+ Ret = self.LogicalExpression()
+ if not self.IsCurrentOp([")"]):
+ raise _ExprError(ST.ERR_EXPR_RIGHT_PAREN % \
+ (self.Token, self.Token[self.Index:]))
+ self.Parens -= 1
+ return Ret
+
+ if self.IsAtomicItem():
+ if self.Token[self.Index - 1] == '"':
+ return self.STRINGITEM
+ return self.LOGICAL
+ elif self.IsAtomicNumVal():
+ return self.ARITH
+ else:
+ raise _ExprError(ST.ERR_EXPR_FACTOR % \
+ (self.Token[self.Index:], self.Token))
+
+ ## IsValidLogicalExpression
+ #
+ def IsValidLogicalExpression(self):
+ if self.Len == 0:
+ return False, ST.ERR_EXPRESS_EMPTY
+ try:
+ if self.LogicalExpression() not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:
+ return False, ST.ERR_EXPR_LOGICAL % self.Token
+ except _ExprError as XExcept:
+ return False, XExcept.Error
+ self.SkipWhitespace()
+ if self.Index != self.Len:
+ return False, (ST.ERR_EXPR_BOOLEAN % \
+ (self.Token[self.Index:], self.Token))
+ return True, ''
+
+## _ValidRangeExpressionParser
+#
+class _ValidRangeExpressionParser(_ExprBase):
+ INT_RANGE_PATTERN = '[\t\s]*[0-9]+[\t\s]*-[\t\s]*[0-9]+'
+ HEX_RANGE_PATTERN = \
+ '[\t\s]*0[xX][a-fA-F0-9]+[\t\s]*-[\t\s]*0[xX][a-fA-F0-9]+'
+ def __init__(self, Token):
+ _ExprBase.__init__(self, Token)
+ self.Parens = 0
+ self.HEX = 1
+ self.INT = 2
+ self.IsParenHappen = False
+ self.IsLogicalOpHappen = False
+
+ ## IsValidRangeExpression
+ #
+ def IsValidRangeExpression(self):
+ if self.Len == 0:
+ return False, ST.ERR_EXPR_RANGE_EMPTY
+ try:
+ if self.RangeExpression() not in [self.HEX, self.INT]:
+ return False, ST.ERR_EXPR_RANGE % self.Token
+ except _ExprError as XExcept:
+ return False, XExcept.Error
+
+ self.SkipWhitespace()
+ if self.Index != self.Len:
+ return False, (ST.ERR_EXPR_RANGE % self.Token)
+ return True, ''
+
+ ## RangeExpression
+ #
+ def RangeExpression(self):
+ Ret = self.Unary()
+ while self.IsCurrentOp(['OR', 'AND', 'and', 'or']):
+ self.IsLogicalOpHappen = True
+ if not self.IsParenHappen:
+ raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token)
+ self.IsParenHappen = False
+ Ret = self.Unary()
+
+ if self.IsCurrentOp(['XOR']):
+ Ret = self.Unary()
+
+ return Ret
+
+ ## Unary
+ #
+ def Unary(self):
+ if self.IsCurrentOp(["NOT"]):
+ return self.Unary()
+
+ return self.ValidRange()
+
+ ## ValidRange
+ #
+ def ValidRange(self):
+ Ret = -1
+ if self.IsCurrentOp(["("]):
+ self.IsLogicalOpHappen = False
+ self.IsParenHappen = True
+ self.Parens += 1
+ if self.Parens > 1:
+ raise _ExprError(ST.ERR_EXPR_RANGE_DOUBLE_PAREN_NESTED % self.Token)
+ Ret = self.RangeExpression()
+ if not self.IsCurrentOp([")"]):
+ raise _ExprError(ST.ERR_EXPR_RIGHT_PAREN % self.Token)
+ self.Parens -= 1
+ return Ret
+
+ if self.IsLogicalOpHappen:
+ raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token)
+
+ if self.IsCurrentOp(["LT", "GT", "LE", "GE", "EQ", "XOR"]):
+ IntMatch = \
+ re.compile(self.INT_PATTERN).match(self.Token[self.Index:])
+ HexMatch = \
+ re.compile(self.HEX_PATTERN).match(self.Token[self.Index:])
+ if HexMatch and HexMatch.start() == 0:
+ self.Index += HexMatch.end()
+ Ret = self.HEX
+ elif IntMatch and IntMatch.start() == 0:
+ self.Index += IntMatch.end()
+ Ret = self.INT
+ else:
+ raise _ExprError(ST.ERR_EXPR_RANGE_FACTOR % (self.Token[self.Index:], self.Token))
+ else:
+ IntRangeMatch = re.compile(
+ self.INT_RANGE_PATTERN).match(self.Token[self.Index:]
+ )
+ HexRangeMatch = re.compile(
+ self.HEX_RANGE_PATTERN).match(self.Token[self.Index:]
+ )
+ if HexRangeMatch and HexRangeMatch.start() == 0:
+ self.Index += HexRangeMatch.end()
+ Ret = self.HEX
+ elif IntRangeMatch and IntRangeMatch.start() == 0:
+ self.Index += IntRangeMatch.end()
+ Ret = self.INT
+ else:
+ raise _ExprError(ST.ERR_EXPR_RANGE % self.Token)
+
+ return Ret
+
+## _ValidListExpressionParser
+#
+class _ValidListExpressionParser(_ExprBase):
+ VALID_LIST_PATTERN = '(0[xX][0-9a-fA-F]+|[0-9]+)([\t\s]*,[\t\s]*(0[xX][0-9a-fA-F]+|[0-9]+))*'
+ def __init__(self, Token):
+ _ExprBase.__init__(self, Token)
+ self.NUM = 1
+
+ def IsValidListExpression(self):
+ if self.Len == 0:
+ return False, ST.ERR_EXPR_LIST_EMPTY
+ try:
+ if self.ListExpression() not in [self.NUM]:
+ return False, ST.ERR_EXPR_LIST % self.Token
+ except _ExprError as XExcept:
+ return False, XExcept.Error
+
+ self.SkipWhitespace()
+ if self.Index != self.Len:
+ return False, (ST.ERR_EXPR_LIST % self.Token)
+
+ return True, ''
+
+ def ListExpression(self):
+ Ret = -1
+ self.SkipWhitespace()
+ ListMatch = re.compile(self.VALID_LIST_PATTERN).match(self.Token[self.Index:])
+ if ListMatch and ListMatch.start() == 0:
+ self.Index += ListMatch.end()
+ Ret = self.NUM
+ else:
+ raise _ExprError(ST.ERR_EXPR_LIST % self.Token)
+
+ return Ret
+
+## _StringTestParser
+#
+class _StringTestParser(_ExprBase):
+ def __init__(self, Token):
+ _ExprBase.__init__(self, Token)
+
+ ## IsValidStringTest
+ #
+ def IsValidStringTest(self):
+ if self.Len == 0:
+ return False, ST.ERR_EXPR_EMPTY
+ try:
+ self.StringTest()
+ except _ExprError as XExcept:
+ return False, XExcept.Error
+ return True, ''
+
+ ## StringItem
+ #
+ def StringItem(self):
+ Match1 = re.compile(self.QUOTED_PATTERN)\
+ .match(self.Token[self.Index:].replace('\\\\', '//')\
+ .replace('\\\"', '\\\''))
+ Match2 = re.compile(self.MACRO_PATTERN).match(self.Token[self.Index:])
+ Match3 = re.compile(self.PCD_PATTERN).match(self.Token[self.Index:])
+ MatchList = [Match1, Match2, Match3]
+ for Match in MatchList:
+ if Match and Match.start() == 0:
+ if not _ValidateToken(
+ self.Token[self.Index:self.Index+Match.end()]
+ ):
+ raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \
+ (self.Token, self.Token[self.Index:]))
+ self.Index += Match.end()
+ Token = self.Token[self.Index - Match.end():self.Index]
+ if Token.strip() in ["EQ", "NE"]:
+ raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \
+ (self.Token, self.Token[self.Index:]))
+ return
+ else:
+ raise _ExprError(ST.ERR_EXPR_STRING_ITEM % \
+ (self.Token, self.Token[self.Index:]))
+
+ ## StringTest
+ #
+ def StringTest(self):
+ self.StringItem()
+ if not self.IsCurrentOp(["==", "EQ", "!=", "NE"]):
+ raise _ExprError(ST.ERR_EXPR_EQUALITY % \
+ (self.Token[self.Index:], self.Token))
+ self.StringItem()
+ if self.Index != self.Len:
+ raise _ExprError(ST.ERR_EXPR_BOOLEAN % \
+ (self.Token[self.Index:], self.Token))
+
+##
+# Check syntax of string test
+#
+# @param Token: string test token
+#
+def IsValidStringTest(Token, Flag=False):
+ #
+ # Not do the check right now, keep the implementation for future enhancement.
+ #
+ if not Flag:
+ return True, ""
+ return _StringTestParser(Token).IsValidStringTest()
+
+
+##
+# Check syntax of logical expression
+#
+# @param Token: expression token
+#
+def IsValidLogicalExpr(Token, Flag=False):
+ #
+ # Not do the check right now, keep the implementation for future enhancement.
+ #
+ if not Flag:
+ return True, ""
+ return _LogicalExpressionParser(Token).IsValidLogicalExpression()
+
+##
+# Check syntax of range expression
+#
+# @param Token: range expression token
+#
+def IsValidRangeExpr(Token):
+ return _ValidRangeExpressionParser(Token).IsValidRangeExpression()
+
+##
+# Check syntax of value list expression token
+#
+# @param Token: value list expression token
+#
+def IsValidListExpr(Token):
+ return _ValidListExpressionParser(Token).IsValidListExpression()
+
+##
+# Check whether the feature flag expression is valid or not
+#
+# @param Token: feature flag expression
+#
+def IsValidFeatureFlagExp(Token, Flag=False):
+ #
+ # Not do the check right now, keep the implementation for future enhancement.
+ #
+ if not Flag:
+ return True, "", Token
+ else:
+ if Token in ['TRUE', 'FALSE', 'true', 'false', 'True', 'False',
+ '0x1', '0x01', '0x0', '0x00']:
+ return True, ""
+ Valid, Cause = IsValidStringTest(Token, Flag)
+ if not Valid:
+ Valid, Cause = IsValidLogicalExpr(Token, Flag)
+ if not Valid:
+ return False, Cause
+ return True, ""
+
+if __name__ == '__main__':
+# print IsValidRangeExpr('LT 9')
+ print(_LogicalExpressionParser('gCrownBayTokenSpaceGuid.PcdPciDevice1BridgeAddressLE0').IsValidLogicalExpression())
+
+
+