def test_parse_with_top_level_ifdef_and_else_blocks(self): source = """ int a; #ifdef CONFIG_SOMETHING struct s { int x; } y; struct s t, u; #else int z; #endif int b; """ actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.TextBlock('int a;'), pre_ast.If(conditional_blocks=[ pre_ast.ConditionalBlock( conditional_expression='defined(CONFIG_SOMETHING)', content=[ pre_ast.TextBlock( '\n'.join(( 'struct s {', ' int x;', '} y;', 'struct s t, u;', )), ), ]), pre_ast.ConditionalBlock(conditional_expression="1", content=[pre_ast.TextBlock('int z;')]) ]), pre_ast.TextBlock('int b;') ]) self.assertASTEqual(actual, expected)
def test_ifdef(self): parsed_pre_ast = self.parser.parse(""" #define BAZ 1024 int Some(text); # if BAZ > 1000 #define BOO 2 int more_Text(); # else #define BOO 4 #endif """) # Learn about the macros defined above. actual = self.visitor.preprocess(parsed_pre_ast) expected = pre_ast.CompositeBlock([ pre_ast.TextBlock(content='int Some(text);'), pre_ast.CompositeBlock( [pre_ast.TextBlock(content='int more_Text();')]) ]) self.assertASTEqual(actual, expected) # Make sure that the right macro was defined. self.assertASTEqual( self.macros.object_likes["BOO"], pre_ast.DefineObjectLike(name="BOO", replacement="2"))
def test_parse_text_block(self): source = 'int x;' actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.TextBlock('int x;'), ]) self.assertASTEqual(actual, expected)
def test_parse_pragma_and_text_block(self): source = '\n'.join(( '#pragma foo bar', 'int x;', )) actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.Pragma("foo bar"), pre_ast.TextBlock('int x;'), ]) self.assertASTEqual(actual, expected)
def test_parse_multiline_define(self): source = '\n'.join([ '#define foo bar\\', ' baz', ' 42', ]) actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement='bar baz', ), pre_ast.TextBlock('42'), ]) self.assertASTEqual(actual, expected)
def parse(self, source): line_continuation = pyparsing.Literal('\\\n') ignorable = ( line_continuation | pyparsing.cppStyleComment.addParseAction( pyparsing.ParserElement.resetCache) # Removed for now because it is too expensive at this point. We can # eliminate those later in the trimming phase. # | parser.extern_field() | self.static_function()).suppress() source = ignorable.transformString(source) source = Sanitizer().transform(source) # Start parsing: Top level node will be a pre_ast.File self.push_node(pre_ast.CompositeBlock(content=[])) last_block_end = 0 scanner = self._preprocessor_directive().parseWithTabs() for tokens, start, end in scanner.scanString(source): text = source[last_block_end:start].strip() if text: # We skipped over a text block - push it on the current node. self.current_node.content.append(pre_ast.TextBlock(text)) last_block_end = end # Now process the different directives. directive, rest_of_line = tokens if directive == "include": self._process_include(rest_of_line) # Im not really sure what #pragma is supposed to do here. elif directive == "pragma": self.current_node.content.append(pre_ast.Pragma(rest_of_line)) elif directive == "error": self.current_node.content.append(pre_ast.Error(rest_of_line)) elif directive == "define": self._define_parser.parseString(rest_of_line) elif directive == "undef": self.current_node.content.append(pre_ast.Undef(rest_of_line)) elif directive == "if": self._add_conditional_block(rest_of_line) elif directive == "ifdef": self._add_conditional_block("defined(%s)" % rest_of_line) elif directive == "ifndef": self._add_conditional_block("!defined(%s)" % rest_of_line) elif directive == "else": self._add_elif_block("1") elif directive == "elif": self._add_elif_block(rest_of_line) elif directive == "endif": # Pop the stack. self.pop_node() # ConditionalBlock self.pop_node() # If block. # Last text node. text = source[last_block_end:].strip() if text: self.current_node.content.append(pre_ast.TextBlock(text)) return self.pop_node()
def visit_text_block(self, text_block): expanded_content = self._macro_expander.expand(text_block.content, eval_mode=False) return pre_ast.TextBlock(expanded_content)
def test_collect_includes_with_text_block(self): node = pre_ast.TextBlock('some_content') actual = self.include_collector.collect_includes(node) expected = [] self.assertEqual(actual, expected)
def test_to_string_with_text_block(self): node = pre_ast.TextBlock('some text content') actual = self.to_string_visitor.to_string(node) expected = 'some text content' self.assertEqual(actual, expected)