public static void WhitespaceHandler(this IProcessorState processor, ref int bufferLength, ref int currentBufferPosition, bool wholeLine = false, bool trim = false, bool trimForward = false, bool trimBackward = false) { if (wholeLine) { processor.ConsumeWholeLine(ref bufferLength, ref currentBufferPosition); return; } if (trim) { trimForward = true; trimBackward = true; } processor.TrimWhitespace(trimForward, trimBackward, ref bufferLength, ref currentBufferPosition); }
public int HandleMatch(IProcessorState processor, int bufferLength, ref int currentBufferPosition, int token, Stream target) { bool flag; if (processor.Config.Flags.TryGetValue(OperationName, out flag) && !flag) { target.Write(Tokens[token].Value, Tokens[token].Start, Tokens[token].Length); return(Tokens[token].Length); } // conditional has not started, or this is the "if" if (_current != null || IsTokenIndexOfType(token, IfTokenBaseIndex) || IsTokenIndexOfType(token, IfTokenActionableBaseIndex)) { if (_definition._wholeLine) { processor.SeekBackUntil(processor.EncodingConfig.LineEndings); } else if (_definition._trimWhitespace) { processor.TrimWhitespace(false, true, ref bufferLength, ref currentBufferPosition); } } BEGIN: //Got the "if" token... if (IsTokenIndexOfType(token, IfTokenBaseIndex) || IsTokenIndexOfType(token, IfTokenActionableBaseIndex)) { if (_current == null) { _current = new EvaluationState(this); } else { _pendingCompletion.Push(_current); _current = new EvaluationState(this); } //If the "if" branch is taken, all else and elseif blocks will be omitted, return // control to the processor so nested "if"s/mutations can be processed. Note that // this block will not be terminated until the corresponding endif is found if (_current.Evaluate(processor, ref bufferLength, ref currentBufferPosition)) { if (_definition.WholeLine) { processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } if (IsTokenIndexOfType(token, IfTokenActionableBaseIndex)) { // "Actionable" if token, so enable the flag operation(s) _current.ToggleActionableOperations(true, processor); } // if (true_condition) was found. return(0); } else { // if (false_condition) was found. Skip to the next token of the if-elseif-elseif-...elseif-else-endif SeekToNextTokenAtSameLevel(processor, ref bufferLength, ref currentBufferPosition, out token); goto BEGIN; } } // If we've got an unbalanced statement, emit the token if (_current == null) { target.Write(Tokens[token].Value, Tokens[token].Start, Tokens[token].Length); return(Tokens[token].Length); } //Got the endif token, exit to the parent "if" scope if it exists if (IsTokenIndexOfType(token, EndTokenBaseIndex)) { if (_pendingCompletion.Count > 0) { _current = _pendingCompletion.Pop(); _current.ToggleActionableOperations(_current.ActionableOperationsEnabled, processor); } else { // disable the special case operations (note: they may already be disabled, but cheaper to do than check) _current.ToggleActionableOperations(false, processor); _current = null; } if (_definition._wholeLine) { processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } else if (_definition._trimWhitespace) { processor.TrimWhitespace(true, false, ref bufferLength, ref currentBufferPosition); } return(0); } if (_current.BranchTaken) { processor.SeekBackUntil(processor.EncodingConfig.LineEndings, true); //A previous branch was taken. Skip to the endif token. // NOTE: this can probably use the new method SeekToNextTokenAtSameLevel() - they do almost the same thing. SkipToMatchingEndif(processor, ref bufferLength, ref currentBufferPosition, ref token); if (_pendingCompletion.Count > 0) { _current = _pendingCompletion.Pop(); _current.ToggleActionableOperations(_current.ActionableOperationsEnabled, processor); } else { // disable the special case operation (note: it may already be disabled, but cheaper to do than check) _current.ToggleActionableOperations(false, processor); _current = null; } if (_definition._wholeLine) { processor.SeekForwardUntil(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } else if (_definition._trimWhitespace) { processor.TrimWhitespace(true, false, ref bufferLength, ref currentBufferPosition); } return(0); } //We have an "elseif" and haven't taken a previous branch if (IsTokenIndexOfType(token, ElseIfTokenBaseIndex) || IsTokenIndexOfType(token, ElseIfTokenActionableBaseIndex)) { // 8-19 attempt to make the same as if() handling // if (_current.Evaluate(processor, ref bufferLength, ref currentBufferPosition)) { if (_definition.WholeLine) { processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } if (IsTokenIndexOfType(token, ElseIfTokenActionableBaseIndex)) { // the elseif branch is taken. _current.ToggleActionableOperations(true, processor); } return(0); } else { SeekToNextTokenAtSameLevel(processor, ref bufferLength, ref currentBufferPosition, out token); // In the original version this was conditional on SeekToToken() succeeding. // Not sure if it should be conditional. It should never fail, unless the template is malformed. goto BEGIN; } } //We have an "else" token and haven't taken any other branches, return control // after setting that a branch has been taken if (IsTokenIndexOfType(token, ElseTokenBaseIndex) || IsTokenIndexOfType(token, ElseTokenActionableBaseIndex)) { if (IsTokenIndexOfType(token, ElseTokenActionableBaseIndex)) { _current.ToggleActionableOperations(true, processor); } _current.BranchTaken = true; processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, wholeLine: _definition._wholeLine, trim: _definition._trimWhitespace); return(0); } else { Debug.Assert(true, "Unknown token index: " + token); return(0); // TODO: revisit. Not sure what's best here. } }
public int HandleMatch(IProcessorState processor, int bufferLength, ref int currentBufferPosition, int token, Stream target) { bool flag; if (processor.Config.Flags.TryGetValue("conditionals", out flag) && !flag) { byte[] tokenValue = Tokens[token]; target.Write(tokenValue, 0, tokenValue.Length); return(tokenValue.Length); } if (_current != null || token == 0) { if (_definition._wholeLine) { processor.SeekBackUntil(processor.EncodingConfig.LineEndings); } else if (_definition._trimWhitespace) { processor.TrimWhitespace(false, true, ref bufferLength, ref currentBufferPosition); } } BEGIN: //Got the "if" token... if (token == 0) { if (_current == null) { _current = new EvaluationState(this); } else { _pendingCompletion.Push(_current); _current = new EvaluationState(this); } //If the "if" branch is taken, all else and elseif blocks will be omitted, return // control to the processor so nested "if"s/mutations can be processed. Note that // this block will not be terminated until the corresponding endif is found if (_current.Evaluate(processor, ref bufferLength, ref currentBufferPosition)) { if (_definition.WholeLine) { processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } return(0); } if (_definition.WholeLine) { processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } SeekToTerminator(processor, ref bufferLength, ref currentBufferPosition, out token); //Keep on scanning until we've hit a balancing token that belongs to us while (token == 0) { int open = 1; while (open != 0) { SeekToTerminator(processor, ref bufferLength, ref currentBufferPosition, out token); if (token == 0) { ++open; } else if (token == 1) { --open; } } SeekToTerminator(processor, ref bufferLength, ref currentBufferPosition, out token); } goto BEGIN; } //If we've got an unbalanced statement, emit the token if (_current == null) { byte[] tokenValue = Tokens[token]; target.Write(tokenValue, 0, tokenValue.Length); return(tokenValue.Length); } //Got the endif token, exit to the parent "if" scope if it exists if (token == 1) { _current = null; if (_pendingCompletion.Count > 0) { _current = _pendingCompletion.Pop(); } if (_definition._wholeLine) { processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } else if (_definition._trimWhitespace) { processor.TrimWhitespace(true, false, ref bufferLength, ref currentBufferPosition); } return(0); } if (_current.BranchTaken) { processor.SeekBackUntil(processor.EncodingConfig.LineEndings, true); //A previous branch was taken. Skip to the endif token. SkipToMatchingEndif(processor, ref bufferLength, ref currentBufferPosition, ref token); return(0); } //We have an "elseif" and haven't taken a previous branch if (token == _elseIfTokenIndex) { //If the elseif branch is taken, return control for replacements to be done as usual if (!_current.Evaluate(processor, ref bufferLength, ref currentBufferPosition)) { if (_definition.WholeLine) { processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } if (SeekToTerminator(processor, ref bufferLength, ref currentBufferPosition, out token)) { goto BEGIN; } } if (_definition.WholeLine) { processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition); } //The "elseif" branch was not taken. Skip to the following else, elseif or endif token return(0); } //We have an "else" token and haven't taken any other branches, return control // after setting that a branch has been taken _current.BranchTaken = true; processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, wholeLine: _definition._wholeLine, trim: _definition._trimWhitespace); return(0); }