Example #1
0
        // --- Cobol text line scanner
        private void MapVariableLengthLineWithReferenceFormat()
        {
            string line = textLine.Text;
            int lastIndexOfLine = line.Length - 1;

            // Test for free format compiler directives embedded in a reference format file
            int compilerDirectiveIndex = FindFirstCharOfCompilerDirectiveBeforeColumn8(line);
            if (compilerDirectiveIndex >= 0)
            {
                // Free text format line embedded in reference format file
                SequenceNumber = new TextArea(TextAreaType.SequenceNumber, 0, compilerDirectiveIndex - 1);
                Indicator = new TextArea(TextAreaType.Indicator, compilerDirectiveIndex, compilerDirectiveIndex - 1);
                Source = new TextArea(TextAreaType.Source, compilerDirectiveIndex, lastIndexOfLine > 71 ? 71 : lastIndexOfLine);
                Comment = new TextArea(TextAreaType.Comment, lastIndexOfLine > 71 ? 72 : lastIndexOfLine + 1, lastIndexOfLine);
            }
            else
            {
                // Cobol reference format
                if (lastIndexOfLine >= 7)
                {
                    SequenceNumber = new TextArea(TextAreaType.SequenceNumber, 0, 5);
                    Indicator = new TextArea(TextAreaType.Indicator, 6, 6);
                    Source = new TextArea(TextAreaType.Source, 7, lastIndexOfLine > 71 ? 71 : lastIndexOfLine);
                    Comment = new TextArea(TextAreaType.Comment, lastIndexOfLine > 71 ? 72 : lastIndexOfLine + 1, lastIndexOfLine);
                }
                else if (lastIndexOfLine == 6)
                {
                    SequenceNumber = new TextArea(TextAreaType.SequenceNumber, 0, 5);
                    Indicator = new TextArea(TextAreaType.Indicator, 6, 6);
                    Source = new TextArea(TextAreaType.Source, 7, 6);
                    Comment = new TextArea(TextAreaType.Comment, 7, 6);
                }
                else
                {
                    SequenceNumber = new TextArea(TextAreaType.SequenceNumber, 0, lastIndexOfLine);
                    Indicator = new TextArea(TextAreaType.Indicator, lastIndexOfLine + 1, lastIndexOfLine);
                    Source = new TextArea(TextAreaType.Source, lastIndexOfLine + 1, lastIndexOfLine);
                    Comment = new TextArea(TextAreaType.Comment, lastIndexOfLine + 1, lastIndexOfLine);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Scan a group of continuation lines
        /// </summary>
        public static void ScanTokensLineContinuationGroup(IList<TokensLine> continuationLinesGroup, MultilineScanState initialScanState, TypeCobolOptions compilerOptions)
        {
            // p54: Continuation lines
            // Any sentence, entry, clause, or phrase that requires more than one line can be
            // continued in Area B of the next line that is neither a comment line nor a blank line.
            // The line being continued is a continued line; the succeeding lines are continuation
            // lines.

            // Track the length of text contributed to the continuation text by each individual line
            TextArea[] textAreasForOriginalLinesInConcatenatedLine = new TextArea[continuationLinesGroup.Count];
            int[] startIndexForTextAreasInOriginalLines = new int[continuationLinesGroup.Count];
            int[] offsetForLiteralContinuationInOriginalLines = new int[continuationLinesGroup.Count];

            // Initialize the continuation text with the complete source text of the first line
            TokensLine firstLine = continuationLinesGroup[0];
            string concatenatedLine = null;
            if (firstLine.Type == CobolTextLineType.Source || (firstLine.Type == CobolTextLineType.Debug && initialScanState.WithDebuggingMode))
            {
                concatenatedLine = firstLine.SourceText;
            }
            else
            {
                concatenatedLine = String.Empty;
                Scanner.ScanTokensLine(firstLine, initialScanState, compilerOptions);
            }
            textAreasForOriginalLinesInConcatenatedLine[0] = new TextArea(TextAreaType.Source, 0, concatenatedLine.Length -1);
            startIndexForTextAreasInOriginalLines[0] = firstLine.Source.StartIndex;
            offsetForLiteralContinuationInOriginalLines[0] = 0;

            // All the following lines are continuation lines
            // => build a character string representing the complete continuation text along the way
            for (int i = 1; i < continuationLinesGroup.Count; i++)
            {
                TokensLine continuationLine = continuationLinesGroup[i];
                int startIndex = continuationLine.Source.StartIndex;
                int lastIndex = continuationLine.Source.EndIndex;
                string line = continuationLine.Text;

                // 1. Match and remove all blank characters at the beginning of the continuation line
                int startOfContinuationIndex = startIndex;
                for (; startOfContinuationIndex <= lastIndex && line[startOfContinuationIndex] == ' '; startOfContinuationIndex++) { }
                if (startOfContinuationIndex > startIndex)
                {
                    Token whitespaceToken = new Token(TokenType.SpaceSeparator, startIndex, startOfContinuationIndex - 1, continuationLine);
                    continuationLine.SourceTokens.Add(whitespaceToken);
                    startIndex = startOfContinuationIndex;
                }
                if (startOfContinuationIndex <= lastIndex)
                {
                    if (startOfContinuationIndex < 4)
                    {
                        continuationLine.AddDiagnostic(MessageCode.AreaAOfContinuationLineMustBeBlank, startOfContinuationIndex, startOfContinuationIndex);
                    }
                }
                else
                {
                    // Nothing but spaces on the continuation line
                    continue;
                }

                // p55: Continuation of alphanumeric and national literals
                // Alphanumeric and national literals can be continued only when there are no DBCS
                // characters in the content of the literal.
                // The following rules apply to alphanumeric and national literals that do not contain
                // DBCS characters:
                // - If the continued line contains an alphanumeric or national literal without a
                //   closing quotation mark, all spaces at the end of the continued line (through
                //   column 72) are considered to be part of the literal. The continuation line must
                //   contain a hyphen in the indicator area, and the first nonblank character must be
                //   a quotation mark. The continuation of the literal begins with the character
                //   immediately following the quotation mark.
                // - If an alphanumeric or national literal that is to be continued on the next line has
                //   as its last character a quotation mark in column 72, the continuation line must
                //   start with two consecutive quotation marks. This will result in a single quotation
                //   mark as part of the value of the literal.
                // - If the last character on the continued line of an alphanumeric or national literal
                //   is a single quotation mark in Area B, the continuation line can start with a single
                //   quotation mark. This will result in two consecutive literals instead of one
                //   continued literal.
                // The rules are the same when an apostrophe is used instead of a quotation mark in
                // delimiters.
                // ... p55 -> p56: examples of continuations and expected behavior ...

                int offsetForLiteralContinuation = 0;
                if (concatenatedLine.Length > 0)
                {
                    // Scan the continuation text, and get its last token so far
                    TokensLine temporaryTokensLine = TokensLine.CreateVirtualLineForInsertedToken(firstLine.InitialLineIndex, concatenatedLine);
                    Scanner.ScanTokensLine(temporaryTokensLine, initialScanState, compilerOptions);
                    Token lastTokenOfConcatenatedLineSoFar = temporaryTokensLine.SourceTokens[temporaryTokensLine.SourceTokens.Count - 1];

                    // Check if the last token so far is an alphanumeric or national literal
                    if (lastTokenOfConcatenatedLineSoFar.TokenFamily == TokenFamily.AlphanumericLiteral)
                    {
                        // The continuation line must contain a hyphen in the indicator area, and the first nonblank character must be a quotation mark
                        if (line[startOfContinuationIndex] != lastTokenOfConcatenatedLineSoFar.ExpectedClosingDelimiter)
                        {
                            continuationLine.AddDiagnostic(MessageCode.InvalidFirstCharForContinuationLine, startOfContinuationIndex, startOfContinuationIndex, lastTokenOfConcatenatedLineSoFar.ExpectedClosingDelimiter);
                        }
                        // The continuation of the literal begins with the character immediately following the quotation mark.
                        else
                        {
                            offsetForLiteralContinuation = 1;

                            // If an alphanumeric literal that is to be continued on the next line has as its last character a quotation mark in column 72,
                            // the continuation line must start with two consecutive quotation marks.
                            if (lastTokenOfConcatenatedLineSoFar.HasClosingDelimiter)
                            {
                                if ((startOfContinuationIndex + 1) > lastIndex || line[startOfContinuationIndex + 1] != lastTokenOfConcatenatedLineSoFar.ExpectedClosingDelimiter)
                                {
                                    continuationLine.AddDiagnostic(MessageCode.InvalidFirstTwoCharsForContinuationLine, startOfContinuationIndex, startOfContinuationIndex + 1, lastTokenOfConcatenatedLineSoFar.ExpectedClosingDelimiter);
                                    // Use the first quotation mark to avoid a complete mess while scanning the rest of the line
                                    offsetForLiteralContinuation = 0;
                                }
                            }
                        }
                    }
                    // Check if the last token so far is a floating comment
                    else if (lastTokenOfConcatenatedLineSoFar.TokenType == TokenType.FloatingComment)
                    {
                        // => remove the floating comment from the text of the continuation
                        concatenatedLine = concatenatedLine.Substring(0, concatenatedLine.Length - lastTokenOfConcatenatedLineSoFar.Length);
                        textAreasForOriginalLinesInConcatenatedLine[i - 1] = new TextArea(TextAreaType.Source, textAreasForOriginalLinesInConcatenatedLine[i - 1].StartIndex, textAreasForOriginalLinesInConcatenatedLine[i - 1].EndIndex - lastTokenOfConcatenatedLineSoFar.Length);
                        TokensLine lineWithFloatingComment = continuationLinesGroup[i - 1];
                        Token floatingCommentToken = new Token(TokenType.FloatingComment, lineWithFloatingComment.Length - lastTokenOfConcatenatedLineSoFar.Length, lineWithFloatingComment.Length - 1, lineWithFloatingComment);
                        lineWithFloatingComment.SourceTokens.Add(floatingCommentToken);
                    }
                    // Check if the last token so far is a comment entry
                    else if (lastTokenOfConcatenatedLineSoFar.TokenType == TokenType.CommentEntry)
                    {
                        // p105: A hyphen in the indicator area (column 7) is not permitted in comment - entries.
                        // => impossible to ignore the continuation indicator here, it is too late
                        //    (we can not know there is a comment entry before scanning the continuation lines groups)
                        // => register an error message
                        continuationLine.AddDiagnostic(MessageCode.HyphenIndicatorNotPermittedInCommenEntries, continuationLine.Indicator.StartIndex + 1, continuationLine.Indicator.EndIndex + 1);
                    }
                }

                // p54: If there is no hyphen (-) in the indicator area (column 7) of a line, the last character
                // of the preceding line is assumed to be followed by a space.
                // If there is a hyphen in the indicator area of a line, the first nonblank character of
                // the continuation line immediately follows the last nonblank character of the
                // continued line without an intervening space.

                // Concatenate the continuation text so far with the text of the current continuation line
                int startIndexOfContinuationStringInContinuationLine = startOfContinuationIndex + offsetForLiteralContinuation;
                int lengthOfContinuationStringInContinuationLine = lastIndex - startIndexOfContinuationStringInContinuationLine + 1;

                textAreasForOriginalLinesInConcatenatedLine[i] = new TextArea(TextAreaType.Source, concatenatedLine.Length, concatenatedLine.Length + lengthOfContinuationStringInContinuationLine - 1);
                startIndexForTextAreasInOriginalLines[i] = startIndexOfContinuationStringInContinuationLine;
                offsetForLiteralContinuationInOriginalLines[i] = offsetForLiteralContinuation;

                concatenatedLine += line.Substring(startIndexOfContinuationStringInContinuationLine, lengthOfContinuationStringInContinuationLine);
            }

            // Scan the complete continuation text as a whole
            TokensLine virtualContinuationTokensLine = TokensLine.CreateVirtualLineForInsertedToken(firstLine.InitialLineIndex, concatenatedLine);
            Scanner.ScanTokensLine(virtualContinuationTokensLine, initialScanState, compilerOptions);

            // Then attribute each token and diagnostic to its corresponding tokens line
            MultilineScanState scanState = initialScanState;
            for (int i = 0; i < continuationLinesGroup.Count; i++)
            {
                TokensLine originalLine = continuationLinesGroup[i];
                originalLine.InitializeScanState(scanState);

                TextArea textAreaForOriginalLine = textAreasForOriginalLinesInConcatenatedLine[i];
                int concatenatedLineToOriginalLineOffset = startIndexForTextAreasInOriginalLines[i] - textAreaForOriginalLine.StartIndex;

                foreach (Token token in virtualContinuationTokensLine.SourceTokens)
                {
                    // Token located after the current line
                    if(token.StartIndex > textAreaForOriginalLine.EndIndex)
                    {
                        break;
                    }
                    // Token located before the current line
                    else if(token.StopIndex < textAreaForOriginalLine.StartIndex)
                    {
                        continue;
                    }
                    // Token completely completely included inside the current line
                    else if(token.StartIndex >= textAreaForOriginalLine.StartIndex && token.StopIndex <= textAreaForOriginalLine.EndIndex)
                    {
                        int startIndexInOriginalLine = token.StartIndex + concatenatedLineToOriginalLineOffset;
                        int stopIndexInOriginalLine = token.StopIndex + concatenatedLineToOriginalLineOffset;

                        token.CorrectTokensLine(originalLine, startIndexInOriginalLine, stopIndexInOriginalLine);
                        originalLine.AddToken(token);

                        foreach(Diagnostic diag in virtualContinuationTokensLine.GetDiagnosticsForToken(token))
                        {
                            originalLine.AddDiagnostic((MessageCode)diag.Info.Code, token, diag.MessageArgs);
                        }
                    }
                    // Multiline continuation token only partially located on this line
                    else
                    {
                        bool isContinuationFromPreviousLine = token.StartIndex < textAreaForOriginalLine.StartIndex;
                        bool isContinuedOnNextLine = token.StopIndex > textAreaForOriginalLine.EndIndex;

                        int startIndexInOriginalLine = 0;
                        if (isContinuationFromPreviousLine)
                        {
                            startIndexInOriginalLine = startIndexForTextAreasInOriginalLines[i] - offsetForLiteralContinuationInOriginalLines[i];
                        }
                        else
                        {
                            startIndexInOriginalLine = token.StartIndex + concatenatedLineToOriginalLineOffset;
                        }
                        int stopIndexInOriginalLine = 0;
                        if (isContinuedOnNextLine)
                        {
                            stopIndexInOriginalLine = originalLine.Source.EndIndex;
                            // If a continued line ends with a floating comment, the continued token ends just before the floating comment
                            if (originalLine.SourceTokens.Count > 0 && originalLine.SourceTokens[originalLine.SourceTokens.Count - 1].TokenType == TokenType.FloatingComment)
                            {
                                stopIndexInOriginalLine -= originalLine.SourceTokens[originalLine.SourceTokens.Count - 1].Length;
                            }
                        }
                        else
                        {
                            stopIndexInOriginalLine = token.StopIndex + concatenatedLineToOriginalLineOffset;
                        }

                        ContinuationToken continuationToken = new ContinuationToken(token, startIndexInOriginalLine, stopIndexInOriginalLine,
                            originalLine, isContinuationFromPreviousLine, isContinuedOnNextLine);
                        originalLine.AddToken(continuationToken);

                        // Copy diagnostics on the first line only
                        if(!isContinuationFromPreviousLine)
                        {
                            foreach (Diagnostic diag in virtualContinuationTokensLine.GetDiagnosticsForToken(token))
                            {
                                originalLine.AddDiagnostic((MessageCode)diag.Info.Code, token, diag.MessageArgs);
                            }
                        }
                    }
                }

                scanState = originalLine.ScanState;
            }
        }
Example #3
0
        private void MapVariableLengthLineWithFreeFormat()
        {
            string line = textLine.Text;
            int lastIndexOfLine = line.Length - 1;

            // No SequenceNumber area in free format text
            SequenceNumber = new TextArea(TextAreaType.SequenceNumber, 0, -1);

            // In free format source text :
            // - a line starting with char * is a comment line or a compiler directive
            if (lastIndexOfLine >= 0 && line[0] == '*')
            {
                // Check for compiler directives
                if ((line.Length >= 5 && line.StartsWith("*CBL ")) ||
                    (line.Length >= 9 && line.StartsWith("*CONTROL ")))
                {
                    Indicator = new TextArea(TextAreaType.Indicator, 0, -1);
                    Source = new TextArea(TextAreaType.Source, 0, lastIndexOfLine);
                }
                else
                {
                    Indicator = new TextArea(TextAreaType.Indicator, 0, 0);
                    Source = new TextArea(TextAreaType.Source, 1, lastIndexOfLine);
                }
            }
            // - a line starting with char / is a comment line
            // - a line starting with char - is a continuation line
            // => a free format program line cannot start with one of these three chars, insert a space before if needed
            else if (lastIndexOfLine >= 0 && (line[0] == '/' || line[0] == '-'))
            {
                Indicator = new TextArea(TextAreaType.Indicator, 0, 0);
                Source = new TextArea(TextAreaType.Source, 1, lastIndexOfLine);
            }
            // - a line starting with d or D + space char is a debug ligne
            else if (lastIndexOfLine >= 1 && ((line[0] == 'd' || line[0] == 'D') & line[1] == ' '))
            {
                Indicator = new TextArea(TextAreaType.Indicator, 0, 1);
                Source = new TextArea(TextAreaType.Source, 2, lastIndexOfLine);
            }
            else // no indicator
            {
                Indicator = new TextArea(TextAreaType.Indicator, 0, -1);
                Source = new TextArea(TextAreaType.Source, 0, lastIndexOfLine);
            }

            // No Comment area in free format text
            Comment = new TextArea(TextAreaType.Comment, lastIndexOfLine + 1, lastIndexOfLine);
        }
Example #4
0
 private void ApplyTextAreaStyle(int lineStartOffset, TextArea textArea, HighlightingColor areaStyle)
 {
     base.ChangeLinePart(lineStartOffset + textArea.StartIndex, // startOffset
                         lineStartOffset + textArea.EndIndex + 1, // endOffset
                         visualLineElement => ApplyColorToElement(visualLineElement, areaStyle));
 }