aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/c-to-c.py10
-rw-r--r--examples/tests/test_c-to-c.py1
-rw-r--r--pycparser/_build_tables.py4
-rw-r--r--pycparser/_c_ast.cfg4
-rw-r--r--pycparser/c_ast.py9
-rw-r--r--pycparser/c_parser.py5
-rw-r--r--tests/test_c_parser.py11
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'''