class Token:

  # --- token types ---
  #
  # Basically the token number can be arbitrary numbers. But to make
  # some comparisons more efficient, the numbers are grouped.
  # group 1: everything below TOK_ATTRIBUTESMAX
  #          Tokens which should not be returned individually, but which are
  #          added as 'attribute' to the previous token.
  tok_COMMENT      = 1   # full line or trailing comment
  tok_COMMENTLINE  = 2   # full line or trailing comment
  tok_F90_DIR      = 3   # !cdir, !$omp etc
  tok_CPP_DIR      = 4   # #include #define #ifdef etc
  tok_IGNORED      = 5   # anything after col 72/132
  tok_CONT_MARK    = 6   # & at begin or end in free, char in col 6 in fixed
  TOK_ATTRIBUTESMAX= 9
  tok_UNKNOWN      = 10  # catch-all class
  tok_LABEL        = 20  #
  tok_QUOTE_START  = 21  # first part of multiline quote
  tok_QUOTE_MIDDLE = 22  # entire line in a multiline quote (ie no quote marks)
  tok_QUOTE_END    = 23  # last part of multiline quote
  tok_QUOTE        = 24  # entire quote that fits on one line
  tok_SEPARATOR    = 25  # ;
  tok_NUMBER       = 26  # number literal
  tok_KEYWORD      = 27  #
  tok_IDENTIFIER   = 28  #
  tok_OPERATOR     = 29  # +,-,*,**,.ge. .and. .not. .true. 
  tok_TRUEFALSE    = 30  # .true. or .false.
  tok_SPECIAL      = 31  # (),
  tok_INCLUDE      = 32  # Special tokens, means that the next token must be
                         # read from an include file - the respective scanner
                         # will be the second element of the token
  tok_DIRECTIVE    = 33  # compiler directive
  tok_PREDIRECTIVE = 34  # preprocessor directive def ScannerFactory(name=None,lines=None,format=None,maxcols=None,
                   project=None):
  """ return an instance of scanner. try to be clever, eg
      work out whether to use fixed or free form, set
      provide a set of lines instead of a file if testing
      is being done, etc """

  use_format = "fixed"
  use_maxcols = 72

  if name:
    if not project:
      # Avoid circular references: project -> Scanner -> project
      from Tools.Project import Project
      project = Project()
      
    dFileOpt = project.dGetFileOptions(name)
    # is it fixed or free format?
    if name[-1] == '0': # f90, F90, ...?
      use_format  = dFileOpt.get("format","free")
      use_maxcols = dFileOpt.get("linelength",132)
    else:
      use_format  = dFileOpt.get("format","fixed")
      use_maxcols = dFileOpt.get("linelength",72)

  # explicit format overrides the guess
  if format:
    use_format = format

  if maxcols:
    use_maxcols = maxcols

  if use_format=="free":
    return FreeformScanner(name,use_maxcols,lines, project)
  else:
    return FixedformScanner(name,use_maxcols,lines, project) class ParseSpecification:

    def __init__(self):
        pass
    # --------------------------------------------------------------------------
    # common-stmt is COMMON [ / [ common-block-name ] / ] common-block-object-list
    #            [ [ , ] / [ common-block-name ] /common-block-object-list ] ...
    # common-block-object is variable-name [ ( explicit-shape-spec-list ) ]
    #                     or proc-pointer-name
    def ParseCommon(self, tokCommon, loc, sLabel=None, sName=None):
        if tokCommon[1].upper()=="GLOBAL":
            tok  = self.GetNextToken()
            com  = Common(loc, tok[1], self.nIndent, sGlobal=tokCommon[1])
        else:
            com  = Common(loc, tokCommon[1], self.nIndent)
        tok      = self.GetNextToken()
        tokComma = (None, None)
        while tok[0]!=Token.tok_SEPARATOR:
            # First: parse the common block name 
            if tok[1]=="//":           # unnamed common block
                com.AddCommonBlockName(sComma = tokComma[1], sSlash1=tok[1])
                tok = self.GetNextToken()
            elif tok[1]=="/":
                tok2 = self.GetNextToken()
                tok3 = self.GetNextToken()
                com.AddCommonBlockName(sComma = tokComma[1], sSlash1=tok[1],
                                       sName=tok2[1], sSlash2=tok3[1]       )
                tok = self.GetNextToken()
            else:
                # Empy common block, without //
                com.AddCommonBlockName()

            #Now read the object list
            while tok[0]!=Token.tok_SEPARATOR and tok[1]!="/" and tok[1]!="//":
                tok, exp = self.ParsePrimary(tok, bNoFuncCall=1)
                var = exp.oGetVariable()
                var.SetAttribute('common',com)
                if self.scanner.bIsIncludeFile():
                    var.SetAttribute('include',
                                     self.scanner.sGetIncludeFilename())
                if not tok or tok[0]==Token.tok_SEPARATOR:
                    com.AddCommonObject(exp)
                    return  self.GetNextToken(), com
                
                # *sigh* This bloody [,] - it means we have to use a lookahead
                # here to figure out if after a ',' another common-block-object
                # follows or if a new common block starts :( In the latter case
                # the comma must be added in front of the common block and 
                if tok[1]==",":
                    tok2 = self.GetNextToken()
                    if tok2[1]=="/" or tok2[1]=="//":
                        com.AddCommonObject(exp)
                        tokComma = tok
                        tok      = tok2
                        break
                    com.AddCommonObject(exp, tok[1])
                    tok = tok2
                else:
                    com.AddCommonObject(exp)
                    
        return self.GetNextToken(), com
    
    # --------------------------------------------------------------------------
    # namelist-stmt is NAMELIST  / namelist-group-name / namelist-group-object-list
    #                    [ [ , ] / namelist-group-name / namelist-group-object-list ] .,,
    # namelist-group-object	is	variable-name
    def ParseNamelist(self, tokCommon, loc, sLabel=None, sName=None):
        namelist  = Namelist(loc, tokCommon[1], self.nIndent)
        tok      = self.GetNextToken()
        tokComma = (None, None)
        while tok[0]!=Token.tok_SEPARATOR:
            # First: parse the name
            assert tok[1]=="/"
            tok2 = self.GetNextToken()
            tok3 = self.GetNextToken()
            assert tok3[1]=="/"
            namelist.AddNamelistName(sComma = tokComma[1], sSlash1=tok[1],
                                     sName=tok2[1], sSlash2=tok3[1]       )
            tok = self.GetNextToken()

            #Now read the object list
            while tok[0]!=Token.tok_SEPARATOR and tok[1]!="/" and tok[1]!="//":
                tok, exp = self.ParsePrimary(tok, bNoFuncCall=1)
                var = exp.oGetVariable()
                var.SetAttribute('namelist',namelist)
                if self.scanner.bIsIncludeFile():
                    var.SetAttribute('include',
                                     self.scanner.sGetIncludeFilename())
                if not tok or tok[0]==Token.tok_SEPARATOR:
                    namelist.AddNamelistObject(exp)
                    return  self.GetNextToken(), namelist
                
                # *sigh* This bloody [,] - it means we have to use a lookahead
                # here to figure out if after a ',' another common-block-object
                # follows or if a new common block starts :( In the latter case
                # the comma must be added in front of the common block and 
                if tok[1]==",":
                    tok2 = self.GetNextToken()
                    if tok2[1]=="/" or tok2[1]=="//":
                        namelist.AddNamelistObject(exp)
                        tokComma = tok
                        tok      = tok2
                        break
                    namelist.AddNamelistObject(exp, tok[1])
                    tok = tok2
                else:
                    namelist.AddNamelistObject(exp)
                    
        return self.GetNextToken(), namelist
    
    # --------------------------------------------------------------------------
    # data-stmt-object	is variable or data-implied-do
    def ParseDataStatementObjectList(self, tok, sLabel=None, sName=None):
        if tok[1]==',':
            datastatement = DataStatementSet(sComma=tok[1])
            tok = self.GetNextToken()
        else:
            datastatement = DataStatementSet()
        while tok[1]!='/':
            if tok[1]=='(':
                # ParsePrimary will parse either a variable or an implied do
                # loop (which of course not an expression, but it is very
                # convenient to do so)
                tok, obj = self.ParsePrimary(tok)
            else:
                # We can not use ParseExpression here, since a data statement
                # might be 'data a/1/', so ParseExpression would try to parse
                # a / expression.
                tok, obj = self.ParsePrimary(tok)
                
            if tok[1]==',':
                datastatement.AddObject(obj, tok[1])
                tok = self.GetNextToken()
            else:
                datastatement.AddObject(obj)
                return tok, datastatement
    # --------------------------------------------------------------------------
    # Parses a list of [ data-stmt-repeat * ] data-stmt-constant
    def ParseDataValueList(self, tokSlash):
        dvl = DataValueList(tokSlash[1])
        tok = self.GetNextToken()
        while tok[1]!='/':
            # Level1 expressions allow a unary -, so 'data x/-5/' will be
            # accepted, which wouldn't be accepted if ParseExpression is used.
            tok, obj = self.Level1Expr(tok)
            if tok[1]=='*':
                repeat = BasicExpression()
                repeat.append(obj, sOperator=tok[1])
                tok, obj = self.Level1Expr(self.GetNextToken())
                repeat.append(obj)
                obj = repeat
            if tok[1]==',':
                dvl.AddValue(obj, tok[1])
                tok = self.GetNextToken()
            else:
                dvl.AddValue(obj)
                dvl.AddSlash(tok[1])
                return self.GetNextToken(), dvl
    # --------------------------------------------------------------------------
    # data-stmt         is DATA data-stmt-set [ [ , ] data-stmt-set ] ...
    # data-stmt-set     is data-stmt-object-list / data-stmt-value-list /
    # data-stmt-object	is variable or data-implied-do
    # data-implied-do   is ( data-i-do-object-list , data-i-do-variable =
    #                      scalar-int-expr , scalar-int-expr
    #                      [ , scalar-int-expr ] )
    # data-i-do-object	is array-element or scalar-structure-component or
    #                      data-implied-do
    # data-stmt-value	is [ data-stmt-repeat * ] data-stmt-constant
    # data-stmt-repeat	is scalar-int-constant or scalar-int-constant-subobject
    def ParseData(self, tok, loc, sLabel=None, sName=None):
        data = Data(loc, tok[1], self.nIndent)
        tok = self.GetNextToken()
        while tok[0]!=Token.tok_SEPARATOR:
            tok, datastatement = self.ParseDataStatementObjectList(tok)
            assert tok[1]=='/'
            tok,dvl = self.ParseDataValueList(tok)
            datastatement.AddValueList(dvl)
            data.AddDataStatement(datastatement)

        return self.GetNextToken(), data
            
    # --------------------------------------------------------------------------
    #DIMENSION [ :: ] array-name (array-spec) [,array-name (array-spec) ] ...
    def ParseDimension(self, tok, loc, sLabel=None, sName=None):
        dim   = Dimension(loc, tok[1], self.nIndent)
        tok   = self.GetNextToken()
        if tok[1]==":":
            dim.AddDoubleColons(tok[1], self.GetNextToken()[1])
            tok = self.GetNextToken()

        while 1:
            var          = self.sub.GetVariable(tok[1])
            tok, arrspec = self.ParseArraySpec(tok=self.GetNextToken(),var=var)
            var.SetAttribute('dimension', arrspec.GetArraySpec())
            if tok and tok[1]==",":
                dim.AddArraySpec(arrspec, tok[1])
            else:
                dim.AddArraySpec(arrspec)
                break
            tok   = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), dim
    # --------------------------------------------------------------------------
    # equivalence-stmt is EQUIVALENCE equivalence-set-list
    # equivalence-set is ( equivalence-object , equivalence-object-list )
    # equivalence-object is variable-name or array-element or substring
    def ParseEquivalence(self, tokEq, loc, sLabel=None, sName=None):
        eq         = Equivalence(loc, tokEq[1], self.nIndent)
        tok        = self.GetNextToken()
        while tok[1]=='(':
            eqitem = EquivalenceItem(tok[1])
            tok = self.GetNextToken()
            while tok[1]!=')':
                tokComma, obj = self.ParsePrimary(tok)
                if tokComma[1]==',':
                    eqitem.AddObject(obj, tokComma[1])
                    tok = self.GetNextToken()
                else:
                    eqitem.AddObject(obj)
                    assert tokComma[1]==')'
                    eqitem.SetParClose(tokComma[1])
                    tok=self.GetNextToken()
                    break
            # Originally this was:
            #for i in eqitem.GetAllUsedVariables():
            # but this would fail if GetAllUsedVariables returned
            # common blocks (because one of the used variables was=
            # part of a common block).
            for i in eqitem.GetAllEquivalentVariables():
                i.SetAttribute('equivalence',eqitem)
            if tok[1]==',':
                eq.AddObject(eqitem, tok[1])
                tok = self.GetNextToken()
            else:
                eq.AddObject(eqitem)
                assert tok[0]==Token.tok_SEPARATOR
                return self.GetNextToken(), eq
    # --------------------------------------------------------------------------
    def ParseExternal(self, tok, loc, sLabel=None, sName=None):
        ext = External(loc, tok[1], self.nIndent)
        tok = self.GetNextToken()
        if tok[1]==':':
            ext.AddDoubleColon(tok[1], self.GetNextToken()[1])
            tok = self.GetNextToken()
        while tok[0]!=Token.tok_SEPARATOR:
            tokComma = self.GetNextToken()
            if tokComma[1]==',':
                ext.AddExternal(tok[1], tokComma[1])
                tok = self.GetNextToken()
            else:
                ext.AddExternal(tok[1])
                tok = tokComma
        return self.GetNextToken(), ext
    # --------------------------------------------------------------------------
    # implicit-stmt is IMPLICIT implicit-spec-list or IMPLICIT NONE
    # implicit-spec is declaration-type-spec ( letter-spec-list )
    # letter-spec   is letter [ - letter ]
    def ParseImplicit(self, tokImplicit, loc, sLabel=None, sName=None):
        tok = self.GetNextToken()
        if tok[1]=="=" or tok[1]=="(":
            self.scanner.UnGet(tok)
            return self.ParseAssignment(tokImplicit, loc=loc, sLabel=sLabel,
                                        sName=sName)
        impl = Implicit(tokImplicit[1], loc=loc, nIndent=self.nIndent)
        if string.upper(tok[1])=="NONE":
            impl.SetImplicitNone(tok[1])
            tok = self.GetNextToken()
        else:
            tokParOpen, type = self.ParseBasicType(tok)
            assert tokParOpen[1]=="("
            # The big problem here: "implicit(a-b)(d-e)". a-b is a kind
            # information, while d-e is the actual implicit statement :(((
            # Do distinguish these two cases, we need a rather large lookahead:
            # So we read all tokens and store them in a list, till we find the
            # closing first parenthesis. If another parenthesis is following,
            # we unget whatever we stored in the list and parse it again as
            # kind information. Otherwise we use the information in the list
            # to get the implicit information
            # At the beginning of the part marked
            # "Parse the actual implicit information"
            # tokParOpen must be the opening parenthesis, and l must contain
            # all tokens till the closing parenthesis. tok must be the
            # tok_SEPARATOR token.

            nOpen=1                     # Count the number of opened parenthesis
            l=[]
            tok = self.GetNextToken()
            while tok[0]!=Token.tok_SEPARATOR:
                l.append(tok)
                if tok[1]=="(":
                    nOpen=nOpen+1
                elif tok[1]==")":
                    nOpen=nOpen-1
                    if nOpen==0: break
                tok = self.GetNextToken()
            tok = self.GetNextToken()
            if tok[1]=="(":
                # Worst case: whatever we have read up to now, was actually
                # kind information. So unget everything, and parse the kind
                # information correctly.
                self.scanner.UnGet(tok)
                for i in range(len(l)-1, -1, -1):
                    self.scanner.UnGet(l[i])
                # Now, tokParOpen is the opening parenthesis, read above
                tokParOpen, type = self.ParseKindCharSelector(tokParOpen, type)
                assert tokParOpen[1]=="("
                # Now read everything till the end of the statement, and store
                # it in the list l. So we have the same state when leaving
                # the if statement: l contains all tokens excluding the
                # separator (and the opening parenthesis). 
                tok = self.GetNextToken()
                l=[]
                while tok[0]!=Token.tok_SEPARATOR:
                    l.append(tok)
                    tok=self.GetNextToken()
            impl.SetType(type)
            
            # Parse the actual implicit information
            # -------------------------------------
            impl.SetParOpen(tokParOpen[1])
            i = 0                            # index in list of tokens
            while l[i][1]!=")":
                if l[i+1][1]=="-":
                    if l[i+3][1]==",":
                        impl.AddLetter(l[i][1],l[i+1][1],l[i+2][1],
                                       sComma=l[i+3][1])
                        self.sub.SetImplicit(type, l[i][1],l[i+2][1])
                        i=i+4
                    else:
                        impl.AddLetter(l[i][1],l[i+1][1],l[i+2][1])
                        self.sub.SetImplicit(type, l[i][1],l[i+2][1])
                        i=i+3
                else:
                    if l[i+1][1]==",":
                        impl.AddLetter(l[i][1], sComma=l[i+1][1])
                        self.sub.SetImplicit(type, l[i][1])
                        i=i+2
                    else:
                        impl.AddLetter(l[i][1])
                        self.sub.SetImplicit(type, l[i][1])
                        i=i+1
            impl.SetParClose(l[i][1])

        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), impl
    # --------------------------------------------------------------------------
    # interface-stmt is INTERFACE [ generic-spec ] or ABSTRACT INTERFACE
    # generic-spec   is generic-name or	OPERATOR ( defined-operator ) or
    # interface-body is function-stmt [ specification-part ] end-function-stmt
    #                or subroutine-stmt [ specification-part ]
    #                   end-subroutine-stmt
    # procedure-stmt is [ MODULE ] PROCEDURE procedure-name-list
    #                   ASSIGNMENT ( = ) or dtio-generic-spec
    #dtio-generic-spec is READ (FORMATTED) or READ (UNFORMATTED) or
    #                  WRITE (FORMATTED) or WRITE (UNFORMATTED)
    def ParseInterface(self, tok, loc, sLabel=None, sName=None):
        iface = InterfaceStatement(loc, sInterface=tok[1])
        tok = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            if string.upper(tok[1])=="OPERATOR":
                while tok[0]!=Token.tok_SEPARATOR:
                    iface.AddGenericSpec(tok[1])
                    tok = self.GetNextToken()
            else:
                iface.AddGenericSpec(tok[1])
                tok = self.GetNextToken()

        assert tok[0]==Token.tok_SEPARATOR

        self.sub.AppendStatement(iface)
        iface.SetEndLocation(self.scanner.GetPreviousLocation())
        tok = self.GetNextToken()
        # If we simple parse the interface. all variables in the interface will
        # be added to the current subroutine, which is wrong. Setting a flag to
        # indicate 'a interface is being parse; don't add any variables to the
        # current program unit' is somewhat complicated: quite a few places need
        # to be changed, and even more because no 'variable' object can easily
        # be returned. So instead a dummy program unit is created which stores
        # the information about variable (which could be used later for
        # something?) and replaces the actual program unit.
        # Unfortunately, this means that all lines of the interface will be
        # added to this dummy program unit instead of the actual program unit.
        # So all lines of the dummy have to be added to the program unit after
        # parsing the interface.
        savesub  = self.sub
        self.sub = ProgUnit()
        tok = self.ParseStatements(tok, dEnd={'END': self.ParseEndInterface,
                                              'ENDINTERFACE':
                                              self.ParseEndInterface},
                                   nIndentModifier=1)
        # Now move all lines from the dummy program unit to the actual
        # program unit:
        for i in self.sub:
            savesub.AppendStatement(i)
        self.sub = savesub
        
        # Return none, since the interface statement was already added (at the
        # beginning of this method). This is necessary to ensure that the
        # statements which are part of the select block are added after the
        # select statement!
        return tok, None

    # --------------------------------------------------------------------------
    # end-interface-stmt is END INTERFACE [ generic-spec ]
    def ParseEndInterface(self, tok, loc, sLabel=None, sName=None):
        sEnd, sInterface = self.tKeywordSplit(tok,"ENDSELECT",3)
        endInterface = EndInterfaceStatement(loc, sEnd, sInterface,
                                             self.nIndent-1)
        tok = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            endInterface.SetName(tok[1])
            tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), endInterface
    # --------------------------------------------------------------------------
    # intrinsic-stmt is INTRINSIC [ :: ] intrinsic-procedure-name-list
    def ParseIntrinsic(self, tok, loc, sLabel=None, sName=None):
        intri = Intrinsic(loc, tok[1], self.nIndent)
        tok = self.GetNextToken()
        if tok[1]==":":
            intri.AddDoubleColons(tok[1], self.GetNextToken()[1])
            tok = self.GetNextToken()
        while tok[0]!=Token.tok_SEPARATOR:
            tokComma = self.GetNextToken()
            if tokComma[1]==",":
                intri.AddIntrinsic(tok[1], tokComma[1])
                tok = self.GetNextToken()
            else:
                intri.AddIntrinsic(tok[1])
                tok = tokComma
        return self.GetNextToken(), intri
    # --------------------------------------------------------------------------
    # procedure-stmt is [ MODULE ] PROCEDURE procedure-name-list
    def ParseModuleProcedure(self, tok, loc, sLabel=None, sName=None):
        if string.upper(tok[1])=="MODULE":
            proc = ModuleProcedure(loc, tok[1], self.GetNextToken()[1],
                                   self.nIndent)
        else:
            proc = ModuleProcedure(loc, sModule=None, sProcedure=tok[1],
                                   nIndent=self.nIndent)
        tok = self.GetNextToken()
        while tok[0]!=Token.tok_SEPARATOR:
            tokComma = self.GetNextToken()
            if tokComma[1]==',':
                proc.AddProcedure(tok[1], tokComma[1])
                tok = self.GetNextToken()
            else:
                proc.AddProcedure(tok[1])
                tok = tokComma
        return self.GetNextToken(), proc
    # --------------------------------------------------------------------------
    # parameter-stmt     is PARAMETER ( named-constant-def-list )
    # named-constant-def is named-constant = initialization-expr
    def ParseParameter(self, tokParam, loc, sLabel=None, sName=None):
        tok = self.GetNextToken()
        assert tok[1]=="("
        para = Parameter(loc, tokParam[1], self.nIndent, tok[1])
        while 1:
            var      = self.sub.GetVariable(self.GetNextToken()[1])
            tokEqual = self.GetNextToken()
            assert tokEqual[1]=="="
            tok      = self.GetNextToken()
            tok, obj = self.ParseExpression(tok)
            if tok[1]==",":
                para.AddVarValue(var=var, sEqual=tokEqual[1], obj=obj,
                                 sComma=tok[1] )
            else:
                para.AddVarValue(var=var, sEqual=tokEqual[1], obj=obj )
            if tok[1]==")":
                para.SetParClose(tok[1])
                tok = self.GetNextToken()
                assert tok[0]==Token.tok_SEPARATOR
                return self.GetNextToken(), para

    # --------------------------------------------------------------------------
    # Two formats are possible: The F90 pointer:
    # pointer-stmt is POINTER [ :: ] pointer-decl-list
    # pointer-decl is object-name [ ( deferred-shape-spec-list ) ] or
    #                 proc-entity-name
    # Format 2 (provided for backward compatibility): Cray Pointers
    # POINTER (pointer-variable, data-variable-declaration)
    #        [(pointer-variable, data-variable-declaration)]...
    def ParsePointer(self, tokPointer, loc, sLabel=None, sName=None):
        tokParen = self.GetNextToken()
        # Test for Cray Pointers
        if tokParen[1]=='(':
            pointer = CrayPointer(loc, tokPointer[1], self.nIndent)
            while 1:
                tokComma, var = self.ParsePrimary(self.GetNextToken())
                assert tokComma[1]==','
                tokParClose, data = self.ParsePrimary(self.GetNextToken())
                assert tokParClose[1]==')'
                pTuple = CrayPointerTuple(tokParen[1], var, tokComma[1],
                                          data, tokParClose[1])
                tok = self.GetNextToken()
                if tok[1]==",":
                    pointer.AddPointer(pTuple, tok[1])
                    tokParen = self.GetNextToken()
                else:
                    pointer.AddPointer(pTuple)
                    assert tok[0]==Token.tok_SEPARATOR
                    return self.GetNextToken(), pointer
                
        else:
            pointer = Pointer(loc, tokPointer[1], self.nIndent)
            if tokParen[1]==':':
                pointer.AddDoubleColons(tokParen[1], self.GetNextToken()[1])
                tokParen = self.GetNextToken()
            while 1:
                tok, exp = self.ParsePrimary(tokParen)
                if tok[1]==',':
                    pointer.AddPointer(exp, tok[1])
                    tokParen = self.GetNextToken()
                else:
                    pointer.AddPointer(exp)
                    assert tok[0]==Token.tok_SEPARATOR
                    return self.GetNextToken(), pointer
            
    # --------------------------------------------------------------------------
    def ParsePublicPrivate(self, tokKeyword, loc, sLabel=None, sName=None):
        sKeyword = string.upper(tokKeyword[1])
        tok  = self.GetNextToken()
        if sKeyword=="PRIVATE":
            obj = Private(loc, tokKeyword[1], self.nIndent)
        else:
            obj = Public(loc, tokKeyword[1], self.nIndent)
            
        if tok[1]==":":
            obj.AddDoubleColons(tok[1], self.GetNextToken()[1])
            tok  = self.GetNextToken()
        while tok[0]!=Token.tok_SEPARATOR:
            tokComma  = self.GetNextToken()
            if sKeyword=="PUBLIC":
                self.sub.GetVariable(tok[1], d={sKeyword:1}, bAutoAdd=1)
            if tokComma[1]==",":
                obj.AddObject(tok[1], sComma=tokComma[1])
                tok  = self.GetNextToken()
            else:
                obj.AddObject(tok[1])
                tok = tokComma
        return self.GetNextToken(), obj
                
    # --------------------------------------------------------------------------
    # save-stmt is SAVE [ [ :: ] saved-entity-list ]
    # saved-entity is object-name or proc-pointer-name or / common-block-name /
    def ParseSave(self, tokSave, loc, sLabel=None, sName=None):
        tok  = self.GetNextToken()
        save = Save(loc, tokSave[1], self.nIndent)
        if tok[1]==":":
            save.AddDoubleColons(tok[1], self.GetNextToken()[1])
            tok  = self.GetNextToken()
        while tok[0]!=Token.tok_SEPARATOR:
            if tok[1]=="/":
                tok2      = self.GetNextToken()
                tok3      = self.GetNextToken()
                tokComma  = self.GetNextToken()
                if tokComma[1]==",":
                    save.AddCommonBlock(tok[1], tok2[1], tok3[1],
                                        sComma=tokComma[1])
                    tok  = self.GetNextToken()
                else:
                    save.AddCommonBlock(tok[1], tok2[1], tok3[1])
                    tok = tokComma
            else:
                tokComma  = self.GetNextToken()
                var = self.sub.GetVariable(tok[1], {"save":1}, bAutoAdd=1)
                if tokComma[1]==",":
                    save.AddObject(var, sComma=tokComma[1])
                    tok  = self.GetNextToken()
                else:
                    save.AddObject(var)
                    tok = tokComma
        return self.GetNextToken(), save
                
    # --------------------------------------------------------------------------
    def ParseSubroutineStatement(self, tok, loc, sLabel=None, sName=None):
        tokName = self.GetNextToken()
        subStatement = SubroutineStatement(loc=loc, lPrefix=[],
                                           sSub=tok[1],
                                           sName=tokName[1],
                                           nIndent=self.nIndent)

        tok = self.ParseArguments(self.GetNextToken(), subStatement)
        if tok[1]==",":
            # Following now: BIND ( C [ , NAME = scalar-char-initialization-expr ] )
            raise Error("language-binding-spec currently not supported")

        assert tok[0]==Token.tok_SEPARATOR
        self.sub.AppendStatement(subStatement)
        subStatement.SetEndLocation(self.scanner.GetPreviousLocation())
        # parseEndProgUnit is defined in ParseExecution
        tok = self.ParseStatements(self.GetNextToken(),
                                   dEnd = {'ENDSUBROUTINE' :
                                           self.SpeciParseEndProgUnit,
                                           'END': self.SpeciParseEndProgUnit},
                                   nIndentModifier=1)
        return tok, None
    # --------------------------------------------------------------------------
    # A simple wrapper for ParseEndprogUnit, which is necessary because the
    # parameters for all functions when parsing the specification part are
    # different from the parameters needed in the execution part.
    def SpeciParseEndProgUnit(self, tok, loc, sLabel=None, sName=None):
        return self.ParseEndProgUnit(sLabel=None, keywordtoken=tok, sName=None,
                                     loc=loc)
    # --------------------------------------------------------------------------
    # This method sets all attributes contained in the declaration DECL
    # to the variable VAR, e.g.:  integer, dimension(20) :: a
    # would set the 'dimension' attribute in the variable a
    def SetAllAttributes(self, var, decl):
        for i in decl.GetAttributes():
            if i.__class__ == ArraySpecWithName:
                var.SetAttribute('dimension', i.GetArraySpec())
            elif i.__class__ == Intent:
                var.SetAttribute('intent', i)
            # We have to handle more special attributes for sure!!!
            elif i.__class__ == str or i.__class__ == AttributeString:
                var.SetAttribute(i.lower())
            else:
                i.__class__
                var.SetAttribute(i)
            
    # --------------------------------------------------------------------------
    # type-declaration-stmt is declaration-type-spec [ [ , attr-spec ] ... :: ]
    #                          entity-decl-list
    # entity-decl is object-name [(array-spec)] [*char-length] [initialization]
    def ParseTypeDeclaration(self, tok, loc, sLabel=None, sName=None):
        tokComma, type = self.ParseTypeSpec(tok)
        if tokComma[1]==",":
            decl           = Declaration(sType=type, sComma=tokComma[1],
                                         loc=loc, nIndent=self.nIndent)
        else:
            decl           = Declaration(sType=type, loc=loc, nIndent=self.nIndent)

        # now loop for attributes
        while tokComma[1]==",":
            tok  = self.GetNextToken()
            sAtt = string.upper(tok[1])
            if sAtt=="DIMENSION":
                tok2=self.GetNextToken()
                tokComma,att = self.ParseArraySpec(sName=tok[1],
                                                   tok=tok2)
            elif sAtt=="INTENT":
                tokParOpen = self.GetNextToken()
                assert tokParOpen[1]=="("
                tokIntent = self.GetNextToken()
                tokParClose = self.GetNextToken()
                assert tokParClose[1]==")"
                att = Intent(tok[1], tokParOpen[1], tokIntent[1],
                             tokParClose[1])
                tokComma = self.GetNextToken()
            else:
                tokComma = self.GetNextToken()
                att = tok[1]
            if tokComma[1]==",":
                decl.AddAttribute(att, tokComma[1])
            else:
                decl.AddAttribute(att)

        if tokComma[1]==":":
            decl.AddDoubleColons(tokComma[1], self.GetNextToken()[1])
            tok = self.GetNextToken()
        else:
            tok = tokComma
        # Next: loop over the list of variables
        while 1:
            var = self.sub.GetVariable(tok[1], {'type':type})
            self.SetAllAttributes(var, decl)
            tok = self.GetNextToken()
            if tok and tok[1]=="(":
                tok,arrspec = self.ParseArraySpec(tok=tok, var=var)
                var.SetAttribute('dimension',arrspec.GetArraySpec())
                declvar = arrspec
                var = declvar
            if tok and tok[1]=='*':
                tok1 = self.GetNextToken()
                if tok1[0]==Token.tok_NUMBER:
                    self.scanner.UnGet(tok1)
                    tokNext, len = self.ParseExpression(self.GetNextToken())
                    declvar = VariableWithLen(var, tok[1], len)
                    tok = tokNext
                else: 
                    declvar = VariableWithLen(var, tok[1])
                    declvar.SetParenthesisStar(tok1[1], self.GetNextToken()[1],
                                               self.GetNextToken()[1])
                    tok = self.GetNextToken()
                    
            else:
                declvar=var
            if tok and tok[1]!=",":
                # Now test if an initialization part is following
                if tok[1]=='=':
                    tokEqual=tok
                    tok, exp = self.ParseExpression(self.GetNextToken())
                    declvar.SetAttribute("init",exp)
                    declvar = VariableWithInit(declvar, sEqual=tokEqual[1],
                                               value=exp)
                elif tok[1]=='/':
                    tok, dvl = self.ParseDataValueList(tok)
                    declvar.SetAttribute("init",dvl)
                    declvar = VariableWithInit(declvar, dataobj=dvl)

            if tok[1]==",":
                decl.AddDeclaredVariable(declvar, tok[1])
                tok = self.GetNextToken()
            else:
                decl.AddDeclaredVariable(declvar)

            if tok[0]==Token.tok_SEPARATOR:
                return (self.GetNextToken(), decl)

            #tok = self.GetNextToken()

