sourcedr: Add integer support to check_vndk_dep

Test: ./run_tests.py
Change-Id: I7b8d3aace8edecf1d6edcb30afbdfc718785e50e
This commit is contained in:
Logan Chien
2018-02-26 18:39:28 +08:00
parent 3a449be4e2
commit 249b75cd54
2 changed files with 127 additions and 8 deletions

View File

@@ -108,9 +108,10 @@ class Token(Enum): # pylint: disable=too-few-public-methods
PLUS = 11
COMMA = 12
STRING = 13
INTEGER = 14
COMMENT = 14
SPACE = 15
COMMENT = 15
SPACE = 16
class LexerError(ValueError):
@@ -330,6 +331,7 @@ class Lexer(object):
(Token.PLUS, '\\+'),
(Token.COMMA, ','),
(Token.STRING, '["`]'),
(Token.INTEGER, '-{0,1}[0-9]+'),
(Token.COMMENT,
'/(?:(?:/[^\\n]*)|(?:\\*(?:(?:[^*]*)|(?:\\*+[^/*]))*\\*+/))'),
@@ -364,7 +366,10 @@ class Lexer(object):
end, literal = cls.lex_string(buf, offset)
else:
end = match.end()
literal = buf[offset:end] if token == Token.IDENT else None
if token in {Token.IDENT, Token.INTEGER}:
literal = buf[offset:end]
else:
literal = None
return (token, end, literal)
@@ -427,6 +432,49 @@ class Bool(Expr): # pylint: disable=too-few-public-methods
return self
class Integer(Expr): # pylint: disable=too-few-public-methods
"""Integer constant literal."""
__slots__ = ('value',)
def __init__(self, value):
"""Create an integer constant literal."""
self.value = value
def __repr__(self):
"""Convert an integer constant literal to string representation."""
return repr(self.value)
def __bool__(self):
"""Convert an integer constant literal to Python bool type."""
return bool(self.value)
__nonzero__ = __bool__
def __int__(self):
"""Convert an integer constant literal to Python int type."""
return self.value
def __eq__(self, rhs):
"""Compare whether two instances are equal."""
return self.value == rhs.value
def __hash__(self):
"""Compute the hashed value."""
return hash(self.value)
def eval(self, env):
"""Evaluate the integer expression under an environment."""
return self
class VarRef(Expr): # pylint: disable=too-few-public-methods
"""A reference to a variable."""
@@ -472,13 +520,13 @@ class Dict(Expr, collections.OrderedDict):
class Concat(Expr): # pylint: disable=too-few-public-methods
"""List/string concatenation operator."""
"""List/string/integer plus operator."""
__slots__ = ('lhs', 'rhs')
def __init__(self, lhs, rhs):
"""Create a list concatenation expression."""
"""Create a list/string/integer plus expression."""
self.lhs = lhs
self.rhs = rhs
@@ -488,14 +536,16 @@ class Concat(Expr): # pylint: disable=too-few-public-methods
def eval(self, env):
"""Evaluate list concatenation operator under an environment."""
"""Evaluate list/string/integer plus operator under an environment."""
lhs = self.lhs.eval(env)
rhs = self.rhs.eval(env)
if isinstance(lhs, List) and isinstance(rhs, List):
return List(itertools.chain(lhs, rhs))
if isinstance(lhs, String) and isinstance(rhs, String):
return String(lhs + rhs)
raise TypeError('bad concatenation')
if isinstance(lhs, Integer) and isinstance(rhs, Integer):
return Integer(int(lhs) + int(rhs))
raise TypeError('bad plus operands')
#------------------------------------------------------------------------------
@@ -608,6 +658,14 @@ class Parser(object):
return string
def parse_integer(self):
"""Parse an integer."""
lexer = self.lexer
integer = Integer(int(lexer.literal))
lexer.consume(Token.INTEGER)
return integer
def parse_operand(self):
"""Parse an operand."""
lexer = self.lexer
@@ -616,6 +674,8 @@ class Parser(object):
return self.parse_string()
if token == Token.IDENT:
return self.parse_ident_rvalue()
if token == Token.INTEGER:
return self.parse_integer()
if token == Token.LBRACKET:
return self.parse_list()
if token == Token.LBRACE:

View File

@@ -20,7 +20,7 @@
import unittest
from blueprint import Bool, Concat, Dict, Expr, List, String, VarRef
from blueprint import Bool, Concat, Dict, Expr, Integer, List, String, VarRef
#------------------------------------------------------------------------------
@@ -91,6 +91,65 @@ class BoolTest(unittest.TestCase):
self.assertEqual('True', repr(Bool(True)))
#------------------------------------------------------------------------------
# Integer
#------------------------------------------------------------------------------
class IntegerTest(unittest.TestCase):
"""Unit tests for the Integer class."""
def test_int(self):
"""Test Integer.__init__(), Integer.__bool__(), Integer.__int__(), and
Integer.eval() methods."""
expr = Integer(0)
self.assertFalse(bool(expr))
self.assertEqual(0, int(expr))
self.assertEqual(0, int(expr.eval({})))
expr = Integer(1)
self.assertTrue(bool(expr))
self.assertEqual(1, int(expr))
self.assertEqual(1, int(expr.eval({})))
expr = Integer(2)
self.assertTrue(bool(expr))
self.assertEqual(2, int(expr))
self.assertEqual(2, int(expr.eval({})))
def test_equal(self):
"""Test Integer.__eq__() method."""
expr_zero1 = Integer(0)
expr_zero2 = Integer(0)
expr_one1 = Integer(1)
expr_one2 = Integer(1)
self.assertIsNot(expr_zero1, expr_zero2)
self.assertEqual(expr_zero1, expr_zero2)
self.assertIsNot(expr_one1, expr_one2)
self.assertEqual(expr_one1, expr_one2)
def test_hash(self):
"""Test Integer.__hash__() method."""
expr_zero = Integer(0)
expr_one = Integer(1)
self.assertEqual(hash(Integer(False)), hash(expr_zero))
self.assertEqual(hash(Integer(True)), hash(expr_one))
def test_repr(self):
"""Test Integer.__repr__() method."""
self.assertEqual('0', repr(Integer(0)))
self.assertEqual('1', repr(Integer(1)))
#------------------------------------------------------------------------------
# String
#------------------------------------------------------------------------------