Skip to content

Conversation

@mayanje
Copy link
Contributor

@mayanje mayanje commented Oct 23, 2020

What have been done.

  • A new class GroupToken to represent for instance the token :: as a group of two tokens ':'
  • At REPLACE directive creating time, the GoupToken is replaced by its sub-tokens
  • The ImportedTokensDocument class that is used as token iterator for handling the REPLACE, now create a preprocessed text fragment which is then scanned again to get the new set of tokens to be iterated.
  • The error message of an empty pseudo text of comparison, which was generated by the Scanner is now generated by the CompilerDirectiveBuilder class.

@trafico-bot trafico-bot bot added the 🔍 Ready for Review Pull Request is not reviewed yet label Oct 23, 2020
@@ -0,0 +1 @@
 No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty file ? Is the file actually required since no generation occurs because of previous errors ?

ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 xxxENT. COPY YxxxENT REPLACING ==::== BY ====.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe modify one of the test to have a non-empty replacement text.

@@ -0,0 +1,10 @@
IDENTIFICATION DIVISION.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the test method for this sample.

Comment on lines +60 to +63
internal bool IsForCopy
{
get;
set;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CompilationUnit is for programs so this property can be made readonly and set at construction time (default true, false when called from CompilationUnit constructor)

}
return list;
}
private bool BuildReplaceOperation(IList<ReplaceOperation> replaceOperations, ref Token comparisonToken, ref Token[] followingComparisonTokens, ref Token replacementToken, ref Token[] replacementTokens, bool replaceTokens, List<Token> operandTokens)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ANTLR-related duplicate method in TypeCobol.Compiler.Preprocessor.CompilerDirectiveBuilder has not been updated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove the Antlr Preprocessor.
I've created #1788 about that.

Comment on lines +96 to +97
TypeCobolOptions tcOptions = new TypeCobolOptions();
tcOptions.AreForCopyParsing = true;//Doing that any "::" will be treated as two tokens
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tcOptions is not used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it must be replaced by the new TypeCobolOptions()

Comment on lines +98 to +100
FileCompiler fileCompiler = new FileCompiler(initialTextDocumentLines, null, null, new TypeCobolOptions(), null, false, null);
fileCompiler.CompilationResultsForProgram.InitialScanStateForCopy = state;
fileCompiler.CompilationResultsForProgram.UpdateTokensLines();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need a whole FileCompiler ? Using Scanner only would be cleaner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a question that I asked to myself, the answer is that it is FileCompiler that connect all things welll.

/// <param name="compilerOptions"></param>
/// <param name="allowWhitespaceTokens">This parameters is used to force whitspaces tokens to be also returned.</param>
/// <returns></returns>
public static ITokensLinesIterator GetProcessedTokensIterator(TextSourceInfo textSourceInfo, ISearchableReadOnlyList<IProcessedTokensLine> lines, TypeCobolOptions compilerOptions, bool allowWhitespaceTokens)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new allowWhitespaceTokens parameter is always false except for one usage, we could use a default value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do that in order to not miss same places where it is called, but at the end, I think yes.

/// <summary>
/// A class that represents a Group Of Tokens.
/// </summary>
public class GroupToken : Token
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TokenGroup class already exists. Can we use it instead (with adaptations if need be) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep... yes you are right I must test it.

Comment on lines +1151 to +1154
//if (!(followingChar == ' ' || followingChar == ',' || followingChar == ';' || followingChar == '.'))
//{
// tokensLine.AddDiagnostic(MessageCode.InvalidCharAfterPseudoTextDelimiter, delimiterToken);
//}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented code may be confusing for future readers, better remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this code is commented because, I still needed to know how to emit this diagnostics in a right context.

@trafico-bot trafico-bot bot added ⚠️ Changes requested Pull Request needs changes before it can be reviewed again and removed 🔍 Ready for Review Pull Request is not reviewed yet labels Oct 23, 2020
// consume two :: chars in token1 and token2
var token1 = ScanOneChar(startIndex, TokenType.ColonSeparator);
var token2 = ScanOneChar(startIndex + 1, TokenType.ColonSeparator);
GroupToken group = new GroupToken(TokenType.QualifiedNameSeparator, startIndex, startIndex + 1, tokensLine);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use a GroupToken for token :: now ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Group of Tokens is needed here in order to still returning one token when GetNextToken() is called, The REPLACE parsing will flat the group into it's groups tokens, and I just wanted to still returning TokenType.QualifiedNameSeparator.
But In fact maybe Group of Token can be avoid if we consider the flag this.compilerOptions.AreForCopyParsing for a Pure Cobol Treatment not TypeCobol.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the TypeCobol operator :: is a single token.
Characters : inside a pseudo Text (like ==:xxxx:==) are single token :.

