Example #1
0
 /// <summary>
 /// Check if the given items are in the source node qualified storage areas.
 /// </summary>
 /// <param name="items">The items to check</param>
 /// <param name="sourceNode">The source node</param>
 /// <param name="qualified_name">The qualified name that corresponds the the items.</param>
 /// <returns>true if the items are in the source node storage areas, false otherwise</returns>
 internal bool AreItemsInNodeQualifiedStorageAreas(IList <SymbolReference> items, Node sourceNode, out string qualified_name)
 {
     qualified_name = null;
     if (sourceNode.QualifiedStorageAreas == null)
     {
         return(false);
     }
     foreach (TypeCobol.Compiler.CodeElements.StorageArea storage_area in sourceNode.QualifiedStorageAreas.Keys)
     {
         if (storage_area.SymbolReference != null && storage_area.SymbolReference.IsTypeCobolQualifiedReference)
         {
             TypeCobolQualifiedSymbolReference tc_sr      = storage_area.SymbolReference as TypeCobolQualifiedSymbolReference;
             IList <SymbolReference>           tcsr_items = tc_sr?.AsList();
             int nCountInner = 0;
             foreach (SymbolReference item in items)
             {
                 if (tcsr_items != null && tcsr_items.IndexOf(item) >= 0)
                 {
                     nCountInner++;
                 }
                 else
                 {
                     break;
                 }
             }
             if (nCountInner == items.Count)
             {
                 qualified_name = sourceNode.QualifiedStorageAreas[storage_area];
                 return(true);
             }
         }
     }
     return(false);
 }
