def test_parse_variable_in_parentheses2(self): # Unfortunately our parser is not that great since it misidentifies the # below with & is substituted for +. It accidentally considers it the # dereference operator. I dont think there is a way to properly parse # without context (i.e. cant make a context free grammer) because you # need to resolve the RHS to the & operator to know if it makes sense. source = '(((x) + 1) | 2)' actual = self.parser.parse(source) expected = c_ast.CNestedExpression( opener='(', closer=')', content=c_ast.CFunctionCall( function_name="|", arguments=[ c_ast.CNestedExpression( opener='(', closer=')', content=c_ast.CFunctionCall( function_name="+", arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('x'), closer=')', ), c_ast.CNumber(1), ])), c_ast.CNumber(2) ])) self.assertASTEqual(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.parse(source) self.assertASTEqual(actual, 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.parse(source) 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.assertASTEqual(actual, 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, 1)
def test_parse_variable_in_parentheses(self): source = '(x)' expected = c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('x'), closer=')', ) actual = self.parser.parse(source) self.assertASTEqual(actual, expected)
def test_parse_number_in_parentheses(self): source = '(42)' expected = c_ast.CNestedExpression( opener='(', content=c_ast.CNumber(42), closer=')', ) actual = self.parser.parse(source) self.assertASTEqual(actual, expected)
def test_parse_complex_parentheses_expression(self): source = '(((x) + (y)) & ~(y))' actual = self.parser.parse(source) 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.assertASTEqual(actual, 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.parse(source) self.assertASTEqual(actual, expected)
def test_parse_parentheses_and_binary_plus(self): source = '(a) + b' actual = self.parser.parse(source) expected = c_ast.CFunctionCall( function_name='+', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('a'), closer=')', ), c_ast.CVariable('b'), ], ) self.assertASTEqual(actual, expected)
def test_casting_killer(self): # Remove the casts. source = '((unsigned int)(4))' actual = self.parser.parse(source) expected = c_ast.CNestedExpression( opener='(', closer=")", content=c_ast.CNestedExpression( opener='(', content=c_ast.CNumber(4), closer=')', ), ) self.assertASTEqual(actual, expected) source = '1024 / (8 * sizeof(long) - 1)' actual = self.parser.evaluate_string(source) self.assertEqual(actual, 1024 // (8 * 8 - 1)) source = """ ((__be32) ((__u32) ((((__u32) ((0x00800000)) & (__u32) 0x000000ffUL) << 24) | (((__u32) ((0x00800000)) & (__u32) 0x0000ff00UL) << 8) | (((__u32) ((0x00800000)) & (__u32) 0x00ff0000UL) >> 8) | (((__u32) ((0x00800000)) & (__u32) 0xff000000UL) >> 24)))) """ actual = self.parser.evaluate_string(source) self.assertEqual(actual, 0x008000)
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.parse(source) self.assertASTEqual(actual, 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.parse(source) self.assertASTEqual(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.parse(source) 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.assertASTEqual(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.parse(source) self.assertASTEqual(actual, expected)