/// <summary> /// Parses an object path expression from a string. /// </summary> /// <param name="expression">The expression text to parse</param> /// <returns>The parsed expression</returns> public static ObjectPathExpression Parse(string expression) { if (expression == null) { throw new ArgumentNullException("path cannot be null"); } if (expression.Length == 0) { throw new FormatException("Cannot parse empty string"); } Tokenizer <ObjectPathToken> tokenizer = new Tokenizer <ObjectPathToken>(); tokenizer.TokenFactory = ObjectPathToken.TokenFactoryImpl; tokenizer.WhitespaceBehavior = WhitespaceBehavior.DelimitAndInclude; tokenizer.DoubleQuoteBehavior = DoubleQuoteBehavior.IncludeQuotedTokensAsStringLiterals; tokenizer.Delimiters.Add("["); tokenizer.Delimiters.Add("]"); tokenizer.Delimiters.Add("."); List <ObjectPathToken> tokens = tokenizer.Tokenize(expression); TokenReader <ObjectPathToken> reader = new TokenReader <ObjectPathToken>(tokens); List <IObjectPathElement> pathElements = new List <IObjectPathElement>(); bool lastTokenWasNavigation = false; while (reader.CanAdvance(skipWhitespace: true)) { var currentToken = reader.Advance(skipWhitespace: true); if (lastTokenWasNavigation == true && currentToken.TokenType == ObjectPathTokenType.IndexerOpen) { throw new FormatException("Expected property, got '['" + " at " + currentToken.Position); } lastTokenWasNavigation = false; if (pathElements.Count == 0 && currentToken.TokenType == ObjectPathTokenType.NavigationElement) { throw new FormatException("Expected property or index, got '" + currentToken.Value + "'" + " at " + currentToken.Position); } if (currentToken.TokenType == ObjectPathTokenType.IndexerClose || currentToken.TokenType == ObjectPathTokenType.StringLiteral) { throw new FormatException("Expected property or index, got '" + currentToken.Value + "'" + " at " + currentToken.Position); } if (currentToken.TokenType == ObjectPathTokenType.IndexerOpen) { // read index value if (reader.TryAdvance(out currentToken, skipWhitespace: true) == false) { throw new FormatException("Expected index value, got end of string"); } if (currentToken.TokenType == ObjectPathTokenType.Identifier || currentToken.TokenType == ObjectPathTokenType.StringLiteral) { string indexValueText = currentToken.Value; if (currentToken.TokenType == ObjectPathTokenType.StringLiteral) { indexValueText = indexValueText.Substring(1, indexValueText.Length - 2); } object indexValue; int indexValueInt; if (int.TryParse(indexValueText, out indexValueInt) == false) { indexValue = indexValueText; } else { indexValue = indexValueInt; } // read index close if (reader.TryAdvance(out currentToken, skipWhitespace: true) == false) { throw new FormatException("Expected ']', got end of string"); } if (currentToken.TokenType != ObjectPathTokenType.IndexerClose) { throw new FormatException("Expected ']', got '" + currentToken.Value + "' at " + currentToken.Position); } IndexerPathElement el = new IndexerPathElement(indexValue); pathElements.Add(el); if (reader.TryAdvance(out currentToken, skipWhitespace: true)) { if (currentToken.TokenType != ObjectPathTokenType.NavigationElement) { throw new FormatException("Expected '.', got '" + currentToken.Value + "' at " + currentToken.Position); } if (reader.CanAdvance(skipWhitespace: true) == false) { throw new FormatException("Expected property, got end of string"); } lastTokenWasNavigation = true; } } else { throw new ArgumentException("Unexpected token '" + currentToken.Value + "' at " + currentToken.Position); } } else if (currentToken.TokenType == ObjectPathTokenType.Identifier) { PropertyPathElement el = new PropertyPathElement(currentToken.Value); pathElements.Add(el); } else if (currentToken.TokenType == ObjectPathTokenType.NavigationElement) { // do nothing } else { throw new ArgumentException("Unexpected token '" + currentToken.Value + "' at " + currentToken.Position); } } return(new ObjectPathExpression(pathElements)); }
/// <summary> /// Parses an object path expression from a string. /// </summary> /// <param name="expression">The expression text to parse</param> /// <returns>The parsed expression</returns> public static ObjectPathExpression Parse(string expression) { if (expression == null) throw new ArgumentNullException("path cannot be null"); if (expression.Length == 0) throw new FormatException("Cannot parse empty string"); Tokenizer<ObjectPathToken> tokenizer = new Tokenizer<ObjectPathToken>(); tokenizer.TokenFactory = ObjectPathToken.TokenFactoryImpl; tokenizer.WhitespaceBehavior = WhitespaceBehavior.DelimitAndInclude; tokenizer.DoubleQuoteBehavior = DoubleQuoteBehavior.IncludeQuotedTokensAsStringLiterals; tokenizer.Delimiters.Add("["); tokenizer.Delimiters.Add("]"); tokenizer.Delimiters.Add("."); List<ObjectPathToken> tokens = tokenizer.Tokenize(expression); TokenReader<ObjectPathToken> reader = new TokenReader<ObjectPathToken>(tokens); List<IObjectPathElement> pathElements = new List<IObjectPathElement>(); bool lastTokenWasNavigation = false; while (reader.CanAdvance(skipWhitespace: true)) { var currentToken = reader.Advance(skipWhitespace: true); if (lastTokenWasNavigation == true && currentToken.TokenType == ObjectPathTokenType.IndexerOpen) { throw new FormatException("Expected property, got '['" + " at " + currentToken.Position); } lastTokenWasNavigation = false; if(pathElements.Count == 0 && currentToken.TokenType == ObjectPathTokenType.NavigationElement) { throw new FormatException("Expected property or index, got '" + currentToken.Value + "'" + " at " + currentToken.Position); } if (currentToken.TokenType == ObjectPathTokenType.IndexerClose || currentToken.TokenType == ObjectPathTokenType.StringLiteral) { throw new FormatException("Expected property or index, got '" + currentToken.Value + "'" + " at " + currentToken.Position); } if (currentToken.TokenType == ObjectPathTokenType.IndexerOpen) { // read index value if (reader.TryAdvance(out currentToken,skipWhitespace: true) == false) throw new FormatException("Expected index value, got end of string"); if (currentToken.TokenType == ObjectPathTokenType.Identifier || currentToken.TokenType == ObjectPathTokenType.StringLiteral) { string indexValueText = currentToken.Value; if(currentToken.TokenType == ObjectPathTokenType.StringLiteral) { indexValueText = indexValueText.Substring(1, indexValueText.Length - 2); } object indexValue; int indexValueInt; if (int.TryParse(indexValueText, out indexValueInt) == false) { indexValue = indexValueText; } else { indexValue = indexValueInt; } // read index close if (reader.TryAdvance(out currentToken, skipWhitespace: true) == false) throw new FormatException("Expected ']', got end of string"); if (currentToken.TokenType != ObjectPathTokenType.IndexerClose) throw new FormatException("Expected ']', got '" + currentToken.Value + "' at " + currentToken.Position); IndexerPathElement el = new IndexerPathElement(indexValue); pathElements.Add(el); if (reader.TryAdvance(out currentToken, skipWhitespace: true)) { if (currentToken.TokenType != ObjectPathTokenType.NavigationElement) throw new FormatException("Expected '.', got '" + currentToken.Value + "' at " + currentToken.Position); if (reader.CanAdvance(skipWhitespace: true) == false) throw new FormatException("Expected property, got end of string"); lastTokenWasNavigation = true; } } else { throw new ArgumentException("Unexpected token '" + currentToken.Value + "' at " + currentToken.Position); } } else if(currentToken.TokenType == ObjectPathTokenType.Identifier) { PropertyPathElement el = new PropertyPathElement(currentToken.Value); pathElements.Add(el); } else if(currentToken.TokenType == ObjectPathTokenType.NavigationElement) { // do nothing } else { throw new ArgumentException("Unexpected token '" + currentToken.Value + "' at " + currentToken.Position); } } return new ObjectPathExpression(pathElements); }