# --------------------------------------------------------------------------
    # USE [ [ , module-nature ] :: ] module-name [ , rename-list ]
    # USE [ [ , module-nature ] :: ] module-name ,  ONLY : [ only-list ]
    # module-nature is INTRINSIC or NON_INTRINSIC
    # rename is local-name => use-name or
    #    OPERATOR (local-defined-operator) =>  OPERATOR (use-defined-operator)
    def ParseUse(self, tokUse, loc, sLabel=None, sName=None):
        use = Use(loc, tokUse[1], self.nIndent)
        tok = self.GetNextToken()
        if tok[1]==",":
            use.SetNature(tok[1], self.GetNextToken()[1] )
            tok = self.GetNextToken()
            assert tok[1]==":"
        if tok[1]==":":
            tok1 = self.GetNextToken()
            assert tok1[1]==":"
            use.AddDoubleColon(tok[1], tok1[1])
            tok = self.GetNextToken()
        use.SetName(tok[1])
        module = self.project.oGetObjectForIdentifier(tok[1], "module")
        if not module:
            Warning("Module '%s' not found"%tok[1])
            
        tokComma=self.GetNextToken()
        # done if no , is following
        if not tokComma or tokComma[1]!=",":
            assert tokComma[0]==Token.tok_SEPARATOR
            if module:
                module.CopyDeclarationTo(self.sub)
            return (self.GetNextToken(), use)

        use.AddComma(tokComma[1])
        # Now we have either an only or an rename use statement
        tok=self.GetNextToken()
        if string.upper(tok[1])=="ONLY":
            use.AddOnlyString(tok[1], self.GetNextToken()[1])
            while 1:
                tok      = self.GetNextToken()
                var      = self.sub.AddVariable(tok[1], {"module":use.GetName()})
                tokComma = self.GetNextToken()
                if module:
                    module.CopyDeclarationTo(self.sub, sVar=tok[1])
                if tokComma[1]!=",":
                    use.AddOnly(var)
                    assert tokComma[0]==Token.tok_SEPARATOR
                    return (self.GetNextToken(), use)
                use.AddOnly(var, sComma=tokComma[1])
        else:
            tokFrom = tok
            while 1:
                if string.upper(tokFrom[1])=="OPERATOR":
                    raise NotYetImplemented("Renaming Operators", self.scanner)
                tokArrow = self.GetNextToken()
                assert tokArrow[1]=="=>"
                tokTo = self.GetNextToken()
                var   = self.sub.AddVariable(tokTo[1], {"module":use.GetName(),
                                                        "renamedfrom":tokFrom[1]})
                tokComma=self.GetNextToken()
                if module:
                    module.CopyDeclarationTo(self.sub, sVar=tokTo[1],
                                             sRenamedTo=tokFrom[1])
                if tokComma[1]!=",":
                    use.AddRename(tokFrom[1], tokArrow[1], tokTo[1])
                    assert tokComma[0]==Token.tok_SEPARATOR
                    return (self.GetNextToken(), use)
                use.AddRename(tokFrom[1], tokArrow[1], tokTo[1], tokComma[1])
                tokFrom = self.GetNextToken()
        
    # --------------------------------------------------------------------------
    # Helper functions
    # --------------------------------------------------------------------------
    # (array-spec) is explicit-shape-spec-list or assumed-shape-spec-list
    #                 or deferred-shape-spec-list or assumed-size-spec
    # or:
    # array-spec:   [ scalar-int-expr : ] scalar-int-expr,...   or
    #               [ scalar-int-expr ] :                ,...   or
    #               :                                    ,...   or
    #               [[ scalar-int-expr : ] scalar-int-expr,]...,
    #                                       [ scalar-int-expr : ] *
    def ParseArraySpec(self, tok=None, sName="", var=""):
        arrayspec = ArraySpecWithName(sName=sName, var=var)
        assert tok[1]=="("
        arrayspec.SetParOpen(tok[1])
        tok = self.GetNextToken()
        while tok[1]!=")":
            if tok[1]=="*":
                oas = OneArraySpec(lower = tok[1])
                tok      = self.GetNextToken()
            elif tok[1]==":":
                oas = OneArraySpec(sColon=tok[1])
                tok=self.GetNextToken()
            else:
                tokColon, lower=self.ParseExpression(tok)
                if tokColon[1]==":":
                    tok = self.GetNextToken()
                    if tok[1]=="*":
                        oas = OneArraySpec(lower=lower, sColon=tokColon[1],
                                           upper=tok[1])
                        tok = self.GetNextToken()
                    elif tok[1]!="," and tok[1]!=")":
                        tok, upper=self.ParseExpression(tok)
                        oas = OneArraySpec(lower=lower, sColon=tokColon[1],
                                           upper = upper)
                    else:
                        oas = OneArraySpec(lower=lower, sColon=tokColon[1])
                else:
                    oas = OneArraySpec(lower=lower)
                    tok = tokColon
            if tok[1]==",":
                arrayspec.AddSubscript(oas, tok[1])
                tok=self.GetNextToken()
            else:
                arrayspec.AddSubscript(oas)
            
        arrayspec.SetParClose(tok[1])
        tok = self.GetNextToken()
        return (tok, arrayspec)
    # --------------------------------------------------------------------------
    # Parses a basic type (integer, char, double precision, ...) and returns
    # a type object. Important thing here is to handle 'doubleprecision' (or
    # 'double precision') correctly. It will not parse any kind information!
    def ParseBasicType(self, tok):
        sType = string.upper(tok[1])
        if sType=='DOUBLEPRECISION':
            if isinstance(tok[1], AttributeString):
                s1, s2 = tok[1].tSplitString(6)
            else:
                s1 = tok[1][0:6]
                s2 = tok[1][6: ]
            type=Type(sType=s1, sType2 = s2)
        elif sType=="DOUBLE":
            tokPrecis=self.GetNextToken()
            type=Type(sType=tok[1], sType2 = tokPrecis[1])
        elif sType=="TYPE":
            tokParOpen = self.GetNextToken()
            tokParClose, subtype = self.ParseBasicType(self.GetNextToken())
            type=UserType(tok[1], tokParOpen[1], subtype, tokParClose[1])
        else:
            type = Type(sType=tok[1])
        return self.GetNextToken(), type

    # --------------------------------------------------------------------------
    # kind-selector is ( [ KIND = ] scalar-int-initialization-expr )
    # char-selector is length-selector or ( LEN = type-param-value ,
    #                                    KIND = scalar-int-initialization-expr )
    #       or ( type-param-value ,  [ KIND = ] scalar-int-initialization-expr )
    # or ( KIND = scalar-int-initialization-expr  [ , LEN = type-param-value ] )
    # As a (non standard) extension, it will also accept a single number,
    # this will allow a declaration like integer *8
    # tok must be ( or *
    def ParseKindCharSelector(self, tok, type):
        if tok[1]=='*':
            type.SetStar(tok[1])
            tok = self.GetNextToken()
            if tok[1]!='(':
                tok, exp = self.ParsePrimary(tok)
                type.SetLen(exp)
                return tok, type
        if tok[1]!='(':
            # e.g. real r
            if tok[1]!='*':
                return tok, type
            # e.g. integer *8 declaration.
            tok, exp = self.ParseExpression(tok)
            type.SetLen(tok[1], exp)
            return tok, type
        type.SetParOpen(tok[1])
        while tok[1]!=')':
            tok = self.GetNextToken()
            s = string.upper(tok[1])
            if s=='KIND' or s=='LEN':
                sKindOrLen = tok[1]
                sEqual = self.GetNextToken()[1]
                tok    = self.GetNextToken()
                if tok[1]!='*':
                    tok, exp = self.ParseExpression(tok)
                else:
                    exp =tok[1]
                    tok = self.GetNextToken()
            else:
                sKindOrLen = None
                sEqual     = None
                if tok[1]=='*':
                    exp = tok[1]
                    tok = self.GetNextToken()
                else:
                    tok, exp = self.ParseExpression(tok)
            if tok[1]==',':
                type.AddKindOrLen(sKindOrLen, sEqual, exp, tok[1])
            else:
                type.AddKindOrLen(sKindOrLen, sEqual, exp)
                
        assert tok[1]==")"
        type.SetParClose(tok[1])
        tokNext = self.GetNextToken()
        return tokNext, type
    # --------------------------------------------------------------------------
    # type-spec        is INTEGER [ kind-selector ]   or REAL [ kind-selector ]
    #                  or DOUBLE PRECISION or COMPLEX [ kind-selector ]
    #                  or CHARACTER [char-selector] or LOGICAL [ kind-selector ]
    # char-selector    is length-selector
    # length-selector  is ( [ LEN = ] type-param-value ) or * char-length [ , ]
    # type-param-value is scalar-int-expr or * or :
    def ParseTypeSpec(self, tok):
        tok, type = self.ParseBasicType(tok)
        if tok[1]=='(' or tok[1]=='*':
            tok, type = self.ParseKindCharSelector(tok, type)
        return tok, type
            
    # -------------------------------------------------------------------------- class ParseExp:
    
    # --------------------------------------------------------------------------
    # expr              is  [ level-5-expr defined-binary-op ]* level-5-expr
    # defined-binary-op is . letter [ letter ] ...  .
    def ParseExpression(self, tok):
        (tok, obj) = self.Level5Expr(tok)
        # Test if no real expr exists - in this case simple return the
        # previous object (i.e. whatever is returned from Level5Expr, which
        # might be a level-4-expr, ...).
        if not tok or tok[0]!=Token.tok_OPERATOR:
            return (tok, obj)
        # Now we do have a real expr, i.e. with a defined binary op.
        # Create the Expression object to store this expression.
        ExpObj = Expression()

        # Add the object returned from Level5Expr and the operator
        ExpObj.append(obj, tok[1])
        tok = self.GetNextToken()
        # Now loop over all further expressions.
        while 1:
            (tok, obj) = self.Level5Expr(tok)
            if tok[0]!=Token.tok_OPERATOR:
                ExpObj.append(obj)
                return (tok, ExpObj)
            ExpObj.append(obj, tok[1])
    # --------------------------------------------------------------------------
    # level-5-expr is [ equiv-operand equiv-op ]* equiv-operand
    # equiv-op     is .EQV. or .NEQV.
    def ParseBasicExpression(self, tok, SubExpressionParser, lOps,
                             classExpression = Expression):
        (tok, obj) = SubExpressionParser(tok)
        if not tok:
            return (tok, obj)
        s = string.upper(tok[1])
        if not (s in lOps):
            return (tok, obj)
        ExpObj = classExpression()
        ExpObj.append(obj, tok[1])
        tok = self.GetNextToken()
        # Now loop over all further expressions.
        while 1:
            (tok, obj) = SubExpressionParser(tok)
            if not tok:
                ExpObj.append(obj)
                return (tok, ExpObj)
            s = string.upper(tok[1])
            if not (s in lOps):
                ExpObj.append(obj)
                return (tok, ExpObj)
            ExpObj.append(obj, tok[1])
            tok = self.GetNextToken()
    # --------------------------------------------------------------------------
    # level-5-expr is [ equiv-operand equiv-op ]* equiv-operand
    # equiv-op     is .EQV. or .NEQV.
    def Level5Expr(self, tok):
        return self.ParseBasicExpression(tok, self.EquivOperand,
                                         ['.EQV', '.NEQV.'])
    # --------------------------------------------------------------------------
    # equiv-operand is [ or-operand .OR. ]* or-operand
    def EquivOperand(self, tok):
        return self.ParseBasicExpression(tok, self.OrOperand, ['.OR.'])
    # --------------------------------------------------------------------------
    # or-operand is [ and-operand .AND. ]* and-operand
    def OrOperand(self, tok):
        return self.ParseBasicExpression(tok, self.AndOperand, ['.AND.'])
    # --------------------------------------------------------------------------
    # and-operand is [ .NOT. ] level-4-expr
    def AndOperand(self, tok):
        sNot = tok[1]
        s = string.upper(sNot)
        if s==".NOT.":
            (tok, obj) = self.Level4Expr(self.GetNextToken())
            return (tok, UnaryExpression(sNot, obj))
        return self.Level4Expr(tok)
    # --------------------------------------------------------------------------
    # level-4-expr is [ level-3-expr rel-op ] level-3-expr
    # rel-op       is .EQ. or .NE. or .LT. or .LE. or .GT. or .GE.
    #                      or ==   or /=   or < or <=  or > or >=
    def Level4Expr(self, tok):
        return self.ParseBasicExpression(tok, self.Level3Expr,
                                    ['.EQ.', '.NE.', '.LT.', '.LE.', '.GT.',
                                     '.GE.', '=='  , '/='  , '<'   , '<='  ,
                                     '>'   , '>='                           ])
    # --------------------------------------------------------------------------
    # level-3-expr is [ level-2-expr // ]* level-2-expr
    def Level3Expr(self, tok):
        return self.ParseBasicExpression(tok, self.Level2Expr, ['//'])
    # --------------------------------------------------------------------------
    # level-2-expr is [add-op] [ add-operand  add-op ]* add-operand
    # add-op       is + or -
    def Level2Expr(self, tok):
        return self.ParseBasicExpression(tok, self.AddOperand, ['+','-'])
    # --------------------------------------------------------------------------
    # add-operand is [ mult-operand mult-op ]* mult-operand
    # mult-op     is * or /
    def AddOperand(self, tok):
        return self.ParseBasicExpression(tok, self.MultOperand, ['*','/'],
                                         classExpression = MultExpression)
    # --------------------------------------------------------------------------
    # mult-operand is level-1-expr [ ** level-1-expr ]*
    # This is actually parsed and stored as
    # mult-operand is [level-1-expr **]* level-1-expr
    # The difference beeing that a**b**c is a**(b**c) in the original grammar,
    # while it is (a**b)**c here - which doesn't really matter for our purpose.
    def MultOperand(self, tok):
        return self.ParseBasicExpression(tok, self.Level1Expr, ['**'],
                                         classExpression = PowerExpression)
    # --------------------------------------------------------------------------
    # level-1-expr     is [ defined-unary-op ] primary
    # defined-unary-op is . letter [ letter ] ...  .
    def Level1Expr(self, tok):
        if tok[0]==Token.tok_OPERATOR:
            sOperator = tok[1]
            tok = self.GetNextToken()
            (tok2, obj) = self.ParsePrimary(tok)
            return (tok2, UnaryExpression(sOperator, obj))
        return self.ParsePrimary(tok)
    # --------------------------------------------------------------------------
    # primary is constant or designator or array-constructor or
    #            structure-constructor or function-reference or
    #            type-param-inquiry or type-param-name    or ( expr )
    # JH TODO primary is designator or array-constructor or
    #            structure-constructor or function-reference or
    #            type-param-inquiry or type-param-name    or ( expr )
    # JH TODO: designator is array-element or array-section or
    #           structure-component or substring
    # ParsePrimary is also used to parse the name of an procedure, which can
    # be data-ref % procedure-component-name. In this case, a '('
    # The parameter bNoFuncCall can be set to 1 if the current expression
    # should not be parsed as a function call. This can happen when parsing
    # a variable declaration, e.g. "real a(100)", since when parsing the
    # variable name 'a', a is not yet entered in the list of variables
    # as being an array, so it would be parsed as a function call instead
    # (see ParseSpecification for examples).
    def ParsePrimary(self, tok, bNoFuncCall=0):
        # Check for a number first
        if tok[0]==Token.tok_NUMBER:
            t = self.GetNextToken()
            # Handle kind constants
            if t[1]=="_":
                t = self.GetNextToken()
                return (self.GetNextToken(),LiteralKind(tok[1],t[1]))
            return (t,Literal(tok[1]))

        if tok[1]=="(":
            sParOpen=tok[1]
            tok = self.GetNextToken()
            tok, obj = self.ParseExpression(tok)
            # Check if this is a parenthesis expression or a complex number:
            if tok[1]==",":
                sComma=tok[1]
                # Now we can either have a complex constant (e.g. (1,2) ), or
                # an implied do loop (e.g. (i,i=1,2). Of course, an implied do
                # loop is not allowed as a 'normal' expression, but it is
                # more convenient to parse this here for all IO calls
                tok, obj2 = self.ParseExpression(self.GetNextToken())
                if tok[1]=="," or tok[1]=="=":
                    tok, obj = self.ParseIODoLoop(sParOpen, obj, sComma,
                                                  obj2, tok)
                else:
                    obj = ComplexConst(sParOpen, obj, sComma, obj2, tok[1] )
            else:
                # It is a parenthesis expression
                obj = ParenthesisExpression(sParOpen=sParOpen, obj=obj,
                                            sParClose=tok[1])
            assert tok[1]==")"
            return self.GetNextToken(), obj

        if tok[1]=="(/":
            return self.ParseArrayConstructor(tok)
            
        # Check for a constant like .true. or .false.
        if tok[0]==Token.tok_TRUEFALSE:
            return (self.GetNextToken(), TrueFalse(tok[1]) )

        # More missing here!!!???
        if tok[0]==Token.tok_QUOTE:
            return self.GetNextToken(), String(tok[1])
        elif tok[0]==Token.tok_QUOTE_START:
            s = String(tok[1])
            tok = self.GetNextToken()
            while tok[0]!=Token.tok_QUOTE_END:
                s.AddContString(tok[1])
                tok = self.GetNextToken()
            s.AddContString(tok[1])
            return self.GetNextToken(), s
        else:
            # Now we know it's a variable name or a function call
            tokNext = self.GetNextToken()
            if tokNext and tokNext[1]=="(":
                var = self.sub.GetVariable(tok[1], bAutoAdd=0)
                # Test for variable or function call: a function call
                # is parsed if the name is not defined, or it is defined
                # but not with a dimension (i.e. external f; integer f ...)
                if not (var and var.bIsArray() ) and not bNoFuncCall:
                    f = FunctionCall(tok[1])
                    self.sub.AddFunctionCall(tok[1], self.scanner.GetLocation())
                    tok = self.ParseProcedureArgs(f, tokNext)
                    return tok, f
                # If var is not defined (which can happen if e.g. a variable
                # is encountered first in a common block or equivalence
                # statement), add the variable so that var is defined.
                if not var:
                    var = self.sub.GetVariable(tok[1], bAutoAdd=1)
                    
                tok, var = self.ParseArrayExpression(var, tokNext[1])
                if not var.oGetVariable().bIsArray():
                    var.oGetVariable().SetAttribute('dimension',var.GetArraySpec())
            else:
                var = self.sub.GetVariable(tok[1])
                tok = tokNext
            if tok and tok[1]=="%":
                tok, var = self.ParseTypeRef(var, tok[1], self.GetNextToken())
                # Test for substring expressions, e.g. a(i)%b(i)(1:2)
                # Using ParseArrayExpression for substring is more than
                # an overkill, it is just very simple to do :)
            if tok and tok[1]=="(":
                tok,var = self.ParseArrayExpression(var, tok[1])
            return (tok, var)
        
    # --------------------------------------------------------------------------
    def ParseArrayConstructor(self, tok):
        ac = ArrayConstructor(tok[1])
        tok = self.GetNextToken()
        while tok[1]!="/)":
            tok, obj = self.ParseExpression(tok)
            if tok[1]==",":
                ac.append(obj, tok[1])
                tok = self.GetNextToken()
            else:
                ac.append(obj)
                ac.SetParClose(tok[1])
                return self.GetNextToken(), ac
    # --------------------------------------------------------------------------
    # data-ref is part-ref [ % part-ref ] ...
    # Token is already the next token of the second part-ref (i.e. the
    # characters following the % sign) - especially token itsels is not a
    # variable
    def ParseTypeRef(self, var, sPercent, tok):
        dr = DataRef(var, sPercent)
        while 1:
            lit = Literal(tok[1])
            tok=self.GetNextToken()
            if tok and tok[1]=="(":
                tok, lit = self.ParseArrayExpression(lit, tok[1])
            if not tok or tok[1]!="%":
                dr.append(lit)
                return (tok, dr)
            dr.append(lit, tok[1])
            tok=self.GetNextToken()
    # --------------------------------------------------------------------------
    # section-subscript is subscript or subscript-triplet or vector-subscript
    # subscript-triplet is [ subscript ] : [ subscript ] [ : stride ]
    # subscript         is scalar-int-expr
    # vector-subscript  is int-expr
    def ParseArrayExpression(self, var, sParOpen):
        ar  = ArraySpecWithName(var=var, sParOpen=sParOpen)
        tok = self.GetNextToken()
        while tok[1]!=")":
            tok, ss = self.ParseSectionSubscript(tok)
            if tok[1]==",":
                ar.AddSubscript(ss, tok[1])
                tok = self.GetNextToken()
            else:
                ar.AddSubscript(ss)
        ar.SetParClose(tok[1])
        return self.GetNextToken(), ar
    
    # --------------------------------------------------------------------------
    def ParseSectionSubscript(self, tok):
        if tok[1]!=":":
            tok, oLower = self.ParseExpression(tok)
        else:
            oLower = None
        sColon1 = tok[1]
        if sColon1!=":":
            return tok, SectionSubscript(oLower)
        else:
            tok = self.GetNextToken()
            # Now test if an upper boundary is given as well
            oUpper  = None
            sColon2 = None
            oStride = None
            if tok[1]!=")" and tok[1]!=",":
                if tok[1]!=":":
                    tok, oUpper = self.ParseExpression(tok)
                # Now test for stride
                if tok[1]==":":
                    sColon2 = tok[1]
                    tok, oStride = self.ParseExpression(self.GetNextToken())
            return tok, SectionSubscript(oLower, sColon1, oUpper,
                                         sColon2, oStride)
        
    # --------------------------------------------------------------------------
    # io-implied-do is ( io-implied-do-object-list , io-implied-do-control )
    # io-implied-do-object is input-item or output-item
    # output-item is expr or io-implied-do
    # input-item is variable or io-implied-do
    # io-implied-do-control is do-variable = scalar-int-expr, scalar-int-expr
    #                          [ , scalar-int-expr ]
    # obj1 is the first expression, obj2 the second expression. The scanner
    # has already read the ',' or the '=' [from (i, i=1,2) or (i,j,i=1,2)].
    # The returned token must be the closing parenthesis!!
    def ParseIODoLoop(self, sParOpen, obj1, sComma1, obj2, tok):
        iol = IODoList(sParOpen, obj1, sComma1)
        obj = obj2
        while tok and tok[1]!="=":
            iol.AddExpr(obj, tok[1])
            tok, obj = self.ParseExpression(self.GetNextToken())
        iol.SetVar(obj, tok[1])
        tok, obj = self.ParseExpression(self.GetNextToken())
        iol.SetFrom(obj, tok[1])
        assert tok[1]==","
        tokComma, obj = self.ParseExpression(self.GetNextToken())
        iol.SetTo(obj)
        if tokComma[1]==",":
            tok, obj = self.ParseExpression(self.GetNextToken())
            iol.SetStep(tokComma[1], obj)
            iol.SetParClose(tok[1])
            return tok, iol
        else:
            iol.SetParClose(tokComma[1])
            return tokComma, iol
    # -------------------------------------------------------------------------- class ParseExecution:
    
    def __init__(self):
        # Mapping of keywords to parser functions to call
        self.dDecl2Function = {
                               # Declaration statements
                               "CHARACTER" : self.ParseTypeDeclaration,
                               "COMPLEX"   : self.ParseTypeDeclaration,
                               "INTEGER"   : self.ParseTypeDeclaration,
                               "DOUBLE"    : self.ParseTypeDeclaration,
                               "DOUBLEPRECISION": self.ParseTypeDeclaration,
                               "LOGICAL"   : self.ParseTypeDeclaration,
                               "REAL"      : self.ParseTypeDeclaration,
                               "TYPE"      : self.ParseTypeDeclaration,
                               "COMMON"    : self.ParseCommon,
                               "NAMELIST"  : self.ParseNamelist,
                               "GLOBAL"    : self.ParseCommon,
                               "DIMENSION" : self.ParseDimension,
                               "IMPLICIT"  : self.ParseImplicit,
                               "INTRINSIC" : self.ParseIntrinsic,
                               "PARAMETER" : self.ParseParameter,
                               "SAVE"      : self.ParseSave,
                               "PUBLIC"    : self.ParsePublicPrivate,
                               "PRIVATE"   : self.ParsePublicPrivate,
                               "USE"       : self.ParseUse,
                               "POINTER"   : self.ParsePointer,
                               "EQUIVALENCE":self.ParseEquivalence,
                               "DATA"      : self.ParseData,
                               "INCLUDE"   : self.ParseInclude,
                               "EXTERNAL"  : self.ParseExternal,
                               "INTERFACE" : self.ParseInterface,
                               "MODULE"    : self.ParseModuleProcedure,
                               "PROCEDURE" : self.ParseModuleProcedure,
                               "SUBROUTINE": self.ParseSubroutineStatement,
                               }
        self.dExec2Function = {
                               # Executable statements
                               "IF"        : self.ParseIf,
                               "DO"        : self.ParseDo,
                               "CONTINUE"  : self.ParseContinue,
                               "RETURN"    : self.ParseReturn,
                               "ALLOCATE"  : self.ParseAllocate,
                               "DEALLOCATE": self.ParseDeallocate,
                               "NULLIFY"   : self.ParseNullify,
                               "CALL"      : self.ParseCall,
                               "PRINT"     : self.ParsePrint,
                               "READ"      : self.ParseRead,
                               "WRITE"     : self.ParseWrite,
                               "CLOSE"     : self.ParseClose,
                               "OPEN"      : self.ParseOpen,
                               "REWIND"    : self.ParseRewind,
                               "BACKSPACE" : self.ParseBackspace,
                               "ENDFILE"   : self.ParseEndfile,
                               "INQUIRE"   : self.ParseInquire,
                               "CYCLE"     : self.ParseCycle,
                               "EXIT"      : self.ParseExit,
                               "GOTO"      : self.ParseGoto,
                               "STOP"      : self.ParseStop,
                               "PAUSE"     : self.ParsePause,
                               "GO"        : self.ParseGoto,
                               "FORMAT"    : self.ParseFormat,
                               "INCLUDE"   : self.ParseInclude,
                               "SELECT"    : self.ParseSelect,
                               "SELECTCASE": self.ParseSelect,
                               "CASE"      : self.ParseCase,
                               # In Parser.py:
                               "CONTAINS"  : self.ParseContained,
                               
                               }

        # The label stack is used for non-blocking do loops, where
        # more than one do loop might have the same continue (or action
        # statement) label.
        self.LabelStack = []
    
    # --------------------------------------------------------------------------
    def NotYet(self, tok, loc=None, sLabel=None, sName=None):
        raise NotYetImplemented("%s statement"%tok[1], self.scanner)
    # --------------------------------------------------------------------------
    # Parse:  execution-part-construct is executable-construct or format-stmt
    #                                  or entry-stmt or data-stmt
    #         executable-construct is action-stmt or associate-construct or
    #                                 case-construct or do-construct or
    #                                 forall-construct or if-construct or
    #                                 select-type-construct or where-construct
    #
    # Parses a block of statements and appends each statement to the current
    # self.sub object. Return value:
    # either a pair (token, execution-block), or a tuple (token,
    # execution-block, end-statement) is returned (see dEnd below). Parameters:
    #
    # tok -- Next token.
    #
    # dEnd -- Dictionary containing all keywords which end the current block
    #         as keys of an dictionary. If the value of the dictionary for a
    #         keyword is 1, the next token (which is the keyword) and the
    #         execution block is returned, otherwise the value must be a parser
    #         function which is then called. In this case, the end object is
    #         returned in addition to the next token and the execution block.
    #       
    # bOnlyOneStatement -- If this is true, only one statement is parsed
    #                      (and returned). This is used for if-statments
    #                      (not if-then-statements)
    #
    # nIndentModifier -- value which is at the beginning added to self.nindent,
    #                    and later subtracted. Used when parsing an indented
    #                    block
    def ParseStatements(self, tok=None, dEnd={}, bOnlyOneStatement=0,
                        nIndentModifier=0):
        if not tok: tok=self.GetNextToken()
        self.nIndent = self.nIndent+nIndentModifier
        sName        = ""
        sLabel       = None
        # Flag which indicates if we are already in the execution part
        # (used to identify e.g. an assignment to a variable called 'data',
        # or 'open'). This does not solve the problem of using keywords as
        # identifiers in all cases, but it helps in most cases (it doesn't work
        # if the assignment to (e.g.) 'data' is the first statement after the
        # specification part)
        
        while 1:
            # Check for end of file
            # ---------------------
            if not tok:
                self.nIndent = self.nIndent-nIndentModifier
                return tok

            # Check for label:
            if tok[0]==Token.tok_LABEL:
                sLabel=tok[1]
                tok = self.GetNextToken()
                if not tok:            # shouldn't happen: label w\out statement
                    self.nIndent = self.nIndent-nIndentModifier
                    return tok


            # Check for certain 'extentions' to the grammar: comment lines,
            # compiler directives, and preprocessor directives are stored in
            # the subroutine object as special objects.
            # ------------------------------------------------------------------
            loc      = self.scanner.GetLocation()

            if tok[0]==Token.tok_DIRECTIVE:
                self.sub.AppendStatement(CompilerDirective(tok[1], loc))
                self.scanner.GetNextToken()       # skip separator
                tok = self.scanner.GetNextToken()
                continue
            if tok[0]==Token.tok_PREDIRECTIVE:
                self.sub.AppendStatement(PreDirective(tok[1], loc))
                self.scanner.GetNextToken()       # skip separator
                tok = self.scanner.GetNextToken()
                continue
            if tok[0]==Token.tok_COMMENTLINE:
                self.sub.AppendStatement(CommentLine(tok[1], loc))
                self.scanner.GetNextToken()       # skip separator
                tok = self.scanner.GetNextToken()
                continue
            
            # Find the parser function to call for the read keyword
            # -----------------------------------------------------
            sKeyword = string.upper(tok[1])

            # First look in the list of end keywords
            # --------------------------------------
            f = dEnd.get(sKeyword, None)
            if f:
                tok, obj = apply(f, (tok, loc, sLabel, sName))
                if obj:
                    self.sub.AppendStatement(obj)
                self.nIndent = self.nIndent-nIndentModifier
                return tok
            
            # Not an end of block statement, so call the parser function
            # ----------------------------------------------------------
            if not self.sub.bIsExec():
                f = self.dDecl2Function.get(sKeyword)
            else:
                f = None
            if not f:
                f = self.dExec2Function.get(sKeyword)
                if f: self.sub.SetIsExec(1)
            #print "keyword",sKeyword, loc, self.sub.bIsExec()
            if f:
                try:
                    tok, obj = apply(f, (tok, loc, sLabel, sName) )
                    if obj:
                        obj.SetEndLocation(self.scanner.GetPreviousLocation())
                    # This is used for parsing if statements (without 'then')
                    # the statement shouldn't be added to the current
                    # subroutine
                    if bOnlyOneStatement:
                        self.nIndent = self.nIndent-nIndentModifier
                        return tok, obj
                    # A none object indicates, that the object was already
                    # added to the subroutine. This happens e.g. in the case
                    # of an if statement: when parsing the if statement, the
                    # if object is added to the subroutine, then ParseStatements
                    # is called to read the statements, elseif, endif, ...
                    # statements. So, when the if returns, nothing should be
                    # added to the subroutine, since all parts of the if
                    # statement (include the endif) have already been added.
                    if obj:
                        self.sub.AppendStatement(obj)

