summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreli.bendersky <devnull@localhost>2010-10-29 15:51:07 +0200
committereli.bendersky <devnull@localhost>2010-10-29 15:51:07 +0200
commit2e907fada2916053a4130cd7f51b4bad41006f6a (patch)
tree5b97cc87aec508bfdac925bc9abd3a74db745c0d
parent79d5cf672bf2119bc136f7ff9b71814898cf38f9 (diff)
downloadpycparser-2e907fada2916053a4130cd7f51b4bad41006f6a.tar.gz
Implemented basic VLA support for C99
-rw-r--r--TODO.txt2
-rw-r--r--pycparser/c_parser.py42
-rw-r--r--tests/test_c_parser.py13
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):