private ReplaceStatus TryAndReplace(Token nextToken, ReplaceOperation replaceOperation) { ReplaceStatus status = new ReplaceStatus(); IList<Token> originalMatchingTokens; #if EUROINFO_LEGACY_REPLACING_SYNTAX // Support for legacy replacing syntax semantics : // Insert SuffixChar before the first '-' in all user defined words found in the COPY text // before copying it into the main program if (CopyReplacingDirective != null && CopyReplacingDirective.InsertSuffixChar && nextToken.TokenType == TokenType.UserDefinedWord) { string originalText = nextToken.Text; int indexOFirstDash = originalText.IndexOf('-'); if (indexOFirstDash > 0) { string replacedText = originalText.Substring(0, indexOFirstDash) + CopyReplacingDirective.SuffixChar + originalText.Substring(indexOFirstDash); TokensLine virtualTokensLine = TokensLine.CreateVirtualLineForInsertedToken(0, replacedText); Token replacementToken = new Token(TokenType.UserDefinedWord, 0, replacedText.Length - 1, virtualTokensLine); status.replacedToken = new ReplacedToken(replacementToken, nextToken); currentPosition.CurrentToken = status.replacedToken; } } #endif if (replaceOperation != null && TryMatchReplaceOperation(nextToken, replaceOperation, out originalMatchingTokens)) { status.replacedToken = CreateReplacedTokens(nextToken, replaceOperation, originalMatchingTokens); if (status.replacedToken != null) { // REPLACE pattern matched => return the first replaced token currentPosition.CurrentToken = status.replacedToken; } else { // If the replacement token set is empty (REPLACE == ... = BY == ==), get next token and try again status.tryAgain = true; } } return status; }
/// <summary> /// Check if the current tokens match with the comparison tokens of the current replace operation /// </summary> private bool TryMatchReplaceOperation(Token originalToken, ReplaceOperation replaceOperation, out IList<Token> originalMatchingTokens) { // Check if the first token matches the replace pattern if (originalToken.CompareForReplace(replaceOperation.ComparisonToken)) { // Multiple tokens pattern => check if the following tokens returned by the underlying iterator all match the pattern if (replaceOperation.Type == ReplaceOperationType.MultipleTokens) { MultipleTokensReplaceOperation multipleTokensReplaceOperation = (MultipleTokensReplaceOperation)replaceOperation; originalMatchingTokens = new List<Token>(); originalMatchingTokens.Add(originalToken); sourceIterator.SaveCurrentPositionSnapshot(); bool comparisonInterrupted = false; foreach (Token comparisonToken in multipleTokensReplaceOperation.FollowingComparisonTokens) { Token nextCandidateToken = sourceIterator.NextToken(); if (!comparisonToken.CompareForReplace(nextCandidateToken)) { comparisonInterrupted = true; break; } else { originalMatchingTokens.Add(nextCandidateToken); } } // The following tokens did not match if (comparisonInterrupted) { // Restore the uderlying iterator position sourceIterator.ReturnToLastPositionSnapshot(); // Match failed originalMatchingTokens = null; return false; } // Multiple tokens match OK else { return true; } } // Single token comparison => match OK else { originalMatchingTokens = null; return true; } } // First token does not match else { originalMatchingTokens = null; return false; } }
/// <summary> /// Create replaced tokens for all matched tokens /// (a ReplacedToken references both the original token and the replacement token) /// </summary> private Token CreateReplacedTokens(Token originalToken, ReplaceOperation replaceOperation, IList<Token> originalMatchingTokens) { switch (replaceOperation.Type) { // One comparison token => zero or one replacement token case ReplaceOperationType.SingleToken: SingleTokenReplaceOperation singleTokenReplaceOperation = (SingleTokenReplaceOperation)replaceOperation; if (singleTokenReplaceOperation.ReplacementToken != null) { ReplacedToken replacedToken = new ReplacedToken(singleTokenReplaceOperation.ReplacementToken, originalToken); return replacedToken; } else { return null; } // One pure partial word => one replacement token case ReplaceOperationType.PartialWord: PartialWordReplaceOperation partialWordReplaceOperation = (PartialWordReplaceOperation)replaceOperation; string originalTokenText = originalToken.Text; string partToReplace = partialWordReplaceOperation.ComparisonToken.Text; //#258 - PartialReplacementToken can be null. In this case, we consider that it's an empty replacement var replacementPart = partialWordReplaceOperation.PartialReplacementToken != null ? partialWordReplaceOperation.PartialReplacementToken.Text : ""; // The index below is always >= 0 because CompareForReplace() above was true int indexOfPartToReplace = originalTokenText.IndexOf(partToReplace, StringComparison.OrdinalIgnoreCase); string replacedTokenText = (indexOfPartToReplace > 0 ? originalTokenText.Substring(0, indexOfPartToReplace) : String.Empty) + replacementPart + ((indexOfPartToReplace + partToReplace.Length) < (originalTokenText.Length - 1) ? originalTokenText.Substring(indexOfPartToReplace + partToReplace.Length) : String.Empty); // TO DO : find a way to transfer the scanner context the of original token to the call below Diagnostic error = null; Token generatedToken = Scanner.Scanner.ScanIsolatedTokenInDefaultContext(replacedTokenText, out error); // TO DO : find a way to report the error above ... ReplacedPartialCobolWord replacedPartialCobolWord = new ReplacedPartialCobolWord(generatedToken, partialWordReplaceOperation.PartialReplacementToken, originalToken); return replacedPartialCobolWord; // One comparison token => more than one replacement tokens case ReplaceOperationType.SingleToMultipleTokens: SingleToMultipleTokensReplaceOperation singleToMultipleTokensReplaceOperation = (SingleToMultipleTokensReplaceOperation)replaceOperation; currentPosition.ReplacementTokensBeingReturned = new Token[singleToMultipleTokensReplaceOperation.ReplacementTokens.Length]; int i = 0; foreach (Token replacementToken in singleToMultipleTokensReplaceOperation.ReplacementTokens) { currentPosition.ReplacementTokensBeingReturned[i] = new ReplacedToken(replacementToken, originalToken); i++; } currentPosition.ReplacementTokenIndexLastReturned = 0; return currentPosition.ReplacementTokensBeingReturned[currentPosition.ReplacementTokenIndexLastReturned]; // One first + several following comparison tokens => zero to many replacement tokens //case ReplaceOperationType.MultipleTokens: default: MultipleTokensReplaceOperation multipleTokensReplaceOperation = (MultipleTokensReplaceOperation)replaceOperation; if (multipleTokensReplaceOperation.ReplacementTokens != null) { if (multipleTokensReplaceOperation.ReplacementTokens.Length == 1) { ReplacedTokenGroup replacedTokenGroup = new ReplacedTokenGroup(multipleTokensReplaceOperation.ReplacementTokens[0], originalMatchingTokens); return replacedTokenGroup; } else { currentPosition.ReplacementTokensBeingReturned = new Token[multipleTokensReplaceOperation.ReplacementTokens.Length]; i = 0; foreach (Token replacementToken in multipleTokensReplaceOperation.ReplacementTokens) { currentPosition.ReplacementTokensBeingReturned[i] = new ReplacedTokenGroup(replacementToken, originalMatchingTokens); i++; } currentPosition.ReplacementTokenIndexLastReturned = 0; return currentPosition.ReplacementTokensBeingReturned[currentPosition.ReplacementTokenIndexLastReturned]; } } else { return null; } } }