In my opinion, this issue should treat characters :: inside a COPY or inside a pseudo text, as 2 separated tokens : and :.
See my proposal in another comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After more investigation, characters :: that need to be replaced, must be generated as a partial Cobol Word Token.
E.g. :
move W-Var1:: to W-Var2
W-Var1:: must be single a single Token of type Partial Cobol Word Token. Otherwise the replacing won't occurs.

@rooksdo rooksdo linked an issue Oct 26, 2020 that may be closed by this pull request
WORKING-STORAGE SECTION.
01 xxxENT. COPY YxxxENT REPLACING ==== BY ====.
PROCEDURE DIVISION.
MOVE 'A' TO xxxENT-FCT01-Var1.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact the test also need to check that variable name inside the copy are correctly replaced;
Can you add this :
01 xxxENT2. COPY YxxxENT REPLACING ==::== BY ====.
01 xxxENT3. COPY YxxxENT REPLACING ==::== BY ==S==.

And this move:
MOVE 'A' TO xxxENTS-FCT01-Var1.

And also create the copy YxxxENT with same content as Codegen/test/resources/input/TypeCobol/CopyReplace4Colon/YxxxENT.cpy

Copy link
Contributor Author

@mayanje mayanje Oct 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I need also further tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add a test with a mix of Empty and non-empty replacing, like:
Copy YDVZOSM:

       01  :MDVZOSM:-A::.
           05 :MDVZOSM:-A::-Var0 pic X.

And the source:

       IDENTIFICATION division.
       PROGRAM-ID. DVZS0OSM.
       data division.
       working-storage section.
       COPY YDVZOSM replacing ==::== by ====
                                         ==:MDVZOSM:== by ==MDVZOSM==.
       COPY YDVZOSM replacing ==::== by ==2==
                                         ==:MDVZOSM:== by ==Foo==.
       procedure division.
           move 'A' to MDVZOSM-A
           move 'A' to Foo-A2
           .
       end program DVZS0OSM.

@fm-117
Copy link
Contributor

fm-117 commented Oct 26, 2020

Although original issue focuses on COPY - REPLACING, could you add a test with a REPLACE ? I think REPLACING and REPLACE should have the same behavior.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. DVZZMFT0.
       data division.
       working-storage section.
       REPLACE ==::== BY ==name1==.
       01 var-:: PIC X.
       REPLACE ==::== BY ====.
       01 var2:: PIC X.
       procedure division.
           display var-name1
           display var2
           goback
           .
       end program DVZZMFT0.

// consume two :: chars in token1 and token2
var token1 = ScanOneChar(startIndex, TokenType.ColonSeparator);
var token2 = ScanOneChar(startIndex + 1, TokenType.ColonSeparator);
GroupToken group = new GroupToken(TokenType.QualifiedNameSeparator, startIndex, startIndex + 1, tokensLine);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the TypeCobol operator :: is a single token.
Characters : inside a pseudo Text (like ==:xxxx:==) are single token :.

In my opinion, this issue should treat characters :: inside a COPY or inside a pseudo text, as 2 separated tokens : and :.
See my proposal in another comment.

Comment on lines -962 to 963
// QualifiedNameSeparator => qualifierName::qualifiedName
if (currentIndex < lastIndex && line[currentIndex + 1] == ':')
if (currentIndex < lastIndex && line[currentIndex + 1] == ':' && (this.compilerOptions == null || !this.compilerOptions.AreForCopyParsing))
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you try the following solution:
Modify this condition:

