public bool Validate(List <Token> tokens, int idx = -1) { Token currentToken = null; CurrentState = CurrentState.GoToNextState(TokenEnums.TokenType.Dollar); // move from the initialstate going forward try { for (int i = idx; i < tokens.Count;) { if (CurrentState.StateAction == StateAction.Accept) { break; } if (CurrentState.StateAction == StateAction.Scan) { // do nothing i++; currentToken = i >= 0 ? tokens[i] : null; } else if (CurrentState.StateAction == StateAction.Read && currentToken.TokenType == TokenEnums.TokenType.Tag) { if (TagStack.Peek() == currentToken.Symbol) { TagStack.Pop(); } } else if (CurrentState.StateAction == StateAction.Read && (currentToken.TokenType == TokenEnums.TokenType.HeaderXmlOpeningSymbol || currentToken.TokenType == TokenEnums.TokenType.HeaderXmlClosingSymbol || currentToken.TokenType == TokenEnums.TokenType.ClosingSymbol || currentToken.TokenType == TokenEnums.TokenType.OpeningSymbol || currentToken.TokenType == TokenEnums.TokenType.OpeningWithBackslashSymbol || currentToken.TokenType == TokenEnums.TokenType.SelfClosingSymbol)) { if (currentToken.TokenType == TokenEnums.TokenType.SelfClosingSymbol || currentToken.TokenType == TokenEnums.TokenType.HeaderXmlClosingSymbol) { TagStack.Pop(); } var peek = SymbolStack.Peek(); if ((currentToken.Partners != null && currentToken.Partners.Any(item => item == peek)) || peek == currentToken.Partner) { SymbolStack.Pop(); } // TO DO: handle partner tags } else if (CurrentState.StateAction == StateAction.Write && (currentToken.TokenType == TokenEnums.TokenType.Tag || currentToken.TokenType == TokenEnums.TokenType.HeaderXmlTag)) { TagStack.Push(currentToken.Symbol); } else if (CurrentState.StateAction == StateAction.Write && (currentToken.TokenType == TokenEnums.TokenType.HeaderXmlClosingSymbol || currentToken.TokenType == TokenEnums.TokenType.HeaderXmlOpeningSymbol || currentToken.TokenType == TokenEnums.TokenType.ClosingSymbol || currentToken.TokenType == TokenEnums.TokenType.OpeningSymbol || currentToken.TokenType == TokenEnums.TokenType.OpeningWithBackslashSymbol || currentToken.TokenType == TokenEnums.TokenType.SelfClosingSymbol)) { SymbolStack.Push(currentToken.Symbol); } var nextState = CurrentState.GoToNextState(currentToken.TokenType); // move from the initialstate going forward if (nextState == null) { //// non-deterministic //// guess next state based on next token var nextToken = (i + 1) >= tokens.Count ? null : tokens[i + 1]; if (nextToken != null) { var states = CurrentState.GetPossibleNextStates(currentToken.TokenType); nextState = states.Where(state => state.StateAction != StateAction.Accept).FirstOrDefault(); } else { // end state var states = CurrentState.GetPossibleNextStates(currentToken.TokenType); nextState = states.Where(state => state.StateAction == StateAction.Accept).FirstOrDefault(); } } CurrentState = nextState; } } catch (Exception ex) { throw; } // scan //foreach (var item in tokens) //{ // if (item.TokenType == TokenEnums.TokenType.Tag) // { // if (tags.Count != 0 && tags.Peek() == item.Symbol) // { // tags.Pop(); // } // else // { // tags.Push(item.Symbol); // } // } // else if (item.TokenType == TokenEnums.TokenType.OpeningSymbol || item.TokenType == TokenEnums.TokenType.OpeningWithBackslashSymbol) // { // symbols.Push(item); // } // else if (symbols.Count != 0 && item.TokenType == TokenEnums.TokenType.ClosingSymbol) // { // if (symbols.Peek().TokenType == TokenEnums.TokenType.OpeningSymbol || symbols.Peek().TokenType == TokenEnums.TokenType.OpeningWithBackslashSymbol) // { // symbols.Pop(); // } // } // else if (item.TokenType == TokenEnums.TokenType.SelfClosingSymbol) // { // tags.Pop(); // } //} if (TagStack.Count == 0 && SymbolStack.Count == 0 && CurrentState == FinalState) { return(true); } return(false); }