File indexing completed on 2024-12-08 04:20:21

0001 # -*- coding: utf-8 -*-
0002 #     Copyright 2007-8 Jim Bublitz <jbublitz@nwinternet.com>
0003 #     Copyright 2009 Simon Edwards <simon@simonzone.com>
0004 #
0005 # This program is free software; you can redistribute it and/or modify
0006 # it under the terms of the GNU General Public License as published by
0007 # the Free Software Foundation; either version 2 of the License, or
0008 # (at your option) any later version.
0009 #
0010 # This program is distributed in the hope that it will be useful,
0011 # but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 # GNU General Public License for more details.
0014 #
0015 # You should have received a copy of the GNU General Public License
0016 # along with this program; if not, write to the
0017 # Free Software Foundation, Inc.,
0018 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0019 
0020 import sys
0021 import re
0022 from .sealed import sealed
0023 import ply.yacc as yacc
0024 import kbindinggenerator.cpplexer as cpplexer
0025 import kbindinggenerator.pplexer as pplexer
0026 import inspect
0027 
0028 def joinp(p, startindex, string=" "):
0029     tmplist = []
0030     i = startindex
0031     while i < len(p):
0032         tmplist.append(p[i])
0033         i += 1
0034     return string.join(tmplist)
0035 
0036 class CppParser(object):
0037     """Parser for C++ header files."""
0038 
0039     @sealed
0040     def __init__(self):
0041         """Instantiate a new C++ parser."""
0042         self._bareMacros = []
0043         self._macros = []
0044         self._preprocessorValues = {}
0045         self._preprocessorSubstitutionMacros = []
0046 
0047         self.lexer = cpplexer.CppLexer()
0048         self.lexer.begin('variable')
0049         self._resetState()
0050         self.tokens = cpplexer.tokens
0051         yacc.yacc(module = self, tabmodule = "cppParserTab")
0052         self._parse = yacc.parse
0053 
0054     def _resetState(self):
0055         self.filename = None
0056         self._scopeStack = []
0057         self.scope = None
0058         self.access = "public"
0059         self._accessStack = []
0060         self.currentFunction = None
0061         self.currentClass = None
0062         self.exprElement = None
0063         self.inTypedef = False
0064 
0065         self.arguments      = []
0066         self.templateParams = []
0067         self.storage        = ''
0068         self.inline         = False
0069         self.template       = None
0070         self.exprElements   = []
0071         self.symbolData = None
0072         self.scope = None
0073 
0074     @property
0075     def bareMacros(self):
0076         """List of bare macro names.
0077 
0078         A bare macro is C++ macro which takes no arguments. Any bare macros
0079         are parsed and recorded in a `ScopedMacro` object."""
0080         return self._bareMacros
0081     @bareMacros.setter
0082     def bareMacros(self,bareMacroList):
0083         self._bareMacros = bareMacroList
0084         self.lexer.lexmodule.setBareMacros(bareMacroList)
0085 
0086     @property
0087     def macros(self):
0088         """List of macro names.
0089 
0090         Any macros are parsed and recorded in a `ScopedMacro` object along
0091         with their arguments."""
0092         return self._macros
0093     @macros.setter
0094     def macros(self,macroList):
0095         self.lexer.lexmodule.setMacros(macroList)
0096         self._macros = macroList
0097 
0098     @property
0099     def preprocessorValues(self):
0100         """List of symbols and values to be used by the preprocessor.
0101 
0102         This is a dict mapping string values to values which can be used when
0103         evaluating preprocessor expressions."""
0104         return self._preprocessorValues
0105     @preprocessorValues.setter
0106     def preprocessorValues(self,valueList):
0107         self._preprocessorValues = valueList
0108         
0109     @property
0110     def preprocessorSubstitutionMacros(self):
0111         """Macros to be substituated by the C++ preprocessor.
0112 
0113         This is a list of tuples. The first value is a string or regular
0114         expression object which is used to match macros in the text, and
0115         the second value is the substituation text."""
0116         return self._preprocessorSubstitutionMacros
0117     @preprocessorSubstitutionMacros.setter
0118     def preprocessorSubstitutionMacros(self,macroList):
0119         self._preprocessorSubstitutionMacros = macroList
0120         
0121     def parse(self, symbolData, text, filename=None, debugLevel = 0):
0122         """Parse the given C++ header text
0123         
0124         Keyword arguments:
0125         symbolData -- cppsymboldata.SymbolData instance. The parsed entities are added to this instance.
0126         text -- String, the text to parse.
0127         filename -- The filename belonging to the given text. This is used for error messages and can be None.
0128         debugLevel -- Turns on debug messages from the lexer and parser. 0, the default, means no debug. 2 lists the
0129                       tokens as they arrive.
0130         
0131         Returns:
0132         -- Newly created `Scope` object containing the parsed data.
0133         
0134         All of the top level things in the given text are parsed and placed inside the top scope inside the
0135         symbolData. 
0136         
0137         If a parse error is encountered, the whole program is exited. Sorry.
0138         """
0139         self._resetState()
0140         self.filename = filename
0141         
0142         self.symbolData = symbolData
0143         self.scope = self.symbolData.newScope()
0144         
0145         chewedText = pplexer.preprocess(text, self._preprocessorValues, self.__compileMacros(self._preprocessorSubstitutionMacros))
0146 
0147         self.lexer.input(chewedText)
0148         self.lexer.lineno = 1
0149         self.lexer.lexpos = 0
0150 
0151         result = self._parse(debug = debugLevel, lexer = self.lexer)
0152         return self.scope
0153         
0154     def __compileMacros(self, macroList):
0155         # Convert the list of macros to regular expressions. Macro which are
0156         # already regexs don't need to changed. Bare string macros and their
0157         # substituation strings are treated as straight string substituations.
0158         compiledMacros = []
0159         for item in macroList:
0160             if not isinstance(item[0],str):
0161                 compiledMacros.append(item)
0162             else:
0163                 compiledMacros.append( (re.compile(item[0]), re.escape(item[1])) )
0164         return compiledMacros
0165 
0166     def _pushScope(self, newScope):
0167         self._scopeStack.append(self.scope)
0168         self.scope = newScope
0169         #print("\n_pushScope")
0170         #self._dumpScopeStack()
0171 
0172     def _popScope(self):
0173         #print("\n_popScope")
0174         self.scope = self._scopeStack.pop()
0175         #self._dumpScopeStack()
0176 
0177     def _dumpScopeStack(self):
0178         print("Scope stack: [" + (", ".join(repr(s) for s in self._scopeStack)) + "]")
0179         for s in inspect.stack()[:4]:
0180             print(repr(s))
0181 
0182     def _pushAccess(self, newAccess):
0183         self._accessStack.append(self.access)
0184         self.access = newAccess
0185         
0186     def _popAccess(self):
0187         self.access = self._accessStack.pop()
0188 
0189     def object_id_list (self, id_list, obj, objType = None):
0190         idList = id_list.split (',')
0191         if self.inTypedef:
0192             self.stateInfo.currentObject ().name = idList [0]
0193             for id in idList [1:]:
0194                 originalObj = self.stateInfo.popObject ()                
0195                 if obj == 'class':
0196                     newObj = self.classObject (id, objType)
0197                 elif obj == 'enum':
0198                     newObj = self.enumObject (id)
0199                     newObj.enumerators = originalObj.enumerators
0200         else:
0201             for id in idList:
0202                 self.variableObject (id, self.stateInfo.currentObject ().name)
0203                 
0204     def commentObject(self,value):
0205         comment = self.symbolData.Comment(self.scope, self.filename, self.lexer.lineno)
0206         comment.setValue(value)
0207         return comment
0208     
0209     def classObject (self, name, type_):
0210         class_ = self.symbolData.CppClass(self.scope, name, self.filename, self.lexer.lineno)
0211         self.currentClass = class_
0212         self._pushScope(class_)
0213         class_.setAccess(self.access)
0214 
0215     def enumObject (self, name):
0216         enum = self.symbolData.Enum(None, name, self.filename, self.lexer.lineno)
0217         enum.setAccess(self.access)
0218         return enum
0219     
0220     def typedefObject(self, typeName, newName):
0221         tdObj = self.symbolData.Typedef(self.scope, newName, self.filename, self.lexer.lineno)
0222         tdObj.setArgumentType(typeName)
0223 #        if typeName.startswith('QFlags<'):
0224 #            tdObj.template = Template('QFlags', typeName [7:-1])
0225 #       else:
0226 #            tdObj.template = self.template
0227 #        self.template = None
0228 #        self._pushScope(tdObj)
0229         return tdObj
0230         
0231     def bareMacro(self,name):
0232         macro = self.symbolData.ScopedMacro(self.scope, name, self.filename, self.lexer.lineno)
0233         return macro
0234     
0235     def argument(self, argumentType, argumentName = None, argumentValue = None):
0236         self.arguments.append ((argumentType, argumentName, argumentValue, self.template, self.exprElements))
0237         self.template = None
0238         self.exprElements = []
0239         return self.arguments
0240     
0241     def argumentList(self):
0242         instanceList = []
0243         for argTuple in self.arguments:
0244             vtype, name, init, template, exprElements = argTuple
0245             instanceList.append(self.symbolData.Argument(vtype, name, init, template))
0246         return instanceList
0247 
0248     def variableObject(self, name, vtype, init = None):
0249         vObj = self.symbolData.Variable(self.scope, name, self.filename, self.lexer.lineno)
0250         vObj.setArgument(self.symbolData.Argument(vtype, name, init, None, self.template))
0251         vObj.setStorage(self.storage)
0252         vObj.setAccess(self.access)
0253         
0254         self.storage = None
0255         self.template = None
0256         return vObj
0257         
0258     def functionObject(self, name, returns):
0259         if returns=='ctor':
0260             functionObj = self.symbolData.Constructor(self.scope, name, self.filename, self.lexer.lineno)
0261         elif returns=='dtor':
0262             functionObj = self.symbolData.Destructor(self.scope, name, self.filename, self.lexer.lineno)
0263         else:
0264             functionObj = self.symbolData.Function(self.scope, name, self.filename, self.lexer.lineno)
0265             returnArg = self.symbolData.Argument(returns)
0266             functionObj.setReturn(returnArg)
0267         functionObj.setAccess(self.access)
0268 
0269         functionObj.setTemplate(self.template)
0270         self.template = None
0271         
0272         self.exprElements = []
0273 
0274         functionObj.setStorage(self.storage)
0275         self.storage = None
0276 
0277         #functionObj.templateParams = self.stateInfo.inTemplate
0278         #self.stateInfo.inTemplate = []
0279         
0280         self.currentFunction = functionObj
0281         
0282         if self.lexer.lexstate not in ['stmt', 'operator']:
0283             self.lexer.begin ('function')
0284         return functionObj
0285                         
0286     precedence = (('right','UMINUS'), )
0287     #precedence = (('left','+','-'), ('left','*','/'), ('right','UMINUS'), )
0288     
0289     # start
0290     def p_declarations (self, p):
0291         """declarations : member
0292                         | member_list member"""
0293         pass
0294         
0295     def p_member (self, p):
0296         """member : namespace_decl
0297                   | class_decl
0298                   | enum_decl
0299                   | typedef_decl
0300                   | typedef_enum_decl
0301                   | function_decl
0302                   | variable_decl
0303                   | bare_macro
0304                   | skip_macro
0305                   | doccomment
0306                   | SEMI"""
0307         self.lexer.lexstate = 'variable'
0308         self.arguments = []
0309         self.template = None
0310         self.exprElement = None
0311 
0312     def p_member2 (self, p):
0313         """member : template_decl"""
0314         self.lexer.lexstate  = 'variable'
0315         self.template = p[1]
0316         self.arguments = []
0317         self.exprElement = None
0318 
0319     def p_member_list (self, p):
0320         """member_list : member
0321                        | member_list member"""
0322         pass
0323 
0324     def p_namespace_decl0 (self, p):
0325         'namespace_decl : namespace_name LBRACE member_list RBRACE'
0326         self._popScope()
0327         
0328     def p_namespace_decl1 (self, p):
0329         'namespace_decl : namespace_name LBRACE RBRACE'
0330         self._popScope()        
0331         
0332     def p_namespace_decl2 (self, p):
0333         'namespace_decl : namespace LBRACE member_list RBRACE'
0334         pass
0335         
0336     def p_namespace_name (self, p):
0337         'namespace_name : namespace ID'
0338         name = p[2]
0339         namespace = self.symbolData.Namespace(self.scope, name, self.filename, self.lexer.lineno)
0340         self._pushScope(namespace)
0341                         
0342     def p_empty (self, p):
0343         'empty :'
0344         pass
0345  
0346     def p_decl_end (self, p):
0347         """decl_end : SEMI
0348                    | inline_code"""
0349         pass
0350         
0351     def p_class_decl0 (self, p):
0352         """class_decl : class_header class_member_list RBRACE decl_end
0353                       | class_header RBRACE decl_end"""
0354         #name, obj = self.stateInfo.popClass ()
0355         self._popAccess()
0356         self._popScope()
0357         #if not obj.opaque:
0358         #    self.symbolData.objectList.append (EndClassMarker (name, self.lexer.lineno, self.stateInfo))
0359     def p_class_declopaque(self,p):
0360         """class_decl : opaque_class"""
0361         self._popScope()
0362 
0363     def p_class_decl1 (self, p):
0364         'class_decl : class_header class_member_list RBRACE id_list decl_end'
0365         if p [1] in ['class', 'struct', 'union']:
0366             self.object_id_list (p [4], p [1])
0367         else:
0368             self.object_id_list (p [4], 'class')
0369         name, obj = self.stateInfo.popClass ()
0370         self._popAccess()
0371         self._popScope()
0372         
0373     def p_class_member (self, p):
0374         """class_member : class_decl
0375                         | enum_decl
0376                         | typedef_decl
0377                         | typedef_enum_decl
0378                         | access_specifier
0379                         | function_decl
0380                         | variable_decl
0381                         | doccomment
0382                         | bare_macro
0383                         | skip_macro
0384                         | SEMI"""
0385         self.lexer.lexstate  = 'variable'
0386         self.arguments   = []
0387         self.template    = None
0388         self.exprElement = None
0389         
0390     def p_class_member2 (self, p):
0391         """class_member : template_decl"""
0392         self.lexer.lexstate  = 'variable'
0393         self.arguments   = []
0394         self.template    = p[1]
0395         self.exprElement = None
0396             
0397     def p_access_specifier (self, p):
0398         """access_specifier : public COLON
0399                             | public slots COLON
0400                             | protected COLON
0401                             | protected slots COLON
0402                             | private COLON
0403                             | private slots COLON
0404                             | signals COLON
0405                             | slots COLON"""
0406         self.access = p[1]
0407 
0408     def p_base_access_specifier (self, p):
0409         """base_access_specifier : public
0410                                  | protected
0411                                  | private"""
0412         pass
0413 
0414     def p_class_member_list (self, p):
0415         """class_member_list : class_member
0416                              | class_member_list class_member"""
0417         pass
0418 
0419     
0420     def p_class_header0 (self, p):
0421         """class_header : class_name LBRACE
0422                         | class_name COLON base_list LBRACE
0423                         | class_from_typedef"""
0424         p[0] = p[1]
0425         self._pushAccess('private')
0426         
0427     def p_class_header1 (self, p):
0428         """class_header : union LBRACE
0429                         | struct LBRACE"""
0430         self.classObject('anonymous', p[1])
0431         self._pushAccess('private')
0432     
0433     def p_class_name (self, p):
0434         """class_name : class ID
0435                       | struct ID
0436                       | union ID
0437                       | class template_type
0438                       | struct template_type"""
0439         self.classObject(p[2], p[1])
0440         
0441     def p_class_name1 (self, p):
0442         """class_name : class BAREMACRO ID
0443                       | struct BAREMACRO ID
0444                       | union BAREMACRO ID
0445                       | class BAREMACRO template_type
0446                       | struct BAREMACRO template_type"""
0447         self.classObject(p[3], p[1])
0448         self.currentClass.addMacro(self.symbolData.Macro(p[2]))
0449         
0450     def p_opaque_class (self, p):
0451         'opaque_class : class_name SEMI'
0452         self.currentClass.setOpaque(True)
0453     
0454     def p_base_list_element0 (self, p):
0455         """base_list_element : base_access_specifier qualified_id
0456                             | base_access_specifier template_type"""
0457         self.currentClass.addBase(p[2])
0458 
0459     def p_base_list_element1 (self, p):
0460         """base_list_element : virtual base_access_specifier qualified_id
0461                             | virtual base_access_specifier template_type"""
0462         self.currentClass.addBase(p[3])
0463      
0464     def p_base_list_element2 (self, p):
0465         'base_list_element : qualified_id'
0466         self.currentClass.addBase(p[1])
0467 
0468     def p_base_list (self, p):
0469         """base_list : base_list_element
0470                      | base_list COMMA base_list_element"""
0471         pass
0472 
0473     def p_enum_decl0 (self, p):
0474         """enum_decl : enum_statement SEMI"""
0475         self.scope.append(p[1])
0476         
0477     def p_enum_decl1 (self, p):
0478         """enum_decl : enum_statement id_list SEMI"""
0479         self.scope.append(p[1])
0480         #self.lexer.begin('variable')
0481         
0482     def p_enum_statement0 (self, p):
0483         """enum_statement : enum_name enumerator_list RBRACE"""
0484         for enum in p[2]:
0485             p[1].appendEnumerator(enum)
0486         #self._popScope()
0487         self.lexer.begin ('variable')
0488         p[0] = p[1]
0489         
0490     def p_enum_statement1 (self, p):
0491         """enum_statement : enum_name RBRACE"""
0492         p[0] = p[1]
0493         self.lexer.begin ('variable')
0494         
0495     def p_enum_name0 (self, p):
0496         """enum_name : enum ID LBRACE
0497                      | enum LBRACE"""                     
0498         if p[2] != "{":
0499             name = p[2]
0500         else:
0501             name = None
0502         p[0] = self.enumObject(name)
0503 
0504     def p_typedef_enum (self, p):
0505         """typedef_enum_decl : typedef enum_statement SEMI
0506                              | typedef enum_statement id_list SEMI"""
0507         name = p[2].name()
0508         if len(p)==5:
0509             name = p[3]
0510         self.symbolData.EnumTypedef(self.scope, name, p[2], self.filename, self.lexer.lineno)
0511         
0512     def p_enumerator0 (self, p):
0513         """enumerator : ID"""
0514         enumerator = self.symbolData.Enumerator(p[1], None)
0515         p[0] = enumerator
0516     
0517     def p_enumerator1 (self, p):
0518         """enumerator : ID EQUALS expression"""
0519         enumerator = self.symbolData.Enumerator(p[1], p[3])
0520         p[0] = enumerator
0521     
0522     def p_enumerator2 (self, p):
0523         """enumerator : DOC ID"""
0524         enumerator = self.symbolData.Enumerator(p[2], None)
0525         #enumerator.setDoc(p[1])
0526         p[0] = enumerator
0527 
0528     def p_enumerator3 (self, p):
0529         """enumerator : DOC ID EQUALS expression"""
0530         enumerator = self.symbolData.Enumerator(p[2], p[4])
0531         #enumerator.setDoc(p[1])
0532         p[0] = enumerator
0533 
0534     def p_enumerator4 (self, p):
0535         """enumerator : ID EQUALS expression enum_doc"""
0536         enumerator = self.symbolData.Enumerator(p[1], p[3])
0537         #enumerator.setDoc(p[4])
0538         p[0] = enumerator
0539             
0540     def p_enumerator5 (self, p):
0541         """enumerator : ID enum_doc"""
0542         enumerator = self.symbolData.Enumerator(p[1], None)
0543         #enumerator.setDoc(p[2])
0544         p[0] = enumerator
0545 
0546     def p_enumerator_list0 (self, p):
0547         """enumerator_list : enumerator"""
0548         p[0] = [p[1]]
0549             
0550     def p_enumerator_list1 (self, p):
0551         """enumerator_list : enumerator_list enum_delim enumerator"""
0552         p[1].append(p[3])
0553         p[0] = p[1]
0554         
0555     def p_enumerator_list2 (self, p):
0556         """enumerator_list : enumerator_list enum_doc"""
0557         p[0] = p[1]
0558         
0559     def p_enum_delim0 (self, p):
0560         """enum_delim : COMMA"""
0561         p[0] = (None,None)  # (DOC,UPDOC)
0562         
0563     def p_enum_delim1 (self, p):
0564         """enum_delim : COMMA enum_doc"""
0565         p[0] = (None,None)  # (DOC,UPDOC)
0566         
0567     def p_enum_doc(self, p):
0568         """enum_doc : enum_doc DOC
0569                  | enum_doc UPDOC
0570                  | DOC
0571                  | UPDOC"""
0572         pass
0573 
0574     def p_id_list_element0 (self, p):
0575         'id_list_element : ID'
0576         p[0] = p[1]
0577         
0578     def p_id_list_element1 (self, p):
0579         """id_list_element : ASTERISK ID
0580                                     | AMPERSAND ID"""
0581         p[0] = p[1]
0582 
0583     def p_id_list (self, p):
0584         """id_list : id_list_element
0585                    | id_list COMMA id_list_element"""
0586         p[0] = joinp(p, 1, "")
0587 
0588     def p_qualified_id (self, p):
0589         """qualified_id : ID
0590                         | nested_name_specifier"""
0591         p [0] = p [1]
0592                         
0593     def p_nested_name_specifier0 (self, p):
0594         """nested_name_specifier : ID COLON2 ID
0595                                  | nested_name_specifier COLON2 ID
0596                                  | template_type COLON2 ID"""
0597         p[0] = joinp(p, 1, "")
0598 
0599     def p_nested_name_specifier1 (self, p):
0600         """nested_name_specifier : ID COLON2 TILDE ID
0601                                  | nested_name_specifier COLON2 TILDE ID
0602                                  | template_type COLON2 TILDE ID"""
0603         p[0] = joinp(p, 1, "")
0604 
0605     def p_nested_name_specifier2 (self, p):
0606         'nested_name_specifier : COLON2 ID'
0607         p [0] = p [2]
0608 
0609     def p_template_type (self, p):
0610         """template_type : qualified_id LT type_specifier_list GT
0611                         | qualified_id LT static_cast_expression GT"""
0612         p[0] = joinp(p, 1, "")
0613 
0614     def p_elaborated_type (self, p):
0615         """elaborated_type : enum qualified_id
0616                            | class qualified_id
0617                            | struct qualified_id
0618                            | union qualified_id
0619                            | typename qualified_id"""
0620         p [0] = p [2]
0621                    
0622     def p_type_specifier_base (self, p):
0623         """type_specifier_base : qualified_id
0624                                | template_type
0625                                | elaborated_type
0626                                | int
0627                                | unsigned int
0628                                | signed int
0629                                | char
0630                                | unsigned char
0631                                | signed char
0632                                | float
0633                                | double
0634                                | long
0635                                | long int
0636                                | unsigned long
0637                                | unsigned long int
0638                                | long unsigned int
0639                                | signed long
0640                                | signed long int
0641                                | long long
0642                                | unsigned long long
0643                                | signed long long
0644                                | signed long long int
0645                                | short
0646                                | unsigned short
0647                                | signed short
0648                                | short int
0649                                | unsigned short int
0650                                | signed short int
0651                                | unsigned
0652                                | signed
0653                                | bool
0654                                | void
0655                                | wchar_t"""
0656         p [0] = joinp(p,1)
0657         
0658     def p_type_specifier0 (self, p):
0659         'type_specifier : type_specifier_base '
0660         p [0] = p [1]
0661 
0662     def p_type_specifier1 (self, p):
0663         'type_specifier : CVQUAL type_specifier_base'
0664         p [0] = '%s %s' % (p [1], p[2])
0665                           
0666     def p_type_specifier2 (self, p):
0667         'type_specifier : type_specifier_base type_decorator'
0668         p [0] = '%s%s' % (p [1], p[2])
0669         
0670     def p_type_specifier3 (self, p):
0671         'type_specifier : CVQUAL type_specifier_base type_decorator'
0672         p [0] = '%s %s%s' % (p [1], p[2], p[3])
0673 
0674     def p_type_specifier4 (self, p):
0675         'type_specifier : type_specifier_base CVQUAL type_decorator'
0676         p [0] = '%s %s%s' % (p [2], p[1], p[3])
0677         
0678     def p_type_specifier5 (self, p):
0679         'type_specifier : type_specifier_base CVQUAL'
0680         p [0] = '%s %s' % (p [2], p[1])
0681 
0682     def p_type_decorator (self, p):
0683         """type_decorator : ASTERISK
0684                           | AMPERSAND
0685                           | ASTERISK CVQUAL
0686                           | ASTERISK AMPERSAND
0687                           | ASTERISK ASTERISK
0688                           | ASTERISK ASTERISK ASTERISK
0689                           | ARRAYOP"""
0690         p [0] = joinp(p, 1, "")
0691 
0692         
0693     def p_type_specifier_list (self, p):
0694         """type_specifier_list : type_specifier
0695                                | type_specifier_list COMMA type_specifier"""
0696         p [0] = joinp(p, 1, "")
0697                    
0698     def p_typedef_decl (self, p):
0699         """typedef_decl : typedef_simple SEMI
0700                         | typedef_elaborated SEMI
0701                         | typedef_function_ptr SEMI"""
0702         self._popScope()
0703        
0704     def p_typedef_simple0 (self, p):
0705         'typedef_simple : typedef type_specifier ID'
0706         tdObj = self.typedefObject(p[2], p[3])
0707         self._pushScope(tdObj)
0708         self.inTypedef = True
0709         
0710     def p_typedef_simple1 (self, p):
0711         'typedef_simple : typedef type_specifier ID ARRAYOP'
0712         tdObj = self.typedefObject('%s*' % p [2], p [3])
0713         self._pushScope(tdObj)
0714         self.inTypedef = True
0715 
0716     def p_typedef_elaborated (self, p):
0717         """typedef_elaborated : typedef class qualified_id ID
0718                               | typedef struct qualified_id ID
0719                               | typedef union qualified_id ID
0720                               | typedef enum qualified_id ID"""
0721         tdObj = self.typedefObject(p[3], p[4])
0722         self._pushScope(tdObj)
0723         self.inTypedef = True
0724         
0725     def p_class_from_typedef0 (self, p):
0726         """class_from_typedef : typedef class ID LBRACE
0727                               | typedef struct ID LBRACE
0728                               | typedef union ID LBRACE"""
0729         p [0] = p [2]
0730         self.classObject (p [3], p [2])
0731         self.inTypedef = True
0732         
0733     def p_class_from_typedef1 (self, p):
0734         """class_from_typedef : typedef struct LBRACE
0735                               | typedef union LBRACE"""
0736         p [0] = p [2]
0737         self.classObject ('anonymous', p [2])
0738         self.inTypedef = True
0739 
0740     def p_pointer_to_function_pfx (self, p):
0741         """pointer_to_function_pfx : ASTERISK FUNCPTR
0742                                    | type_specifier FUNCPTR"""
0743         if p[1] == '*':
0744             p [0] = '*%s' % p[2]
0745         else:
0746             p [0] = p[1]
0747         
0748     def p_pointer_to_function_name (self, p):
0749         'pointer_to_function_name : pointer_to_function_pfx ID'
0750         p [0] = "|".join ([p[1], p[2]])
0751         
0752     def p_pointer_to_function_args (self, p):
0753         """pointer_to_function_args : RPAREN LPAREN type_specifier_list
0754                                     | RPAREN LPAREN empty"""
0755         p [0] = p [3]
0756         
0757     def p_pointer_to_function (self, p):
0758         'pointer_to_function : pointer_to_function_name pointer_to_function_args RPAREN'
0759         if p [2]:
0760             p [0] = "|".join ([p [1], p [2]])
0761         else:
0762             p [0] = "|".join ([p [1], ""])
0763                 
0764     def p_typedef_function_ptr (self, p):
0765         'typedef_function_ptr : typedef pointer_to_function'
0766         
0767         ptrType, name, args = p [2].split ('|', 2)
0768 
0769         fa = self.symbolData.FunctionArgument(name, ptrType, args)
0770         typedefObj = self.symbolData.FunctionPointerTypedef(self.scope, fa, self.filename, self.lexer.lineno)
0771         typedefObj.setAccess(self.access)
0772         self.inTypedef = True
0773         
0774         self._pushScope(typedefObj)
0775         
0776     def p_array_variable (self, p):
0777         'array_variable : ID ARRAYOP'
0778         p [0] = p[1] + " " + p[2]
0779                 
0780     def p_argument_specifier0 (self, p):
0781         """argument_specifier : type_specifier
0782                               | ELLIPSIS"""
0783         p [0] = self.argument (p [1])
0784         
0785     def p_argument_specifier1 (self, p):
0786         """argument_specifier : type_specifier ID
0787                               | type_specifier array_variable"""
0788         p [0] = self.argument (p [1], p [2])
0789 
0790     def p_argument_specifier2 (self, p):
0791         'argument_specifier : type_specifier EQUALS expression'
0792         p [0] = self.argument (p [1], None, p [3])
0793         
0794     def p_argument_specifier3 (self, p):
0795         """argument_specifier : type_specifier ID EQUALS expression
0796                               | type_specifier array_variable EQUALS expression"""
0797         p [0] = self.argument (p [1], p [2], p [4])
0798         
0799     def p_argument_specifier4 (self, p):
0800         'argument_specifier : pointer_to_function'
0801         argType, name, args = p [1].split ('|', 2)
0802         p[0] = self.argument('$fp' + argType, name, args)
0803                               
0804     def p_argument_list0 (self, p):
0805         """argument_list : argument_specifier"""
0806 #                         | type_specifier"""
0807         p [0] = [p [1]]
0808         
0809     def p_argument_list1 (self, p):
0810         """argument_list : argument_list COMMA argument_specifier
0811                          | argument_list COMMA type_specifier"""
0812         if p [0]:
0813             p [0].append (p [3])
0814         else:
0815             p [0] = [p [3]]
0816 
0817     def p_decl_starter0 (self, p):
0818         'decl_starter : type_specifier qualified_id'
0819         p [0] = joinp(p, 1, "|")
0820         
0821     def p_decl_starter1 (self, p):
0822         'decl_starter : type_specifier bare_macro qualified_id'
0823         p [0] = p[1] + "|" + p[3]
0824 
0825     def p_decl_starter2 (self, p):
0826         'decl_starter : STORAGE type_specifier qualified_id'
0827         p [0] = joinp(p, 2, "|")
0828         self.storage = p [1]
0829         
0830     def p_decl_starter3 (self, p):
0831         'decl_starter : STORAGE bare_macro type_specifier qualified_id'
0832         p [0] = joinp(3, "|")
0833         self.storage = p [1]
0834             
0835     def p_decl_starter4 (self, p):
0836         'decl_starter : STORAGE type_specifier bare_macro qualified_id'
0837         p [0] = p[2] + "|" + p[4]
0838         self.storage = p [1]
0839             
0840     def p_variable_decl0 (self, p):
0841         'variable_decl : decl_starter SEMI'
0842         vtype, name = p [1].split ('|')
0843         self.variableObject (name, vtype)
0844     
0845     def p_variable_decl1 (self, p):
0846         'variable_decl : argument_specifier SEMI'
0847         vtype, name, init = p[1][0][:3]
0848         self.variableObject (name, vtype, init)
0849         
0850     def p_variable_decl2 (self, p):
0851         'variable_decl : STORAGE argument_specifier SEMI'
0852         vtype, name, eqsign, init = p [2][0][:4]
0853         self.variableObject (name, vtype, init)
0854     
0855     def p_variable_decl3 (self, p):
0856         'variable_decl : type_specifier id_list SEMI'
0857         vtype = p [1]
0858         names = p[2].split (',')
0859         for name in names:
0860             self.variableObject (name, vtype)           
0861                 
0862     def p_variable_decl4 (self, p):
0863         'variable_decl : STORAGE type_specifier id_list SEMI'
0864         self.storage = p[1]
0865         vtype = p [2]
0866         names = p[3].split (',')
0867         for name in names:
0868             self.variableObject (name, vtype)           
0869 
0870     def p_variable_decl5 (self, p):
0871         'variable_decl : type_specifier CVQUAL ID SEMI'
0872         vObj = self.variableObject (p [3], p [1])
0873         vObj.variable.attributes.cv = p [2]
0874         
0875     def p_variable_decl6 (self, p):
0876         'variable_decl : type_specifier ID COLON ICONST SEMI'
0877         vObj = self.variableObject (p [2], p [1])
0878         vObj.setBitfield(p[4])
0879 
0880     def p_variable_decl7 (self, p):
0881         'variable_decl : pointer_to_function SEMI'
0882         varType, name, args = p [1].split ("|", 2)
0883         varObj = self.variableObject (name, varType, None)
0884         
0885         if args:
0886             varObj.functionPtr = args.split (',')
0887         else:
0888             varObj.functionPtr = []
0889             
0890     def p_function_name (self, p):
0891         'function_name : decl_starter LPAREN'
0892         returns, name = p [1].split ('|')
0893         func = self.functionObject(name, returns)
0894         func.setAccess(self.access)
0895         self.arguments = []
0896         
0897     def p_operator_pfx (self, p):
0898         'operator_pfx : type_specifier operator'
0899         p [0] = p [1]      
0900         
0901     def p_operator_pfx2 (self, p):
0902         'operator_pfx : type_specifier bare_macro operator'
0903         p [0] = p [1]
0904     
0905     def p_operator_pfx3 (self, p):
0906         'operator_pfx : type_specifier bare_macro type_decorator operator'
0907         p [0] = p [1]
0908 
0909     def p_operator_pfx4 (self, p):
0910         'operator_pfx : type_specifier ID COLON2 operator'
0911         p [0] = p[1] + " " + p[2] + p[3]
0912 
0913     def p_operatorpfx5(self, p):
0914         'operator_pfx : type_specifier template_type COLON2 operator'
0915         p[0] = p[1] + " " + p[2] + p[3]
0916 
0917     def p_operator_name (self, p):
0918         """operator_name : operator_pfx operator_type"""
0919         if p[1] is not None:
0920             self.functionObject ('operator' + p[2], p[1])
0921             self.arguments = []
0922         
0923     def p_operator_type (self, p):
0924         """operator_type : PLUS LPAREN
0925                          | MINUS LPAREN
0926                          | ASTERISK LPAREN
0927                          | SLASH LPAREN
0928                          | PERCENT LPAREN
0929                          | VBAR LPAREN
0930                          | AMPERSAND LPAREN
0931                          | LT LPAREN
0932                          | LT LT LPAREN
0933                          | GT LPAREN
0934                          | GT GT LPAREN
0935                          | LOR LPAREN
0936                          | LAND LPAREN
0937                          | BANG LPAREN
0938                          | LE LPAREN
0939                          | GE LPAREN
0940                          | EQ LPAREN
0941                          | EQUALS LPAREN
0942                          | TIMESEQUAL LPAREN
0943                          | DIVEQUAL LPAREN
0944                          | MODEQUAL LPAREN
0945                          | PLUSEQUAL LPAREN
0946                          | MINUSEQUAL LPAREN
0947                          | LSHIFTEQUAL LPAREN
0948                          | GT GE LPAREN
0949                          | ANDEQUAL LPAREN
0950                          | OREQUAL LPAREN
0951                          | XOREQUAL LPAREN
0952                          | PLUSPLUS LPAREN
0953                          | MINUSMINUS LPAREN
0954                          | ARRAYOP LPAREN
0955                          | LPAREN RPAREN LPAREN
0956                          | ARROW LPAREN
0957                          | NE LPAREN"""
0958         if len(p) == 3:
0959             p[0] = p[1]
0960         elif len(p) == 4:
0961             p[0] = p[1] + p[2]
0962 
0963     def p_cast_operator_operator(self, p):
0964         """cast_operator_keyword : operator"""
0965         self.lexer.begin('function')
0966         
0967     def p_cast_operator_name0 (self, p):
0968         'cast_operator_name : cast_operator_keyword type_specifier LPAREN RPAREN'
0969         self.functionObject ('operator ' + p [2], p[2])
0970         self.arguments  = []
0971         
0972     def p_cast_operator_name1 (self, p):
0973         'cast_operator_name : cast_operator_keyword type_specifier LPAREN RPAREN CVQUAL'
0974         fObj = self.functionObject ('operator ' + p [2], p[2])
0975         fObj.addQualifier(p[5])
0976         self.arguments  = []        
0977         
0978     def p_cast_operator_stmt (self, p):
0979         """cast_operator_stmt : cast_operator_name decl_end
0980                                         | virtual cast_operator_name decl_end"""
0981         self.currentFunction.setArguments(self.argumentList())
0982         if len(p) == 4:
0983             self.currentFunction.addQualifier('virtual')
0984 
0985     def p_operator_primary0 (self, p):
0986         """operator_primary : operator_name argument_list RPAREN
0987                             | operator_name RPAREN"""
0988         if self.currentFunction is not None:
0989             self.currentFunction.setArguments(self.argumentList())
0990 
0991     def p_operator_primary1 (self, p):
0992         """operator_primary : virtual operator_name argument_list RPAREN
0993                             | virtual operator_name RPAREN"""
0994         self.currentFunction.setArguments(self.argumentList())
0995         self.currentFunction.addQualifier('virtual')
0996             
0997     def p_operator_stmt0 (self, p):
0998         """operator_stmt : operator_primary decl_end
0999                          | operator_primary pure_virtual_suffix decl_end"""
1000         pass
1001         
1002     def p_operator_stmt1 (self, p):
1003         """operator_stmt : operator_primary CVQUAL decl_end
1004                          | operator_primary CVQUAL pure_virtual_suffix"""
1005         if self.currentFunction is not None:
1006             self.currentFunction.addQualifier(p[2])
1007 
1008     def p_ctor_name0 (self, p):
1009         'ctor_name : qualified_id LPAREN'
1010         self.functionObject(p[1], 'ctor')
1011         self.arguments = []
1012         
1013     def p_ctor_name1 (self, p):
1014         'ctor_name : explicit qualified_id LPAREN'
1015         fo = self.functionObject(p[2], 'ctor')
1016         fo.addQualifier('explicit')
1017         self.arguments = []
1018 
1019     def p_dtor_name (self, p):
1020         'dtor_name : TILDE ID'
1021         self.functionObject(p[2], 'dtor')
1022         self.arguments = []
1023         
1024     def p_virtual_dtor_name (self, p):
1025         'virtual_dtor_name : virtual dtor_name'
1026         self.arguments = []
1027                             
1028     def p_function_decl (self, p):
1029         """function_decl : ctor_stmt
1030                          | dtor_stmt
1031                          | function_stmt
1032                          | operator_stmt
1033                          | cast_operator_stmt
1034                          | virtual_stmt
1035                          | pure_virtual"""
1036         self.currentFunction = None
1037                                  
1038     def p_function_primary (self, p):
1039         """function_primary : function_name RPAREN
1040                             | function_name argument_list RPAREN"""
1041         self.currentFunction.setArguments(self.argumentList())
1042     
1043     def p_function_stmt0 (self, p):
1044         'function_stmt : function_primary decl_end'
1045         pass
1046         
1047     def p_function_stmt1 (self, p):
1048         'function_stmt : function_primary CVQUAL decl_end'
1049         self.currentFunction.addQualifier(p[2])
1050                             
1051     def p_ctor_primary (self, p):
1052         """ctor_primary : ctor_name RPAREN
1053                        | ctor_name argument_list RPAREN"""
1054         self.currentFunction.setArguments(self.argumentList())
1055     
1056     def p_ctor_initializer (self, p):
1057         """ctor_initializer : qualified_id LPAREN expression_list RPAREN
1058                             | qualified_id LPAREN RPAREN
1059                             | template_type LPAREN expression_list RPAREN
1060                             | template_type LPAREN RPAREN"""
1061         pass
1062         
1063     def p_ctor_initializer_list (self, p):
1064         """ctor_initializer_list : ctor_initializer
1065                                  | ctor_initializer_list COMMA ctor_initializer"""
1066                                  
1067         pass
1068         
1069     def p_ctor_stmt (self, p):
1070         """ctor_stmt : ctor_primary decl_end
1071                      | ctor_primary COLON ctor_initializer_list decl_end"""
1072         pass
1073         
1074     def p_dtor_primary0 (self, p):
1075         'dtor_primary : dtor_name LPAREN RPAREN'
1076         pass
1077 
1078     def p_dtor_primary1 (self, p):
1079         'dtor_primary_pure : dtor_name LPAREN RPAREN pure_virtual_suffix'
1080         self.currentFunction.addQualifier('pure')
1081 
1082         
1083     def p_dtor_primary2 (self, p):
1084         'dtor_primary : virtual_dtor_name LPAREN RPAREN'
1085         self.currentFunction.addQualifier('virtual')
1086     
1087     def p_dtor_primary3 (self, p):
1088         'dtor_primary_pure_virtual : virtual_dtor_name LPAREN RPAREN pure_virtual_suffix'
1089         self.currentFunction.addQualifier('virtual')
1090         self.currentFunction.addQualifier('pure')
1091 
1092     def p_dtor_stmt (self, p):
1093         """dtor_stmt : dtor_primary decl_end
1094                      | dtor_primary_pure_virtual
1095                      | dtor_primary_pure"""
1096         pass
1097         
1098     def p_virtual_primary (self, p):
1099         """virtual_primary : virtual function_name RPAREN
1100                           | virtual function_name argument_list RPAREN"""
1101         self.currentFunction.setArguments(self.argumentList())
1102         self.currentFunction.addQualifier('virtual')
1103         
1104     def p_virtual_stmt0 (self, p):
1105         'virtual_stmt : virtual_primary decl_end'
1106         pass
1107     
1108     def p_virtual_stmt1 (self, p):
1109         'virtual_stmt : virtual_primary CVQUAL decl_end'
1110         self.currentFunction.addQualifier(p[2])
1111 
1112     def p_pure_virtual_suffix (self, p):
1113         'pure_virtual_suffix : EQUALS PURESFX'
1114         pass
1115             
1116     def p_pure_virtual (self, p):
1117         """pure_virtual : virtual_primary pure_virtual_suffix 
1118                         | virtual_primary CVQUAL pure_virtual_suffix"""
1119         self.currentFunction.addQualifier('pure')
1120         if p[2] in ['const', 'volatile']:
1121             self.currentFunction.addQualifier(p[2])
1122 
1123     def p_template_param (self, p):
1124         """template_param : type_specifier
1125                          | type_specifier ID"""
1126         p[0] = joinp(p, 1)
1127         
1128     def p_template_param_list (self, p):
1129         """template_param_list : template_param"""
1130         p[0] = [p[1]]
1131         
1132     def p_template_param_list2 (self, p):
1133         """template_param_list : template_param_list COMMA template_param"""
1134         p[1].append(p[3])
1135         p[0] = p[1]
1136         
1137     def p_template_decl (self, p):
1138         'template_decl : template LT template_param_list GT'
1139         p[0] = p[3]
1140         
1141     def p_template_decl2 (self, p):
1142         'template_decl : template LT GT'
1143         p[0] = []
1144 
1145 # expression handling for argument default values - just parses and
1146 # then reassembles the default value expression (no evaluation)
1147 
1148     def p_expression_list (self, p):
1149         """expression_list : expression
1150                           | expression_list COMMA expression"""
1151         pass                          
1152 
1153     def p_expression0 (self, p):
1154         """expression : add_expression
1155                       | sub_expression
1156                       | mult_expression
1157                       | div_expression
1158                       | mod_expression
1159                       | unary_expression
1160                       | or_expression
1161                       | and_expression
1162                       | xor_expression
1163                       | bitor_expression
1164                       | bitand_expression
1165                       | lt_expression
1166                       | le_expression
1167                       | eq_expression
1168                       | ge_expression
1169                       | gt_expression
1170                       | lshift_expression
1171                       | rshift_expression
1172                       | ptr_expression
1173                       | dot_expression
1174                       | new_expression
1175                       | static_cast_expression
1176                       | ICONST
1177                       | FCONST
1178                       | HEXCONST
1179                       | CCONST
1180                       | SCONST"""
1181         p [0] = p [1]
1182             
1183     def p_expression1 (self, p):
1184         'expression : LPAREN expression RPAREN'
1185         p [0] = joinp(p, 1, "")
1186 
1187     def p_expression2 (self, p):
1188         'expression : qualified_id'
1189         p [0] = p [1]
1190         self.exprElements.append (p [1])
1191     
1192     def p_expression3 (self, p):
1193         """expression : type_specifier LPAREN expression_list RPAREN
1194                       | type_specifier LPAREN RPAREN"""
1195         p [0] = joinp(p, 1, "")
1196         self.exprElements.append ('%s()' % p [1])
1197         
1198     def p_expression4 (self, p):
1199         """expression : type_specifier PERIOD ID LPAREN expression_list RPAREN
1200                       | type_specifier PERIOD ID LPAREN RPAREN"""
1201         p [0] = joinp(p, 1, "")
1202         self.exprElements.append ('%s.%s()' % (p [1], p [3]))
1203 
1204     def p_expression5 (self, p):
1205         'expression : type_specifier PERIOD ID'
1206         p [0] = p [1]
1207         self.exprElements.append ('%s.%s' % (p [1], p [3]))
1208     
1209     def p_expression_list (self, p):
1210         """expression_list : expression
1211                            | expression_list COMMA expression"""
1212         p [0] = joinp(p, 1, "")
1213 
1214     def p_unary_expression (self, p):
1215         """unary_expression : sign_expression
1216                             | not_expression
1217                             | bitnot_expression
1218                             | new_expression"""
1219         p [0] = p [1]
1220 
1221     def p_add_expression (self, p):
1222         'add_expression : expression PLUS expression'
1223         p [0] = joinp(p, 1, "")
1224 
1225     def p_sub_expression (self, p):
1226         'sub_expression : expression MINUS expression'
1227         p [0] = joinp(p, 1, "")
1228 
1229     def p_mult_expression (self, p):
1230         'mult_expression : expression ASTERISK expression'
1231         p [0] = joinp(p, 1, "")
1232 
1233     def p_div_expression (self, p):
1234         'div_expression : expression SLASH expression'
1235         p [0] = joinp(p, 1, "")
1236 
1237     def p_mod_expression (self, p):
1238         'mod_expression : expression PERCENT expression'
1239         p [0] = joinp(p, 1, "")
1240 
1241     def p_sign_expression (self, p):
1242         'sign_expression : MINUS expression %prec UMINUS'
1243         p [0] = joinp(p, 1, "")
1244 
1245     def p_or_expression (self, p):
1246         'or_expression : expression LOR expression'
1247         p [0] = joinp(p, 1, "")
1248 
1249     def p_and_expression (self, p):
1250         'and_expression : expression LAND expression'
1251         p [0] = joinp(p, 1, "")
1252 
1253     def p_xor_expression (self, p):
1254         'xor_expression : expression CARET expression'
1255         p [0] = joinp(p, 1, "")
1256 
1257     def p_bitor_expression (self, p):
1258         'bitor_expression : expression VBAR expression'
1259         p [0] = joinp(p, 1, "")
1260 
1261     def p_bitand_expression (self, p):
1262         'bitand_expression : expression AMPERSAND expression'
1263         p [0] = joinp(p, 1, "")
1264 
1265     def p_lt_expression (self, p):
1266         'lt_expression : expression LT expression'
1267         p [0] = joinp(p, 1, "")
1268 
1269     def p_le_expression (self, p):
1270         'le_expression : expression LE expression'
1271         p [0] = joinp(p, 1, "")
1272 
1273     def p_eq_expression (self, p):
1274         'eq_expression : expression EQ expression'
1275         p [0] = joinp(p, 1, "")
1276 
1277     def p_ge_expression (self, p):
1278         'ge_expression : expression GE expression'
1279         p [0] = joinp(p, 1, "")
1280 
1281     def p_gt_expression (self, p):
1282         'gt_expression : expression GT expression'
1283         p [0] = joinp(p, 1, "")
1284 
1285     def p_lshift_expression (self, p):
1286         'lshift_expression : expression GT GT expression'
1287         p [0] = joinp(p, 1, "")
1288 
1289     def p_rshift_expression (self, p):
1290         'rshift_expression : expression LT LT expression'
1291         p [0] = joinp(p, 1, "")
1292 
1293     def p_not_expression (self, p):
1294         'not_expression : BANG expression'
1295         p [0] = joinp(p, 1, "")
1296 
1297     def p_bitnot_expression (self, p):
1298         'bitnot_expression : TILDE expression'
1299         p [0] = joinp(p, 1, "")
1300 
1301     def p_new_expression (self, p):
1302         'new_expression : new expression'
1303         p [0] = joinp(p, 1, "")
1304 
1305     def p_static_cast_expression (self, p):
1306         'static_cast_expression : static_cast LT type_specifier GT LPAREN expression RPAREN'
1307         p [0] = joinp(p, 1)
1308         self.exprElements.append (p [3])
1309     
1310     def p_ptr_expression (self, p):
1311         'ptr_expression : expression ARROW expression'
1312         p [0] = joinp(p, 1, "")
1313 
1314     def p_dot_expression (self, p):
1315         'dot_expression : expression PERIOD expression'
1316         p [0] = joinp(p, 1, "")
1317 
1318 # inline code/statements
1319 # the second and last cases are incorrect syntax, but show up in KDE
1320     def p_inline_code (self, p):
1321         """inline_code : STMT_BEGIN code_list STMT_END
1322                       |  STMT_BEGIN code_list STMT_END SEMI
1323                       | STMT_BEGIN STMT_END
1324                       | STMT_BEGIN STMT_END SEMI"""
1325         pass
1326 
1327     def p_code_list_block (self, p):
1328         """code_list_block : CODE_STMT_BEGIN code_list STMT_END
1329                                     | CODE_STMT_BEGIN STMT_END"""
1330         pass
1331                           
1332     def p_code_list (self, p):
1333         """code_list : CODE_TOKEN
1334                     | code_list_block
1335                     | code_list code_list_block
1336                     | code_list CODE_TOKEN"""
1337 
1338 # calls to mostly ignored macros
1339     def p_skip_macro (self, p):
1340         'skip_macro : MACROCALL MACRO_CALL_BEGIN macro_call_element_list MACRO_CALL_END'
1341         #if p [1] == 'Q_DISABLE_COPY':
1342         #    fcn  = self.functionObject (p [3], 'ctor')
1343         #    fcn.setArguments (self.argument ('const %s&' % p[3]))
1344         #    self.stateInfo.popObject ()
1345         #else:
1346         #    pass
1347         macro = self.bareMacro(p[1])
1348         macro.setArgument(p[3])
1349         macro.setAccess(self.access)
1350         
1351     def p_bare_macro(self,p):
1352         'bare_macro : BAREMACRO'
1353         macro = self.bareMacro(p[1])
1354         macro.setAccess(self.access)
1355     
1356     def p_macro_call_parens (self, p):
1357         """macro_call_parens : LPAREN RPAREN
1358                             | LPAREN macro_call_element_list RPAREN"""
1359         pass
1360                             
1361     def p_macro_call_element_list0 (self, p):
1362         'macro_call_element_list : MACRO_ELEMENT'
1363         p [0] = p[1]
1364 
1365     def p_macro_call_element_list1 (self, p):
1366         'macro_call_element_list : macro_call_element_list MACRO_ELEMENT'
1367         p [0] = joinp(p, 1)
1368 
1369     def p_macro_call_element_list2 (self, p):
1370         'macro_call_element_list : macro_call_element_list macro_call_parens'
1371         p [0] = p [1]
1372 
1373     def p_macro_call_element_list3 (self, p):
1374         'macro_call_element_list : macro_call_parens'
1375         p [0] = ''
1376 
1377     def p_doccomment(self, p):
1378         'doccomment : DOC'
1379         self.commentObject(p[1])
1380 
1381     def p_error(self, p):
1382         if p is not None:
1383             print("File: " + repr(self.filename) + " Line: " + str(self.lexer.lineno) + " Syntax error in input. Token type: %s, token value: %s, lex state: %s" % (p.type, p.value, self.lexer.lexstate))
1384         else:
1385             print("File: " + repr(self.filename) + " Line: " + str(self.lexer.lineno) + " Syntax error in input. Lex state: %s" % (self.lexer.lexstate,) )
1386         sys.exit (-1)
1387         
1388 if __name__ == '__main__':
1389 
1390     text = """
1391 enum global {earth, orb, globe};    
1392 friend class whatever;
1393 friend int max (int a, int b);
1394 
1395 namespace foo
1396 {    
1397 enum fooEnum {apples, peaches, pumpkin_pie};
1398 class bar
1399 {
1400 public:
1401     bar ();
1402     int baz ();
1403     int baz (double, long);
1404     QString method (int foo = 0);
1405     bar (int);
1406     bar (int, QList<QString>);
1407 using dont care what;
1408 enum barEnum {
1409     peas,
1410     carrots,
1411     beans
1412     } veggies;
1413 typedef global::qint inttype;    
1414 };
1415 typedef enum elaborated something;
1416 typedef enum simple {easy, bobsyouruncle, noproblem};
1417 typedef QList<QPair<QString,QString>> stringpairlist;
1418 typedef QString& stringref;
1419 typedef QObject* objPtr;
1420 typedef QObject** objPtrPtr;
1421 typedef QString*& reftoStringPtr;
1422 enum tail {end, posterior, ass};
1423 }
1424     int baz ();
1425     virtual int baz (double);
1426     int baz (double, long long);
1427     int baz (double, long, unsigned long = ulong);
1428     virtual const QString& method (int foo = 0) = 0;
1429     QString method (int foo = 0, long fool = 20);
1430     bar (int a[40]);
1431     bar (int, QList<QString>);
1432     char* tmpl (QPair<QString, QString*> pair, const int foo);
1433     const char* string (QObject* object = QObject::type ());
1434     int varInt;
1435     double varDbl1, varDb12;
1436     QString s = 25;
1437     bar (int);
1438     bar (int a[40]);
1439     char *c[10];
1440     typedef void (* fptr)(int, double*);
1441     typedef int (* otherptr)();
1442     Q_OBJECT
1443     Q_SETS (who cares)
1444     double (*doublePtr)(float, QString*);
1445     bool test (int, int);
1446     bool operator == (int);
1447     int operator + (double);
1448     int operator >> (int);
1449     bool operator <<= (int a, int b);
1450     double (*doublePtr)();
1451     void* foo (int, double (*doublePtr)(float, QString*));
1452     void* foo (int, double (*doublePtr)());
1453     Q_DECLARE_FLAGS (Conditions, Condition)
1454     void plug () {
1455 x = 1;
1456      y = 2;
1457 }
1458 class kdecore::KAccel raise (class QWidget elab) {
1459 xyzabc = 1;
1460      y = 2;
1461      {
1462      if (x)
1463      {
1464         abc = 12;
1465      }
1466      }
1467      {
1468      while 1:
1469          x = 0;
1470      }
1471        
1472 }
1473     """
1474     text = """
1475 
1476 namespace Soprano {
1477 
1478     class Model;
1479 
1480     namespace Client {
1481 
1482         class DBusModel;
1483 
1484         /**
1485          * \class DBusClient dbusclient.h Soprano/Client/DBusClient
1486          *
1487          * \brief Core class to handle a connection to a Soprano server through the
1488          * DBus interface.
1489          *
1490          * DBusClient creates a connection to a running Soprano Server via its DBus
1491          * interface. All DBus communication is handled internally.
1492          *
1493          * See DBusModel for details about thread-safety.
1494          *
1495          * \author Sebastian Trueg <trueg@kde.org>
1496          *
1497          * \sa \ref soprano_server_dbus
1498          */
1499         class DBusClient : public QObject, public Error::ErrorCache
1500         {
1501             
1502        };
1503     }
1504 }
1505 
1506 """
1507     text = """
1508     class Foo {
1509     public:
1510         const KTimeZone::Transition *transition(const QDateTime &dt, const Transition **secondTransition = 0, bool *validTime = 0) const;
1511 };
1512 """
1513     
1514     from symboldata import Data
1515     from stateInfo import StateInfo
1516 
1517     symbolData = Data ()
1518     stateInfo  = StateInfo ()
1519     parser = CppParser ()
1520 #    print "\n".join (parser.parse (symbolData, stateInfo, text, 2) [1])
1521     parser.parse (symbolData, stateInfo, text, 2)