Example #2
0
            /// <summary>
            /// Checks and handles any procedure call resolution.
            /// </summary>
            /// <param name="items">The items to check if they correspond to the procedure qualified name</param>
            /// <returns>true if it was a Procedure style call, false otherwise.</returns>
            private bool IsProcedureStyleCallItems(IList <SymbolReference> items, out string hashFunction)
            {
                hashFunction = null;

                TypeCobol.Compiler.Nodes.ProcedureStyleCall procStyleCall = CurrentNode as TypeCobol.Compiler.Nodes.ProcedureStyleCall;
                if (procStyleCall != null)
                {
                    ProcedureStyleCallStatement procStyleCallStmt = procStyleCall.CodeElement as ProcedureStyleCallStatement;
                    if (procStyleCallStmt != null)
                    {
                        TypeCobolQualifiedSymbolReference tcqsr = procStyleCallStmt.ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction as
                                                                  TypeCobolQualifiedSymbolReference ?? procStyleCallStmt.ProcdurePointerOrTCProcedureFunction as TypeCobolQualifiedSymbolReference;

                        if (tcqsr != null)
                        {
                            IList <SymbolReference> names_items = tcqsr.AsList();
                            if (names_items.Count != items.Count)
                            {
                                return(false);
                            }
                            if (EqualItems(items, names_items))
                            {//This is a reference to a Function Call.
                                hashFunction = procStyleCall.FunctionDeclaration.Hash;
                                if (ProcCallerStack != null && ProcCallerStack.Count > 0)
                                {   //Memorize the (hash,ProcedureStyleCall) In the Program procedure style call dictionary.
                                    var program = ProcCallerStack.Peek();
                                    if (!program.ProcStyleCalls.ContainsKey(hashFunction))
                                    {
                                        program.ProcStyleCalls[hashFunction] = new Tuple <IList <SymbolReference>, TypeCobol.Compiler.Nodes.ProcedureStyleCall>(items, procStyleCall);
                                    }
                                }
                                return(true);
                            }
                        }
                    }
                }
                return(false);
            }
        ////////////////////
        // PROCEDURE CALL //
        ////////////////////

        public override void EnterTcCallStatement(CodeElementsParser.TcCallStatementContext context)
        {
            var cbCallProc = context.procedurePointerOrFunctionPointerVariableOrfunctionNameReference;

            // Register call parameters (shared storage areas) information at the CodeElement level
            CallSite callSite = null;
            ProcedureStyleCallStatement statement = null;

            Context = context;

            //Incomplete CallStatement, create an empty CodeElement and return + Error due to issue #774
            if (cbCallProc == null)
            {
                CodeElement = new ProcedureStyleCallStatement
                {
                    Diagnostics = new List <Diagnostic>
                    {
                        new Diagnostic(MessageCode.SyntaxErrorInParser, context.Start.Column,
                                       context.Stop.Column, context.Start.Line, "Empty CALL is not authorized")
                    }
                };
                return;
            }


            //Here ambiguousSymbolReference with either CandidatesType:
            // - ProgramNameOrProgramEntry
            // - data, condition, UPSISwitch, TCFunctionName
            var ambiguousSymbolReference = CobolExpressionsBuilder.CreateProcedurePointerOrFunctionPointerVariableOrTCFunctionProcedure(cbCallProc);


            //If (inputs, inouts ou outputs).Count > 0, then it's a procedure call
            if (context.callOutputParameter().Length > 0 || context.callInputParameter().Length > 0 || context.callInoutParameter().Length > 0)
            {
                callSite = new CallSite();
                #region Setup Input Output Inout CallSitesParameters

                var inputs  = new List <CallSiteParameter>();
                var inouts  = new List <CallSiteParameter>();
                var outputs = new List <CallSiteParameter>();

                SyntaxProperty <ParameterSharingMode> mode = null;
                foreach (var p in context.callInputParameter())
                {
                    CreateSharingMode(p, ref mode); // TCRFUN_INPUT_BY
                    var callSiteParameter = new CallSiteParameter
                    {
                        SharingMode = mode,
                    };


                    if (p.sharedVariableOrFileName() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = CobolExpressionsBuilder.CreateSharedVariableOrFileName(p.sharedVariableOrFileName());
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedVariableOrFileName() != null || p.OMITTED() != null)
                    {
                        inputs.Add(callSiteParameter);
                    }
                }

                foreach (var p in context.callInoutParameter())
                {
                    var callSiteParameter = new CallSiteParameter
                    {
                        // TCRFUN_CALL_INOUT_AND_OUTPUT_BY_REFERENCE
                        SharingMode =
                            new SyntaxProperty <ParameterSharingMode>(ParameterSharingMode.ByReference, null),
                    };

                    if (p.sharedStorageArea1() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = new Variable(CobolExpressionsBuilder.CreateSharedStorageArea(p.sharedStorageArea1()));
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedStorageArea1() != null || p.OMITTED() != null)
                    {
                        inouts.Add(callSiteParameter);
                    }
                }

                foreach (var p in context.callOutputParameter())
                {
                    var callSiteParameter = new CallSiteParameter
                    {
                        // TCRFUN_CALL_INOUT_AND_OUTPUT_BY_REFERENCE
                        SharingMode =
                            new SyntaxProperty <ParameterSharingMode>(ParameterSharingMode.ByReference, null),
                    };

                    if (p.sharedStorageArea1() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = new Variable(CobolExpressionsBuilder.CreateSharedStorageArea(p.sharedStorageArea1()));
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedStorageArea1() != null || p.OMITTED() != null)
                    {
                        outputs.Add(callSiteParameter);
                    }
                }

                int parametersCount = inputs.Count + outputs.Count + inouts.Count;
                callSite.Parameters = new CallSiteParameter[parametersCount];
                int i = 0;

                //Add inputs to global callsites parameters
                if (inputs.Count > 0)
                {
                    foreach (var param in inputs)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                //Add outputs to global callsites parameters
                if (outputs.Count > 0)
                {
                    foreach (var param in outputs)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                //Add inouts to global callsites parameters
                if (inouts.Count > 0)
                {
                    foreach (var param in inouts)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                #endregion

                //Check Type or CandidatesTypes to see if a TCFunctionName is possible
                if (ambiguousSymbolReference.MainSymbolReference != null &&
                    ambiguousSymbolReference.MainSymbolReference.IsOrCanBeOfType(SymbolType.TCFunctionName))
                {
                    SymbolReferenceVariable TCFunctionNameRefVariable;

                    if (ambiguousSymbolReference.MainSymbolReference.IsQualifiedReference)
                    {
                        var nonAmbiguousHead =
                            new SymbolReference(
                                (ambiguousSymbolReference.MainSymbolReference as TypeCobolQualifiedSymbolReference)?.Head
                                .NameLiteral, SymbolType.TCFunctionName);
                        var nonAmbiguousTail =
                            new SymbolReference(
                                (ambiguousSymbolReference.MainSymbolReference as TypeCobolQualifiedSymbolReference)?.Tail
                                .NameLiteral, SymbolType.ProgramName);

                        TypeCobolQualifiedSymbolReference newQualifiedSymbolReferece =
                            new TypeCobolQualifiedSymbolReference(nonAmbiguousHead, nonAmbiguousTail);
                        TCFunctionNameRefVariable = new SymbolReferenceVariable(StorageDataType.MethodName,
                                                                                newQualifiedSymbolReferece);
                    }
                    else
                    {
                        //If so, create ProcedureStyleCallStatement with a ProcedureCall and fix SymbolReference so it's not ambiguous
                        var nonAmbiguousSymbolRef =
                            new SymbolReference(ambiguousSymbolReference.MainSymbolReference.NameLiteral,
                                                SymbolType.TCFunctionName);
                        TCFunctionNameRefVariable = new SymbolReferenceVariable(StorageDataType.MethodName,
                                                                                nonAmbiguousSymbolRef);
                    }

                    //CobolExpressionsBuilder store every StorageArea created into storageAreaReads and then after
                    //storageAreaReads is set to the CodeElement
                    //We must remove it as TCFunctionNameRefVariable doesn't contains a StorageArea
                    if (ambiguousSymbolReference.StorageArea != null)
                    {
                        CobolExpressionsBuilder.storageAreaReads.Remove(ambiguousSymbolReference.StorageArea);
                    }

                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(TCFunctionNameRefVariable.MainSymbolReference,
                                                                          inputs, inouts, outputs))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction =
                            TCFunctionNameRefVariable.MainSymbolReference
                    };

                    callSite.CallTarget = TCFunctionNameRefVariable.MainSymbolReference;
                }
                else
                {
                    //else it's an error
                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                          inputs, inouts, outputs))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction = ambiguousSymbolReference.MainSymbolReference,
                        Diagnostics = new List <Diagnostic>
                        {
                            new Diagnostic(MessageCode.ImplementationError, context.Start.Column,
                                           context.Stop.Column, context.Start.Line,
                                           "A call with arguments is not a TCFunctionName")
                        },
                    };

                    callSite.CallTarget = ambiguousSymbolReference.MainSymbolReference;
                }
            }
            else
            {
                if (ambiguousSymbolReference.MainSymbolReference != null &&
                    ambiguousSymbolReference.MainSymbolReference.IsOrCanBeOfType(SymbolType.DataName, SymbolType.TCFunctionName))
                {
                    //TODO think about uniformity of CandidateTypes inside QualifiedReference.
                    //Maybe just define CandidatesTypes for the Head...
                    if (ambiguousSymbolReference.MainSymbolReference.IsQualifiedReference)
                    {
                        var qualifiedSymbolReference = (QualifiedSymbolReference)ambiguousSymbolReference.MainSymbolReference;


                        AmbiguousSymbolReference.ApplyCandidatesTypes(qualifiedSymbolReference, new[] { SymbolType.DataName, SymbolType.ProgramName });
                        //Adjust candidate types only for the first element
                        if (qualifiedSymbolReference.First.IsAmbiguous)
                        {
                            ((AmbiguousSymbolReference)qualifiedSymbolReference.First).CandidateTypes = new[] { SymbolType.DataName, SymbolType.TCFunctionName };
                        }
                    }
                    else
                    {
                        ((AmbiguousSymbolReference)ambiguousSymbolReference.MainSymbolReference).CandidateTypes = new[] { SymbolType.DataName, SymbolType.TCFunctionName };
                    }

                    statement = new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                                  null, null, null))
                    {
                        ProcdurePointerOrTCProcedureFunction = ambiguousSymbolReference.MainSymbolReference
                    };
                    callSite            = new CallSite();
                    callSite.CallTarget = statement.ProcdurePointerOrTCProcedureFunction;
                }
                else     //else, it's an error
                {
                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                          null, null, null))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction =
                            ambiguousSymbolReference.MainSymbolReference,
                    };
                    statement.Diagnostics.Add(new Diagnostic(MessageCode.SyntaxErrorInParser, context.Start.Column,
                                                             context.Stop.Column, context.Start.Line, "Error in detecting Procedure Call type"));
                    callSite            = new CallSite();
                    callSite.CallTarget = statement.ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction;
                }
            }


            if (callSite != null)
            {
                if (statement.CallSites == null)
                {
                    statement.CallSites = new List <CallSite>();
                }
                statement.CallSites.Add(callSite);
            }

            CodeElement = statement;
        }
