public PairAwareState GetPairsState() { return(new PairAwareState() { CurrentTokenDirection = CurrentTokenDirection, PairStack = new Stack <PairSymbol>(PairStack.Reverse()), OpenedPair = OpenedPair }); }
private List <int[]> MergeFromList(List <Tuple <int, string> > list) { var result = new List <int[]>(); var stack = new PairStack(); for (int i = 0; i < list.Count; i++) { if (0 == list[i].Item2.CompareTo(FRONT)) { stack.Push(list[i]); } else { Tuple <int, string> lastF = stack.Pop(); if (stack.IsEmpty(stack)) { result.Add(MakeElement(Front: lastF, Back: list[i])); } } } return(result); }
public bool IsEmpty(PairStack stack) { return(stack.Count == 0); }
public override IToken GetNextToken() { switch (CurrentTokenDirection) { case Direction.Down: PairStack.Push(OpenedPair); OpenedPair = null; break; case Direction.Up: PairStack.Pop(); break; } CurrentTokenDirection = Direction.Forward; var token = base.GetNextToken(); if (CustomBlockDefinition != null && CustomBlockDefinition.BaseToken == token.Name) { if (CustomBlockDefinition.IsStartLexem(token.Text)) { var newBlock = new CustomBlockNode { Location = new SegmentLocation { Start = token.Location.Start }, Start = new Node(token.Name, new LocalOptions { ExactMatch = true, Priority = LocalOptions.BASE_PRIORITY }) }; newBlock.Start.SetLocation(token.Location.Start, token.Location.End); newBlock.Start.SetValue(CustomBlockDefinition.GetName(token.Text)); CustomBlockStack.Push(newBlock); } else if (CustomBlockDefinition.IsEndLexem(token.Text)) { /// Отлавливаем ситуацию, когда количество закрытий блока не совпадает с количеством открытий if (CustomBlockStack.Count == 0) { Log.Add(Message.Error( $"Неожиданная закрывающая конструкция {this.GetTokenInfoForMessage(token)} для пользовательского блока", token.Location.Start )); } else { var currentBlock = CustomBlockStack.Pop(); currentBlock.End = new Node(token.Name); currentBlock.End.SetLocation(token.Location.Start, token.Location.End); currentBlock.Location.End = token.Location.End; CustomBlocks.Add(currentBlock); } } } /// Предполагается, что токен может быть началом ровно одной пары, или концом ровно одной пары, /// или одновременно началом и концом ровно одной пары var closed = GrammarObject.Pairs.FirstOrDefault(p => p.Value.Right.Contains(token.Name)); /// Если текущий токен закрывает некоторую конструкцию if (closed.Value != null) { /// и при этом не открывает её же if (!closed.Value.Left.Contains(token.Name)) { /// проверяем, есть ли на стеке то, что можно этой конструкцией закрыть if (PairStack.Count == 0) { Log.Add(Message.Error( $"Отсутствует открывающая конструкция для парной закрывающей {this.GetTokenInfoForMessage(token)}", token.Location.Start )); return(Lexer.CreateToken(Grammar.ERROR_TOKEN_NAME)); } else if (PairStack.Peek() != closed.Value) { Log.Add(Message.Error( $"Неожиданная закрывающая конструкция {this.GetTokenInfoForMessage(token)}, ожидается {String.Join("или ", PairStack.Peek().Right.Select(e => GrammarObject.Userify(e)))} для открывающей конструкции {String.Join("или ", PairStack.Peek().Left.Select(e => GrammarObject.Userify(e)))}", token.Location.Start )); return(Lexer.CreateToken(Grammar.ERROR_TOKEN_NAME)); } else { CurrentTokenDirection = Direction.Up; } } /// иначе, если текущий токен одновременно открывающий и закрывающий else { /// и есть что закрыть, закрываем if (PairStack.Count > 0 && PairStack.Peek() == closed.Value) { CurrentTokenDirection = Direction.Up; } else { CurrentTokenDirection = Direction.Down; OpenedPair = closed.Value; } } } else { var opened = GrammarObject.Pairs.FirstOrDefault(p => p.Value.Left.Contains(token.Name)); if (opened.Value != null) { CurrentTokenDirection = Direction.Down; OpenedPair = opened.Value; } } return(token); }