#                 except SystemExit, e:
#                     print "==================================================="
#                     print e
#                     print "==================================================="
#                     self.nIndent = self.nIndent-nIndentModifier
#                     while tok and tok[0]!=Token.tok_SEPARATOR:
#                         tok = self.GetNextToken()
#                     if not tok: return tok
#                     tok = self.GetNextToken()
                except NotYetImplemented, e:
                    print "==================================================="
                    print e
                    print "==================================================="
                    self.nIndent = self.nIndent-nIndentModifier
                    while tok and tok[0]!=Token.tok_SEPARATOR:
                        tok = self.GetNextToken()
                    if not tok: return tok
                    tok = self.GetNextToken()
                except:
                    print "Error in'%s'"%self.scanner.GetFileLocation()
                    print "Line: '%s'"%self.scanner.GetCurrentLine()
                    self.bErrorDuringParsing = 1
                    excp, value, tb = sys.exc_info()
                    print_exception(excp, value, tb)
                    while tok and tok[0]!=Token.tok_SEPARATOR:
                        tok = self.GetNextToken()
                    if not tok: return tok
                    tok = self.GetNextToken()
            else:
                nexttoken = self.GetNextToken()
                # Test if this is the name of a statement. A name is
                # identified by a ':' after a literal. Unfortunately,
                # if the next token is not a ":", we have an assignment,
                # and we have to unget this last token.
                if nexttoken[1]==":":
                    sName = tok[1]+nexttoken[1]
                    tok   = self.GetNextToken()
                    continue
                
                # Now it must be an assignment or 
                # a pointer assignment statement
                # -------------------------------
                self.scanner.UnGet(nexttoken)
                try:
                    tok, obj = self.ParseAssignment(tok,
                                                    self.scanner.GetLocation(),
                                                    sLabel, sName)
                except ValueError:
                    print 'Problem with statement',self.scanner.GetFileLocation()
                    print self.scanner.GetCurrentLine()
                    print 'This statement is ignored'
                    obj = None
                    tok = self.GetBeginOfNextStatement()

                if bOnlyOneStatement:
                    self.nIndent = self.nIndent-nIndentModifier
                    return tok, obj
                # This if statement is basically meant for error handling
                # only, since in this case obj is None
                if obj:
                    self.sub.AppendStatement(obj)

            # Reset the label and name statement variable
            # -------------------------------------------
            sLabel = None
            sName  = None

            # Now check if on the top of the stack is a 'none'. This is
            # only the case if we are parsing a non-block do loop, and
            # the statement ending a (more) inner do loop was found.
            # This means, that we have to end parsing the (more outer)
            # loop now, and do not have an end statement for this
            # do block. This is indicated by appending a 'none' as
            # to self.sub 
            # ParseDo will move the last statement (the just appended
            # none) to ParseDo.end, where it is treated correctly.
            if self.LabelStack and self.LabelStack[-1]==None:
                del self.LabelStack[-1]
                self.nIndent = self.nIndent-nIndentModifier
                return tok

            # See if a do loop is parsed and the label of the current
            # statement is the same as an end-label of the last do loop.
            # If so, that means that the last do loop and all previous
            # do loops with the same end-label are completed (this is for
            # non-blocked do loops). In this case set the end-label for
            # all those completed do loops to none, which signals that
            # these do loops are non-blocked ones and so do not have
            # an end statement. The 'higher level' ParseStatements
            # calls will check if the LabelStack entry was set to None
            # (which will tell ParseDo that this is a non-blocked do)
            # and return, without trying to read the closing statement
            # [see if-statement above where this is checked]
            if self.LabelStack and self.sub and \
               self.sub[-1].LabelIs(self.LabelStack[-1]):
                del self.LabelStack[-1]
                if self.LabelStack and \
                   self.sub[-1].LabelIs(self.LabelStack[-1]):
                    for i in range(len(self.LabelStack)):
                        if self.sub[-1].LabelIs(self.LabelStack[i]):
                            self.LabelStack[i]=None
                self.nIndent = self.nIndent-nIndentModifier
                return tok

    # --------------------------------------------------------------------------
    # Error handling function - find the begin of the next statement
    def GetBeginOfNextStatement(self):
        # This unget isn't nice, but sometimes if a short statement isn't
        # detected correctly, the next token might already be part of the
        # second-next statement, therefore ignoring one statement. By doing
        # an unget first, we seem to get more useful results.
        self.scanner.UnGet(None)
        tok = self.GetNextToken()
        while tok and tok[0]!=Token.tok_SEPARATOR:
            tok = self.GetNextToken()
        return self.GetNextToken()
    # --------------------------------------------------------------------------
    # This function is called from ParseStatements and ParseSpecification -
    def ParseInclude(self, tok, loc=None, sLabel=None, sName=None):
        tokName = self.GetNextToken()
        include = Include(loc=loc, nIndent=self.nIndent, sInclude=tok[1],
                          sFilename=tokName[1])
        tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        # The include filename is a string which includes '' - so these
        # quotes have to be removed.
        self.scanner.DoInclude(tokName[1][1:-1])
        return self.GetNextToken(), include
                          
    # --------------------------------------------------------------------------
    # allocate-stmt is ALLOCATE ( [ type-spec :: ] allocation-list
    #                             [, alloc-opt-list ] )
    # alloc-opt	is STAT = stat-variable or ERRMSG = errmsg-variable or
    #              SOURCE = source-variable
    # allocation is allocate-object [ ( allocate-shape-spec-list ) ]
    # allocate-shape-spec is [ allocate-lower-bound : ] allocate-upper-bound
    # allocate-object is variable-name or structure-component
    def ParseAllocate(self, tok, loc=None, sLabel=None, sName=None):
        return self.SubAllocateParam(tok, loc, sLabel, Allocate,
                                     ["STAT","ERRMSG","SOURCE"])
    # --------------------------------------------------------------------------
    # assignment-stmt is variable = expr
    def ParseAssignment(self, tok, loc=None, sLabel=None, sName=None):
        # We have to test if we are dealing with a statement function
        var=self.sub.GetVariable(tok[1], bAutoAdd=0)
        cl = Assignment
        # A statement function is identified by having an opening parenthesis
        # after the name, but not being declared as an array
        if not (var and var.bIsArray()):
            tokNext = self.GetNextToken()
            if tokNext[1]=='(':
                cl = StatementFunction
            else:
                self.sub.SetIsExec(1) # It's an assignment
            self.scanner.UnGet(tokNext)
        else:
            # It is an assignment, so we set the 'parsing executable
            # statements' flag
            self.sub.SetIsExec(1)
        tokEqual, lhs = self.ParsePrimary(tok)
        
        assert tokEqual[1]=="=" or tokEqual[1]=='=>'
        tok, rhs = self.ParseExpression(self.GetNextToken())
        assign = cl(sLabel, loc, self.nIndent,
                    lhs, tokEqual[1], rhs)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), assign
        
    # --------------------------------------------------------------------------
    # call-stmt is CALL procedure-designator [ ( [ actual-arg-spec-list ] ) ]
    # procedure-designator is procedure-name or
    #                         data-ref % procedure-component-name
    #                         data-ref % binding-name
    # actual-arg-spec is [ keyword = ] actual-arg
    # actual-arg is expr or variable or procedure-name or alt-return-spec
    # alt-return-spec is * label
    def ParseCall(self, tok, loc=None, sLabel=None, sName=None):
        # The procedure-designator can be an expression, but we can't
        # simply use ParseExpression, since it would (try to) parse
        # the actual arguments as well (as an array expression or function
        # call).
        tokName = self.GetNextToken()
        nexttok = self.GetNextToken()
        if nexttok and nexttok[1]=="%":
            raise NotYetImplemented("data-ref for calls: a%b",self.scanner)
        
        call = Call(sLabel, loc, tok[1], tokName[1], self.nIndent)
        self.sub.AddCall(tok[1], loc, "subroutine")
        tok = nexttok

        if tok[1]!="(":
            assert tok[0]==Token.tok_SEPARATOR
            return self.GetNextToken(), call
        tok = self.ParseProcedureArgs(call, tok)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), call
    # --------------------------------------------------------------------------
    # Parses the arguments of a function or subroutine call
    def ParseProcedureArgs(self, call, tok):
        call.SetParOpen(tok[1])
        # Now parse the actual arguments
        tok = self.GetNextToken()
        while tok[1]!=")":
            # First test if this is a "keyword=arg" argument
            tokNext = self.GetNextToken()
            if tokNext[1]=="=":
                keyword=tok[1]
                tokLookAhead=self.GetNextToken()
                if tokLookAhead[1]=="*":
                    tokLabel=self.GetNextToken()
                    tokSecondNext=self.GetNextToken()
                    if tokSecondNext[1]==",":
                        call.AddKeywordAltReturn(sKeyword=keyword,
                                                 sEqual=tokNext[1],
                                                 sStar=tokLookAhead[1],
                                                 sLabel=tokLabel[1],
                                                 sComma=tokSecondNext[1])
                        tokSecondNext = self.GetNextToken()
                    else:
                        call.AddKeywordAltReturn(sKeyword=keyword,
                                                 sEqual=tokNext[1],
                                                 sStar=tokLookAhead[1],
                                                 sLabel=tokLabel[1])
                else:
                    tokSecondNext, obj = self.ParseExpression(tokLookAhead)
                    if tokSecondNext[1]==",":
                        call.AddKeywordArgument(sKeyword=tok[1],
                                                sEqual=tokNext[1], obj=obj,
                                                sComma = tokSecondNext[1])
                        tokSecondNext = self.GetNextToken()
                    else:
                        call.AddKeywordArgument(sKeyword=tok[1],
                                                sEqual=tokNext[1], obj=obj)
                tok=tokSecondNext
                continue
            
            self.scanner.UnGet(tokNext)
            if tok[1]=="*":
                tokLabel = self.GetNextToken()
                tokComma = self.GetNextToken()
                if tokComma[1]==",":
                    call.AddAltReturn(sStar=tok[1], sLabel=tokLabel[1],
                                      sComma=tokComma[1])
                    tok = self.GetNextToken()
                else:
                    call.AddAltReturn(sStar=tok[1], sLabel=tokLabel[1])
                    tok = tokComma
            else:
                tokComma, arg = self.ParseExpression(tok)
                if tokComma[1]==",":                    
                    call.AddArgument(arg=arg, sComma=tokComma[1])
                    tok = self.GetNextToken()
                else:
                    call.AddArgument(arg=arg)
                    tok = tokComma
        call.SetParClose(tok[1])
        #tok = self.GetNextToken()
        return self.GetNextToken()
    # --------------------------------------------------------------------------
    # close-stmt is CLOSE ( close-spec-list )
    # close-spec is [ UNIT = ] file-unit-number or IOSTAT = scalar-int-variable
    #            or IOMSG = iomsg-variable or ERR = label
    #            or STATUS = scalar-default-char-expr
    def ParseClose(self, keywordtoken, loc=None, sLabel=None, sName=None):
        close = Close(sLabel, loc, self.nIndent, keywordtoken[1],
                      self.GetNextToken()[1])
        tok   = self.ParseIOControlSpec(self.GetNextToken(), close)
        close.SetParClose(tok[1])
        tok   = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), close
    # --------------------------------------------------------------------------
    # continue-stmt is CONTINUE
    def ParseContinue(self, keywordtoken, loc=None, sLabel=None, sName=None):
        tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), Continue(sLabel, loc,
                                             keywordtoken[1],
                                             self.nIndent)

    # --------------------------------------------------------------------------
    def ParseDeallocate(self, tok, loc=None, sLabel=None, sName=None):
        return self.SubAllocateParam(tok, loc, sLabel, Deallocate,
                                     ["STAT","ERRMSG"])
    # --------------------------------------------------------------------------
    # nullify-stmt is NULLIFY ( pointer-object-list )
    # pointer-object is variable-name or structure-component or	proc-pointer-name
    def ParseNullify(self, tok, loc=None, sLabel=None, sName=None):
        nullify = Nullify(sLabel, loc, tok[1],
                          self.GetNextToken()[1], self.nIndent)
        tok = self.GetNextToken()
        while tok[1]!=')':
            tok, expr = self.ParseExpression(tok)
            if tok[1]==",":
                nullify.AddExpression(expr, tok[1])
                tok = self.GetNextToken()
            else:
                nullify.AddExpression(expr)
        nullify.SetParClose(tok[1])
        tok=self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), nullify
    # --------------------------------------------------------------------------
    # do-construct       is block-do-construct or nonblock-do-construct
    # block-do-construct is do-stmt do-block end-do
    # do-stmt            is label-do-stmt or nonlabel-do-stmt
    # label-do-stmt      is [ do-construct-name : ] DO label [ loop-control ]
    # nonlabel-do-stmt   is [ do-construct-name : ] DO [ loop-control ]
    # loop-control       is [ , ] do-variable = scalar-int-expr,
    #                             scalar-int-expr  [ , scalar-int-expr ]
    #                    or [ , ] WHILE ( scalar-logical-expr )
    # do-variable        is scalar-int-variable
    # do-block           is block
    # end-do             is end-do-stmt or continue-stmt
    # end-do-stmt        is END DO [ do-construct-name ]
    # continue-stmt      is CONTINUE

    def ParseDo(self, tok, loc=None, sLabel=None, sName=None):
        tokNext  = self.GetNextToken()
        sDoLabel = None
        if tokNext[0]==Token.tok_NUMBER:
            sDoLabel = tokNext[1]
            tokNext = self.GetNextToken()
        sOptComma=None
        if tokNext[1]==',':
            sOptComma = tokNext[1]
            tokNext = self.GetNextToken()
            
        if tokNext[0]==Token.tok_SEPARATOR:
            do = ControlLessDo(sLabel, sName, loc, tok[1],
                               sDoLabel, self.nIndent)
            tok = tokNext
        elif string.upper(tokNext[1])=='WHILE':
            do = DoWhile(sLabel, sName, loc, tok[1], sDoLabel,
                         sOptComma, tokNext[1], self.GetNextToken()[1],
                         self.nIndent)
            tok, exp = self.ParseExpression(self.GetNextToken())
            assert tok[1]==')'
            do.SetExpression(exp, tok[1])
            tok = self.GetNextToken()
        else:
            do  = Do(sLabel, sName, loc, tok[1], sDoLabel, sOptComma,
                     self.nIndent)
            tok, var = self.ParsePrimary(tokNext)
            do.SetVariable(var, tok[1])
            assert tok[1]=="="
            tok, exp = self.ParseExpression(self.GetNextToken())
            do.SetFrom(exp, tok[1])
            assert tok[1]==","
            tokComma, exp = self.ParseExpression(self.GetNextToken())
            do.SetTo(exp)
            if tokComma[1]==",":
                tok, exp = self.ParseExpression(self.GetNextToken())
                do.SetStep(tokComma[1], exp)
            else:
                tok = tokComma

        assert tok[0]==Token.tok_SEPARATOR
        if sDoLabel:
            self.LabelStack.append(int(sDoLabel))
        else:
            self.LabelStack.append(-1)
        self.sub.AppendStatement(do)
        
        do.SetEndLocation(self.scanner.GetPreviousLocation())
        tok = self.GetNextToken()
        tok = self.ParseStatements(tok,
                                   dEnd={"END":  self.ParseEndDo,
                                         "ENDDO":self.ParseEndDo},
                                   nIndentModifier=1)
        # Return none, since the Do statement was already added (at the
        # beginning of this method). This is necessary to ensure that
        # the statements which are part of the do block are added
        # after the do statement!
        return tok, None
    # --------------------------------------------------------------------------
    # else-if-stmt is ELSE IF ( scalar-logical-expr ) THEN [ if-construct-name ]
    # else-stmt	   is ELSE [ if-construct-name ]
    def ParseElseOrElseIf(self, tok, loc=None, sLabel=None, sName=None):
        if string.upper(tok[1])=="ELSEIF":
            if isinstance(tok[1], AttributeString):
                sElse, sIf = tok[1].tSplitString(4)
            else:
                sElse = tok[1][0:4]
                sIf   = tok[1][4: ]
        else:
            sElse=tok[1]
            tokNext = self.GetNextToken()
            if string.upper(tokNext[1])=="IF":
                sIf = tokNext[1]
            else:
                self.scanner.UnGet(tokNext)
                sIf = None
        # Check if we are parsing an else if or an else:
        if sIf:
            obj = ElseIf(sLabel, loc, sElse, sIf, self.nIndent-1)
            tokParOpen = self.GetNextToken()
            assert tokParOpen[1]=="("
            tokParClose, expr = self.ParseExpression(self.GetNextToken())
            obj.AddExpr(tokParOpen[1], expr, tokParClose[1])
            assert tokParClose[1]==")"
            tok = self.GetNextToken()
            assert string.upper(tok[1])=="THEN"
            obj.SetThen(tok[1])
            
        else:
            obj = Else(sLabel, loc, sElse, self.nIndent-1)
        
        tok = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            obj.SetName(tok[1])                  # Name
            tok = self.GetNextToken()
        return self.GetNextToken(), obj
    # --------------------------------------------------------------------------
    # This method is called if an 'END' or an 'END...' is encountered
    # It will NOT parse a potential name following the end do, since
    # this function can not determine if a following label is actually
    # a do-construct-name or an variablename (at least not without
    # having information about the end of a statement, e.g. ';' or
    # newline).
    def ParseEndDo(self, keywordtoken, loc=None, sLabel=None, sName=None):
        sEnd, sDo = self.tKeywordSplit(keywordtoken, "ENDDO", 3)
        assert string.upper(sDo)=="DO"
        enddo = EndDo(sLabel, loc, sEnd=sEnd, sDo=sDo, nIndent=self.nIndent-1)
        tok = self.GetNextToken()

        if tok[0]!=Token.tok_SEPARATOR:
            enddo.SetName(tok[1])
            tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        del self.LabelStack[-1]
        return self.GetNextToken(), enddo
    # --------------------------------------------------------------------------
    # end-if-stmt is END IF [ if-construct-name ]
    def ParseEndOrEndif(self, tok, loc=None, sLabel=None, sName=None):
        sEnd, sIf = self.tKeywordSplit(tok, "ENDIF",3)
        assert string.upper(sIf)=="IF"
        endif = EndIf(sLabel, loc, sEnd=sEnd, sIf=sIf, nIndent=self.nIndent-1)
        tok   = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            endif.SetName(tok[1])                # Name
            tok = self.GetNextToken()
        return self.GetNextToken(), endif
        
    # --------------------------------------------------------------------------
    # end-subroutine-stmt is END [ SUBROUTINE [ subroutine-name ] ]
    # end-function-stmt	is END [ FUNCTION [ function-name ] ]
    # end-program-stmt	is END [ PROGRAM [ program-name ] ]
    def ParseEndProgUnit(self, keywordtoken=None, loc=None, sLabel=None, sName=None):
        es  = EndProgUnit(sLabel=sLabel, loc=loc, sEnd=keywordtoken[1],
                          nIndent=self.nIndent-1)
        tok = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            tokname = self.GetNextToken()
            if tokname[0]!=Token.tok_SEPARATOR:
                es.SetName(tok[1], tokname[1])
                tok = self.GetNextToken()
            else:
                es.SetName(tok[1])
                tok = tokname
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), es
    # --------------------------------------------------------------------------
    # exit-stmt is EXIT [ do-construct-name ]
    def ParseExit(self, tok, loc=None, sLabel=None, sName=None):
        tokLabel = self.GetNextToken()
        if tokLabel[0]==Token.tok_SEPARATOR:
            sExitLabel = None
        else:
            sExitLabel = tokLabel[1]
            tokLabel = self.GetNextToken()
        exit = Exit(sLabel, loc, tok[1], sExitLabel=sExitLabel,
                    nIndent=self.nIndent)
        assert tokLabel[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), exit
    # --------------------------------------------------------------------------
    # exit-stmt is EXIT [ do-construct-name ]
    def ParseCycle(self, tok, loc=None, sLabel=None, sName=None):
        tokLabel = self.GetNextToken()
        if tokLabel[0]==Token.tok_SEPARATOR:
            sCycleLabel = None
        else:
            sCycleLabel = tokLabel[1]
            tokLabel = self.GetNextToken()
        cycle = Cycle(sLabel, loc, tok[1], sCycleLabel=sCycleLabel,
                    nIndent=self.nIndent)
        assert tokLabel[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), cycle
    # --------------------------------------------------------------------------
    # Now, format is parsed rather crude: every token is read and appended
    # to the format (including the opening and closing parenthesis), till the
    # end of statement is reached. It is pretty hard to really parse a format
    # statement without changing the scanner signficantly, since different
    # tokens must be produced for the scanner, consider: 3(1X,/)  (where '/)'
    # has to be returned as a single token (looks like an array constructor).
    def ParseFormat(self, tok, loc=None, sLabel=None, sName=None):
        form = Format(sLabel, loc, tok[1], self.nIndent)
        tok = self.GetNextToken()
        # Tricky: a valid format is "format(//,2x)" - but the scanner
        # returns (/ as a single token. So we only assert that the first
        # charaters is a (
        assert tok[1][0]=="("
        while tok[0]!=Token.tok_SEPARATOR:
            form.append(tok[1])
            tok = self.GetNextToken()
        return self.GetNextToken(), form
    # --------------------------------------------------------------------------
    # computed-goto-stmt is GO TO ( label-list ) [ , ] scalar-int-expr

    def ParseGoto(self, tok, loc=None, sLabel=None, sName=None):
        sGo, sTo = self.tKeywordSplit(tok, "GOTO", 2)
        assert string.upper(sTo)=="TO"
        tok = self.GetNextToken()
        
        # Computed goto
        if tok[1]=="(":
            cgoto = ComputedGoto(sLabel, loc, sGo=sGo, sTo=sTo, sParOpen=tok[1])
            tok = self.GetNextToken()
            while tok[1]!=")":
                tokComma = self.GetNextToken()
                if tokComma[1]==",":
                    cgoto.AddLabel(tok[1], tokComma[1])
                    tok = self.GetNextToken()
                else:
                    cgoto.AddLabel(tok[1])
                    assert tokComma[1]==")"
                    tok = tokComma
            cgoto.SetParClose(tok[1])
            tok = self.GetNextToken()
            if tok[1]==",":
                cgoto.AddComma(tok[1])
                tok = self.GetNextToken()
            tok, obj = self.ParseExpression(tok)
            cgoto.SetExp(obj)
            return self.GetNextToken(), cgoto

        goto = Goto(sLabel, loc, sGo=sGo, sTo=sTo, sGotoLabel=tok[1],
                    nIndent=self.nIndent)
        tok  = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), goto
    # --------------------------------------------------------------------------
    def ParseStop(self, tok, loc=None, sLabel=None, sName=None):
        stop = Stop( sLabel, loc, sStop=tok[1], nIndent=self.nIndent)
        tok = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            tok, obj = self.ParsePrimary(tok)
            stop.SetStopCode(obj)
            assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(),stop
    # --------------------------------------------------------------------------
    def ParsePause(self, tok, loc=None, sLabel=None, sName=None):
        pause = Pause( sLabel, loc, sPause=tok[1], nIndent=self.nIndent)
        tok = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            tok, obj = self.ParsePrimary(tok)
            pause.SetStopCode(obj)
            assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(),pause
    # --------------------------------------------------------------------------
    # if-construct is if-then-stmt block [ else-if-stmt block ] ...
    #                 [ else-stmt block ] end-if-stmt
    # if-then-stmt is [ if-construct-name : ] IF ( scalar-logical-expr ) THEN
    # else-if-stmt is ELSE IF ( scalar-logical-expr ) THEN [ if-construct-name ]
    # else-stmt    is ELSE [ if-construct-name ]
    # end-if-stmt  is END IF [ if-construct-name ]
    # if-stmt is      IF ( scalar-logical-expr ) action-stmt
    def ParseIf(self, tokIf, loc=None, sLabel=None, sName=None):
        tokParOpen = self.GetNextToken()
        assert tokParOpen[1]=="("
        tokParClose, ifcond = self.ParseExpression(self.GetNextToken())
        assert tokParClose[1]==")"
        
        tok = self.GetNextToken()

        if tok[0]==Token.tok_NUMBER:
            arithIf = ArithmeticIf(sLabel, loc, tokIf[1], tokParOpen[1],
                                   ifcond, tokParClose[1], self.nIndent)
            while tok[0]!=Token.tok_SEPARATOR:
                tokNext = self.GetNextToken()
                if tokNext[1]==',':
                    arithIf.AppendLabel(tok[1], tokNext[1])
                    tok = self.GetNextToken()
                else:
                    arithIf.AppendLabel(tok[1])
                    tok = tokNext
            return self.GetNextToken(), arithIf
                    
        if string.upper(tok[1])!="THEN":                   # if-stmt
            tok, statement = self.ParseStatements(tok, bOnlyOneStatement=1,
                                                  nIndentModifier=1)
            ifonly = IfOnly(sLabel, loc, tokIf[1], tokParOpen[1], ifcond,
                            tokParClose[1], statement, self.nIndent)
            self.sub.AppendStatement(ifonly)
            ifonly.SetEndLocation(self.scanner.GetPreviousLocation())
            return tok, None
        ifobj = If(sLabel, sName, loc, tokIf[1], self.nIndent,
                   tokParOpen[1], ifcond, tokParClose[1], tok[1])
        self.sub.AppendStatement(ifobj)
        ifobj.SetEndLocation(self.scanner.GetPreviousLocation())
        # Now we are parsing an if-then(-else) statement
        # ==============================================
        tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        tok = self.GetNextToken()
        while 1:
            tok = self.ParseStatements(tok,
                                       dEnd = {"ELSE"  :self.ParseElseOrElseIf,
                                               "ELSEIF":self.ParseElseOrElseIf,
                                               "END"   :self.ParseEndOrEndif,
                                               "ENDIF" :self.ParseEndOrEndif},
                                       nIndentModifier=1)
            if self.sub[-1].__class__==EndIf: break
            if not tok:
                raise Error("Line %d, column %d: Problem with If statement" %
                            (self.scanner.GetLinenumber(),
                             self.scanner.GetColumnnumber()))
        # Return none, since the If statement was already added (at the
        # beginning of this method). This is necessary to ensure that
        # the statements which are part of the if (or else-if or then) block
        # are added after the do statement!
        return tok, None
                
    # --------------------------------------------------------------------------
    # Parses an expression list like "a, (b(i), i=1, 2)"
    def ParseIOExpressionList(self, obj, tok):
        while tok[0]!=Token.tok_SEPARATOR:
            tok, exp = self.ParseExpression(tok)
            if tok[1]==",":
                obj.AddIOExpression(exp, tok[1])
                tok = self.GetNextToken()
            else:
                obj.AddIOExpression(exp)
        return tok, obj
    # --------------------------------------------------------------------------
    # print-stmt is PRINT format [ , output-item-list ]
    # format is default-char-expr or label or *
    def ParsePrint(self, tok, loc=None, sLabel=None, sName=None):
        pr = Print(sLabel, loc, tok[1], self.nIndent)
        tok = self.GetNextToken()
        if tok[1]=="*":
            pr.SetFormat(tok[1])
            tok = self.GetNextToken()
        elif tok[0]==Token.tok_NUMBER:
            pr.SetFormat(int(tok[1]))
            tok = self.GetNextToken()
        else:
            tok, obj = self.ParseExpression(tok)
            pr.SetFormat(obj)
        if tok[1]!=",":
            assert tok[0]==Token.tok_SEPARATOR
            return self.GetNextToken(), pr
        pr.SetComma(tok[1])
        tok, pr = self.ParseIOExpressionList(pr, self.GetNextToken())
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), pr
    # --------------------------------------------------------------------------
    # Parses a statement with the format 'keyword ([a=]b,[c=]d)'
    def ParseBasicIOStatement(self, cl, tok, loc=None, sLabel=None, sName=None):
        rewind = cl(sLabel, loc, self.nIndent, tok[1])
        tok = self.GetNextToken()
        if tok[1]=='(':
            rewind.SetParOpen(tok[1])
            tok = self.ParseIOControlSpec(self.GetNextToken(), rewind)
            assert tok[1]==')'
            rewind.SetParClose(tok[1])
        else:
            rewind.AddUnitNumber(tok[1])
        return self.GetNextToken(), rewind
    # --------------------------------------------------------------------------
    # rewind-stmt REWIND file-unit-number or REWIND ( position-spec-list )
    # position-spec is [ UNIT = ] file-unit-number  or IOMSG = iomsg-variable
    #               or IOSTAT = scalar-int-variable or ERR = label
    def ParseRewind(self, tok, loc=None, sLabel=None, sName=None):
        tok, rew = self.ParseBasicIOStatement(Rewind, tok, loc, sLabel, sName)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), rew
    # --------------------------------------------------------------------------
    # backspace-stmt is BACKSPACE file-unit-number
    #                or BACKSPACE ( position-spec-list )
    def ParseBackspace(self, tok, loc=None, sLabel=None, sName=None):
        tok, back=self.ParseBasicIOStatement(Backspace, tok, loc, sLabel, sName)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), back
    # --------------------------------------------------------------------------
    # endfile-stmt is ENDFILE file-unit-number or ENDFILE ( position-spec-list )
    def ParseEndfile(self, tok, loc=None, sLabel=None, sName=None):
        tok, endfile=self.ParseBasicIOStatement(Endfile, tok, loc, sLabel, sName)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), endfile
    # --------------------------------------------------------------------------
    # open-stmt is OPEN ( connect-spec-list )
    def ParseOpen(self, tok, loc=None, sLabel=None, sName=None):
        # Check if open is a variable name - this test works only if the
        # variable is a scalar! (you can declare a variable 'open(20)', and
        # then use it as "open(20) = 1"  - arrrrgh!
        var     = self.sub.GetVariable(tok[1], bAutoAdd=0)
        tokNext = self.GetNextToken()
        if var:
            if tokNext[1]!='(':
                self.scanner.UnGet(tokNext)
                return self.ParseAssignment(tok, loc=loc, sLabel=sLabel,
                                            sName=sName)
        o   = Open(sLabel, loc, self.nIndent, tok[1], tokNext[1])
        tok = self.ParseIOControlSpec(self.GetNextToken(), o)
        assert tok[1]==')'
        o.SetParClose(tok[1])
        assert self.GetNextToken()[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), o
    # --------------------------------------------------------------------------
    # read-stmt is READ ( io-control-spec-list ) [ input-item-list ]
    #           or READ format [ , input-item-list ]
    def ParseRead(self, tok, loc=None, sLabel=None, sName=None):
        tokPar = self.GetNextToken()
        if tokPar[1]=='(':
            read  = Read(sLabel, loc, self.nIndent, tok[1],tokPar[1])
            tok   = self.GetNextToken()
            tok   = self.ParseIOControlSpec(tok, read)
            read.SetParClose(tok[1])
            tok=self.GetNextToken()
        else:
            read  = Read(sLabel, loc, self.nIndent, tok[1])
            tok = self.GetNextToken()
            if tok[1]==',':
                read.SetFormat(tokPar[1], tok[1])
            else:
                read.SetFormat(tokPar[1])
            tok=self.GetNextToken()
        # Test for 'empty' read statements, e.g. "read 10"
        if not tok: return self.GetNextToken(), read
        tok, read = self.ParseIOExpressionList(read, tok)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), read
    # --------------------------------------------------------------------------
    # inquire-stmt is INQUIRE ( inquire-spec-list )
    #                 INQUIRE ( IOLENGTH = scalar-int-variable ) output-item-list
    def ParseInquire(self, tok, loc=None, sLabel=None, sName=None):
        tok, inquire = self.ParseBasicIOStatement(Inquire, tok, loc, sLabel, sName)
        tok, inquire = self.ParseIOExpressionList(inquire, tok)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), inquire
    # --------------------------------------------------------------------------
    # write-stmt      is WRITE ( io-control-spec-list ) [ output-item-list ]
    # io-control-spec is [ UNIT = ] io-unit or [ FMT = ] format
    #                 or [ NML = ] namelist-group-name
    #                 or ADVANCE = scalar-default-char-expr    ...
    def ParseWrite(self, tok, loc=None, sLabel=None, sName=None):
        tok, write = self.ParseBasicIOStatement(Write, tok, loc, sLabel, sName)
        tok, write = self.ParseIOExpressionList(write, tok)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), write
    # --------------------------------------------------------------------------
    def ParseIOControlSpec(self, tok, obj):
        while tok[1]!=')':
            tokNext = self.GetNextToken()
            if tokNext[1]=='=':
                tokComma, exp = self.ParseExpression(self.GetNextToken())
                exp = OptionString(tok[1], tokNext[1], exp)
            else:
                self.scanner.UnGet(tokNext)
                if tok[1]=='*':
                    exp=tok[1]
                    tokComma = self.GetNextToken()
                else:
                    tokComma, exp = self.ParseExpression(tok)
            if tokComma[1]==',':
                obj.AddIOOpt(exp, tokComma[1])
                tok = self.GetNextToken()
            else:
                obj.AddIOOpt(exp)
                tok = tokComma
        return tok
    # --------------------------------------------------------------------------
    # This method is called if a 'return' is found. sName is actually
    # not used, but potentially passed in as a parameter from ParseStatements.
    def ParseReturn(self, tok, loc=None, sLabel=None, sName=None):
        tokNext = self.GetNextToken()
        if tokNext[0]!=Token.tok_SEPARATOR:
            ret = Return(sLabel, loc, tok[1], self.nIndent)
            tok, obj = self.ParseExpression(tokNext)
            ret.SetReturnValue(obj)
        else:
            ret = Return(sLabel, loc, tok[1], self.nIndent)
            
        return self.GetNextToken(), ret
    # --------------------------------------------------------------------------
    # select-case-stmt is [ case-construct-name : ] SELECT CASE ( case-expr )
    # case-expr        is scalar-int-expr or scalar-char-expr or
    #                     scalar-logical-expr
    def ParseSelect(self, tokSelect, loc=None, sLabel=None, sName=None):
        sSelect, sCase   = self.tKeywordSplit(tokSelect, "SELECTCASE",6)
        tokParOpen       = self.GetNextToken()
        tokParClose, exp = self.ParseExpression(self.GetNextToken())
        select           = Select(sLabel, sName, loc, sSelect, sCase,
                                  tokParOpen[1], exp, tokParClose[1],
                                  self.nIndent)
        self.sub.AppendStatement(select)
        select.SetEndLocation(self.scanner.GetPreviousLocation())
        tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        tok = self.GetNextToken()
        # The indentation is increased by two, but each case statement will
        # be stored with current indentation-1, so the case statements will
        # be indented by 1, while each other statement within the case
        # statements will be indented by 2 (relative to the select statement),
        # and indented by 1 relative to each case statement.
        tok = self.ParseStatements(tok,
                                   dEnd={"END":      self.ParseEndSelect,
                                         "ENDSELECT":self.ParseEndSelect},
                                   nIndentModifier=2)
        # Return none, since the select statement was already added (at the
        # beginning of this method). This is necessary to ensure that
        # the statements which are part of the select block are added
        # after the select statement!
        return tok, None
    # --------------------------------------------------------------------------
    # case-stmt        is CASE case-selector [case-construct-name]
    # case-selector    is ( case-value-range-list ) or DEFAULT
    # case-value-range is case-value or case-value :  or
    #                     : case-value or case-value : case-value
    def ParseCase(self, tokCase, loc=None, sLabel=None, sName=None):
        tok  = self.GetNextToken()
        # ParseSelect increases the indentation by 2, so to get the
        # case statements on the right level, 1 is subtracted. This has
        # the advantage that each statement belonging to a case will be
        # indented correctly, and we don't have to deal with ending the
        # indentation level for case statements.
        case = Case(sLabel, loc, tokCase[1], self.nIndent-1)
        if tok[1]=='(':
            case.SetParOpen(tok[1])
            while 1:
                tok = self.GetNextToken()
                tokComma, obj = self.ParseSectionSubscript(tok)
                if tokComma[1]==',':
                    case.AddSelector(obj, tokComma[1])
                else:
                    case.AddSelector(obj)
                    assert tokComma[1]==')'
                    case.SetParClose(tokComma[1])
                    break
        else:                           # must be DEFAULT now
            case.AddSelector(sDefault=tok[1])
        tok = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            case.SetName(tok[1])
            tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), case
    # --------------------------------------------------------------------------
    # end-select-stmt  is END SELECT [ case-construct-name ]
    def ParseEndSelect(self, keywordtoken, loc=None, sLabel=None, sName=None):
        sEnd, sSelect = self.tKeywordSplit(keywordtoken,"ENDSELECT",3)
        endselect = EndSelect(sLabel, loc, sEnd, sSelect, self.nIndent-2)
        tok = self.GetNextToken()
        if tok[0]!=Token.tok_SEPARATOR:
            endselect.SetName(tok[1])
            tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), endselect
    # --------------------------------------------------------------------------
    # Helper functions
    # --------------------------------------------------------------------------
    # This function checks if a two word keyword (like END DO) is written
    # as one word. If so, the string will be split into two parts, n specifying
    # the number of characters for the first word. If the keyword is written
    # as two words, the next token (which must be the second part of the
    # keyword) will be read and returned as well.
    def tKeywordSplit(self, tok, sCombinedName, n):
        sKeyword = string.upper(tok[1])
        if sKeyword==sCombinedName:
            if isinstance(tok[1],AttributeString):
                s1, s2 = tok[1].tSplitString(n) # split combined keywords
                                                # and preserve attributes 
            else:
                s1 = tok[1][0:n]                # split combined keywords
                s2 = tok[1][n: ]                # (there are no attributes)
        else:
            s1 = tok[1]                         # already two separate tokens
            s2 = self.GetNextToken()[1]
        return s1, s2
    # --------------------------------------------------------------------------
    # Used by ParseAllocate and ParseDeallocate, since the parameters are
    # identical.
    def SubAllocateParam(self, tok, loc, sLabel, Obj, lKeys):
        tokParen = self.GetNextToken()
        assert tokParen[1]=="("
        allocate = Obj(sLabel, loc=loc, sOp=tok[1],
                       sParOpen=tokParen[1], nIndent=self.nIndent)
        tok = self.GetNextToken()

        # First loop: parse the variables to allocate
        while tok[1]!=")":
            sKey = string.upper(tok[1])
            if sKey in lKeys: break
            tok, obj = self.ParseExpression(tok)
            if tok[1]==',':
                allocate.AddVariable(obj, tok[1])
                tok=self.GetNextToken()
            else:
                allocate.AddVariable(obj)

        # Second loop: parse the alloc-opt-list
        while tok[1]!=")":
            sName=tok[1]
            tokEqual=self.GetNextToken()
            assert tokEqual[1]=="="
            tok, obj = self.ParsePrimary(self.GetNextToken())
            if tok[1]==',':
                allocate.AddOption(sName, tokEqual[1], obj, tok[1])
                tok=self.GetNextToken()
            else:
                allocate.AddOption(sName, tokEqual[1], obj)
                
        allocate.SetParClose(tok[1])
        tok = self.GetNextToken()
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), allocate class AttributeString(str):
    def __init__(self, s):
        str.__init__(self, s)
        # If this object is initialised with an AttributeString,
        # copy the attributes as well
        if isinstance(s, AttributeString):
            self.lPrefix  = s.GetPrefixAttributes()[:]
            self.lPostfix = s.GetPostfixAttributes()[:]
        else:
            self.lPrefix  = []
            self.lPostfix = []
    # --------------------------------------------------------------------------
    # Creates a new attribute string which has the same pre- and postfix
    # attributes, but a new string.
    def sCreateCopy(self, s):
        new = AttributeString(s)
        new.SetPrefixAttributes(self.GetPrefixAttributes())
        new.SetPostfixAttributes(self.GetPostfixAttributes())
        return new
    # --------------------------------------------------------------------------
    # Splits an AttributeString into two strings, the first one containing
    # all prefix attributes, the second one all postfix ones. The parameter
    # n specified the number of character to for the first string.
    def tSplitString(self, n):
        s1 = AttributeString(self[0:n])
        s2 = AttributeString(self[n: ])
        s1.SetPrefixAttributes(self.GetPrefixAttributes())
        s2.SetPostfixAttributes(self.GetPostfixAttributes())
        return s1,s2
    # --------------------------------------------------------------------------
    def SetPrefixAttributes(self,  l) : self.lPrefix = l[:]
    # --------------------------------------------------------------------------
    def SetPostfixAttributes(self, l) : self.lPostfix = l[:]
    # --------------------------------------------------------------------------
    def AppendPrefix(self,  o):
        if type(o)==ListType:
            self.lPrefix.extend(o)
        else:
            self.lPrefix.append(o)
    # --------------------------------------------------------------------------
    def AppendPostfix(self, o):
        if type(o)==ListType:
            self.lPostfix.extend(o)
        else:
            self.lPostfix.append(o)
    # --------------------------------------------------------------------------
    def GetPrefixAttributes(self ): return self.lPrefix
    # --------------------------------------------------------------------------
    def GetPostfixAttributes(self): return self.lPostfix
    # --------------------------------------------------------------------------
    def GetString(self): return str.__str__(self)
    # --------------------------------------------------------------------------
    # We have to overwrite this method so that a new AttributeString is
    # returned!
    def upper(self):
        return self.sCreateCopy(str.__str__(self).upper())
    # --------------------------------------------------------------------------
    # We have to overwrite this method so that a new AttributeString is
    # returned!
    def lower(self):
        return self.sCreateCopy(str.__str__(self).lower())
    # --------------------------------------------------------------------------
    # We have to overwrite this method so that a new AttributeString is
    # returned!
    def capitalize(self):
        return self.sCreateCopy(str.__str__(self).capitalize())
    # --------------------------------------------------------------------------
    #def ToList(self, stylesheet, l): return l.append(str.__str__(self))
    def ToList(self, stylesheet, l): return l.append(self)
    # --------------------------------------------------------------------------
    #def __repr__(self): return str.__str__(self)
    # Debug: output an attribute string with all attributes
    def __repr__(self):
        return "%s-%s-%s"%(`self.lPrefix`,str.__str__(self),`self.lPostfix`) class File(BasicRepr, UserList):

    # Constructor for File object. Parameters:
    #
    # sFilename -- Filename, including path
    #
    # sFormat   -- Format of the file: 'fix' or 'free'
    #
    def __init__(self, sFilename, sFormat):
        # The list stores all information contained in the file
        UserList.__init__(self)
        self.sFilename  = sFilename
        self.sFormat    = sFormat
        self.stylesheet = None
        assert self.sFormat in ["fixed","free"]

    # --------------------------------------------------------------------------
    def sGetFilename(self): return self.sFilename
    
    # --------------------------------------------------------------------------
    def sGetFormat(self): return self.sFormat
    
    # --------------------------------------------------------------------------
    # Returns a string representation of the object, which is suitable for
    # the format in which this file was written (fixed/free).
    def sFormatObject(self, obj, bIgnoreAttributes=0, stylesheet=None):
        if not stylesheet:
            # avoid creating a stylesheet over and over again
            if not self.stylesheet:
                if self.sFormat=="fixed":
                    self.stylesheet=f77()
                else:
                    self.stylesheet=DefaultStylesheet()
            stylesheet=self.stylesheet
        return stylesheet.ToString(obj, bIgnoreAttributes)
    # --------------------------------------------------------------------------
    def ToList(self, stylesheet, l):
        for i in self:
            stylesheet.ToList(i, l)
    # --------------------------------------------------------------------------
    dType2Class = {'subroutine' : Subroutine,
                   'function'   : Function,
                   'module'     : Module,
                   'blockdata'  : Blockdata }
    def GetIdentifier(self, sId, sType):
        c = File.dType2Class.get(sType.lower(),None)
        if not c:
            raise FatalError("Type '%s' undefined in File.bHasIdentifier"%sType)
        s = sId.lower()
        for i in self:
            if isinstance(i,c) and i.sGetName().lower()==s:
                return i
        return None
            
    # --------------------------------------------------------------------------
    # Returns a list of all statements of a certain class. Parameter:
    #
    # class -- Class to which all returned object should belong
    def GetAllProgUnits(self, c):
        return filter(lambda x,c=c: isinstance(x,c), self)
    # --------------------------------------------------------------------------
    # Returns a list of all subroutines
    def GetAllSubroutines(self): return self.GetAllProgUnits(Subroutine)
    # --------------------------------------------------------------------------
    # Returns a list of all funcions
    def GetAllFunctions(self): return self.GetAllProgUnits(Function)
    # --------------------------------------------------------------------------
    # Returns a list of all Program(s)
    def GetAllPrograms(self): return self.GetAllProgUnits(Program) class IncompleteProgUnit(ProgUnit):
    def __init__(self):
        ProgUnit.__init__(self)
    # --------------------------------------------------------------------------
    def sGetName(self): return ""
    # --------------------------------------------------------------------------
    def GetArguments(self): return []
    # --------------------------------------------------------------------------
    def sGetPrefix(self): return [] class Subroutine(ProgUnit):
    # Constructor for a subroutine object. Parameter:
    #
    # sSubName -- Name of function
    #
    def __init__(self, subStatement=None):
        ProgUnit.__init__(self, subStatement) class SubroutineStatement(BasicStatement):
    def __init__(self, loc=None, lPrefix=[], sSub="SUBROUTINE", sName="",
                 nIndent=0, oSub = None):
        BasicStatement.__init__(self, None, loc, nIndent)
        self.lPrefix     = lPrefix
        self.sSub        = sSub
        self.sName       = sName
        self.lArgs       = DoubleList()
        self.sParOpen    = None
        self.sParClose   = None
        self.oSub        = oSub
    # --------------------------------------------------------------------------
    def SetParOpen(self, sParOpen): self.sParOpen = sParOpen
    # --------------------------------------------------------------------------
    def SetParClose(self, sParClose): self.sParClose = sParClose
    # --------------------------------------------------------------------------
    def GetName(self): return self.sName
    # --------------------------------------------------------------------------
    def GetPrefix(self): return self.lPrefix
    # --------------------------------------------------------------------------
    def GetArguments(self): return self.lArgs.GetMainList()
    # --------------------------------------------------------------------------
    def AddArgument(self, sName, sComma=None, d=None):
        if self.sParOpen==None: self.sParOpen="("
        self.sParClose = ")"
        if sComma==None and \
               len(self.lArgs.lGetSecondaryList())==len(self.lArgs)-1:
            self.lArgs.append(",", sName)
        else:
            self.lArgs.append(sName, sComma)
            
        if self.oSub:
            self.oSub.AddArgument(sName, sComma=sComma, d=d)
            
    # --------------------------------------------------------------------------
    def ToList(self, stylesheet, l):
        BasicStatement.ToList(self, stylesheet, l)
        for i in self.lPrefix:
            l.append(stylesheet.sKeyword(i), nIndentNext=1)
        l.append(stylesheet.sKeyword(self.sSub), nIndentNext=1)
        l.append(self.sName)
        if not self.sParOpen:
            return 
        l.append(self.sParOpen)
        self.lArgs.ToList(stylesheet, l)
        l.append(self.sParClose)
                 
    # -------------------------------------------------------------------------- class Function(ProgUnit):
    # Constructor for a subroutine object. Parameter:
    #
    # sSubName -- Name of function
    #
    def __init__(self, FuncStatement):
        ProgUnit.__init__(self, FuncStatement) class FunctionStatement(BasicStatement):
    def __init__(self, loc=None, nIndent=0, lType=None, sFunc="FUNCTION", sName="",
                 oFunc = None):
        BasicStatement.__init__(self, None, loc, nIndent, isDeclaration=0)
        self.sFunc       = sFunc
        self.sName       = sName
        self.lArgs       = DoubleList()
        self.sParOpen    = None
        self.sParClose   = None
        self.lType       = lType
        self.oFunc       = oFunc
        self.lResult     = []
    # --------------------------------------------------------------------------
    def SetParOpen(self, sParOpen  ): self.sParOpen  = sParOpen
    # --------------------------------------------------------------------------
    def SetParClose(self, sParClose): self.sParClose = sParClose
    # --------------------------------------------------------------------------
    def GetName(self): return self.sName
    # --------------------------------------------------------------------------
    def GetType(self): return self.lType
    # --------------------------------------------------------------------------
    def GetArguments(self): return self.lArgs.GetMainList()
    # --------------------------------------------------------------------------
    def AddArgument(self, sName, sComma=None, d=None):
        self.lArgs.append(sName, sComma)
        if self.oFunc:
            self.oFunc.AddArgument(sName, sComma=sComma, d=d)
    # --------------------------------------------------------------------------
    def SetResult(self, sResult, sParOpen, sName, sParClose):
        self.lResult = [sResult, sParOpen, sName, sParClose]
    # --------------------------------------------------------------------------
    def ToList(self, stylesheet, l):
        BasicStatement.ToList(self, stylesheet, l)
        for i in self.lType:
            if i.__class__==Type:
                i.ToList(stylesheet, l)
            else:
                l.append(stylesheet.sKeyword(i))
            l.indent(1)
        l.append(stylesheet.sKeyword(self.sFunc), nIndentNext=1)
        l.append(self.sName)
        if not self.sParOpen:
            return
        l.append(self.sParOpen)
        self.lArgs.ToList(stylesheet, l)
        l.append(self.sParClose)
        if self.lResult:
            l.indent(1)
            l.extend(self.lResult)
                 
    # -------------------------------------------------------------------------- class Blockdata(ProgUnit):
    # Constructor for a subroutine object. Parameter:
    #
    # sSubName -- Name of function
    #
    def __init__(self, blockdataStatement):
        ProgUnit.__init__(self, blockdataStatement) class BlockdataStatement(BasicStatement):
    def __init__(self, loc=None, sBlock='BLOCK', sData='DATA',
                 sName=None, nIndent=0):
        BasicStatement.__init__(self, None, loc, nIndent)
        self.sBlock = sBlock
        self.sData  = sData
        self.sName  = sName
    # --------------------------------------------------------------------------
    def GetName(self): return self.sName
    # --------------------------------------------------------------------------
    def ToList(self, stylesheet):
        l=BasicStatement.ToList(self, stylesheet)
        l.extend([stylesheet.sKeyword(self.sBlock),
                  stylesheet.sKeyword(self.sData)])
        if self.sName:
            l.extend([' ',self.sName])
        return l class EndBlockdata(BasicStatement):
    def __init__(self, loc=None, sEnd='END', sBlock='BLOCK', sData='DATA',
                 sName=None, nIndent=0):
        BasicStatement.__init__(self, None, loc, nIndent)
        self.sEnd   = sEnd
        self.sBlock = sBlock
        self.sData  = sData
        self.sName  = sName
    # --------------------------------------------------------------------------
    def ToList(self, stylesheet):
        l=BasicStatement.ToList(self, stylesheet)
        l.append(stylesheet.sKeyword(self.sEnd))
        if self.sBlock:
            l.extend([' ', stylesheet.sKeyword(self.sBlock),
                           stylesheet.sKeyword(self.sData)])
        if self.sName:
            l.extend([' ', self.sName])
        return l class Module(ProgUnit):
    # Constructor for a module object. Parameter:
    #
    # modStatement -- the actual module statement
    #
    def __init__(self, modStatement=None):
        ProgUnit.__init__(self, modStatement) class ModuleStatement(BasicStatement):
    def __init__(self, loc=None, sModule="MODULE", sName="",
                 nIndent=0, oModule = None):
        BasicStatement.__init__(self, None, loc, nIndent)
        self.sModule     = sModule
        self.sName       = sName
        self.oModule     = oModule
    # --------------------------------------------------------------------------
    def GetName(self): return self.sName
    # --------------------------------------------------------------------------
    def ToList(self, stylesheet, l):
        BasicStatement.ToList(self, stylesheet, l)
        l.append(stylesheet.sKeyword(self.sModule), nIndentNext=1)
        l.append(self.sName)
    # -------------------------------------------------------------------------- class Contains(BasicStatement):

    # Stores a contains statement
    #
    def __init__(self, sLabel=None, loc=None, sContains="CONTAINS", nIndent=0):
        BasicStatement.__init__(self, sLabel, loc, nIndent)
        self.sContains = sContains
    # --------------------------------------------------------------------------
    def ToList(self, stylesheet, l):
        BasicStatement.ToList(self, stylesheet, l)
        l.append(self.sContains) class CommentLine(BasicNonStatement):
    def __init__(self, sComment, loc=None):
        BasicNonStatement.__init__(self, sComment, loc) class CompilerDirective(BasicNonStatement):
    def __init__(self, sCompilerDirective, loc):
        BasicNonStatement.__init__(self, sCompilerDirective, loc) class PreDirective(BasicNonStatement):
    def __init__(self, sPreDirective, loc):
        BasicNonStatement.__init__(self, sPreDirective, loc) class NotYetImplemented(Warning):
    def __init__(self, sWarningMessage, scanner):
        Warning.__init__(self, sWarningMessage)
        self.nLinenumber   = scanner.GetLinenumber()
        self.nColumnnumber = scanner.GetColumnnumber()
    # ----------------------------------------------------
    def __repr__(self):
        return "Line %d, column %d: %s not yet implemented."%\
               (self.nLinenumber, self.nColumnnumber,
                Warning.__repr__(self) ) class Error:
    def __init__(self, sErrorMessage):
        self.sErrorMessage = sErrorMessage
    # ----------------------------------------------------
    def sGetError(self):
        return self.__str__()
    # ----------------------------------------------------
    def __str__(self):
        return self.sErrorMessage
