Example #1
0
            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.
                }
            }