diff options
Diffstat (limited to 'pycparser')
| -rw-r--r-- | pycparser/_c_ast.cfg | 2 | ||||
| -rw-r--r-- | pycparser/c_ast.py | 21 | ||||
| -rw-r--r-- | pycparser/c_generator.py | 8 | ||||
| -rw-r--r-- | pycparser/c_lexer.py | 18 | ||||
| -rw-r--r-- | pycparser/c_parser.py | 17 |
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] |
