/// <summary> /// Closes a block at the specified index. /// </summary> /// <param name="index">The index.</param> private void Close(int index) { var block = OpenedBlocks[index]; // If the pending object is removed, we need to remove it from the parent container if (block.Parser != null) { if (!block.Parser.Close(this, block)) { block.Parent?.Remove(block); if (block is LeafBlock leaf) { leaf.Lines.Release(); } } else { // Invoke the Closed event var blockClosed = block.Parser.GetClosedEvent; blockClosed?.Invoke(this, block); } } OpenedBlocks.RemoveAt(index); }
static private string WhileBlockAdd(int command_ptr, ref int NextIndex, ref int line_ptr, string Command, ref int?SkipTo, ref bool DontSkipNextCommand) { OpenedBlocks.Push(new Block(command_ptr, NextIndex, line_ptr, BlockType.While)); string expression; var res = GetNextExpression(Command, ref NextIndex, ref line_ptr, out expression, true); if (!res) { return("BAD_EXPRESSION"); } bool while_result; var Result = GetBoolFuncExpressionResult(expression, out while_result); if (Result == null) { DontSkipNextCommand = true; if (while_result) { return(null); } else { SkipTo = OpenedBlocks.Count - 1; return(null); } } else { return(Result); } }
/// <summary> /// Processes any new blocks that have been pushed to <see cref="NewBlocks"/>. /// </summary> /// <param name="result">The last result of matching.</param> /// <param name="allowClosing">if set to <c>true</c> the processing of a new block will close existing opened blocks].</param> /// <exception cref="InvalidOperationException">The NewBlocks is not empty. This is happening if a LeafBlock is not the last to be pushed</exception> private void ProcessNewBlocks(BlockState result, bool allowClosing) { var newBlocks = NewBlocks; while (newBlocks.Count > 0) { var block = newBlocks.Pop(); if (block.Parser == null) { ThrowHelper.InvalidOperationException($"The new block [{block.GetType()}] must have a valid Parser property"); } block.Line = LineIndex; // If we have a leaf block var leaf = block as LeafBlock; if (leaf != null) { if (!result.IsDiscard()) { leaf.AppendLine(ref Line, Column, LineIndex, CurrentLineStartPosition); } if (newBlocks.Count > 0) { ThrowHelper.InvalidOperationException( "The NewBlocks is not empty. This is happening if a LeafBlock is not the last to be pushed"); } } if (allowClosing) { // Close any previous blocks not opened CloseAll(false); } // If previous block is a container, add the new block as a children of the previous block if (block.Parent == null) { UpdateLastBlockAndContainer(); CurrentContainer.Add(block); } block.IsOpen = result.IsContinue(); // Add a block BlockProcessor to the stack (and leave it opened) OpenedBlocks.Add(block); if (leaf != null) { ContinueProcessingLine = false; return; } } ContinueProcessingLine = !result.IsDiscard(); }
private void Reset() { Line = StringSlice.Empty; Column = 0; ColumnBeforeIndent = 0; StartBeforeIndent = 0; OpenedBlocks.Clear(); NewBlocks.Clear(); }
/// <summary> /// Discards the specified block from the stack, remove from its parent. /// </summary> /// <param name="block">The block.</param> public void Discard(Block block) { for (int i = OpenedBlocks.Count - 1; i >= 1; i--) { if (OpenedBlocks[i] == block) { block.Parent.Remove(block); OpenedBlocks.RemoveAt(i); break; } } }
/// <summary> /// Opens the specified block. /// </summary> /// <param name="block">The block.</param> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException">The block must be opened</exception> public void Open(Block block) { if (block == null) { ThrowHelper.ArgumentNullException(nameof(block)); } if (!block.IsOpen) { ThrowHelper.ArgumentException("The block must be opened", nameof(block)); } OpenedBlocks.Add(block); }
static private string Break(ref int?SkipTo, ref bool DontSkipNextCommand) { var BlockList = OpenedBlocks.ToList(); for (var i = 0; i < BlockList.Count; i++) { if (BlockList[i].type == BlockType.While || BlockList[i].type == BlockType.For || BlockList[i].type == BlockType.DoUntil) { DontSkipNextCommand = false; SkipTo = BlockList.Count - i - 1; return(null); } } return("BAD_BREAK"); }
static private string Continue(ref int command_ptr, ref int NextIndex, ref int line_ptr, ref bool DontSkipNextCommand) { while (OpenedBlocks.Count > 0) { var NextBlock = OpenedBlocks.Peek(); if (NextBlock.type == BlockType.While || NextBlock.type == BlockType.For || NextBlock.type == BlockType.DoUntil) { command_ptr = NextBlock.command_ptr; line_ptr = NextBlock.line_ptr; NextIndex = NextBlock.NextIndex; DontSkipNextCommand = false; return(null); } OpenedBlocks.Pop(); } return("BAD_CONTINUE"); }
static private string DoUntilBlockProcess(ref int command_ptr, ref int NextIndex, ref int line_ptr, string Command) { var DoUntilBlock = OpenedBlocks.Peek(); if (DoUntilBlock.type != BlockType.DoUntil) { return("BAD_BLOCK"); } string expression; var res = GetNextExpression(Command, ref NextIndex, ref line_ptr, out expression, true); if (!res) { return("BAD_EXPRESSION"); } bool until_result; var Result = GetBoolFuncExpressionResult(expression, out until_result); if (Result == null) { if (until_result) { OpenedBlocks.Pop(); return(null); } else { command_ptr = DoUntilBlock.command_ptr; NextIndex = DoUntilBlock.NextIndex; line_ptr = DoUntilBlock.line_ptr; return(null); } } else { return(Result); } }
internal bool IsOpen(Block block) { return(OpenedBlocks.Contains(block)); }
static private string ForBlockAdd(int command_ptr, ref int NextIndex, ref int line_ptr, string Command, ref int?SkipTo, ref bool DontSkipNextCommand) { var ForBlock = new Block(command_ptr, NextIndex, line_ptr, BlockType.For); if (!CheckNextSymbol(Command, NextIndex, ',')) { var result = DefineVariable(ref NextIndex, ref line_ptr, Command, GetNextLiteral(Command, ref NextIndex, ref line_ptr), ForBlock, true); if (result != null) { return(result); } } else { GetNextSymbol(Command, ref NextIndex, ref line_ptr); } ForBlock.NextIndex = NextIndex; ForBlock.line_ptr = line_ptr; OpenedBlocks.Push(ForBlock); string expression; if (!CheckNextSymbol(Command, NextIndex, ',')) { var res = GetNextExpression(Command, ref NextIndex, ref line_ptr, out expression, true); if (!res) { return("BAD_EXPRESSION"); } } else { GetNextSymbol(Command, ref NextIndex, ref line_ptr); expression = "true"; } bool for_result; var Result = GetBoolFuncExpressionResult(expression, out for_result); if (Result == null) { DontSkipNextCommand = true; var result = GetNextExpression(Command, ref NextIndex, ref line_ptr, out expression, true); if (for_result) { if (result) { return(null); } } else { SkipTo = OpenedBlocks.Count - 1; if (result) { return(null); } } return("BAD_EXPRESSION"); } else { return(Result); } }
static private void DoUntilBlockAdd(int command_ptr, int NextIndex, int line_ptr) { OpenedBlocks.Push(new Block(command_ptr, NextIndex, line_ptr, BlockType.DoUntil)); }