if (!currentState.InsidePseudoText //No QualifiedNameSeparator allowed in pseudoText
                        && (we are not in a COPY) //No QualifiedNameSeparator allowed in COPY 
                        && currentIndex< lastIndex && line[currentIndex + 1] == ':')
                    {

Delete line 2307 in original Scanner.cs, because now we allow empty pseudoText ==::==

            // no legal cobol word chars found 
            if (index == startIndex + 1 && !CobolChar.IsCobolWordChar(line[index])) return false;

Keep your fix in TypeCobol/Compiler/Scanner/Token.cs
Still return a bool from method BuildReplaceOperation in TypeCobol/Compiler/CupPreprocessor/CompilerDirectiveBuilder.cs to report Diagnostic : "REPLACE Empty Comparison Pseudo Text." and "REPLACE Empty Pseudo Text Delimiter"

Otherwise all of the rest of the C# code can be deleted.

I didn't test Codegen, but it worked on Parser part.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, I forgot to launch all tests.
In my previous comment, the original line 2307 in original Scanner.cs must be changed as:

if (index == startIndex + 1 && !CobolChar.IsCobolWordChar(line[index]))
            {
                //Empty partialCobolWord are only allowed inside pseudo text and copy
                if (!(currentState.InsidePseudoText || is inside a COPY))
                {
                    return false;
                }
            }

And the MultilineScanState currentState must now be a parameter of method CheckForPartialCobolWordPattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it works like that!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to create a new PR and give up this one. I didn't know Partial Cobol Word pattern and how it works :-|

Comment on lines -962 to 963
// QualifiedNameSeparator => qualifierName::qualifiedName
if (currentIndex < lastIndex && line[currentIndex + 1] == ':')
if (currentIndex < lastIndex && line[currentIndex + 1] == ':' && (this.compilerOptions == null || !this.compilerOptions.AreForCopyParsing))
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, I forgot to launch all tests.
In my previous comment, the original line 2307 in original Scanner.cs must be changed as:

if (index == startIndex + 1 && !CobolChar.IsCobolWordChar(line[index]))
            {
                //Empty partialCobolWord are only allowed inside pseudo text and copy
                if (!(currentState.InsidePseudoText || is inside a COPY))
                {
                    return false;
                }
            }

And the MultilineScanState currentState must now be a parameter of method CheckForPartialCobolWordPattern.

@trafico-bot trafico-bot bot added 🔍 Ready for Review Pull Request is not reviewed yet and removed ⚠️ Changes requested Pull Request needs changes before it can be reviewed again labels Oct 27, 2020
WORKING-STORAGE SECTION.
01 xxxENT. COPY YxxxENT REPLACING ==== BY ====.
PROCEDURE DIVISION.
MOVE 'A' TO xxxENT-FCT01-Var1.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add a test with a mix of Empty and non-empty replacing, like:
Copy YDVZOSM:

       01  :MDVZOSM:-A::.
           05 :MDVZOSM:-A::-Var0 pic X.

And the source:

       IDENTIFICATION division.
       PROGRAM-ID. DVZS0OSM.
       data division.
       working-storage section.
       COPY YDVZOSM replacing ==::== by ====
                                         ==:MDVZOSM:== by ==MDVZOSM==.
       COPY YDVZOSM replacing ==::== by ==2==
                                         ==:MDVZOSM:== by ==Foo==.
       procedure division.
           move 'A' to MDVZOSM-A
           move 'A' to Foo-A2
           .
       end program DVZS0OSM.

@trafico-bot trafico-bot bot added ⚠️ Changes requested Pull Request needs changes before it can be reviewed again and removed 🔍 Ready for Review Pull Request is not reviewed yet labels Oct 27, 2020
@mayanje
Copy link
Contributor Author

mayanje commented Oct 28, 2020

@smedilol So The last requested test fails with smedilol method but succeed with the method of this PR, I am looking why.
The one with Copy YDVZOSM.

@mayanje
Copy link
Contributor Author

mayanje commented Oct 29, 2020

As a new solution has been suggested by @smedilol a new pull request has been created:
#1794

@rooksdo rooksdo added this to the CobolEditor milestone Nov 5, 2020
/// Set the initial position of the iterator with startToken.
/// </summary>
public CopyTokensLinesIterator(string sourceFileName, IReadOnlyList<IProcessedTokensLine> tokensLines, int channelFilter, bool allowWhitespaceTokens)
public CopyTokensLinesIterator(string sourceFileName, IReadOnlyList<IProcessedTokensLine> tokensLines, int channelFilter, Func<Token, bool> tokenFilterCallback)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both channelFilter and tokenFilterCallback are used to select/discard tokens during iteration so they should be merged together, adding a default value (filtering based on channel like before the change).

@mayanje
Copy link
Contributor Author

mayanje commented Nov 17, 2020

Replaced by PR #1794

@mayanje mayanje closed this Nov 17, 2020
@mayanje
Copy link
Contributor Author

mayanje commented Nov 17, 2020

Handle by PR #1794

@mayanje mayanje deleted the 1752_Handle_copy_replacing_with_4colon branch November 17, 2020 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚠️ Changes requested Pull Request needs changes before it can be reviewed again

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle copy replacing with ==::==

5 participants