-
Notifications
You must be signed in to change notification settings - Fork 25
WI #1752 Implements Replace :: by two characters :. #1787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| @@ -0,0 +1 @@ | |||
| No newline at end of file | |||
There was a problem hiding this comment.
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 ====. |
There was a problem hiding this comment.
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. | |||
There was a problem hiding this comment.
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.
| internal bool IsForCopy | ||
| { | ||
| get; | ||
| set; |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
| TypeCobolOptions tcOptions = new TypeCobolOptions(); | ||
| tcOptions.AreForCopyParsing = true;//Doing that any "::" will be treated as two tokens |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tcOptions is not used.
There was a problem hiding this comment.
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()
| FileCompiler fileCompiler = new FileCompiler(initialTextDocumentLines, null, null, new TypeCobolOptions(), null, false, null); | ||
| fileCompiler.CompilationResultsForProgram.InitialScanStateForCopy = state; | ||
| fileCompiler.CompilationResultsForProgram.UpdateTokensLines(); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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) ?
There was a problem hiding this comment.
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.
| //if (!(followingChar == ' ' || followingChar == ',' || followingChar == ';' || followingChar == '.')) | ||
| //{ | ||
| // tokensLine.AddDiagnostic(MessageCode.InvalidCharAfterPseudoTextDelimiter, delimiterToken); | ||
| //} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
| // 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); |
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
| WORKING-STORAGE SECTION. | ||
| 01 xxxENT. COPY YxxxENT REPLACING ==== BY ====. | ||
| PROCEDURE DIVISION. | ||
| MOVE 'A' TO xxxENT-FCT01-Var1. |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.|
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); |
There was a problem hiding this comment.
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.
| // QualifiedNameSeparator => qualifierName::qualifiedName | ||
| if (currentIndex < lastIndex && line[currentIndex + 1] == ':') | ||
| if (currentIndex < lastIndex && line[currentIndex + 1] == ':' && (this.compilerOptions == null || !this.compilerOptions.AreForCopyParsing)) | ||
| { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
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 :-|
| // QualifiedNameSeparator => qualifierName::qualifiedName | ||
| if (currentIndex < lastIndex && line[currentIndex + 1] == ':') | ||
| if (currentIndex < lastIndex && line[currentIndex + 1] == ':' && (this.compilerOptions == null || !this.compilerOptions.AreForCopyParsing)) | ||
| { |
There was a problem hiding this comment.
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.
| WORKING-STORAGE SECTION. | ||
| 01 xxxENT. COPY YxxxENT REPLACING ==== BY ====. | ||
| PROCEDURE DIVISION. | ||
| MOVE 'A' TO xxxENT-FCT01-Var1. |
There was a problem hiding this comment.
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.|
@smedilol So The last requested test fails with smedilol method but succeed with the method of this PR, I am looking why. |
| /// 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) |
There was a problem hiding this comment.
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).
|
Replaced by PR #1794 |
|
Handle by PR #1794 |
What have been done.