diff options
-rw-r--r-- | examples/c-to-c.py | 10 | ||||
-rw-r--r-- | examples/tests/test_c-to-c.py | 1 | ||||
-rw-r--r-- | pycparser/_build_tables.py | 4 | ||||
-rw-r--r-- | pycparser/_c_ast.cfg | 4 | ||||
-rw-r--r-- | pycparser/c_ast.py | 9 | ||||
-rw-r--r-- | pycparser/c_parser.py | 5 | ||||
-rw-r--r-- | tests/test_c_parser.py | 11 |
7 files changed, 37 insertions, 7 deletions
diff --git a/examples/c-to-c.py b/examples/c-to-c.py index 93de0aa..e0f6af0 100644 --- a/examples/c-to-c.py +++ b/examples/c-to-c.py @@ -173,6 +173,9 @@ class CGenerator(object): s += self._make_indent() + '}\n' return s + def visit_EmptyStatement(self, n): + return ';' + def visit_ParamList(self, n): return ', '.join(self.visit(param) for param in n.params) @@ -402,11 +405,8 @@ def zz_test_translate(): int main(void) { - int a; - int b = a++; - int c = ++a; - int d = a--; - int e = --a; + ; + return 0; } ''' parser = c_parser.CParser() diff --git a/examples/tests/test_c-to-c.py b/examples/tests/test_c-to-c.py index cba62f5..8015891 100644 --- a/examples/tests/test_c-to-c.py +++ b/examples/tests/test_c-to-c.py @@ -81,6 +81,7 @@ class TestCtoC(unittest.TestCase): int main() {
int a;
a = 5;
+ ;
return a;
}''')
diff --git a/pycparser/_build_tables.py b/pycparser/_build_tables.py index a15824e..779c8f9 100644 --- a/pycparser/_build_tables.py +++ b/pycparser/_build_tables.py @@ -4,7 +4,7 @@ # A dummy for generating the lexing/parsing tables and and # compiling them into .pyc for faster execution in optimized mode. # Also generates AST code from the configuration file. -# Should be called from the installation directory. +# Should be called from the pycparser directory. # # Copyright (C) 2008-2011, Eli Bendersky # License: BSD @@ -16,6 +16,8 @@ from _ast_gen import ASTCodeGenerator ast_gen = ASTCodeGenerator('_c_ast.cfg') ast_gen.generate(open('c_ast.py', 'w')) +import sys +sys.path.extend(['.', '..']) from pycparser import c_parser # Generates the tables diff --git a/pycparser/_c_ast.cfg b/pycparser/_c_ast.cfg index 3af0459..159dc78 100644 --- a/pycparser/_c_ast.cfg +++ b/pycparser/_c_ast.cfg @@ -68,6 +68,10 @@ DoWhile: [cond*, stmt*] #
EllipsisParam: []
+# An empty statement (a semicolon ';' on its own)
+#
+EmptyStatement: []
+
# Enumeration type specifier
# name: an optional ID
# values: an EnumeratorList
diff --git a/pycparser/c_ast.py b/pycparser/c_ast.py index 9ebdb74..ad35209 100644 --- a/pycparser/c_ast.py +++ b/pycparser/c_ast.py @@ -322,6 +322,15 @@ class EllipsisParam(Node): attr_names = ()
+class EmptyStatement(Node):
+ def __init__(self, coord=None):
+ self.coord = coord
+
+ def children(self):
+ return ()
+
+ attr_names = ()
+
class Enum(Node):
def __init__(self, name, values, coord=None):
self.name = name
diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py index 9687a66..99d9d96 100644 --- a/pycparser/c_parser.py +++ b/pycparser/c_parser.py @@ -1133,7 +1133,10 @@ class CParser(PLYParser): def p_expression_statement(self, p): """ expression_statement : expression_opt SEMI """ - p[0] = p[1] + if p[1] is None: + p[0] = c_ast.EmptyStatement(self._coord(p.lineno(1))) + else: + p[0] = p[1] def p_expression(self, p): """ expression : assignment_expression diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py index 63b4c6f..ea95644 100644 --- a/tests/test_c_parser.py +++ b/tests/test_c_parser.py @@ -1263,6 +1263,17 @@ class TestCParser_whole_code(TestCParser_base): self.assert_num_klass_nodes(ps3, DoWhile, 1) self.assert_num_ID_refs(ps3, 'a', 4) self.assert_all_Constants(ps3, ['0', '0', '1']) + + def test_empty_statement(self): + s1 = r''' + void foo(void){ + ; + return; + } + ''' + ps1 = self.parse(s1) + self.assert_num_klass_nodes(ps1, EmptyStatement, 1) + self.assert_num_klass_nodes(ps1, Return, 1) def test_for_statement(self): s2 = r''' |