import sys
import string
import re
import os
import getopt
        import profile
from   traceback                  import print_exception
from   Scanner.Token              import Token
from   Scanner.Scanner            import ScannerFactory
from   Grammar.ParseSpecification import ParseSpecification
from   Grammar.ParseExp           import ParseExp
from   Grammar.ParseExecution     import ParseExecution
from   AOR.AttributeString        import AttributeString
from   AOR.File                   import File
from   AOR.ProgUnit               import IncompleteProgUnit
from   AOR.Subroutine             import Subroutine, SubroutineStatement
from   AOR.Function               import Function, FunctionStatement
from   AOR.Blockdata              import Blockdata,  BlockdataStatement, \
                                         EndBlockdata
from   AOR.Module                 import Module, ModuleStatement
from   AOR.Statements             import Contains
from   AOR.SpecialStatements      import CommentLine, CompilerDirective, \
                                         PreDirective
from   Tools.Error                import NotYetImplemented, Error
                from Stylesheets.f77 import f77
                from Analyser.Interface import GenerateInterface
                from Stylesheets.f77    import f77
        assert tok[0]==Token.tok_SEPARATOR
        self.sub = Blockdata(blockdataStatement)
        
        # Only append the subroutine to the file object, if we are not parsing
        # a contained statement (in the latter case the subroutine is appended
        # to the 'outer' subroutine in ParseContained).
        if not bIsContained:
            self.oFile.append(self.sub)
        else:
            self.oldsub.AddContained(self.sub)
        self.ParseDeclarationAndExecutionPart(self.GetNextToken())
