public void BracketPairs_Should_Generate2_N_2() { BracketPairs bp = new BracketPairs(); var results = bp.GenerateBracketPairs2(2); results.Should().NotBeNull("results should not be null with n = 2 in recursive2"); results.Count.Should().Be(2, "results should have exactly 2 results with n = 2 in recursive2"); results.Contains("(())").Should().BeTrue("results does not contain value (()) with n = 2 in recursive2"); results.Contains("()()").Should().BeTrue("results does not contain value ()() with n = 2 in recursive2"); }
public void BracketPairs_Should_Generate_N_0() { BracketPairs bp = new BracketPairs(); var results = bp.GenerateBracketPairs(0, true); results.Should().NotBeNull("results should not be null with n = 0 in recursive"); results.Count.Should().Be(0, "results should have exactly 0 result with n = 0 in recursive"); results = bp.GenerateBracketPairs(0, false); results.Should().NotBeNull("results should not be null with n = 0 in iterative"); results.Count.Should().Be(0, "results should have exactly 0 result with n = 0 in iterative"); }
public void BracketPairs_Should_Generate_N_1() { BracketPairs bp = new BracketPairs(); var results = bp.GenerateBracketPairs(1, true); results.Should().NotBeNull("results should not be null with n = 1 in recursive"); results.Count.Should().Be(1, "results should have exactly 1 result with n = 1 in recursive"); results[0].Should().Be("()", "results was not incorrect with n = 1 in recursive"); results = bp.GenerateBracketPairs(1, false); results.Should().NotBeNull("results should not be null with n = 1 in iterative"); results.Count.Should().Be(1, "results should have exactly 1 result with n = 1 in iterative"); results[0].Should().Be("()", "results was not incorrect with n = 1 in iterative"); }
public void BracketPairs_Should_Generate_N_3() { BracketPairs bp = new BracketPairs(); var results = bp.GenerateBracketPairs(3, true); results.Should().NotBeNull("results should not be null with n = 3 in recursive"); results.Count.Should().Be(5, "results should have exactly 5 results with n = 3 in recursive"); results.Contains("((()))").Should().BeTrue("results does not contain value ((())) with n = 3 in recursive"); results.Contains("(())()").Should().BeTrue("results does not contain value (())() with n = 3 in recursive"); results.Contains("()(())").Should().BeTrue("results does not contain ()(()) with n = 3 in recursive"); results.Contains("(()())").Should().BeTrue("results does not contain value (()()) with n = 3 in recursive"); results.Contains("()()()").Should().BeTrue("results does not contain value ()()() with n = 3 in recursive"); results = bp.GenerateBracketPairs(3, false); results.Should().NotBeNull("results should not be null with n = 3 in iterative"); results.Count.Should().Be(5, "results should have exactly 5 results with n = 3 in iterative"); results.Contains("((()))").Should().BeTrue("results does not contain value ((())) with n = 3 in iterative"); results.Contains("(())()").Should().BeTrue("results does not contain value (())() with n = 3 in iterative"); results.Contains("()(())").Should().BeTrue("results does not contain ()(()) with n = 3 in iterative"); results.Contains("(()())").Should().BeTrue("results does not contain value (()()) with n = 3 in iterative"); results.Contains("()()()").Should().BeTrue("results does not contain value ()()() with n = 3 in iterative"); }
public IEnumerable<Token<TokenType>> ReadToScopeClose(TokenType open, TokenType close, BracketPairs bracketPairs) { SkipSpace(); _stack.Clear(); Token<TokenType> token = null; while (!End) { token = ReadToken(); if (bracketPairs.ContainsOpening(token.Identifier) || open == token.Identifier) // Allows nesting { _stack.Push(token); } else if (bracketPairs.ContainsClosing(token.Identifier) || token.Identifier == close) // Allows nesting { // Since this method assumes that the first opening bracket was already read, an empty _stack indicates main scope closure. if (!_stack.Any() && token.Identifier == close) { yield break; } var lastOpening = _stack.Pop(); if (!bracketPairs.Contains(lastOpening.Identifier, token.Identifier)) { throw new ManhoodException(_source, token, "Invalid closure '" + lastOpening.Value + " ... " + token.Value + "' - expected '" + Lexer.Rules.GetSymbolForId(bracketPairs.GetClosing(lastOpening.Identifier)) + "'"); } } yield return token; } throw new ManhoodException(_source, null, "Unexpected end of file - expected '" + Lexer.Rules.GetSymbolForId(close) + "'."); }
public IEnumerable<IEnumerable<Token<TokenType>>> ReadItemsToClosureTrimmed(TokenType open, TokenType close, TokenType separator, BracketPairs bracketPairs) { SkipSpace(); _stack.Clear(); Token<TokenType> token = null; int start = _pos; while (!End) { token = PeekToken(); if (bracketPairs.ContainsOpening(token.Identifier) || open == token.Identifier) // Allows nesting { _stack.Push(token); } else if (bracketPairs.ContainsClosing(token.Identifier) || token.Identifier == close) // Allows nesting { // Since this method assumes that the first opening bracket was already read, an empty _stack indicates main scope closure. if (!_stack.Any() && token.Identifier == close) { yield return _tokens.SkipWhile((t, i) => i < start).TakeWhile((t, i) => i < _pos - start).ToArray(); _pos++; yield break; } var lastOpening = _stack.Pop(); if (!bracketPairs.Contains(lastOpening.Identifier, token.Identifier)) { throw new ManhoodException(_source, token, "Invalid closure '" + lastOpening.Value + " ... " + token.Value + "' - expected '" + Lexer.Rules.GetSymbolForId(bracketPairs.GetClosing(lastOpening.Identifier)) + "'"); } } else if (token.Identifier == separator && !_stack.Any()) { yield return _tokens.SkipWhile((t, i) => i < start).TakeWhile((t, i) => i < _pos - start).ToArray(); _pos++; TakeAll(TokenType.Whitespace); start = _pos; continue; } _pos++; } throw new ManhoodException(_source, null, "Unexpected end of file - expected '" + Lexer.Rules.GetSymbolForId(close) + "'."); }
public IEnumerable<IEnumerable<Token<TokenType>>> ReadMultiItemScope(TokenType open, TokenType close, TokenType separator, BracketPairs bracketPairs) { _stack.Clear(); // This exception should not happen when running patterns - only if I mess something up in the code. if (!IsNext(open)) throw new InvalidOperationException("The specified opening token does not occur at the reader position."); int start = _pos + 1; Token<TokenType> token = null; while (!End) { // Peek but don't consume - this saves some calculations later on. token = PeekToken(); // Opening bracket if (bracketPairs.ContainsOpening(token.Identifier) || open == token.Identifier) // Previous bracket allows nesting { _stack.Push(token); } // Closing bracket else if (bracketPairs.ContainsClosing(token.Identifier) || close == token.Identifier) // Previous bracket allows nesting { var lastOpening = _stack.Pop(); // Handle invalid closures if (!bracketPairs.Contains(lastOpening.Identifier, token.Identifier)) // Not in main pair { throw new ManhoodException(_source, token, "Invalid closure '" + lastOpening.Value + " ... " + token.Value + "' - expected '" + Lexer.Rules.GetSymbolForId(bracketPairs.GetClosing(lastOpening.Identifier)) + "'"); } // If the _stack is empty, this is the last item. Stop the iterator. if (!_stack.Any()) { yield return _tokens.SkipWhile((t, i) => i < start).TakeWhile((t, i) => i < _pos - start).ToArray(); _pos++; yield break; } } // Separator else if (token.Identifier == separator && _stack.Count == 1) { yield return _tokens.SkipWhile((t, i) => i < start).TakeWhile((t, i) => i < _pos - start).ToArray(); start = _pos + 1; } // Move to next position _pos++; } throw new ManhoodException(_source, null, "Unexpected end of file - expected '" + Lexer.Rules.GetSymbolForId(close) + "'."); }
private void TryParse() { string text = Text; int count = text.Length; int nestLevel = 0; Stack <int> unbalanced = new Stack <int>(); for (int index = 0; index < count; ++index) { char c = text[index]; if (c == '(' || c == '[' || c == '{' || c == '<') { unbalanced.Push(index); nestLevel++; } else if (c == ')' || c == ']' || c == '}' || c == '>') { nestLevel--; char closeChar = c; if (unbalanced.Count == 0) { Exceptions.Add(new Exception("Unbalanced close symbol at index " + index)); return; } int openIndex = unbalanced.Peek(); char openChar = text[openIndex]; char expectedOpenChar = '\0'; switch (closeChar) { case ')': expectedOpenChar = '('; break; case ']': expectedOpenChar = '['; break; case '}': expectedOpenChar = '{'; break; case '>': expectedOpenChar = '<'; break; } if (openChar != expectedOpenChar) { Exceptions.Add(new Exception("Mismatched close symbol " + closeChar + " at " + index + ". The open symbol is " + openChar + " at " + openIndex + ".")); return; } var pair = new BracketPair() { OpenChar = openChar, OpenIndex = openIndex, CloseChar = closeChar, CloseIndex = index, NestLevel = (nestLevel + 1) }; BracketPairs.Add(pair); unbalanced.Pop(); } } BracketPairs.Sort((BracketPair p1, BracketPair p2) => (p1.OpenIndex - p2.OpenIndex)); }
public IEnumerable <Token <TokenType> > ReadToScopeClose(TokenType open, TokenType close, BracketPairs bracketPairs) { SkipSpace(); _stack.Clear(); Token <TokenType> token = null; while (!End) { token = ReadToken(); if (bracketPairs.ContainsOpening(token.Identifier) || open == token.Identifier) // Allows nesting { _stack.Push(token); } else if (bracketPairs.ContainsClosing(token.Identifier) || token.Identifier == close) // Allows nesting { // Since this method assumes that the first opening bracket was already read, an empty _stack indicates main scope closure. if (!_stack.Any() && token.Identifier == close) { yield break; } var lastOpening = _stack.Pop(); if (!bracketPairs.Contains(lastOpening.Identifier, token.Identifier)) { throw new RantException(_source, token, "Invalid closure '" + lastOpening.Value + " ... " + token.Value + "' - expected '" + Lexer.Rules.GetSymbolForId(bracketPairs.GetClosing(lastOpening.Identifier)) + "'"); } } yield return(token); } throw new RantException(_source, null, "Unexpected end of file - expected '" + Lexer.Rules.GetSymbolForId(close) + "'."); }
public IEnumerable <IEnumerable <Token <TokenType> > > ReadItemsToClosureTrimmed(TokenType open, TokenType close, TokenType separator, BracketPairs bracketPairs) { SkipSpace(); _stack.Clear(); Token <TokenType> token = null; int start = _pos; while (!End) { token = PeekToken(); if (bracketPairs.ContainsOpening(token.Identifier) || open == token.Identifier) // Allows nesting { _stack.Push(token); } else if (bracketPairs.ContainsClosing(token.Identifier) || token.Identifier == close) // Allows nesting { // Since this method assumes that the first opening bracket was already read, an empty _stack indicates main scope closure. if (!_stack.Any() && token.Identifier == close) { yield return(_tokens.SkipWhile((t, i) => i < start).TakeWhile((t, i) => i < _pos - start).ToArray()); _pos++; yield break; } var lastOpening = _stack.Pop(); if (!bracketPairs.Contains(lastOpening.Identifier, token.Identifier)) { throw new RantException(_source, token, "Invalid closure '" + lastOpening.Value + " ... " + token.Value + "' - expected '" + Lexer.Rules.GetSymbolForId(bracketPairs.GetClosing(lastOpening.Identifier)) + "'"); } } else if (token.Identifier == separator && !_stack.Any()) { yield return(_tokens.SkipWhile((t, i) => i < start).TakeWhile((t, i) => i < _pos - start).ToArray()); _pos++; TakeAll(TokenType.Whitespace); start = _pos; continue; } _pos++; } throw new RantException(_source, null, "Unexpected end of file - expected '" + Lexer.Rules.GetSymbolForId(close) + "'."); }
public IEnumerable <IEnumerable <Token <TokenType> > > ReadMultiItemScope(TokenType open, TokenType close, TokenType separator, BracketPairs bracketPairs) { _stack.Clear(); // This exception should not happen when running patterns - only if I mess something up in the code. if (!IsNext(open)) { throw new InvalidOperationException("The specified opening token does not occur at the reader position."); } int start = _pos + 1; Token <TokenType> token = null; while (!End) { // Peek but don't consume - this saves some calculations later on. token = PeekToken(); // Opening bracket if (bracketPairs.ContainsOpening(token.Identifier) || open == token.Identifier) // Previous bracket allows nesting { _stack.Push(token); } // Closing bracket else if (bracketPairs.ContainsClosing(token.Identifier) || close == token.Identifier) // Previous bracket allows nesting { var lastOpening = _stack.Pop(); // Handle invalid closures if (!bracketPairs.Contains(lastOpening.Identifier, token.Identifier)) // Not in main pair { throw new RantException(_source, token, "Invalid closure '" + lastOpening.Value + " ... " + token.Value + "' - expected '" + Lexer.Rules.GetSymbolForId(bracketPairs.GetClosing(lastOpening.Identifier)) + "'"); } // If the _stack is empty, this is the last item. Stop the iterator. if (!_stack.Any()) { yield return(_tokens.SkipWhile((t, i) => i < start).TakeWhile((t, i) => i < _pos - start).ToArray()); _pos++; yield break; } } // Separator else if (token.Identifier == separator && _stack.Count == 1) { yield return(_tokens.SkipWhile((t, i) => i < start).TakeWhile((t, i) => i < _pos - start).ToArray()); start = _pos + 1; } // Move to next position _pos++; } throw new RantException(_source, null, "Unexpected end of file - expected '" + Lexer.Rules.GetSymbolForId(close) + "'."); }