Merge pull request #4 from Syeberman/dollar-in-identifier
Dollar signs in identifiers
diff --git a/CHANGES b/CHANGES
index 5896ff2..0f96f4d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
+ Version 2.10 (??)
- BitBucket issue #9: c_generator error for ExprList in expression context.
+ - Github pull request #2: assume default int type for functions whose
+ argument or return types were not specified.
+ Version 2.09.1 (29.12.2012)
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 102126b..1ccd56f 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -17,6 +17,7 @@
* Rory Yorke
* Rubin
* Scott Tsai
+* Sye van der Veen
* Thomas W. Barr
* Tomer Segal
* Weyllor
diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py
index f75769f..610bbbe 100644
--- a/pycparser/c_lexer.py
+++ b/pycparser/c_lexer.py
@@ -176,7 +176,7 @@
hex_digits = '[0-9a-fA-F]+'
# integer constants (K&R2: A.2.5.1)
- integer_suffix_opt = r'(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?'
+ integer_suffix_opt = r'(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?'
decimal_constant = '(0'+integer_suffix_opt+')|([1-9][0-9]*'+integer_suffix_opt+')'
octal_constant = '0[0-7]*'+integer_suffix_opt
hex_constant = hex_prefix+hex_digits+integer_suffix_opt
diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py
index 88fe21d..abe7604 100644
--- a/pycparser/c_parser.py
+++ b/pycparser/c_parser.py
@@ -273,11 +273,22 @@
type.type = tn
return decl
- # At this point, we know that typename is a list of IdentifierType
- # nodes. Concatenate all the names into a single list.
- type.type = c_ast.IdentifierType(
- [name for id in typename for name in id.names],
- coord=typename[0].coord)
+ if not typename:
+ # Functions default to returning int
+ #
+ if not isinstance(decl.type, c_ast.FuncDecl):
+ self._parse_error(
+ "Missing type in declaration", decl.coord)
+ type.type = c_ast.IdentifierType(
+ ['int'],
+ coord=decl.coord)
+ else:
+ # At this point, we know that typename is a list of IdentifierType
+ # nodes. Concatenate all the names into a single list.
+ #
+ type.type = c_ast.IdentifierType(
+ [name for id in typename for name in id.names],
+ coord=typename[0].coord)
return decl
def _add_declaration_specifier(self, declspec, newspec, kind):
@@ -411,8 +422,13 @@
def p_function_definition_1(self, p):
""" function_definition : declarator declaration_list_opt compound_statement
"""
- # no declaration specifiers
- spec = dict(qual=[], storage=[], type=[])
+ # no declaration specifiers - 'int' becomes the default type
+ spec = dict(
+ qual=[],
+ storage=[],
+ type=[c_ast.IdentifierType(['int'],
+ coord=self._coord(p.lineno(1)))],
+ function=[])
p[0] = self._build_function_definition(
decl=p[1],
diff --git a/tests/test_c_lexer.py b/tests/test_c_lexer.py
index 14242b8..790ab39 100644
--- a/tests/test_c_lexer.py
+++ b/tests/test_c_lexer.py
@@ -55,9 +55,14 @@
def test_integer_constants(self):
self.assertTokensTypes('12', ['INT_CONST_DEC'])
self.assertTokensTypes('12u', ['INT_CONST_DEC'])
+ self.assertTokensTypes('12l', ['INT_CONST_DEC'])
self.assertTokensTypes('199872Ul', ['INT_CONST_DEC'])
+ self.assertTokensTypes('199872lU', ['INT_CONST_DEC'])
self.assertTokensTypes('199872LL', ['INT_CONST_DEC'])
self.assertTokensTypes('199872ull', ['INT_CONST_DEC'])
+ self.assertTokensTypes('199872llu', ['INT_CONST_DEC'])
+ self.assertTokensTypes('1009843200000uLL', ['INT_CONST_DEC'])
+ self.assertTokensTypes('1009843200000LLu', ['INT_CONST_DEC'])
self.assertTokensTypes('077', ['INT_CONST_OCT'])
self.assertTokensTypes('0123456L', ['INT_CONST_OCT'])
diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py
index e1ceec3..bae764c 100644
--- a/tests/test_c_parser.py
+++ b/tests/test_c_parser.py
@@ -260,6 +260,15 @@
],
['TypeDecl', ['IdentifierType', ['int']]]]])
+ # function return values and parameters may not have type information
+ self.assertEqual(self.get_decl('extern foobar(foo, bar);'),
+ ['Decl', 'foobar',
+ ['FuncDecl',
+ [ ['ID', 'foo'],
+ ['ID', 'bar']
+ ],
+ ['TypeDecl', ['IdentifierType', ['int']]]]])
+
def test_nested_decls(self): # the fun begins
self.assertEqual(self.get_decl('char** ar2D;'),
['Decl', 'ar2D',
@@ -1067,6 +1076,20 @@
self.assertEqual(expand_decl(f3.param_decls[1]),
['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
+ # function return values and parameters may not have type information
+ f4 = parse_fdef('''
+ que(p)
+ {
+ return 3;
+ }
+ ''')
+
+ self.assertEqual(fdef_decl(f4),
+ ['Decl', 'que',
+ ['FuncDecl',
+ [['ID', 'p']],
+ ['TypeDecl', ['IdentifierType', ['int']]]]])
+
def test_unified_string_literals(self):
# simple string, for reference
d1 = self.get_decl_init('char* s = "hello";')
diff --git a/z_test.py b/z.py
similarity index 85%
rename from z_test.py
rename to z.py
index c1aab48..2247bb3 100644
--- a/z_test.py
+++ b/z.py
@@ -8,7 +8,7 @@
""" Converts the declaration into a nested list.
"""
typ = type(decl)
-
+
if typ == TypeDecl:
return ['TypeDecl', expand_decl(decl.type)]
elif typ == IdentifierType:
@@ -18,9 +18,9 @@
elif typ in [Struct, Union]:
decls = [expand_decl(d) for d in decl.decls or []]
return [typ.__name__, decl.name, decls]
- else:
+ else:
nested = expand_decl(decl.type)
-
+
if typ == Decl:
if decl.quals:
return ['Decl', decl.quals, decl.name, nested]
@@ -49,22 +49,22 @@
class NodeVisitor(object):
def __init__(self):
self.current_parent = None
-
+
def visit(self, node):
- """ Visit a node.
+ """ Visit a node.
"""
method = 'visit_' + node.__class__.__name__
visitor = getattr(self, method, self.generic_visit)
return visitor(node)
-
+
def visit_FuncCall(self, node):
print("Visiting FuncCall")
print(node.show())
print('---- parent ----')
print(self.current_parent.show())
-
+
def generic_visit(self, node):
- """ Called if no explicit visitor function exists for a
+ """ Called if no explicit visitor function exists for a
node. Implements preorder visiting of the node.
"""
oldparent = self.current_parent
@@ -74,20 +74,17 @@
self.current_parent = oldparent
-if __name__ == "__main__":
+if __name__ == "__main__":
source_code = r'''
- typedef int foobar;
- typedef int foobar;
- void main(void) {
- foobar i;
- }
+ struct sample
+ {
+ int nodeId;
+ char nodeName[10];
+ } SSample;
'''
- parser = CParser(lex_optimize=False, yacc_optimize=False, yacc_debug=True)
+ parser = CParser()
ast = parser.parse(source_code, filename='zz')
ast.show(showcoord=False, attrnames=True, nodenames=True)
- #~ nv=NodeVisitor()
- #~ nv.visit(ast)
- print('-- done --')