#         try:
#             #print "declaration parsing",tok
#             #tokEnd       = self.ParseSpecification(self.GetNextToken() )
#             tokEnd       = self.ParseStatements(self.GetNextToken(),
#                                                 dEnd={"END":self.ParseEndProgUnit},\
#                                                 nIndentModifier=1)
#             print tokEnd
#             assert string.upper(tokEnd[1])=='END'
#             print "Declaration stopping at",tokEnd
#         except :
#             print "Error while parsing declaration part of %s"%\
#                   self.sub.GetName()
#             print "file:",self.scanner.GetFileLocation()
#             print self.scanner.GetCurrentLine()
#             excp, value, tb = sys.exc_info()
#             print_exception(excp, value, tb)
#             return None                 # this aborts the outer loop

#        tok = self.GetNextToken()
        return self.GetNextToken(), self.sub
        if tok[0]!=Token.tok_SEPARATOR:
            if string.upper(tok[1])=='BLOCK':
                sBlock = tok[1]
                sData = self.GetNextToken()[1]
            else:
                if isinstance(tok[1], AttributeString):
                    sBlock, sData = tok[1].tSplitString(5)
                else:
                    sBlock = tok[1][0:5]
                    sData  = tok[1][5: ]
            tok = self.GetNextToken()
            if tok and tok[0]!=Token.tok_SEPARATOR:
                sName = tok[1]
                tok[0] = self.GetNextToken()
            else:
                sName = None
        else:
            sName  = None
            sBlock = None
            sData  = None
        ebd = EndBlockdata(sEnd=tokEnd[1], sBlock=sBlock,  sData=sData,
                           sName=sName, nIndent=self.nIndent-1)
        self.sub.AppendStatement(ebd)
        assert tok[0]==Token.tok_SEPARATOR
        return self.GetNextToken(), self.sub
    # --------------------------------------------------------------------------
    def ParseIncompleteFile(self, stack, tok, bIsTest=0, bIsContained=0):
        # Push back all read tokens to get a clear start for parsing.
        # The stack is [ (token,location), (token, location), ...]
        self.scanner.UnGet(tok)
        for i in range(len(stack)-1, 0, -1):
            self.scanner.UnGet(stack[i][0])
        # The first token is still on the stack
        
        self.sub = IncompleteProgUnit()
        self.oFile.append(self.sub)
        tok = self.ParseDeclarationAndExecutionPart(stack[0][0])
        return tok, self.sub
        
    # --------------------------------------------------------------------------
    # --------------------------------------------------------------------------
    # --------------------------------------------------------------------------
            
