## @file\r
# This file is used to check PCD logical expression\r
#\r
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>\r
#\r
# This program and the accompanying materials are licensed and made available \r
# under the terms and conditions of the BSD License which accompanies this \r
'>' : '=',\r
'<' : '='\r
}\r
+ \r
for Operator in OpList:\r
if not self.Token[self.Index:].startswith(Operator):\r
continue\r
+ \r
self.Index += len(Operator)\r
Char = self.Token[self.Index : self.Index + 1]\r
+\r
if (Operator in LetterOp and (Char == '_' or Char.isalnum())) \\r
or (Operator in OpMap and OpMap[Operator] == Char):\r
self.Index -= len(Operator)\r
break\r
+ \r
return True\r
+ \r
return False\r
\r
## _LogicalExpressionParser\r
return False\r
\r
return True\r
+ \r
return False\r
\r
def IsAtomicNumVal(self):\r
#\r
def LogicalExpression(self):\r
Ret = self.SpecNot()\r
- while self.IsCurrentOp(['||', 'OR', 'or', '&&', 'AND', 'and', 'XOR']):\r
+ while self.IsCurrentOp(['||', 'OR', 'or', '&&', 'AND', 'and', 'XOR', 'xor', '^']):\r
if self.Token[self.Index-1] == '|' and self.Parens <= 0:\r
- raise _ExprError(ST.ERR_EXPR_OR)\r
- if Ret == self.ARITH:\r
+ raise _ExprError(ST.ERR_EXPR_OR % self.Token)\r
+ if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:\r
raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)\r
Ret = self.SpecNot()\r
- if Ret == self.ARITH:\r
+ if Ret not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:\r
raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)\r
Ret = self.REALLOGICAL\r
return Ret\r
\r
def SpecNot(self):\r
- if self.IsCurrentOp(["NOT", "!"]):\r
+ if self.IsCurrentOp(["NOT", "!", "not"]):\r
return self.SpecNot()\r
return self.Rel()\r
\r
- ## A < B, A > B, A <= B, A >= b\r
+ ## A < B, A > B, A <= B, A >= B\r
#\r
def Rel(self):\r
Ret = self.Expr()\r
if self.IsCurrentOp(["<=", ">=", ">", "<", "GT", "LT", "GE", "LE",\r
"==", "EQ", "!=", "NE"]):\r
- if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:\r
+ if Ret == self.STRINGITEM:\r
raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)\r
Ret = self.Expr()\r
- if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:\r
+ if Ret == self.REALLOGICAL:\r
raise _ExprError(ST.ERR_EXPR_LOGICAL % self.Token)\r
Ret = self.REALLOGICAL\r
return Ret\r
#\r
def Expr(self):\r
Ret = self.Factor()\r
- while self.IsCurrentOp(["+", "-", "&", "|", "^"]):\r
+ while self.IsCurrentOp(["+", "-", "&", "|", "^", "XOR", "xor"]):\r
if self.Token[self.Index-1] == '|' and self.Parens <= 0:\r
raise _ExprError(ST.ERR_EXPR_OR)\r
if Ret == self.STRINGITEM or Ret == self.REALLOGICAL:\r
return self.ARITH\r
else:\r
raise _ExprError(ST.ERR_EXPR_FACTOR % \\r
- (self.Token, self.Token[self.Index:]))\r
+ (self.Token[self.Index:], self.Token))\r
\r
## IsValidLogicalExpression\r
#\r
def IsValidLogicalExpression(self):\r
if self.Len == 0:\r
- return False, ST.ERR_EXPR_EMPTY\r
+ return False, ST.ERR_EXPRESS_EMPTY\r
try:\r
- if self.LogicalExpression() == self.ARITH:\r
+ if self.LogicalExpression() not in [self.ARITH, self.LOGICAL, self.REALLOGICAL, self.STRINGITEM]:\r
return False, ST.ERR_EXPR_LOGICAL % self.Token\r
except _ExprError, XExcept:\r
return False, XExcept.Error\r
'[\t\s]*0[xX][a-fA-F0-9]+[\t\s]*-[\t\s]*0[xX][a-fA-F0-9]+'\r
def __init__(self, Token):\r
_ExprBase.__init__(self, Token)\r
+ self.Parens = 0\r
+ self.HEX = 1\r
+ self.INT = 2\r
+ self.IsParenHappen = False\r
+ self.IsLogicalOpHappen = False\r
\r
## IsValidRangeExpression\r
#\r
def IsValidRangeExpression(self):\r
if self.Len == 0:\r
- return False\r
+ return False, ST.ERR_EXPR_RANGE_EMPTY\r
try:\r
- self.RangeExpression()\r
- except _ExprError:\r
- return False\r
+ if self.RangeExpression() not in [self.HEX, self.INT]:\r
+ return False, ST.ERR_EXPR_RANGE % self.Token\r
+ except _ExprError, XExcept:\r
+ return False, XExcept.Error\r
+ \r
self.SkipWhitespace()\r
if self.Index != self.Len:\r
- return False\r
- return True\r
+ return False, (ST.ERR_EXPR_RANGE % self.Token)\r
+ return True, ''\r
\r
## RangeExpression\r
#\r
def RangeExpression(self):\r
- self.Unary()\r
- while self.IsCurrentOp(['OR', 'AND', 'XOR']):\r
- self.Unary()\r
+ Ret = self.Unary()\r
+ while self.IsCurrentOp(['OR', 'AND', 'and', 'or']):\r
+ self.IsLogicalOpHappen = True\r
+ if not self.IsParenHappen:\r
+ raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token)\r
+ self.IsParenHappen = False\r
+ Ret = self.Unary()\r
+ \r
+ if self.IsCurrentOp(['XOR']):\r
+ Ret = self.Unary()\r
+ \r
+ return Ret\r
\r
## Unary\r
#\r
def Unary(self):\r
- if self.IsCurrentOp(["NOT", "-"]):\r
+ if self.IsCurrentOp(["NOT"]):\r
return self.Unary()\r
+ \r
return self.ValidRange()\r
\r
## ValidRange\r
# \r
def ValidRange(self):\r
+ Ret = -1\r
if self.IsCurrentOp(["("]):\r
- self.RangeExpression()\r
+ self.IsLogicalOpHappen = False\r
+ self.IsParenHappen = True\r
+ self.Parens += 1\r
+ if self.Parens > 1:\r
+ raise _ExprError(ST.ERR_EXPR_RANGE_DOUBLE_PAREN_NESTED % self.Token)\r
+ Ret = self.RangeExpression()\r
if not self.IsCurrentOp([")"]):\r
- raise _ExprError('')\r
- return\r
+ raise _ExprError(ST.ERR_EXPR_RIGHT_PAREN % self.Token)\r
+ self.Parens -= 1\r
+ return Ret\r
+ \r
+ if self.IsLogicalOpHappen:\r
+ raise _ExprError(ST.ERR_PAREN_NOT_USED % self.Token)\r
\r
- if self.IsCurrentOp(["LT", "GT", "LE", "GE", "EQ"]):\r
+ if self.IsCurrentOp(["LT", "GT", "LE", "GE", "EQ", "XOR"]):\r
IntMatch = \\r
re.compile(self.INT_PATTERN).match(self.Token[self.Index:])\r
HexMatch = \\r
re.compile(self.HEX_PATTERN).match(self.Token[self.Index:])\r
if HexMatch and HexMatch.start() == 0:\r
self.Index += HexMatch.end()\r
+ Ret = self.HEX\r
elif IntMatch and IntMatch.start() == 0:\r
self.Index += IntMatch.end()\r
+ Ret = self.INT\r
else:\r
- raise _ExprError('')\r
+ raise _ExprError(ST.ERR_EXPR_RANGE_FACTOR % (self.Token[self.Index:], self.Token))\r
else:\r
IntRangeMatch = re.compile(\r
self.INT_RANGE_PATTERN).match(self.Token[self.Index:]\r
)\r
if HexRangeMatch and HexRangeMatch.start() == 0:\r
self.Index += HexRangeMatch.end()\r
+ Ret = self.HEX\r
elif IntRangeMatch and IntRangeMatch.start() == 0:\r
self.Index += IntRangeMatch.end()\r
+ Ret = self.INT\r
else:\r
- raise _ExprError('')\r
+ raise _ExprError(ST.ERR_EXPR_RANGE % self.Token)\r
+\r
+ return Ret\r
+\r
+## _ValidListExpressionParser\r
+#\r
+class _ValidListExpressionParser(_ExprBase):\r
+ VALID_LIST_PATTERN = '(0[xX][0-9a-fA-F]+|[0-9]+)([\t\s]*,[\t\s]*(0[xX][0-9a-fA-F]+|[0-9]+))*'\r
+ def __init__(self, Token):\r
+ _ExprBase.__init__(self, Token)\r
+ self.NUM = 1\r
\r
- if self.Token[self.Index:self.Index+1] == '_' or \\r
- self.Token[self.Index:self.Index+1].isalnum():\r
- raise _ExprError('')\r
+ def IsValidListExpression(self):\r
+ if self.Len == 0:\r
+ return False, ST.ERR_EXPR_LIST_EMPTY\r
+ try:\r
+ if self.ListExpression() not in [self.NUM]:\r
+ return False, ST.ERR_EXPR_LIST % self.Token\r
+ except _ExprError, XExcept:\r
+ return False, XExcept.Error\r
\r
+ self.SkipWhitespace()\r
+ if self.Index != self.Len:\r
+ return False, (ST.ERR_EXPR_LIST % self.Token)\r
+\r
+ return True, ''\r
+ \r
+ def ListExpression(self):\r
+ Ret = -1\r
+ self.SkipWhitespace()\r
+ ListMatch = re.compile(self.VALID_LIST_PATTERN).match(self.Token[self.Index:])\r
+ if ListMatch and ListMatch.start() == 0:\r
+ self.Index += ListMatch.end()\r
+ Ret = self.NUM\r
+ else:\r
+ raise _ExprError(ST.ERR_EXPR_LIST % self.Token)\r
+\r
+ return Ret\r
+ \r
## _StringTestParser\r
#\r
class _StringTestParser(_ExprBase):\r
self.StringItem()\r
if not self.IsCurrentOp(["==", "EQ", "!=", "NE"]):\r
raise _ExprError(ST.ERR_EXPR_EQUALITY % \\r
- (self.Token, self.Token[self.Index:]))\r
+ (self.Token[self.Index:], self.Token))\r
self.StringItem()\r
if self.Index != self.Len:\r
raise _ExprError(ST.ERR_EXPR_BOOLEAN % \\r
(self.Token[self.Index:], self.Token))\r
\r
##\r
-# Check syntax of logical expression\r
+# Check syntax of string test\r
#\r
-# @param Token: expression token\r
+# @param Token: string test token\r
#\r
-def IsValidLogicalExpr(Token, Flag=False):\r
+def IsValidStringTest(Token, Flag=False):\r
#\r
# Not do the check right now, keep the implementation for future enhancement.\r
#\r
if not Flag:\r
return True, ""\r
- return _LogicalExpressionParser(Token).IsValidLogicalExpression()\r
+ return _StringTestParser(Token).IsValidStringTest()\r
+\r
\r
##\r
-# Check syntax of string test\r
+# Check syntax of logical expression\r
#\r
-# @param Token: string test token\r
+# @param Token: expression token\r
#\r
-def IsValidStringTest(Token, Flag=False):\r
+def IsValidLogicalExpr(Token, Flag=False):\r
#\r
# Not do the check right now, keep the implementation for future enhancement.\r
#\r
if not Flag:\r
return True, ""\r
- return _StringTestParser(Token).IsValidStringTest()\r
+ return _LogicalExpressionParser(Token).IsValidLogicalExpression()\r
\r
##\r
# Check syntax of range expression\r
def IsValidRangeExpr(Token):\r
return _ValidRangeExpressionParser(Token).IsValidRangeExpression()\r
\r
+##\r
+# Check syntax of value list expression token\r
+#\r
+# @param Token: value list expression token \r
+#\r
+def IsValidListExpr(Token):\r
+ return _ValidListExpressionParser(Token).IsValidListExpression()\r
+\r
##\r
# Check whether the feature flag expression is valid or not\r
#\r
return True, ""\r
\r
if __name__ == '__main__':\r
- print _LogicalExpressionParser('a ^ b > a + b').IsValidLogicalExpression()\r
+# print IsValidRangeExpr('LT 9')\r
+ print _LogicalExpressionParser('gCrownBayTokenSpaceGuid.PcdPciDevice1BridgeAddressLE0').IsValidLogicalExpression()\r
+\r
+\r
+ \r