diff options
author | eli.bendersky <devnull@localhost> | 2010-10-29 15:51:07 +0200 |
---|---|---|
committer | eli.bendersky <devnull@localhost> | 2010-10-29 15:51:07 +0200 |
commit | 2e907fada2916053a4130cd7f51b4bad41006f6a (patch) | |
tree | 5b97cc87aec508bfdac925bc9abd3a74db745c0d | |
parent | 79d5cf672bf2119bc136f7ff9b71814898cf38f9 (diff) | |
download | pycparser-2e907fada2916053a4130cd7f51b4bad41006f6a.tar.gz |
Implemented basic VLA support for C99
-rw-r--r-- | TODO.txt | 2 | ||||
-rw-r--r-- | pycparser/c_parser.py | 42 | ||||
-rw-r--r-- | tests/test_c_parser.py | 13 |
3 files changed, 50 insertions, 7 deletions
@@ -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): |