1#-------------------------------------------------------------------------
2# CxxTest: A lightweight C++ unit testing library.
3# Copyright (c) 2008 Sandia Corporation.
4# This software is distributed under the LGPL License v2.1
5# For more information, see the COPYING file in the top CxxTest directory.
6# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7# the U.S. Government retains certain rights in this software.
8#-------------------------------------------------------------------------
9
10# vim: fileencoding=utf-8
11
12#
13# This is a PLY parser for the entire ANSI C++ grammar.  This grammar was
14# adapted from the FOG grammar developed by E. D. Willink.  See
15#
16#    http://www.computing.surrey.ac.uk/research/dsrg/fog/
17#
18# for further details.
19#
20# The goal of this grammar is to extract information about class, function and
21# class method declarations, along with their associated scope.  Thus, this
22# grammar can be used to analyze classes in an inheritance heirarchy, and then
23# enumerate the methods in a derived class.
24#
25# This grammar parses blocks of <>, (), [] and {} in a generic manner.  Thus,
26# There are several capabilities that this grammar does not support:
27#
28# 1. Ambiguous template specification.  This grammar cannot parse template
29#       specifications that do not have paired <>'s in their declaration.  In
30#       particular, ambiguous declarations like
31#
32#           foo<A, c<3 >();
33#
34#       cannot be correctly parsed.
35#
36# 2. Template class specialization.  Although the goal of this grammar is to
37#       extract class information, specialization of templated classes is
38#       not supported.  When a template class definition is parsed, it's
39#       declaration is archived without information about the template
40#       parameters.  Class specializations will be stored separately, and
41#       thus they can be processed after the fact.  However, this grammar
42#       does not attempt to correctly process properties of class inheritence
43#       when template class specialization is employed.
44#
45
46#
47# TODO: document usage of this file
48#
49
50
51
52import os
53import ply.lex as lex
54import ply.yacc as yacc
55import re
56try:
57    from collections import OrderedDict
58except ImportError:
59    from ordereddict import OrderedDict
60
61lexer = None
62scope_lineno = 0
63identifier_lineno = {}
64_parse_info=None
65_parsedata=None
66noExceptionLogic = True
67
68def ply_init(data):
69    global _parsedata
70    _parsedata=data
71
72
73class Scope(object):
74
75    def __init__(self,name,abs_name,scope_t,base_classes,lineno):
76        self.function=[]
77        self.name=name
78        self.scope_t=scope_t
79        self.sub_scopes=[]
80        self.base_classes=base_classes
81        self.abs_name=abs_name
82        self.lineno=lineno
83
84    def insert(self,scope):
85        self.sub_scopes.append(scope)
86
87
88class CppInfo(object):
89
90    def __init__(self, filter=None):
91        self.verbose=0
92        if filter is None:
93            self.filter=re.compile("[Tt][Ee][Ss][Tt]|createSuite|destroySuite")
94        else:
95            self.filter=filter
96        self.scopes=[""]
97        self.index=OrderedDict()
98        self.index[""]=Scope("","::","namespace",[],1)
99        self.function=[]
100
101    def push_scope(self,ns,scope_t,base_classes=[]):
102        name = self.scopes[-1]+"::"+ns
103        if self.verbose>=2:
104            print("-- Starting "+scope_t+" "+name)
105        self.scopes.append(name)
106        self.index[name] = Scope(ns,name,scope_t,base_classes,scope_lineno-1)
107
108    def pop_scope(self):
109        scope = self.scopes.pop()
110        if self.verbose>=2:
111            print("-- Stopping "+scope)
112        return scope
113
114    def add_function(self, fn):
115        fn = str(fn)
116        if self.filter.search(fn):
117            self.index[self.scopes[-1]].function.append((fn, identifier_lineno.get(fn,lexer.lineno-1)))
118            tmp = self.scopes[-1]+"::"+fn
119            if self.verbose==2:
120                print("-- Function declaration "+fn+"  "+tmp)
121            elif self.verbose==1:
122                print("-- Function declaration "+tmp)
123
124    def get_functions(self,name,quiet=False):
125        if name == "::":
126            name = ""
127        scope = self.index[name]
128        fns=scope.function
129        for key in scope.base_classes:
130            cname = self.find_class(key,scope)
131            if cname is None:
132                if not quiet:
133                    print("Defined classes: ",list(self.index.keys()))
134                    print("WARNING: Unknown class "+key)
135            else:
136                fns += self.get_functions(cname,quiet)
137        return fns
138
139    def find_class(self,name,scope):
140        if ':' in name:
141            if name in self.index:
142                return name
143            else:
144                return None
145        tmp = scope.abs_name.split(':')
146        name1 = ":".join(tmp[:-1] + [name])
147        if name1 in self.index:
148            return name1
149        name2 = "::"+name
150        if name2 in self.index:
151            return name2
152        return None
153
154    def __repr__(self):
155        return str(self)
156
157    def is_baseclass(self,cls,base):
158        '''Returns true if base is a base-class of cls'''
159        if cls in self.index:
160            bases = self.index[cls]
161        elif "::"+cls in self.index:
162            bases = self.index["::"+cls]
163        else:
164            return False
165            #raise IOError, "Unknown class "+cls
166        if base in bases.base_classes:
167            return True
168        for name in bases.base_classes:
169            if self.is_baseclass(name,base):
170                return True
171        return False
172
173    def __str__(self):
174        ans=""
175        keys = list(self.index.keys())
176        keys.sort()
177        for key in keys:
178            scope = self.index[key]
179            ans += scope.scope_t+" "+scope.abs_name+"\n"
180            if scope.scope_t == "class":
181                ans += "  Base Classes: "+str(scope.base_classes)+"\n"
182                for fn in self.get_functions(scope.abs_name):
183                    ans += "  "+fn+"\n"
184            else:
185                for fn in scope.function:
186                    ans += "  "+fn+"\n"
187        return ans
188
189
190def flatten(x):
191    """Flatten nested list"""
192    try:
193        strtypes = str
194    except: # for python3 etc
195        strtypes = (str, bytes)
196
197    result = []
198    for el in x:
199        if hasattr(el, "__iter__") and not isinstance(el, strtypes):
200            result.extend(flatten(el))
201        else:
202            result.append(el)
203    return result
204
205#
206# The lexer (and/or a preprocessor) is expected to identify the following
207#
208#  Punctuation:
209#
210#
211literals = "+-*/%^&|~!<>=:()?.\'\"\\@$;,"
212
213#
214reserved = {
215    'private' : 'PRIVATE',
216    'protected' : 'PROTECTED',
217    'public' : 'PUBLIC',
218
219    'bool' : 'BOOL',
220    'char' : 'CHAR',
221    'double' : 'DOUBLE',
222    'float' : 'FLOAT',
223    'int' : 'INT',
224    'long' : 'LONG',
225    'short' : 'SHORT',
226    'signed' : 'SIGNED',
227    'unsigned' : 'UNSIGNED',
228    'void' : 'VOID',
229    'wchar_t' : 'WCHAR_T',
230
231    'class' : 'CLASS',
232    'enum' : 'ENUM',
233    'namespace' : 'NAMESPACE',
234    'struct' : 'STRUCT',
235    'typename' : 'TYPENAME',
236    'union' : 'UNION',
237
238    'const' : 'CONST',
239    'volatile' : 'VOLATILE',
240
241    'auto' : 'AUTO',
242    'explicit' : 'EXPLICIT',
243    'export' : 'EXPORT',
244    'extern' : 'EXTERN',
245    '__extension__' : 'EXTENSION',
246    'friend' : 'FRIEND',
247    'inline' : 'INLINE',
248    'mutable' : 'MUTABLE',
249    'register' : 'REGISTER',
250    'static' : 'STATIC',
251    'template' : 'TEMPLATE',
252    'typedef' : 'TYPEDEF',
253    'using' : 'USING',
254    'virtual' : 'VIRTUAL',
255
256    'asm' : 'ASM',
257    'break' : 'BREAK',
258    'case' : 'CASE',
259    'catch' : 'CATCH',
260    'const_cast' : 'CONST_CAST',
261    'continue' : 'CONTINUE',
262    'default' : 'DEFAULT',
263    'delete' : 'DELETE',
264    'do' : 'DO',
265    'dynamic_cast' : 'DYNAMIC_CAST',
266    'else' : 'ELSE',
267    'false' : 'FALSE',
268    'for' : 'FOR',
269    'goto' : 'GOTO',
270    'if' : 'IF',
271    'new' : 'NEW',
272    'operator' : 'OPERATOR',
273    'reinterpret_cast' : 'REINTERPRET_CAST',
274    'return' : 'RETURN',
275    'sizeof' : 'SIZEOF',
276    'static_cast' : 'STATIC_CAST',
277    'switch' : 'SWITCH',
278    'this' : 'THIS',
279    'throw' : 'THROW',
280    'true' : 'TRUE',
281    'try' : 'TRY',
282    'typeid' : 'TYPEID',
283    'while' : 'WHILE',
284    '"C"' : 'CLiteral',
285    '"C++"' : 'CppLiteral',
286
287    '__attribute__' : 'ATTRIBUTE',
288    '__cdecl__' : 'CDECL',
289    '__typeof' : 'uTYPEOF',
290    'typeof' : 'TYPEOF',
291
292    'CXXTEST_STD' : 'CXXTEST_STD'
293}
294
295tokens = [
296    "CharacterLiteral",
297    "FloatingLiteral",
298    "Identifier",
299    "IntegerLiteral",
300    "StringLiteral",
301 "RBRACE",
302 "LBRACE",
303 "RBRACKET",
304 "LBRACKET",
305 "ARROW",
306 "ARROW_STAR",
307 "DEC",
308 "EQ",
309 "GE",
310 "INC",
311 "LE",
312 "LOG_AND",
313 "LOG_OR",
314 "NE",
315 "SHL",
316 "SHR",
317 "ASS_ADD",
318 "ASS_AND",
319 "ASS_DIV",
320 "ASS_MOD",
321 "ASS_MUL",
322 "ASS_OR",
323 "ASS_SHL",
324 "ASS_SHR",
325 "ASS_SUB",
326 "ASS_XOR",
327 "DOT_STAR",
328 "ELLIPSIS",
329 "SCOPE",
330] + list(reserved.values())
331
332t_ignore = " \t\r"
333
334t_LBRACE = r"(\{)|(<%)"
335t_RBRACE = r"(\})|(%>)"
336t_LBRACKET = r"(\[)|(<:)"
337t_RBRACKET = r"(\])|(:>)"
338t_ARROW = r"->"
339t_ARROW_STAR = r"->\*"
340t_DEC = r"--"
341t_EQ = r"=="
342t_GE = r">="
343t_INC = r"\+\+"
344t_LE = r"<="
345t_LOG_AND = r"&&"
346t_LOG_OR = r"\|\|"
347t_NE = r"!="
348t_SHL = r"<<"
349t_SHR = r">>"
350t_ASS_ADD = r"\+="
351t_ASS_AND = r"&="
352t_ASS_DIV = r"/="
353t_ASS_MOD = r"%="
354t_ASS_MUL = r"\*="
355t_ASS_OR  = r"\|="
356t_ASS_SHL = r"<<="
357t_ASS_SHR = r">>="
358t_ASS_SUB = r"-="
359t_ASS_XOR = r"^="
360t_DOT_STAR = r"\.\*"
361t_ELLIPSIS = r"\.\.\."
362t_SCOPE = r"::"
363
364# Discard comments
365def t_COMMENT(t):
366    r'(/\*(.|\n)*?\*/)|(//.*?\n)|(\#.*?\n)'
367    t.lexer.lineno += t.value.count("\n")
368
369t_IntegerLiteral = r'(0x[0-9A-F]+)|([0-9]+(L){0,1})'
370t_FloatingLiteral = r"[0-9]+[eE\.\+-]+[eE\.\+\-0-9]+"
371t_CharacterLiteral = r'\'([^\'\\]|\\.)*\''
372#t_StringLiteral = r'"([^"\\]|\\.)*"'
373def t_StringLiteral(t):
374    r'"([^"\\]|\\.)*"'
375    t.type = reserved.get(t.value,'StringLiteral')
376    return t
377
378def t_Identifier(t):
379    r"[a-zA-Z_][a-zA-Z_0-9\.]*"
380    t.type = reserved.get(t.value,'Identifier')
381    return t
382
383
384def t_error(t):
385    print("Illegal character '%s'" % t.value[0])
386    #raise IOError, "Parse error"
387    #t.lexer.skip()
388
389def t_newline(t):
390    r'[\n]+'
391    t.lexer.lineno += len(t.value)
392
393precedence = (
394    ( 'right', 'SHIFT_THERE', 'REDUCE_HERE_MOSTLY', 'SCOPE'),
395    ( 'nonassoc', 'ELSE', 'INC', 'DEC', '+', '-', '*', '&', 'LBRACKET', 'LBRACE', '<', ':', ')')
396    )
397
398start = 'translation_unit'
399
400#
401#  The %prec resolves the 14.2-3 ambiguity:
402#  Identifier '<' is forced to go through the is-it-a-template-name test
403#  All names absorb TEMPLATE with the name, so that no template_test is
404#  performed for them.  This requires all potential declarations within an
405#  expression to perpetuate this policy and thereby guarantee the ultimate
406#  coverage of explicit_instantiation.
407#
408#  The %prec also resolves a conflict in identifier : which is forced to be a
409#  shift of a label for a labeled-statement rather than a reduction for the
410#  name of a bit-field or generalised constructor.  This is pretty dubious
411#  syntactically but correct for all semantic possibilities.  The shift is
412#  only activated when the ambiguity exists at the start of a statement.
413#  In this context a bit-field declaration or constructor definition are not
414#  allowed.
415#
416
417def p_identifier(p):
418    '''identifier : Identifier
419    |               CXXTEST_STD '(' Identifier ')'
420    '''
421    if p[1][0] in ('t','T','c','d'):
422        identifier_lineno[p[1]] = p.lineno(1)
423    p[0] = p[1]
424
425def p_id(p):
426    '''id :                         identifier %prec SHIFT_THERE
427    |                               template_decl
428    |                               TEMPLATE id
429    '''
430    p[0] = get_rest(p)
431
432def p_global_scope(p):
433    '''global_scope :               SCOPE
434    '''
435    p[0] = get_rest(p)
436
437def p_id_scope(p):
438    '''id_scope : id SCOPE'''
439    p[0] = get_rest(p)
440
441def p_id_scope_seq(p):
442    '''id_scope_seq :                id_scope
443    |                                id_scope id_scope_seq
444    '''
445    p[0] = get_rest(p)
446
447#
448#  A :: B :: C; is ambiguous How much is type and how much name ?
449#  The %prec maximises the (type) length which is the 7.1-2 semantic constraint.
450#
451def p_nested_id(p):
452    '''nested_id :                  id %prec SHIFT_THERE
453    |                               id_scope nested_id
454    '''
455    p[0] = get_rest(p)
456
457def p_scoped_id(p):
458    '''scoped_id :                  nested_id
459    |                               global_scope nested_id
460    |                               id_scope_seq
461    |                               global_scope id_scope_seq
462    '''
463    global scope_lineno
464    scope_lineno = lexer.lineno
465    data = flatten(get_rest(p))
466    if data[0] != None:
467        p[0] = "".join(data)
468
469#
470#  destructor_id has to be held back to avoid a conflict with a one's
471#  complement as per 5.3.1-9, It gets put back only when scoped or in a
472#  declarator_id, which is only used as an explicit member name.
473#  Declarations of an unscoped destructor are always parsed as a one's
474#  complement.
475#
476def p_destructor_id(p):
477    '''destructor_id :              '~' id
478    |                               TEMPLATE destructor_id
479    '''
480    p[0]=get_rest(p)
481
482#def p_template_id(p):
483#    '''template_id :                empty
484#    |                               TEMPLATE
485#    '''
486#    pass
487
488def p_template_decl(p):
489    '''template_decl :              identifier '<' nonlgt_seq_opt '>'
490    '''
491    #
492    # WEH: should we include the lt/gt symbols to indicate that this is a
493    # template class?  How is that going to be used later???
494    #
495    #p[0] = [p[1] ,"<",">"]
496    p[0] = p[1]
497
498def p_special_function_id(p):
499    '''special_function_id :        conversion_function_id
500    |                               operator_function_id
501    |                               TEMPLATE special_function_id
502    '''
503    p[0]=get_rest(p)
504
505def p_nested_special_function_id(p):
506    '''nested_special_function_id : special_function_id
507    |                               id_scope destructor_id
508    |                               id_scope nested_special_function_id
509    '''
510    p[0]=get_rest(p)
511
512def p_scoped_special_function_id(p):
513    '''scoped_special_function_id : nested_special_function_id
514    |                               global_scope nested_special_function_id
515    '''
516    p[0]=get_rest(p)
517
518# declarator-id is all names in all scopes, except reserved words
519def p_declarator_id(p):
520    '''declarator_id :              scoped_id
521    |                               scoped_special_function_id
522    |                               destructor_id
523    '''
524    p[0]=p[1]
525
526#
527# The standard defines pseudo-destructors in terms of type-name, which is
528# class/enum/typedef, of which class-name is covered by a normal destructor.
529# pseudo-destructors are supposed to support ~int() in templates, so the
530# grammar here covers built-in names. Other names are covered by the lack
531# of identifier/type discrimination.
532#
533def p_built_in_type_id(p):
534    '''built_in_type_id :           built_in_type_specifier
535    |                               built_in_type_id built_in_type_specifier
536    '''
537    pass
538
539def p_pseudo_destructor_id(p):
540    '''pseudo_destructor_id :       built_in_type_id SCOPE '~' built_in_type_id
541    |                               '~' built_in_type_id
542    |                               TEMPLATE pseudo_destructor_id
543    '''
544    pass
545
546def p_nested_pseudo_destructor_id(p):
547    '''nested_pseudo_destructor_id : pseudo_destructor_id
548    |                               id_scope nested_pseudo_destructor_id
549    '''
550    pass
551
552def p_scoped_pseudo_destructor_id(p):
553    '''scoped_pseudo_destructor_id : nested_pseudo_destructor_id
554    |                               global_scope scoped_pseudo_destructor_id
555    '''
556    pass
557
558#-------------------------------------------------------------------------------
559# A.2 Lexical conventions
560#-------------------------------------------------------------------------------
561#
562
563def p_literal(p):
564    '''literal :                    IntegerLiteral
565    |                               CharacterLiteral
566    |                               FloatingLiteral
567    |                               StringLiteral
568    |                               TRUE
569    |                               FALSE
570    '''
571    pass
572
573#-------------------------------------------------------------------------------
574# A.3 Basic concepts
575#-------------------------------------------------------------------------------
576def p_translation_unit(p):
577    '''translation_unit :           declaration_seq_opt
578    '''
579    pass
580
581#-------------------------------------------------------------------------------
582# A.4 Expressions
583#-------------------------------------------------------------------------------
584#
585#  primary_expression covers an arbitrary sequence of all names with the
586#  exception of an unscoped destructor, which is parsed as its unary expression
587#  which is the correct disambiguation (when ambiguous).  This eliminates the
588#  traditional A(B) meaning A B ambiguity, since we never have to tack an A
589#  onto the front of something that might start with (. The name length got
590#  maximised ab initio. The downside is that semantic interpretation must split
591#  the names up again.
592#
593#  Unification of the declaration and expression syntax means that unary and
594#  binary pointer declarator operators:
595#      int * * name
596#  are parsed as binary and unary arithmetic operators (int) * (*name). Since
597#  type information is not used
598#  ambiguities resulting from a cast
599#      (cast)*(value)
600#  are resolved to favour the binary rather than the cast unary to ease AST
601#  clean-up. The cast-call ambiguity must be resolved to the cast to ensure
602#  that (a)(b)c can be parsed.
603#
604#  The problem of the functional cast ambiguity
605#      name(arg)
606#  as call or declaration is avoided by maximising the name within the parsing
607#  kernel. So  primary_id_expression picks up
608#      extern long int const var = 5;
609#  as an assignment to the syntax parsed as "extern long int const var". The
610#  presence of two names is parsed so that "extern long into const" is
611#  distinguished from "var" considerably simplifying subsequent
612#  semantic resolution.
613#
614#  The generalised name is a concatenation of potential type-names (scoped
615#  identifiers or built-in sequences) plus optionally one of the special names
616#  such as an operator-function-id, conversion-function-id or destructor as the
617#  final name.
618#
619
620def get_rest(p):
621    return [p[i] for i in range(1, len(p))]
622
623def p_primary_expression(p):
624    '''primary_expression :         literal
625    |                               THIS
626    |                               suffix_decl_specified_ids
627    |                               abstract_expression %prec REDUCE_HERE_MOSTLY
628    '''
629    p[0] = get_rest(p)
630
631#
632#  Abstract-expression covers the () and [] of abstract-declarators.
633#
634def p_abstract_expression(p):
635    '''abstract_expression :        parenthesis_clause
636    |                               LBRACKET bexpression_opt RBRACKET
637    |                               TEMPLATE abstract_expression
638    '''
639    pass
640
641def p_postfix_expression(p):
642    '''postfix_expression :         primary_expression
643    |                               postfix_expression parenthesis_clause
644    |                               postfix_expression LBRACKET bexpression_opt RBRACKET
645    |                               postfix_expression LBRACKET bexpression_opt RBRACKET attributes
646    |                               postfix_expression '.' declarator_id
647    |                               postfix_expression '.' scoped_pseudo_destructor_id
648    |                               postfix_expression ARROW declarator_id
649    |                               postfix_expression ARROW scoped_pseudo_destructor_id
650    |                               postfix_expression INC
651    |                               postfix_expression DEC
652    |                               DYNAMIC_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
653    |                               STATIC_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
654    |                               REINTERPRET_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
655    |                               CONST_CAST '<' nonlgt_seq_opt '>' '(' expression ')'
656    |                               TYPEID parameters_clause
657    '''
658    #print "HERE",str(p[1])
659    p[0] = get_rest(p)
660
661def p_bexpression_opt(p):
662    '''bexpression_opt :            empty
663    |                               bexpression
664    '''
665    pass
666
667def p_bexpression(p):
668    '''bexpression :                nonbracket_seq
669    |                               nonbracket_seq bexpression_seq bexpression_clause nonbracket_seq_opt
670    |                               bexpression_seq bexpression_clause nonbracket_seq_opt
671    '''
672    pass
673
674def p_bexpression_seq(p):
675    '''bexpression_seq :            empty
676    |                               bexpression_seq bexpression_clause nonbracket_seq_opt
677    '''
678    pass
679
680def p_bexpression_clause(p):
681    '''bexpression_clause :          LBRACKET bexpression_opt RBRACKET
682    '''
683    pass
684
685
686
687def p_expression_list_opt(p):
688    '''expression_list_opt :        empty
689    |                               expression_list
690    '''
691    pass
692
693def p_expression_list(p):
694    '''expression_list :            assignment_expression
695    |                               expression_list ',' assignment_expression
696    '''
697    pass
698
699def p_unary_expression(p):
700    '''unary_expression :           postfix_expression
701    |                               INC cast_expression
702    |                               DEC cast_expression
703    |                               ptr_operator cast_expression
704    |                               suffix_decl_specified_scope star_ptr_operator cast_expression
705    |                               '+' cast_expression
706    |                               '-' cast_expression
707    |                               '!' cast_expression
708    |                               '~' cast_expression
709    |                               SIZEOF unary_expression
710    |                               new_expression
711    |                               global_scope new_expression
712    |                               delete_expression
713    |                               global_scope delete_expression
714    '''
715    p[0] = get_rest(p)
716
717def p_delete_expression(p):
718    '''delete_expression :          DELETE cast_expression
719    '''
720    pass
721
722def p_new_expression(p):
723    '''new_expression :             NEW new_type_id new_initializer_opt
724    |                               NEW parameters_clause new_type_id new_initializer_opt
725    |                               NEW parameters_clause
726    |                               NEW parameters_clause parameters_clause new_initializer_opt
727    '''
728    pass
729
730def p_new_type_id(p):
731    '''new_type_id :                type_specifier ptr_operator_seq_opt
732    |                               type_specifier new_declarator
733    |                               type_specifier new_type_id
734    '''
735    pass
736
737def p_new_declarator(p):
738    '''new_declarator :             ptr_operator new_declarator
739    |                               direct_new_declarator
740    '''
741    pass
742
743def p_direct_new_declarator(p):
744    '''direct_new_declarator :      LBRACKET bexpression_opt RBRACKET
745    |                               direct_new_declarator LBRACKET bexpression RBRACKET
746    '''
747    pass
748
749def p_new_initializer_opt(p):
750    '''new_initializer_opt :        empty
751    |                               '(' expression_list_opt ')'
752    '''
753    pass
754
755#
756# cast-expression is generalised to support a [] as well as a () prefix. This covers the omission of
757# DELETE[] which when followed by a parenthesised expression was ambiguous. It also covers the gcc
758# indexed array initialisation for free.
759#
760def p_cast_expression(p):
761    '''cast_expression :            unary_expression
762    |                               abstract_expression cast_expression
763    '''
764    p[0] = get_rest(p)
765
766def p_pm_expression(p):
767    '''pm_expression :              cast_expression
768    |                               pm_expression DOT_STAR cast_expression
769    |                               pm_expression ARROW_STAR cast_expression
770    '''
771    p[0] = get_rest(p)
772
773def p_multiplicative_expression(p):
774    '''multiplicative_expression :  pm_expression
775    |                               multiplicative_expression star_ptr_operator pm_expression
776    |                               multiplicative_expression '/' pm_expression
777    |                               multiplicative_expression '%' pm_expression
778    '''
779    p[0] = get_rest(p)
780
781def p_additive_expression(p):
782    '''additive_expression :        multiplicative_expression
783    |                               additive_expression '+' multiplicative_expression
784    |                               additive_expression '-' multiplicative_expression
785    '''
786    p[0] = get_rest(p)
787
788def p_shift_expression(p):
789    '''shift_expression :           additive_expression
790    |                               shift_expression SHL additive_expression
791    |                               shift_expression SHR additive_expression
792    '''
793    p[0] = get_rest(p)
794
795#    |                               relational_expression '<' shift_expression
796#    |                               relational_expression '>' shift_expression
797#    |                               relational_expression LE shift_expression
798#    |                               relational_expression GE shift_expression
799def p_relational_expression(p):
800    '''relational_expression :      shift_expression
801    '''
802    p[0] = get_rest(p)
803
804def p_equality_expression(p):
805    '''equality_expression :        relational_expression
806    |                               equality_expression EQ relational_expression
807    |                               equality_expression NE relational_expression
808    '''
809    p[0] = get_rest(p)
810
811def p_and_expression(p):
812    '''and_expression :             equality_expression
813    |                               and_expression '&' equality_expression
814    '''
815    p[0] = get_rest(p)
816
817def p_exclusive_or_expression(p):
818    '''exclusive_or_expression :    and_expression
819    |                               exclusive_or_expression '^' and_expression
820    '''
821    p[0] = get_rest(p)
822
823def p_inclusive_or_expression(p):
824    '''inclusive_or_expression :    exclusive_or_expression
825    |                               inclusive_or_expression '|' exclusive_or_expression
826    '''
827    p[0] = get_rest(p)
828
829def p_logical_and_expression(p):
830    '''logical_and_expression :     inclusive_or_expression
831    |                               logical_and_expression LOG_AND inclusive_or_expression
832    '''
833    p[0] = get_rest(p)
834
835def p_logical_or_expression(p):
836    '''logical_or_expression :      logical_and_expression
837    |                               logical_or_expression LOG_OR logical_and_expression
838    '''
839    p[0] = get_rest(p)
840
841def p_conditional_expression(p):
842    '''conditional_expression :     logical_or_expression
843    |                               logical_or_expression '?' expression ':' assignment_expression
844    '''
845    p[0] = get_rest(p)
846
847
848#
849# assignment-expression is generalised to cover the simple assignment of a braced initializer in order to
850# contribute to the coverage of parameter-declaration and init-declaration.
851#
852#    |                               logical_or_expression assignment_operator assignment_expression
853def p_assignment_expression(p):
854    '''assignment_expression :      conditional_expression
855    |                               logical_or_expression assignment_operator nonsemicolon_seq
856    |                               logical_or_expression '=' braced_initializer
857    |                               throw_expression
858    '''
859    p[0]=get_rest(p)
860
861def p_assignment_operator(p):
862    '''assignment_operator :        '='
863                           | ASS_ADD
864                           | ASS_AND
865                           | ASS_DIV
866                           | ASS_MOD
867                           | ASS_MUL
868                           | ASS_OR
869                           | ASS_SHL
870                           | ASS_SHR
871                           | ASS_SUB
872                           | ASS_XOR
873    '''
874    pass
875
876#
877# expression is widely used and usually single-element, so the reductions are arranged so that a
878# single-element expression is returned as is. Multi-element expressions are parsed as a list that
879# may then behave polymorphically as an element or be compacted to an element.
880#
881
882def p_expression(p):
883    '''expression :                 assignment_expression
884    |                               expression_list ',' assignment_expression
885    '''
886    p[0] = get_rest(p)
887
888def p_constant_expression(p):
889    '''constant_expression :        conditional_expression
890    '''
891    pass
892
893#---------------------------------------------------------------------------------------------------
894# A.5 Statements
895#---------------------------------------------------------------------------------------------------
896# Parsing statements is easy once simple_declaration has been generalised to cover expression_statement.
897#
898#
899# The use of extern here is a hack.  The 'extern "C" {}' block gets parsed
900# as a function, so when nested 'extern "C"' declarations exist, they don't
901# work because the block is viewed as a list of statements... :(
902#
903def p_statement(p):
904    '''statement :                  compound_statement
905    |                               declaration_statement
906    |                               try_block
907    |                               labeled_statement
908    |                               selection_statement
909    |                               iteration_statement
910    |                               jump_statement
911    '''
912    pass
913
914def p_compound_statement(p):
915    '''compound_statement :         LBRACE statement_seq_opt RBRACE
916    '''
917    pass
918
919def p_statement_seq_opt(p):
920    '''statement_seq_opt :          empty
921    |                               statement_seq_opt statement
922    '''
923    pass
924
925#
926#  The dangling else conflict is resolved to the innermost if.
927#
928def p_selection_statement(p):
929    '''selection_statement :        IF '(' condition ')' statement    %prec SHIFT_THERE
930    |                               IF '(' condition ')' statement ELSE statement
931    |                               SWITCH '(' condition ')' statement
932    '''
933    pass
934
935def p_condition_opt(p):
936    '''condition_opt :              empty
937    |                               condition
938    '''
939    pass
940
941def p_condition(p):
942    '''condition :                  nonparen_seq
943    |                               nonparen_seq condition_seq parameters_clause nonparen_seq_opt
944    |                               condition_seq parameters_clause nonparen_seq_opt
945    '''
946    pass
947
948def p_condition_seq(p):
949    '''condition_seq :              empty
950    |                               condition_seq parameters_clause nonparen_seq_opt
951    '''
952    pass
953
954def p_labeled_statement(p):
955    '''labeled_statement :          identifier ':' statement
956    |                               CASE constant_expression ':' statement
957    |                               DEFAULT ':' statement
958    '''
959    pass
960
961def p_try_block(p):
962    '''try_block :                  TRY compound_statement handler_seq
963    '''
964    global noExceptionLogic
965    noExceptionLogic=False
966
967def p_jump_statement(p):
968    '''jump_statement :             BREAK ';'
969    |                               CONTINUE ';'
970    |                               RETURN nonsemicolon_seq ';'
971    |                               GOTO identifier ';'
972    '''
973    pass
974
975def p_iteration_statement(p):
976    '''iteration_statement :        WHILE '(' condition ')' statement
977    |                               DO statement WHILE '(' expression ')' ';'
978    |                               FOR '(' nonparen_seq_opt ')' statement
979    '''
980    pass
981
982def p_declaration_statement(p):
983    '''declaration_statement :      block_declaration
984    '''
985    pass
986
987#---------------------------------------------------------------------------------------------------
988# A.6 Declarations
989#---------------------------------------------------------------------------------------------------
990def p_compound_declaration(p):
991    '''compound_declaration :       LBRACE declaration_seq_opt RBRACE
992    '''
993    pass
994
995def p_declaration_seq_opt(p):
996    '''declaration_seq_opt :        empty
997    |                               declaration_seq_opt declaration
998    '''
999    pass
1000
1001def p_declaration(p):
1002    '''declaration :                block_declaration
1003    |                               function_definition
1004    |                               template_declaration
1005    |                               explicit_specialization
1006    |                               specialised_declaration
1007    '''
1008    pass
1009
1010def p_specialised_declaration(p):
1011    '''specialised_declaration :    linkage_specification
1012    |                               namespace_definition
1013    |                               TEMPLATE specialised_declaration
1014    '''
1015    pass
1016
1017def p_block_declaration(p):
1018    '''block_declaration :          simple_declaration
1019    |                               specialised_block_declaration
1020    '''
1021    pass
1022
1023def p_specialised_block_declaration(p):
1024    '''specialised_block_declaration :      asm_definition
1025    |                               namespace_alias_definition
1026    |                               using_declaration
1027    |                               using_directive
1028    |                               TEMPLATE specialised_block_declaration
1029    '''
1030    pass
1031
1032def p_simple_declaration(p):
1033    '''simple_declaration :         ';'
1034    |                               init_declaration ';'
1035    |                               init_declarations ';'
1036    |                               decl_specifier_prefix simple_declaration
1037    '''
1038    global _parse_info
1039    if len(p) == 3:
1040        if p[2] == ";":
1041            decl = p[1]
1042        else:
1043            decl = p[2]
1044        if decl is not None:
1045            fp = flatten(decl)
1046            if len(fp) >= 2 and fp[0] is not None and fp[0]!="operator" and fp[1] == '(':
1047                p[0] = fp[0]
1048                _parse_info.add_function(fp[0])
1049
1050#
1051#  A decl-specifier following a ptr_operator provokes a shift-reduce conflict for * const name which is resolved in favour of the pointer, and implemented by providing versions of decl-specifier guaranteed not to start with a cv_qualifier.  decl-specifiers are implemented type-centrically. That is the semantic constraint that there must be a type is exploited to impose structure, but actually eliminate very little syntax. built-in types are multi-name and so need a different policy.
1052#
1053#  non-type decl-specifiers are bound to the left-most type in a decl-specifier-seq, by parsing from the right and attaching suffixes to the right-hand type. Finally residual prefixes attach to the left.
1054#
1055def p_suffix_built_in_decl_specifier_raw(p):
1056    '''suffix_built_in_decl_specifier_raw : built_in_type_specifier
1057    |                               suffix_built_in_decl_specifier_raw built_in_type_specifier
1058    |                               suffix_built_in_decl_specifier_raw decl_specifier_suffix
1059    '''
1060    pass
1061
1062def p_suffix_built_in_decl_specifier(p):
1063    '''suffix_built_in_decl_specifier :     suffix_built_in_decl_specifier_raw
1064    |                               TEMPLATE suffix_built_in_decl_specifier
1065    '''
1066    pass
1067
1068#    |                                       id_scope_seq
1069#    |                                       SCOPE id_scope_seq
1070def p_suffix_named_decl_specifier(p):
1071    '''suffix_named_decl_specifier :        scoped_id
1072    |                               elaborate_type_specifier
1073    |                               suffix_named_decl_specifier decl_specifier_suffix
1074    '''
1075    p[0]=get_rest(p)
1076
1077def p_suffix_named_decl_specifier_bi(p):
1078    '''suffix_named_decl_specifier_bi :     suffix_named_decl_specifier
1079    |                               suffix_named_decl_specifier suffix_built_in_decl_specifier_raw
1080    '''
1081    p[0] = get_rest(p)
1082    #print "HERE",get_rest(p)
1083
1084def p_suffix_named_decl_specifiers(p):
1085    '''suffix_named_decl_specifiers :       suffix_named_decl_specifier_bi
1086    |                               suffix_named_decl_specifiers suffix_named_decl_specifier_bi
1087    '''
1088    p[0] = get_rest(p)
1089
1090def p_suffix_named_decl_specifiers_sf(p):
1091    '''suffix_named_decl_specifiers_sf :    scoped_special_function_id
1092    |                               suffix_named_decl_specifiers
1093    |                               suffix_named_decl_specifiers scoped_special_function_id
1094    '''
1095    #print "HERE",get_rest(p)
1096    p[0] = get_rest(p)
1097
1098def p_suffix_decl_specified_ids(p):
1099    '''suffix_decl_specified_ids :          suffix_built_in_decl_specifier
1100    |                               suffix_built_in_decl_specifier suffix_named_decl_specifiers_sf
1101    |                               suffix_named_decl_specifiers_sf
1102    '''
1103    if len(p) == 3:
1104        p[0] = p[2]
1105    else:
1106        p[0] = p[1]
1107
1108def p_suffix_decl_specified_scope(p):
1109    '''suffix_decl_specified_scope : suffix_named_decl_specifiers SCOPE
1110    |                               suffix_built_in_decl_specifier suffix_named_decl_specifiers SCOPE
1111    |                               suffix_built_in_decl_specifier SCOPE
1112    '''
1113    p[0] = get_rest(p)
1114
1115def p_decl_specifier_affix(p):
1116    '''decl_specifier_affix :       storage_class_specifier
1117    |                               function_specifier
1118    |                               FRIEND
1119    |                               TYPEDEF
1120    |                               cv_qualifier
1121    '''
1122    pass
1123
1124def p_decl_specifier_suffix(p):
1125    '''decl_specifier_suffix :      decl_specifier_affix
1126    '''
1127    pass
1128
1129def p_decl_specifier_prefix(p):
1130    '''decl_specifier_prefix :      decl_specifier_affix
1131    |                               TEMPLATE decl_specifier_prefix
1132    '''
1133    pass
1134
1135def p_storage_class_specifier(p):
1136    '''storage_class_specifier :    REGISTER
1137    |                               STATIC
1138    |                               MUTABLE
1139    |                               EXTERN                  %prec SHIFT_THERE
1140    |                               EXTENSION
1141    |                               AUTO
1142    '''
1143    pass
1144
1145def p_function_specifier(p):
1146    '''function_specifier :         EXPLICIT
1147    |                               INLINE
1148    |                               VIRTUAL
1149    '''
1150    pass
1151
1152def p_type_specifier(p):
1153    '''type_specifier :             simple_type_specifier
1154    |                               elaborate_type_specifier
1155    |                               cv_qualifier
1156    '''
1157    pass
1158
1159def p_elaborate_type_specifier(p):
1160    '''elaborate_type_specifier :   class_specifier
1161    |                               enum_specifier
1162    |                               elaborated_type_specifier
1163    |                               TEMPLATE elaborate_type_specifier
1164    '''
1165    pass
1166
1167def p_simple_type_specifier(p):
1168    '''simple_type_specifier :      scoped_id
1169    |                               scoped_id attributes
1170    |                               built_in_type_specifier
1171    '''
1172    p[0] = p[1]
1173
1174def p_built_in_type_specifier(p):
1175    '''built_in_type_specifier : Xbuilt_in_type_specifier
1176    |                            Xbuilt_in_type_specifier attributes
1177    '''
1178    pass
1179
1180def p_attributes(p):
1181    '''attributes :                 attribute
1182    |                               attributes attribute
1183    '''
1184    pass
1185
1186def p_attribute(p):
1187    '''attribute :                  ATTRIBUTE '(' parameters_clause ')'
1188    '''
1189
1190def p_Xbuilt_in_type_specifier(p):
1191    '''Xbuilt_in_type_specifier :    CHAR
1192    | WCHAR_T
1193    | BOOL
1194    | SHORT
1195    | INT
1196    | LONG
1197    | SIGNED
1198    | UNSIGNED
1199    | FLOAT
1200    | DOUBLE
1201    | VOID
1202    | uTYPEOF parameters_clause
1203    | TYPEOF parameters_clause
1204    '''
1205    pass
1206
1207#
1208#  The over-general use of declaration_expression to cover decl-specifier-seq_opt declarator in a function-definition means that
1209#      class X { };
1210#  could be a function-definition or a class-specifier.
1211#      enum X { };
1212#  could be a function-definition or an enum-specifier.
1213#  The function-definition is not syntactically valid so resolving the false conflict in favour of the
1214#  elaborated_type_specifier is correct.
1215#
1216def p_elaborated_type_specifier(p):
1217    '''elaborated_type_specifier :  class_key scoped_id %prec SHIFT_THERE
1218    |                               elaborated_enum_specifier
1219    |                               TYPENAME scoped_id
1220    '''
1221    pass
1222
1223def p_elaborated_enum_specifier(p):
1224    '''elaborated_enum_specifier :  ENUM scoped_id   %prec SHIFT_THERE
1225    '''
1226    pass
1227
1228def p_enum_specifier(p):
1229    '''enum_specifier :             ENUM scoped_id enumerator_clause
1230    |                               ENUM enumerator_clause
1231    '''
1232    pass
1233
1234def p_enumerator_clause(p):
1235    '''enumerator_clause :          LBRACE enumerator_list_ecarb
1236    |                               LBRACE enumerator_list enumerator_list_ecarb
1237    |                               LBRACE enumerator_list ',' enumerator_definition_ecarb
1238    '''
1239    pass
1240
1241def p_enumerator_list_ecarb(p):
1242    '''enumerator_list_ecarb :      RBRACE
1243    '''
1244    pass
1245
1246def p_enumerator_definition_ecarb(p):
1247    '''enumerator_definition_ecarb :        RBRACE
1248    '''
1249    pass
1250
1251def p_enumerator_definition_filler(p):
1252    '''enumerator_definition_filler :       empty
1253    '''
1254    pass
1255
1256def p_enumerator_list_head(p):
1257    '''enumerator_list_head :       enumerator_definition_filler
1258    |                               enumerator_list ',' enumerator_definition_filler
1259    '''
1260    pass
1261
1262def p_enumerator_list(p):
1263    '''enumerator_list :            enumerator_list_head enumerator_definition
1264    '''
1265    pass
1266
1267def p_enumerator_definition(p):
1268    '''enumerator_definition :      enumerator
1269    |                               enumerator '=' constant_expression
1270    '''
1271    pass
1272
1273def p_enumerator(p):
1274    '''enumerator :                 identifier
1275    '''
1276    pass
1277
1278def p_namespace_definition(p):
1279    '''namespace_definition :       NAMESPACE scoped_id push_scope compound_declaration
1280    |                               NAMESPACE push_scope compound_declaration
1281    '''
1282    global _parse_info
1283    scope = _parse_info.pop_scope()
1284
1285def p_namespace_alias_definition(p):
1286    '''namespace_alias_definition : NAMESPACE scoped_id '=' scoped_id ';'
1287    '''
1288    pass
1289
1290def p_push_scope(p):
1291    '''push_scope :                 empty'''
1292    global _parse_info
1293    if p[-2] == "namespace":
1294        scope=p[-1]
1295    else:
1296        scope=""
1297    _parse_info.push_scope(scope,"namespace")
1298
1299def p_using_declaration(p):
1300    '''using_declaration :          USING declarator_id ';'
1301    |                               USING TYPENAME declarator_id ';'
1302    '''
1303    pass
1304
1305def p_using_directive(p):
1306    '''using_directive :            USING NAMESPACE scoped_id ';'
1307    '''
1308    pass
1309
1310#    '''asm_definition :             ASM '(' StringLiteral ')' ';'
1311def p_asm_definition(p):
1312    '''asm_definition :             ASM '(' nonparen_seq_opt ')' ';'
1313    '''
1314    pass
1315
1316def p_linkage_specification(p):
1317    '''linkage_specification :      EXTERN CLiteral declaration
1318    |                               EXTERN CLiteral compound_declaration
1319    |                               EXTERN CppLiteral declaration
1320    |                               EXTERN CppLiteral compound_declaration
1321    '''
1322    pass
1323
1324#---------------------------------------------------------------------------------------------------
1325# A.7 Declarators
1326#---------------------------------------------------------------------------------------------------
1327#
1328# init-declarator is named init_declaration to reflect the embedded decl-specifier-seq_opt
1329#
1330
1331def p_init_declarations(p):
1332    '''init_declarations :          assignment_expression ',' init_declaration
1333    |                               init_declarations ',' init_declaration
1334    '''
1335    p[0]=get_rest(p)
1336
1337def p_init_declaration(p):
1338    '''init_declaration :           assignment_expression
1339    '''
1340    p[0]=get_rest(p)
1341
1342def p_star_ptr_operator(p):
1343    '''star_ptr_operator :          '*'
1344    |                               star_ptr_operator cv_qualifier
1345    '''
1346    pass
1347
1348def p_nested_ptr_operator(p):
1349    '''nested_ptr_operator :        star_ptr_operator
1350    |                               id_scope nested_ptr_operator
1351    '''
1352    pass
1353
1354def p_ptr_operator(p):
1355    '''ptr_operator :               '&'
1356    |                               nested_ptr_operator
1357    |                               global_scope nested_ptr_operator
1358    '''
1359    pass
1360
1361def p_ptr_operator_seq(p):
1362    '''ptr_operator_seq :           ptr_operator
1363    |                               ptr_operator ptr_operator_seq
1364    '''
1365    pass
1366
1367#
1368# Independently coded to localise the shift-reduce conflict: sharing just needs another %prec
1369#
1370def p_ptr_operator_seq_opt(p):
1371    '''ptr_operator_seq_opt :       empty %prec SHIFT_THERE
1372    |                               ptr_operator ptr_operator_seq_opt
1373    '''
1374    pass
1375
1376def p_cv_qualifier_seq_opt(p):
1377    '''cv_qualifier_seq_opt :       empty
1378    |                               cv_qualifier_seq_opt cv_qualifier
1379    '''
1380    pass
1381
1382# TODO: verify that we should include attributes here
1383def p_cv_qualifier(p):
1384    '''cv_qualifier :               CONST
1385    |                               VOLATILE
1386    |                               attributes
1387    '''
1388    pass
1389
1390def p_type_id(p):
1391    '''type_id :                    type_specifier abstract_declarator_opt
1392    |                               type_specifier type_id
1393    '''
1394    pass
1395
1396def p_abstract_declarator_opt(p):
1397    '''abstract_declarator_opt :    empty
1398    |                               ptr_operator abstract_declarator_opt
1399    |                               direct_abstract_declarator
1400    '''
1401    pass
1402
1403def p_direct_abstract_declarator_opt(p):
1404    '''direct_abstract_declarator_opt :     empty
1405    |                               direct_abstract_declarator
1406    '''
1407    pass
1408
1409def p_direct_abstract_declarator(p):
1410    '''direct_abstract_declarator : direct_abstract_declarator_opt parenthesis_clause
1411    |                               direct_abstract_declarator_opt LBRACKET RBRACKET
1412    |                               direct_abstract_declarator_opt LBRACKET bexpression RBRACKET
1413    '''
1414    pass
1415
1416def p_parenthesis_clause(p):
1417    '''parenthesis_clause :         parameters_clause cv_qualifier_seq_opt
1418    |                               parameters_clause cv_qualifier_seq_opt exception_specification
1419    '''
1420    p[0] = ['(',')']
1421
1422def p_parameters_clause(p):
1423    '''parameters_clause :          '(' condition_opt ')'
1424    '''
1425    p[0] = ['(',')']
1426
1427#
1428# A typed abstract qualifier such as
1429#      Class * ...
1430# looks like a multiply, so pointers are parsed as their binary operation equivalents that
1431# ultimately terminate with a degenerate right hand term.
1432#
1433def p_abstract_pointer_declaration(p):
1434    '''abstract_pointer_declaration :       ptr_operator_seq
1435    |                               multiplicative_expression star_ptr_operator ptr_operator_seq_opt
1436    '''
1437    pass
1438
1439def p_abstract_parameter_declaration(p):
1440    '''abstract_parameter_declaration :     abstract_pointer_declaration
1441    |                               and_expression '&'
1442    |                               and_expression '&' abstract_pointer_declaration
1443    '''
1444    pass
1445
1446def p_special_parameter_declaration(p):
1447    '''special_parameter_declaration :      abstract_parameter_declaration
1448    |                               abstract_parameter_declaration '=' assignment_expression
1449    |                               ELLIPSIS
1450    '''
1451    pass
1452
1453def p_parameter_declaration(p):
1454    '''parameter_declaration :      assignment_expression
1455    |                               special_parameter_declaration
1456    |                               decl_specifier_prefix parameter_declaration
1457    '''
1458    pass
1459
1460#
1461# function_definition includes constructor, destructor, implicit int definitions too.  A local destructor is successfully parsed as a function-declaration but the ~ was treated as a unary operator.  constructor_head is the prefix ambiguity between a constructor and a member-init-list starting with a bit-field.
1462#
1463def p_function_definition(p):
1464    '''function_definition :        ctor_definition
1465    |                               func_definition
1466    '''
1467    pass
1468
1469def p_func_definition(p):
1470    '''func_definition :            assignment_expression function_try_block
1471    |                               assignment_expression function_body
1472    |                               decl_specifier_prefix func_definition
1473    '''
1474    global _parse_info
1475    if p[2] is not None and p[2][0] == '{':
1476        decl = flatten(p[1])
1477        #print "HERE",decl
1478        if decl[-1] == ')':
1479            decl=decl[-3]
1480        else:
1481            decl=decl[-1]
1482        p[0] = decl
1483        if decl != "operator":
1484            _parse_info.add_function(decl)
1485    else:
1486        p[0] = p[2]
1487
1488def p_ctor_definition(p):
1489    '''ctor_definition :            constructor_head function_try_block
1490    |                               constructor_head function_body
1491    |                               decl_specifier_prefix ctor_definition
1492    '''
1493    if p[2] is None or p[2][0] == "try" or p[2][0] == '{':
1494        p[0]=p[1]
1495    else:
1496        p[0]=p[1]
1497
1498def p_constructor_head(p):
1499    '''constructor_head :           bit_field_init_declaration
1500    |                               constructor_head ',' assignment_expression
1501    '''
1502    p[0]=p[1]
1503
1504def p_function_try_block(p):
1505    '''function_try_block :         TRY function_block handler_seq
1506    '''
1507    global noExceptionLogic
1508    noExceptionLogic=False
1509    p[0] = ['try']
1510
1511def p_function_block(p):
1512    '''function_block :             ctor_initializer_opt function_body
1513    '''
1514    pass
1515
1516def p_function_body(p):
1517    '''function_body :              LBRACE nonbrace_seq_opt RBRACE
1518    '''
1519    p[0] = ['{','}']
1520
1521def p_initializer_clause(p):
1522    '''initializer_clause :         assignment_expression
1523    |                               braced_initializer
1524    '''
1525    pass
1526
1527def p_braced_initializer(p):
1528    '''braced_initializer :         LBRACE initializer_list RBRACE
1529    |                               LBRACE initializer_list ',' RBRACE
1530    |                               LBRACE RBRACE
1531    '''
1532    pass
1533
1534def p_initializer_list(p):
1535    '''initializer_list :           initializer_clause
1536    |                               initializer_list ',' initializer_clause
1537    '''
1538    pass
1539
1540#---------------------------------------------------------------------------------------------------
1541# A.8 Classes
1542#---------------------------------------------------------------------------------------------------
1543#
1544#  An anonymous bit-field declaration may look very like inheritance:
1545#      const int B = 3;
1546#      class A : B ;
1547#  The two usages are too distant to try to create and enforce a common prefix so we have to resort to
1548#  a parser hack by backtracking. Inheritance is much the most likely so we mark the input stream context
1549#  and try to parse a base-clause. If we successfully reach a { the base-clause is ok and inheritance was
1550#  the correct choice so we unmark and continue. If we fail to find the { an error token causes
1551#  back-tracking to the alternative parse in elaborated_type_specifier which regenerates the : and
1552#  declares unconditional success.
1553#
1554
1555def p_class_specifier_head(p):
1556    '''class_specifier_head :       class_key scoped_id ':' base_specifier_list LBRACE
1557    |                               class_key ':' base_specifier_list LBRACE
1558    |                               class_key scoped_id LBRACE
1559    |                               class_key LBRACE
1560    '''
1561    global _parse_info
1562    base_classes=[]
1563    if len(p) == 6:
1564        scope = p[2]
1565        base_classes = p[4]
1566    elif len(p) == 4:
1567        scope = p[2]
1568    elif len(p) == 5:
1569        base_classes = p[3]
1570    else:
1571        scope = ""
1572    _parse_info.push_scope(scope,p[1],base_classes)
1573
1574
1575def p_class_key(p):
1576    '''class_key :                  CLASS
1577    | STRUCT
1578    | UNION
1579    '''
1580    p[0] = p[1]
1581
1582def p_class_specifier(p):
1583    '''class_specifier :            class_specifier_head member_specification_opt RBRACE
1584    '''
1585    scope = _parse_info.pop_scope()
1586
1587def p_member_specification_opt(p):
1588    '''member_specification_opt :   empty
1589    |                               member_specification_opt member_declaration
1590    '''
1591    pass
1592
1593def p_member_declaration(p):
1594    '''member_declaration :         accessibility_specifier
1595    |                               simple_member_declaration
1596    |                               function_definition
1597    |                               using_declaration
1598    |                               template_declaration
1599    '''
1600    p[0] = get_rest(p)
1601    #print "Decl",get_rest(p)
1602
1603#
1604#  The generality of constructor names (there need be no parenthesised argument list) means that that
1605#          name : f(g), h(i)
1606#  could be the start of a constructor or the start of an anonymous bit-field. An ambiguity is avoided by
1607#  parsing the ctor-initializer of a function_definition as a bit-field.
1608#
1609def p_simple_member_declaration(p):
1610    '''simple_member_declaration :  ';'
1611    |                               assignment_expression ';'
1612    |                               constructor_head ';'
1613    |                               member_init_declarations ';'
1614    |                               decl_specifier_prefix simple_member_declaration
1615    '''
1616    global _parse_info
1617    decl = flatten(get_rest(p))
1618    if len(decl) >= 4 and decl[-3] == "(":
1619        _parse_info.add_function(decl[-4])
1620
1621def p_member_init_declarations(p):
1622    '''member_init_declarations :   assignment_expression ',' member_init_declaration
1623    |                               constructor_head ',' bit_field_init_declaration
1624    |                               member_init_declarations ',' member_init_declaration
1625    '''
1626    pass
1627
1628def p_member_init_declaration(p):
1629    '''member_init_declaration :    assignment_expression
1630    |                               bit_field_init_declaration
1631    '''
1632    pass
1633
1634def p_accessibility_specifier(p):
1635    '''accessibility_specifier :    access_specifier ':'
1636    '''
1637    pass
1638
1639def p_bit_field_declaration(p):
1640    '''bit_field_declaration :      assignment_expression ':' bit_field_width
1641    |                               ':' bit_field_width
1642    '''
1643    if len(p) == 4:
1644        p[0]=p[1]
1645
1646def p_bit_field_width(p):
1647    '''bit_field_width :            logical_or_expression
1648    |                               logical_or_expression '?' bit_field_width ':' bit_field_width
1649    '''
1650    pass
1651
1652def p_bit_field_init_declaration(p):
1653    '''bit_field_init_declaration : bit_field_declaration
1654    |                               bit_field_declaration '=' initializer_clause
1655    '''
1656    pass
1657
1658#---------------------------------------------------------------------------------------------------
1659# A.9 Derived classes
1660#---------------------------------------------------------------------------------------------------
1661def p_base_specifier_list(p):
1662    '''base_specifier_list :        base_specifier
1663    |                               base_specifier_list ',' base_specifier
1664    '''
1665    if len(p) == 2:
1666        p[0] = [p[1]]
1667    else:
1668        p[0] = p[1]+[p[3]]
1669
1670def p_base_specifier(p):
1671    '''base_specifier :             scoped_id
1672    |                               access_specifier base_specifier
1673    |                               VIRTUAL base_specifier
1674    '''
1675    if len(p) == 2:
1676        p[0] = p[1]
1677    else:
1678        p[0] = p[2]
1679
1680def p_access_specifier(p):
1681    '''access_specifier :           PRIVATE
1682    |                               PROTECTED
1683    |                               PUBLIC
1684    '''
1685    pass
1686
1687#---------------------------------------------------------------------------------------------------
1688# A.10 Special member functions
1689#---------------------------------------------------------------------------------------------------
1690def p_conversion_function_id(p):
1691    '''conversion_function_id :     OPERATOR conversion_type_id
1692    '''
1693    p[0] = ['operator']
1694
1695def p_conversion_type_id(p):
1696    '''conversion_type_id :         type_specifier ptr_operator_seq_opt
1697    |                               type_specifier conversion_type_id
1698    '''
1699    pass
1700
1701#
1702#  Ctor-initialisers can look like a bit field declaration, given the generalisation of names:
1703#      Class(Type) : m1(1), m2(2) { }
1704#      NonClass(bit_field) : int(2), second_variable, ...
1705#  The grammar below is used within a function_try_block or function_definition.
1706#  See simple_member_declaration for use in normal member function_definition.
1707#
1708def p_ctor_initializer_opt(p):
1709    '''ctor_initializer_opt :       empty
1710    |                               ctor_initializer
1711    '''
1712    pass
1713
1714def p_ctor_initializer(p):
1715    '''ctor_initializer :           ':' mem_initializer_list
1716    '''
1717    pass
1718
1719def p_mem_initializer_list(p):
1720    '''mem_initializer_list :       mem_initializer
1721    |                               mem_initializer_list_head mem_initializer
1722    '''
1723    pass
1724
1725def p_mem_initializer_list_head(p):
1726    '''mem_initializer_list_head :  mem_initializer_list ','
1727    '''
1728    pass
1729
1730def p_mem_initializer(p):
1731    '''mem_initializer :            mem_initializer_id '(' expression_list_opt ')'
1732    '''
1733    pass
1734
1735def p_mem_initializer_id(p):
1736    '''mem_initializer_id :         scoped_id
1737    '''
1738    pass
1739
1740#---------------------------------------------------------------------------------------------------
1741# A.11 Overloading
1742#---------------------------------------------------------------------------------------------------
1743
1744def p_operator_function_id(p):
1745    '''operator_function_id :       OPERATOR operator
1746    |                               OPERATOR '(' ')'
1747    |                               OPERATOR LBRACKET RBRACKET
1748    |                               OPERATOR '<'
1749    |                               OPERATOR '>'
1750    |                               OPERATOR operator '<' nonlgt_seq_opt '>'
1751    '''
1752    p[0] = ["operator"]
1753
1754#
1755#  It is not clear from the ANSI standard whether spaces are permitted in delete[]. If not then it can
1756#  be recognised and returned as DELETE_ARRAY by the lexer. Assuming spaces are permitted there is an
1757#  ambiguity created by the over generalised nature of expressions. operator new is a valid delarator-id
1758#  which we may have an undimensioned array of. Semantic rubbish, but syntactically valid. Since the
1759#  array form is covered by the declarator consideration we can exclude the operator here. The need
1760#  for a semantic rescue can be eliminated at the expense of a couple of shift-reduce conflicts by
1761#  removing the comments on the next four lines.
1762#
1763def p_operator(p):
1764    '''operator :                   NEW
1765    |                               DELETE
1766    |                               '+'
1767    |                               '-'
1768    |                               '*'
1769    |                               '/'
1770    |                               '%'
1771    |                               '^'
1772    |                               '&'
1773    |                               '|'
1774    |                               '~'
1775    |                               '!'
1776    |                               '='
1777    |                               ASS_ADD
1778    |                               ASS_SUB
1779    |                               ASS_MUL
1780    |                               ASS_DIV
1781    |                               ASS_MOD
1782    |                               ASS_XOR
1783    |                               ASS_AND
1784    |                               ASS_OR
1785    |                               SHL
1786    |                               SHR
1787    |                               ASS_SHR
1788    |                               ASS_SHL
1789    |                               EQ
1790    |                               NE
1791    |                               LE
1792    |                               GE
1793    |                               LOG_AND
1794    |                               LOG_OR
1795    |                               INC
1796    |                               DEC
1797    |                               ','
1798    |                               ARROW_STAR
1799    |                               ARROW
1800    '''
1801    p[0]=p[1]
1802
1803#    |                               IF
1804#    |                               SWITCH
1805#    |                               WHILE
1806#    |                               FOR
1807#    |                               DO
1808def p_reserved(p):
1809    '''reserved :                   PRIVATE
1810    |                               CLiteral
1811    |                               CppLiteral
1812    |                               IF
1813    |                               SWITCH
1814    |                               WHILE
1815    |                               FOR
1816    |                               DO
1817    |                               PROTECTED
1818    |                               PUBLIC
1819    |                               BOOL
1820    |                               CHAR
1821    |                               DOUBLE
1822    |                               FLOAT
1823    |                               INT
1824    |                               LONG
1825    |                               SHORT
1826    |                               SIGNED
1827    |                               UNSIGNED
1828    |                               VOID
1829    |                               WCHAR_T
1830    |                               CLASS
1831    |                               ENUM
1832    |                               NAMESPACE
1833    |                               STRUCT
1834    |                               TYPENAME
1835    |                               UNION
1836    |                               CONST
1837    |                               VOLATILE
1838    |                               AUTO
1839    |                               EXPLICIT
1840    |                               EXPORT
1841    |                               EXTERN
1842    |                               FRIEND
1843    |                               INLINE
1844    |                               MUTABLE
1845    |                               REGISTER
1846    |                               STATIC
1847    |                               TEMPLATE
1848    |                               TYPEDEF
1849    |                               USING
1850    |                               VIRTUAL
1851    |                               ASM
1852    |                               BREAK
1853    |                               CASE
1854    |                               CATCH
1855    |                               CONST_CAST
1856    |                               CONTINUE
1857    |                               DEFAULT
1858    |                               DYNAMIC_CAST
1859    |                               ELSE
1860    |                               FALSE
1861    |                               GOTO
1862    |                               OPERATOR
1863    |                               REINTERPRET_CAST
1864    |                               RETURN
1865    |                               SIZEOF
1866    |                               STATIC_CAST
1867    |                               THIS
1868    |                               THROW
1869    |                               TRUE
1870    |                               TRY
1871    |                               TYPEID
1872    |                               ATTRIBUTE
1873    |                               CDECL
1874    |                               TYPEOF
1875    |                               uTYPEOF
1876    '''
1877    if p[1] in ('try', 'catch', 'throw'):
1878        global noExceptionLogic
1879        noExceptionLogic=False
1880
1881#---------------------------------------------------------------------------------------------------
1882# A.12 Templates
1883#---------------------------------------------------------------------------------------------------
1884def p_template_declaration(p):
1885    '''template_declaration :       template_parameter_clause declaration
1886    |                               EXPORT template_declaration
1887    '''
1888    pass
1889
1890def p_template_parameter_clause(p):
1891    '''template_parameter_clause :  TEMPLATE '<' nonlgt_seq_opt '>'
1892    '''
1893    pass
1894
1895#
1896#  Generalised naming makes identifier a valid declaration, so TEMPLATE identifier is too.
1897#  The TEMPLATE prefix is therefore folded into all names, parenthesis_clause and decl_specifier_prefix.
1898#
1899# explicit_instantiation:           TEMPLATE declaration
1900#
1901def p_explicit_specialization(p):
1902    '''explicit_specialization :    TEMPLATE '<' '>' declaration
1903    '''
1904    pass
1905
1906#---------------------------------------------------------------------------------------------------
1907# A.13 Exception Handling
1908#---------------------------------------------------------------------------------------------------
1909def p_handler_seq(p):
1910    '''handler_seq :                handler
1911    |                               handler handler_seq
1912    '''
1913    pass
1914
1915def p_handler(p):
1916    '''handler :                    CATCH '(' exception_declaration ')' compound_statement
1917    '''
1918    global noExceptionLogic
1919    noExceptionLogic=False
1920
1921def p_exception_declaration(p):
1922    '''exception_declaration :      parameter_declaration
1923    '''
1924    pass
1925
1926def p_throw_expression(p):
1927    '''throw_expression :           THROW
1928    |                               THROW assignment_expression
1929    '''
1930    global noExceptionLogic
1931    noExceptionLogic=False
1932
1933def p_exception_specification(p):
1934    '''exception_specification :    THROW '(' ')'
1935    |                               THROW '(' type_id_list ')'
1936    '''
1937    global noExceptionLogic
1938    noExceptionLogic=False
1939
1940def p_type_id_list(p):
1941    '''type_id_list :               type_id
1942    |                               type_id_list ',' type_id
1943    '''
1944    pass
1945
1946#---------------------------------------------------------------------------------------------------
1947# Misc productions
1948#---------------------------------------------------------------------------------------------------
1949def p_nonsemicolon_seq(p):
1950    '''nonsemicolon_seq :           empty
1951    |                               nonsemicolon_seq nonsemicolon
1952    '''
1953    pass
1954
1955def p_nonsemicolon(p):
1956    '''nonsemicolon :               misc
1957    |                               '('
1958    |                               ')'
1959    |                               '<'
1960    |                               '>'
1961    |                               LBRACKET nonbracket_seq_opt RBRACKET
1962    |                               LBRACE nonbrace_seq_opt RBRACE
1963    '''
1964    pass
1965
1966def p_nonparen_seq_opt(p):
1967    '''nonparen_seq_opt :           empty
1968    |                               nonparen_seq_opt nonparen
1969    '''
1970    pass
1971
1972def p_nonparen_seq(p):
1973    '''nonparen_seq :               nonparen
1974    |                               nonparen_seq nonparen
1975    '''
1976    pass
1977
1978def p_nonparen(p):
1979    '''nonparen :                   misc
1980    |                               '<'
1981    |                               '>'
1982    |                               ';'
1983    |                               LBRACKET nonbracket_seq_opt RBRACKET
1984    |                               LBRACE nonbrace_seq_opt RBRACE
1985    '''
1986    pass
1987
1988def p_nonbracket_seq_opt(p):
1989    '''nonbracket_seq_opt :         empty
1990    |                               nonbracket_seq_opt nonbracket
1991    '''
1992    pass
1993
1994def p_nonbracket_seq(p):
1995    '''nonbracket_seq :             nonbracket
1996    |                               nonbracket_seq nonbracket
1997    '''
1998    pass
1999
2000def p_nonbracket(p):
2001    '''nonbracket :                 misc
2002    |                               '<'
2003    |                               '>'
2004    |                               '('
2005    |                               ')'
2006    |                               ';'
2007    |                               LBRACKET nonbracket_seq_opt RBRACKET
2008    |                               LBRACE nonbrace_seq_opt RBRACE
2009    '''
2010    pass
2011
2012def p_nonbrace_seq_opt(p):
2013    '''nonbrace_seq_opt :           empty
2014    |                               nonbrace_seq_opt nonbrace
2015    '''
2016    pass
2017
2018def p_nonbrace(p):
2019    '''nonbrace :                   misc
2020    |                               '<'
2021    |                               '>'
2022    |                               '('
2023    |                               ')'
2024    |                               ';'
2025    |                               LBRACKET nonbracket_seq_opt RBRACKET
2026    |                               LBRACE nonbrace_seq_opt RBRACE
2027    '''
2028    pass
2029
2030def p_nonlgt_seq_opt(p):
2031    '''nonlgt_seq_opt :             empty
2032    |                               nonlgt_seq_opt nonlgt
2033    '''
2034    pass
2035
2036def p_nonlgt(p):
2037    '''nonlgt :                     misc
2038    |                               '('
2039    |                               ')'
2040    |                               LBRACKET nonbracket_seq_opt RBRACKET
2041    |                               '<' nonlgt_seq_opt '>'
2042    |                               ';'
2043    '''
2044    pass
2045
2046def p_misc(p):
2047    '''misc :                       operator
2048    |                               identifier
2049    |                               IntegerLiteral
2050    |                               CharacterLiteral
2051    |                               FloatingLiteral
2052    |                               StringLiteral
2053    |                               reserved
2054    |                               '?'
2055    |                               ':'
2056    |                               '.'
2057    |                               SCOPE
2058    |                               ELLIPSIS
2059    |                               EXTENSION
2060    '''
2061    pass
2062
2063def p_empty(p):
2064    '''empty : '''
2065    pass
2066
2067
2068
2069#
2070# Compute column.
2071#     input is the input text string
2072#     token is a token instance
2073#
2074def _find_column(input,token):
2075    ''' TODO '''
2076    i = token.lexpos
2077    while i > 0:
2078        if input[i] == '\n': break
2079        i -= 1
2080    column = (token.lexpos - i)+1
2081    return column
2082
2083def p_error(p):
2084    if p is None:
2085        tmp = "Syntax error at end of file."
2086    else:
2087        tmp = "Syntax error at token "
2088        if p.type is "":
2089            tmp = tmp + "''"
2090        else:
2091            tmp = tmp + str(p.type)
2092        tmp = tmp + " with value '"+str(p.value)+"'"
2093        tmp = tmp + " in line " + str(lexer.lineno-1)
2094        tmp = tmp + " at column "+str(_find_column(_parsedata,p))
2095    raise IOError( tmp )
2096
2097
2098
2099#
2100# The function that performs the parsing
2101#
2102def parse_cpp(data=None, filename=None, debug=0, optimize=0, verbose=False, func_filter=None):
2103    if debug > 0:
2104        print("Debugging parse_cpp!")
2105        #
2106        # Always remove the parser.out file, which is generated to create debugging
2107        #
2108        if os.path.exists("parser.out"):
2109            os.remove("parser.out")
2110        #
2111        # Remove the parsetab.py* files.  These apparently need to be removed
2112        # to ensure the creation of a parser.out file.
2113        #
2114        if os.path.exists("parsetab.py"):
2115           os.remove("parsetab.py")
2116        if os.path.exists("parsetab.pyc"):
2117           os.remove("parsetab.pyc")
2118        global debugging
2119        debugging=True
2120    #
2121    # Build lexer
2122    #
2123    global lexer
2124    lexer = lex.lex()
2125    #
2126    # Initialize parse object
2127    #
2128    global _parse_info
2129    _parse_info = CppInfo(filter=func_filter)
2130    _parse_info.verbose=verbose
2131    #
2132    # Build yaccer
2133    #
2134    write_table = not os.path.exists("parsetab.py")
2135    yacc.yacc(debug=debug, optimize=optimize, write_tables=write_table)
2136    #
2137    # Parse the file
2138    #
2139    global _parsedata
2140    if not data is None:
2141        _parsedata=data
2142        ply_init(_parsedata)
2143        yacc.parse(data,debug=debug)
2144    elif not filename is None:
2145        f = open(filename)
2146        data = f.read()
2147        f.close()
2148        _parsedata=data
2149        ply_init(_parsedata)
2150        yacc.parse(data, debug=debug)
2151    else:
2152        return None
2153    #
2154    if not noExceptionLogic:
2155        _parse_info.noExceptionLogic = False
2156    else:
2157        for key in identifier_lineno:
2158            if 'ASSERT_THROWS' in key:
2159                _parse_info.noExceptionLogic = False
2160                break
2161        _parse_info.noExceptionLogic = True
2162    #
2163    return _parse_info
2164
2165
2166
2167import sys
2168
2169if __name__ == '__main__':
2170    #
2171    # This MAIN routine parses a sequence of files provided at the command
2172    # line.  If '-v' is included, then a verbose parsing output is
2173    # generated.
2174    #
2175    for arg in sys.argv[1:]:
2176        if arg == "-v":
2177            continue
2178        print("Parsing file '"+arg+"'")
2179        if '-v' in sys.argv:
2180            parse_cpp(filename=arg,debug=2,verbose=2)
2181        else:
2182            parse_cpp(filename=arg,verbose=2)
2183        #
2184        # Print the _parse_info object summary for this file.
2185        # This illustrates how class inheritance can be used to
2186        # deduce class members.
2187        #
2188        print(str(_parse_info))
2189
2190