diff options
Diffstat (limited to 'BaseTools/Source/Python/UPT/Library/ExpressionValidate.py')
| -rw-r--r-- | BaseTools/Source/Python/UPT/Library/ExpressionValidate.py | 1134 |
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()) + + + |
