From 2e907fada2916053a4130cd7f51b4bad41006f6a Mon Sep 17 00:00:00 2001 From: "eli.bendersky" Date: Fri, 29 Oct 2010 15:51:07 +0200 Subject: Implemented basic VLA support for C99 --- TODO.txt | 2 +- pycparser/c_parser.py | 42 ++++++++++++++++++++++++++++++++++++------ tests/test_c_parser.py | 13 +++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/TODO.txt b/TODO.txt index 3a8df61..d1dbfb7 100644 --- a/TODO.txt +++ b/TODO.txt @@ -5,7 +5,7 @@ Pycparser 2: the idea is to "mostly" support C99 Implement: -- new keywords restrict, inline +V- new keywords restrict, inline - mix declarations and statements inside a block - VLAs (non-constants in arr[n]), including [*] for parameter lists V- declarations in the first expression of "for" loops diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py index b9fa7a8..2d0a8b6 100644 --- a/pycparser/c_parser.py +++ b/pycparser/c_parser.py @@ -76,7 +76,7 @@ class CParser(PLYParser): rules_with_opt = [ 'abstract_declarator', - 'constant_expression', + 'assignment_expression', 'declaration_list', 'declaration_specifiers', 'expression', @@ -756,7 +756,7 @@ class CParser(PLYParser): p[0] = p[2] def p_direct_declarator_3(self, p): - """ direct_declarator : direct_declarator LBRACKET constant_expression_opt RBRACKET + """ direct_declarator : direct_declarator LBRACKET assignment_expression_opt RBRACKET """ arr = c_ast.ArrayDecl( type=None, @@ -765,7 +765,19 @@ class CParser(PLYParser): p[0] = self._type_modify_decl(decl=p[1], modifier=arr) + # Special for VLAs + # def p_direct_declarator_4(self, p): + """ direct_declarator : direct_declarator LBRACKET TIMES RBRACKET + """ + arr = c_ast.ArrayDecl( + type=None, + dim=c_ast.ID(p[3], self._coord(p.lineno(3))), + coord=p[1].coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=arr) + + def p_direct_declarator_5(self, p): """ direct_declarator : direct_declarator LPAREN parameter_type_list RPAREN | direct_declarator LPAREN identifier_list_opt RPAREN """ @@ -917,7 +929,7 @@ class CParser(PLYParser): p[0] = p[2] def p_direct_abstract_declarator_2(self, p): - """ direct_abstract_declarator : direct_abstract_declarator LBRACKET constant_expression_opt RBRACKET + """ direct_abstract_declarator : direct_abstract_declarator LBRACKET assignment_expression_opt RBRACKET """ arr = c_ast.ArrayDecl( type=None, @@ -927,14 +939,32 @@ class CParser(PLYParser): p[0] = self._type_modify_decl(decl=p[1], modifier=arr) def p_direct_abstract_declarator_3(self, p): - """ direct_abstract_declarator : LBRACKET constant_expression_opt RBRACKET + """ direct_abstract_declarator : LBRACKET assignment_expression_opt RBRACKET """ p[0] = c_ast.ArrayDecl( type=c_ast.TypeDecl(None, None, None), dim=p[2], coord=self._coord(p.lineno(1))) - + def p_direct_abstract_declarator_4(self, p): + """ direct_abstract_declarator : direct_abstract_declarator LBRACKET TIMES RBRACKET + """ + arr = c_ast.ArrayDecl( + type=None, + dim=c_ast.ID(p[3], self._coord(p.lineno(3))), + coord=p[1].coord) + + p[0] = self._type_modify_decl(decl=p[1], modifier=arr) + + def p_direct_abstract_declarator_5(self, p): + """ direct_abstract_declarator : LBRACKET TIMES RBRACKET + """ + p[0] = c_ast.ArrayDecl( + type=c_ast.TypeDecl(None, None, None), + dim=c_ast.ID(p[3], self._coord(p.lineno(3))), + coord=self._coord(p.lineno(1))) + + def p_direct_abstract_declarator_6(self, p): """ direct_abstract_declarator : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN """ func = c_ast.FuncDecl( @@ -944,7 +974,7 @@ class CParser(PLYParser): p[0] = self._type_modify_decl(decl=p[1], modifier=func) - def p_direct_abstract_declarator_5(self, p): + def p_direct_abstract_declarator_7(self, p): """ direct_abstract_declarator : LPAREN parameter_type_list_opt RPAREN """ p[0] = c_ast.FuncDecl( diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py index ccedb01..ef6f85c 100644 --- a/tests/test_c_parser.py +++ b/tests/test_c_parser.py @@ -878,6 +878,19 @@ class TestCParser_fundamentals(unittest.TestCase): def test_inline_specifier(self): ps2 = self.parse('static inline void inlinefoo(void);') self.assertEqual(ps2.ext[0].funcspec, ['inline']) + + # variable length array + def test_vla(self): + ps2 = self.parse(r''' + int main() { + int size; + int var[size = 5]; + + int var2[*]; + } + ''') + self.failUnless(isinstance(ps2.ext[0].body.decls[1].type.dim, Assignment)) + self.failUnless(isinstance(ps2.ext[0].body.decls[2].type.dim, ID)) class TestCParser_whole_code(unittest.TestCase): -- cgit v1.2.1