summaryrefslogtreecommitdiff
path: root/pycparser
diff options
context:
space:
mode:
Diffstat (limited to 'pycparser')
-rw-r--r--pycparser/_c_ast.cfg2
-rw-r--r--pycparser/c_ast.py21
-rw-r--r--pycparser/c_generator.py8
-rw-r--r--pycparser/c_lexer.py18
-rw-r--r--pycparser/c_parser.py17
5 files changed, 59 insertions, 7 deletions
diff --git a/pycparser/_c_ast.cfg b/pycparser/_c_ast.cfg
index 2f5b087..e9b5685 100644
--- a/pycparser/_c_ast.cfg
+++ b/pycparser/_c_ast.cfg
@@ -152,6 +152,8 @@ PtrDecl: [quals, type*]
Return: [expr*]
+StaticAssert: [cond*, message*]
+
# name: struct tag name
# decls: declaration of members
#
diff --git a/pycparser/c_ast.py b/pycparser/c_ast.py
index 0ce8fef..192c106 100644
--- a/pycparser/c_ast.py
+++ b/pycparser/c_ast.py
@@ -863,6 +863,27 @@ class Return(Node):
attr_names = ()
+class StaticAssert(Node):
+ __slots__ = ('cond', 'message', 'coord', '__weakref__')
+ def __init__(self, cond, message, coord=None):
+ self.cond = cond
+ self.message = message
+ self.coord = coord
+
+ def children(self):
+ nodelist = []
+ if self.cond is not None: nodelist.append(("cond", self.cond))
+ if self.message is not None: nodelist.append(("message", self.message))
+ return tuple(nodelist)
+
+ def __iter__(self):
+ if self.cond is not None:
+ yield self.cond
+ if self.message is not None:
+ yield self.message
+
+ attr_names = ()
+
class Struct(Node):
__slots__ = ('name', 'decls', 'coord', '__weakref__')
def __init__(self, name, decls, coord=None):
diff --git a/pycparser/c_generator.py b/pycparser/c_generator.py
index 983d578..ded8c65 100644
--- a/pycparser/c_generator.py
+++ b/pycparser/c_generator.py
@@ -286,6 +286,14 @@ class CGenerator(object):
s += ');'
return s
+ def visit_StaticAssert(self, n):
+ s = '_Static_assert('
+ s += self.visit(n.cond)
+ s += ','
+ s += self.visit(n.message)
+ s += ')'
+ return s
+
def visit_Switch(self, n):
s = 'switch (' + self.visit(n.cond) + ')\n'
s += self._generate_stmt(n.stmt, add_indent=True)
diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py
index 045d24e..96c4aa7 100644
--- a/pycparser/c_lexer.py
+++ b/pycparser/c_lexer.py
@@ -100,7 +100,7 @@ class CLexer(object):
## Reserved keywords
##
keywords = (
- '_BOOL', '_COMPLEX', 'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST',
+ 'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST',
'CONTINUE', 'DEFAULT', 'DO', 'DOUBLE', 'ELSE', 'ENUM', 'EXTERN',
'FLOAT', 'FOR', 'GOTO', 'IF', 'INLINE', 'INT', 'LONG',
'REGISTER', 'OFFSETOF',
@@ -109,19 +109,23 @@ class CLexer(object):
'VOLATILE', 'WHILE', '__INT128',
)
+ keywords_new = (
+ '_BOOL', '_COMPLEX',
+ '_NORETURN', '_THREAD_LOCAL', '_STATIC_ASSERT'
+ )
+
keyword_map = {}
+
for keyword in keywords:
- if keyword == '_BOOL':
- keyword_map['_Bool'] = keyword
- elif keyword == '_COMPLEX':
- keyword_map['_Complex'] = keyword
- else:
keyword_map[keyword.lower()] = keyword
+ for keyword in keywords_new:
+ keyword_map[keyword[:2].upper() + keyword[2:].lower()] = keyword
+
##
## All the tokens recognized by the lexer
##
- tokens = keywords + (
+ tokens = keywords + keywords_new + (
# Identifiers
'ID',
diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py
index d246900..b8ad4b1 100644
--- a/pycparser/c_parser.py
+++ b/pycparser/c_parser.py
@@ -554,6 +554,16 @@ class CParser(PLYParser):
"""
p[0] = []
+ def p_external_declaration_5(self, p):
+ """ external_declaration : static_assert
+ """
+ p[0] = p[1]
+
+ def p_static_assert_declaration(self, p):
+ """ static_assert : _STATIC_ASSERT LPAREN constant_expression COMMA unified_string_literal RPAREN
+ """
+ p[0] = [c_ast.StaticAssert(p[3], p[5], self._token_coord(p, 1))]
+
def p_pp_directive(self, p):
""" pp_directive : PPHASH
"""
@@ -599,6 +609,10 @@ class CParser(PLYParser):
param_decls=p[3],
body=p[4])
+ # Note, according to C18 A.2.2 6.7.10 static_assert-declaration _Static_assert
+ # is a declaration, not a statement. We additionally recognise it as a statement
+ # to fix parsing of _Static_assert inside the functions.
+ #
def p_statement(self, p):
""" statement : labeled_statement
| expression_statement
@@ -607,6 +621,7 @@ class CParser(PLYParser):
| iteration_statement
| jump_statement
| pppragma_directive
+ | static_assert
"""
p[0] = p[1]
@@ -806,11 +821,13 @@ class CParser(PLYParser):
| STATIC
| EXTERN
| TYPEDEF
+ | _THREAD_LOCAL
"""
p[0] = p[1]
def p_function_specifier(self, p):
""" function_specifier : INLINE
+ | _NORETURN
"""
p[0] = p[1]