Example #4
0
            /// <summary>
            /// Generate TypeCobol Qualified Symbol Reference node for a given StorageArea.
            /// </summary>
            /// <param name="storageArea">The Storage Area to generate the node</param>
            /// <param name="codeElement">The underlying code element</param>
            /// <returns>true if some nodes have been generated, false otherwise</returns>
            private bool GenQualifiedStorage(StorageArea storageArea, CodeElement codeElement)
            {
                if (storageArea.SymbolReference != null && !storageArea.SymbolReference.IsTypeCobolQualifiedReference)
                {
                    return(false);
                }
                if (CurrentNode == null)
                {
                    return(false);
                }
                TypeCobolQualifiedSymbolReference tcqsr = storageArea.SymbolReference as TypeCobolQualifiedSymbolReference;
                int start = -1;

                for (int i = 0; i < codeElement.ConsumedTokens.Count; i++)
                {
                    if (codeElement.ConsumedTokens[i] == tcqsr?.Head.NameLiteral.Token)
                    {
                        start = i;
                        break;
                    }
                }
                int end = -1;

                for (int i = 0; i < codeElement.ConsumedTokens.Count; i++)
                {
                    if (codeElement.ConsumedTokens[i] == tcqsr?.Tail.NameLiteral.Token)
                    {
                        end = i;
                        break;
                    }
                }
                List <GenerateToken> items = new List <GenerateToken>();
                List <string>        names = new List <string>();

                for (int i = end; i <= start; i++)
                {
                    if (codeElement.ConsumedTokens[i].TokenType == Compiler.Scanner.TokenType.QualifiedNameSeparator)
                    {
                        GenerateToken qns = new GenerateToken(new TokenCodeElement(codeElement.ConsumedTokens[i]), string.Intern(" OF "),
                                                              null);
                        qns.SetFlag(Node.Flag.HasBeenTypeCobolQualifierVisited, true);
                        CurrentNode.Add(qns);
                    }
                    else
                    {
                        GenerateToken item = new GenerateToken(
                            new TokenCodeElement(codeElement.ConsumedTokens[i]), codeElement.ConsumedTokens[i].Text,
                            null);
                        item.SetFlag(Node.Flag.HasBeenTypeCobolQualifierVisited, true);
                        CurrentNode.Add(item);
                        items.Add(item);
                        names.Add(codeElement.ConsumedTokens[i].Text);
                    }
                }
                names.Reverse();
                for (int i = 0; i < names.Count; i++)
                {
                    items[i].ReplaceCode = names[i];
                }
                return(items.Count > 0);
            }