X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FExpression.py;h=8b112d50b39b0627b6e09b271902de2c0ed5a007;hp=e2889a8dd30e7e3ca9c1b80b74b1254e943b42df;hb=d0acc87a41d9aa25fe87eb096efa62afacd1f865;hpb=b7891584a58d5e5e26f35c0944cae5f03efd880b diff --git a/BaseTools/Source/Python/Common/Expression.py b/BaseTools/Source/Python/Common/Expression.py index e2889a8dd3..8b112d50b3 100644 --- a/BaseTools/Source/Python/Common/Expression.py +++ b/BaseTools/Source/Python/Common/Expression.py @@ -14,7 +14,6 @@ # from Common.GlobalData import * from CommonDataClass.Exceptions import BadExpression -from CommonDataClass.Exceptions import SymbolNotFound from CommonDataClass.Exceptions import WrnExpression from Misc import GuidStringToGuidStructureString @@ -36,6 +35,7 @@ ERR_RELCMP_STR_OTHERS = 'Operator taking Operand of string type and Boolean/Nu ERR_STRING_CMP = 'Unicode string and general string cannot be compared: [%s %s %s]' ERR_ARRAY_TOKEN = 'Bad C array or C format GUID token: [%s].' ERR_ARRAY_ELE = 'This must be HEX value for NList or Array: [%s].' +ERR_EMPTY_EXPR = 'Empty expression is not allowed.' ## SplitString # Split string to list according double quote @@ -133,7 +133,7 @@ class ValueExpression(object): @staticmethod def Eval(Operator, Oprand1, Oprand2 = None): WrnExp = None - + if Operator not in ["==", "!=", ">=", "<=", ">", "<", "in", "not in"] and \ (type(Oprand1) == type('') or type(Oprand2) == type('')): raise BadExpression(ERR_STRING_EXPR % Operator) @@ -166,13 +166,13 @@ class ValueExpression(object): raise WrnExp else: raise BadExpression(ERR_RELCMP_STR_OTHERS % Operator) - elif TypeDict[type(Oprand1)] != TypeDict[type(Oprand2)]: + elif TypeDict[type(Oprand1)] != TypeDict[type(Oprand2)]: if Operator in ["==", "!=", ">=", "<=", ">", "<"] and set((TypeDict[type(Oprand1)], TypeDict[type(Oprand2)])) == set((TypeDict[type(True)], TypeDict[type(0)])): # comparison between number and boolean is allowed pass - elif Operator in ['&', '|', '^', "&&", "||"] and set((TypeDict[type(Oprand1)], TypeDict[type(Oprand2)])) == set((TypeDict[type(True)], TypeDict[type(0)])): + elif Operator in ['&', '|', '^', "and", "or"] and set((TypeDict[type(Oprand1)], TypeDict[type(Oprand2)])) == set((TypeDict[type(True)], TypeDict[type(0)])): # bitwise and logical operation between number and boolean is allowed - pass + pass else: raise BadExpression(ERR_EXPR_TYPE) if type(Oprand1) == type('') and type(Oprand2) == type(''): @@ -198,7 +198,7 @@ class ValueExpression(object): Val = True else: Val = False - + if WrnExp: WrnExp.result = Val raise WrnExp @@ -216,8 +216,7 @@ class ValueExpression(object): ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH']) if not self._Expr.strip(): - self._NoProcess = True - return + raise BadExpression(ERR_EMPTY_EXPR) # # The symbol table including PCD and macro mapping @@ -227,25 +226,64 @@ class ValueExpression(object): self._Idx = 0 self._Len = len(self._Expr) self._Token = '' + self._WarnExcept = None # Literal token without any conversion self._LiteralToken = '' # Public entry for this class - def __call__(self): + # @param RealValue: False: only evaluate if the expression is true or false, used for conditional expression + # True : return the evaluated str(value), used for PCD value + # + # @return: True or False if RealValue is False + # Evaluated value of string format if RealValue is True + # + def __call__(self, RealValue=False): if self._NoProcess: return self._Expr + self._Expr = self._Expr.strip() + if RealValue: + self._Token = self._Expr + if self.__IsNumberToken(): + return self._Expr + + Token = self._GetToken() + if type(Token) == type('') and Token.startswith('{') and Token.endswith('}') and self._Idx >= self._Len: + return self._Expr + + self._Idx = 0 + self._Token = '' + Val = self._OrExpr() - if type(Val) == type('') and Val == 'L""': - Val = '' + RealVal = Val + if type(Val) == type(''): + if Val == 'L""': + Val = False + elif not Val: + Val = False + RealVal = '""' + elif not Val.startswith('L"') and not Val.startswith('{'): + Val = True + RealVal = '"' + RealVal + '"' # The expression has been parsed, but the end of expression is not reached # It means the rest does not comply EBNF of if self._Idx != self._Len: raise BadExpression(ERR_SNYTAX % self._Expr[self._Idx:]) - return Val + if RealValue: + RetVal = str(RealVal) + elif Val: + RetVal = True + else: + RetVal = False + + if self._WarnExcept: + self._WarnExcept.result = RetVal + raise self._WarnExcept + else: + return RetVal # Template function to parse binary operators which have same precedence # Expr [Operator Expr]* @@ -253,7 +291,11 @@ class ValueExpression(object): Val = EvalFunc() while self._IsOperator(OpLst): Op = self._Token - Val = self.Eval(Op, Val, EvalFunc()) + try: + Val = self.Eval(Op, Val, EvalFunc()) + except WrnExpression, Warn: + self._WarnExcept = Warn + Val = Warn.result return Val # A [|| B]* @@ -285,7 +327,11 @@ class ValueExpression(object): if not self._IsOperator(["IN", "in"]): raise BadExpression(ERR_REL_NOT_IN) Op += ' ' + self._Token - Val = self.Eval(Op, Val, self._RelExpr()) + try: + Val = self.Eval(Op, Val, self._RelExpr()) + except WrnExpression, Warn: + self._WarnExcept = Warn + Val = Warn.result return Val # A [ > B]* @@ -300,7 +346,11 @@ class ValueExpression(object): def _UnaryExpr(self): if self._IsOperator(["!", "NOT", "not"]): Val = self._UnaryExpr() - return self.Eval('not', Val) + try: + return self.Eval('not', Val) + except WrnExpression, Warn: + self._WarnExcept = Warn + return Warn.result return self._IdenExpr() # Parse identifier or encapsulated expression @@ -407,8 +457,8 @@ class ValueExpression(object): # PCD token if self.PcdPattern.match(self._Token): if self._Token not in self._Symb: - raise SymbolNotFound(ERR_PCD_RESOLVE % self._Token) - self._Token = ValueExpression(self._Symb[self._Token], self._Symb)() + raise BadExpression(ERR_PCD_RESOLVE % self._Token) + self._Token = ValueExpression(self._Symb[self._Token], self._Symb)(True) if type(self._Token) != type(''): self._LiteralToken = hex(self._Token) return @@ -459,7 +509,7 @@ class ValueExpression(object): if not Token: self._LiteralToken = '0x0' else: - self._LiteralToken = '0x' + Token + self._LiteralToken = '0x' + Token.lower() return True return False @@ -488,7 +538,7 @@ class ValueExpression(object): if Match and not Expr[Match.end():Match.end()+1].isalnum() \ and Expr[Match.end():Match.end()+1] != '_': self._Idx += Match.end() - self._Token = ValueExpression(GuidStringToGuidStructureString(Expr[0:Match.end()]))() + self._Token = ValueExpression(GuidStringToGuidStructureString(Expr[0:Match.end()]))(True) return self._Token elif self.__IsIdChar(Ch): return self.__GetIdToken() @@ -526,7 +576,7 @@ class ValueExpression(object): OpToken = '' for Ch in Expr: if Ch in self.NonLetterOpLst: - if '!' == Ch and OpToken in ['!=', '!']: + if '!' == Ch and OpToken: break self._Idx += 1 OpToken += Ch @@ -551,5 +601,15 @@ class ValueExpression(object): if __name__ == '__main__': pass - - + while True: + input = raw_input('Input expr: ') + if input in 'qQ': + break + try: + print ValueExpression(input)(True) + print ValueExpression(input)(False) + except WrnExpression, Ex: + print Ex.result + print str(Ex) + except Exception, Ex: + print str(Ex)