# ==============================================================================
def Parser(sFilename=None, sInput=None, lInputLines=None,
           sFormat=None, project=None):
    p = ParserClass(sFilename=sFilename, sInput=sInput, sFormat=sFormat,
                    lInputLines=lInputLines, project=project)
    return p.GetFileObject()
# ==============================================================================
def usage():
    print "Usage: Parser.py [-P] [-i] <list of files>"
    print
    print "-P: Profile"
    print "-i: Generate interface"
# ------------------------------------    
if __name__=="__main__":

    bDoProfile = 0
    bDoPrint   = 0
    bDoTest    = 0
    bInterface = 0
    # P : Profile
    # O : Output tokens
    lOpt, lArgs = getopt.getopt(sys.argv[1:],"PoTi")
    for i in lOpt:
        if i[0]=="-P":
            bDoProfile=1
        elif i[0]=="-o":
            bDoPrint=1
        elif i[0]=="-T":
            bDoTest=1
        elif i[0]=="-i":
            bInterface=1
            
    if len(lArgs)<1:
        usage()

    project = DummyProject()
    if not bDoProfile:
        for i in lArgs:
            objFile = Parser(i)
            if bDoPrint:
                s = f77()
                print s.ToString(objFile)

            if bInterface:
                ssheet = f77()
                ssheet['keywordcase']='upper'

                for i in objFile.GetAllProgUnits(Subroutine):