def test_keep_parentheses_in_nested_expression(self): evaluator = ( macro_expression_evaluator_visitor.MacroExpressionEvaluatorVisitor( object_likes=self.object_likes, function_likes=self.function_likes, functions=self.functions, lazy_functions=self.lazy_functions, keep_parentheses=True, ) ) self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CNumber(42), string_replacement='42', ), 'bar': pre_ast.DefineObjectLike( name='bar', replacement=c_ast.CNumber(33), string_replacement='33', ), }) expression = c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('foo'), closer=')', ) actual = evaluator.evaluate(expression) expected = c_ast.CNestedExpression( opener='(', content=c_ast.CNumber(42), closer=')', ) self.assertEqual(actual, expected)
def test_parse_unary_operator_on_expression_in_parentheses(self): source = '!(x > 0 || y == 0)' expected = c_ast.CFunctionCall( function_name='!', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='||', arguments=[ c_ast.CFunctionCall( function_name='>', arguments=[ c_ast.CVariable('x'), c_ast.CNumber(0), ], ), c_ast.CFunctionCall( function_name='==', arguments=[ c_ast.CVariable('y'), c_ast.CNumber(0), ], ), ], ), closer=')', ), ], ) actual = self.parser.parseString(source, parseAll=True) self.assertEqual(actual.asList(), [expected])
def test_multiplication_in_parentheses_and_binary_minus(self): # This is tricky because it's not a cast and an unary minus. # To fully distinguish those cases we would need to know what identifiers # are types and what identifiers are variables, e.g. # (x) - y # depends on the meaning of x. If x is a type then it can be a cast and # an unary minus, if x is a variable then it is a binary minus. source = '(a * b) - c' actual = self.parser.parseString(source, parseAll=True) expected = c_ast.CFunctionCall( function_name='-', arguments=[ c_ast.CNestedExpression(opener='(', content=c_ast.CFunctionCall( function_name='*', arguments=[ c_ast.CVariable('a'), c_ast.CVariable('b'), ], ), closer=')'), c_ast.CVariable('c'), ], ) self.assertEqual(actual.asList(), [expected])
def test_visit_nested_expression(self): expression = c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('a'), closer=')', ) actual = self.expression_evaluator.evaluate(expression) self.assertEqual(actual, 'b')
def test_parse_variable_in_parentheses(self): source = '(x)' expected = c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('x'), closer=')', ) actual = self.parser.parseString(source, parseAll=True) self.assertEqual(actual.asList(), [expected])
def test_str(self): nested_expression = c_ast.CNestedExpression( opener='(', content=42, closer='}', ) actual = str(nested_expression) expected = '(42}' self.assertEqual(actual, expected)
def test_parse_complex_parentheses_expression(self): source = '(((x) + (y)) & ~(y))' actual = self.parser.parseString(source, parseAll=True) expected = c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='&', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='+', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('x'), closer=')', ), c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('y'), closer=')', ), ], ), closer=')', ), c_ast.CFunctionCall( function_name='~', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('y'), closer=')', ), ], ), ], ), closer=')', ) self.assertEqual(actual.asList(), [expected])
def test_parse_attribute(self): source = '__attribute__((x))' expected = c_ast.CFunctionCall( function_name='__attribute__', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('x'), closer=')', ), ], ) actual = self.parser.parseString(source, parseAll=True) self.assertEqual(actual.asList(), [expected])
def test_unary_operator_and_parentheses(self): source = '-(33)' expected = c_ast.CFunctionCall( function_name='-', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CNumber(33), closer=')', ), ], ) actual = self.parser.parseString(source, parseAll=True) self.assertEqual(actual.asList(), [expected])
def test_parse_parentheses_and_binary_plus(self): source = '(a) + b' actual = self.parser.parseString(source, parseAll=True) expected = c_ast.CFunctionCall( function_name='+', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('a'), closer=')', ), c_ast.CVariable('b'), ], ) self.assertEqual(actual.asList(), [expected])
def test_parse_define_object_like_with_parentheses_expression(self): source = '#define foo (bar)' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('bar'), closer=')', ), string_replacement=' (bar)', ), ]), ) self.assertEqual(actual, expected)
def test_parse_offsetof_expression_with_additional_parentheses(self): source = '(((size_t)&((struct raw_spinlock *)0)->dep_map))' actual = self.parser.parseString(source, parseAll=True) expected = c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='offsetof', arguments=[ c_ast.CLiteral('struct raw_spinlock'), c_ast.CLiteral('dep_map'), ], ), closer=')', ) self.assertEqual(actual.asList(), [expected])
def visit_c_nested_expression( self, nested_expression, arguments, currently_evaluating, ): evaluated_content = self.evaluate( nested_expression.content, arguments, currently_evaluating, ) if self._keep_parentheses: return c_ast.CNestedExpression( opener=nested_expression.opener, content=evaluated_content, closer=nested_expression.closer, ) else: return evaluated_content
def test_parse_comparison_and_shift_with_parentheses_on_right(self): source = 'x < (1 << 14)' expected = c_ast.CFunctionCall( function_name='<', arguments=[ c_ast.CVariable('x'), c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall(function_name='<<', arguments=[ c_ast.CNumber(1), c_ast.CNumber(14), ]), closer=')', ), ], ) actual = self.parser.parseString(source, parseAll=True) self.assertEqual(actual.asList(), [expected])
def test_parse_parentheses_with_addition_and_multiplication(self): source = '(a + b) * c' expected = c_ast.CFunctionCall(function_name='*', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='+', arguments=[ c_ast.CVariable('a'), c_ast.CVariable('b'), ], ), closer=')', ), c_ast.CVariable('c'), ]) actual = self.parser.parseString(source, parseAll=True) self.assertEqual(actual.asList(), [expected])
def test_parse_define_object_like_as_attribute(self): source = '#define foo __attribute__((packed))' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CFunctionCall( function_name='__attribute__', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('packed'), closer=')', ), ], ), string_replacement=' __attribute__((packed))', ), ]), ) self.assertEqual(actual, expected)
def test_parse_sizeof_and_binary_plus_operators_and_additional_parentheses( self, ): source = """ ( sizeof(struct ymmh_struct) + sizeof(struct lwp_struct) + sizeof(struct mpx_struct) ) """ actual = self.parser.parseString(source, parseAll=True) expected = c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='+', arguments=[ c_ast.CFunctionCall( function_name='+', arguments=[ c_ast.CFunctionCall( function_name='sizeof', arguments=[ c_ast.CLiteral('struct ymmh_struct') ], ), c_ast.CFunctionCall( function_name='sizeof', arguments=[ c_ast.CLiteral('struct lwp_struct') ], ), ], ), c_ast.CFunctionCall( function_name='sizeof', arguments=[c_ast.CLiteral('struct mpx_struct')], ), ], ), closer=')', ) self.assertEqual(actual.asList(), [expected])
def test_evaluate_nested_expression(self): self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CNumber(42), string_replacement='42', ), 'bar': pre_ast.DefineObjectLike( name='bar', replacement=c_ast.CNumber(33), string_replacement='33', ), }) expression = c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('foo'), closer=')', ) actual = self.evaluator.evaluate(expression) expected = c_ast.CNumber(42) self.assertEqual(actual, expected)
def test_parse_binary_operators_with_parentheses_on_right(self): source = 'x < 4 || (y == 4 && z < 1)' expected = c_ast.CFunctionCall( function_name='||', arguments=[ c_ast.CFunctionCall( function_name='<', arguments=[ c_ast.CVariable('x'), c_ast.CNumber(4), ], ), c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='&&', arguments=[ c_ast.CFunctionCall( function_name='==', arguments=[ c_ast.CVariable('y'), c_ast.CNumber(4), ], ), c_ast.CFunctionCall( function_name='<', arguments=[ c_ast.CVariable('z'), c_ast.CNumber(1), ], ), ], ), closer=')', ), ], ) actual = self.parser.parseString(source, parseAll=True) self.assertEqual(actual.asList(), [expected])
def test_parse_sizeof_and_binary_operators(self): source = """ ((((1 << 0)) + (8 * sizeof(long)) - 1) / (8 * sizeof(long))) """ actual = self.parser.parseString(source, parseAll=True) expected = c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='/', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='-', arguments=[ c_ast.CFunctionCall( function_name='+', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='<<', arguments=[ c_ast.CNumber(1), c_ast.CNumber(0), ], ), closer=')', ), closer=')', ), c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='*', arguments=[ c_ast.CNumber(8), c_ast.CFunctionCall( function_name='sizeof', arguments=[ c_ast.CLiteral( 'long'), ], ), ], ), closer=')', ), ], ), c_ast.CNumber(1), ], ), closer=')', ), c_ast.CNestedExpression( opener='(', content=c_ast.CFunctionCall( function_name='*', arguments=[ c_ast.CNumber(8), c_ast.CFunctionCall( function_name='sizeof', arguments=[c_ast.CLiteral('long')], ), ], ), closer=')', ), ], ), closer=')', ) self.assertEqual(actual.asList(), [expected])