private static Dictionary <string, object> PrepareArguments(ParserNode node, bool checkedScope) { var args = default(Dictionary <string, object>); if (node.Childs.Count <= 1 || node.Childs[1].Childs.Count <= 0) { return(null); } args = new Dictionary <string, object>(); var argIdx = 0; foreach (var argNode in node.Childs[1].Childs) { if (argNode.Type == TokenType.Colon) { Ensure(argNode, 2, TokenType.Identifier); var argName = argNode.Childs[0].Value; args[argName] = argNode.Childs[1].ToExpressionTree(checkedScope); } else { var argName = (argIdx++).ToString(); args[argName] = argNode.ToExpressionTree(checkedScope); } } return(args); }
private static void Ensure(ParserNode node, int childCount, params TokenType[] childTypes) { if (node.Childs.Count < childCount) { throw new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_PARSER_INVALIDCHILDCOUNTOFNODE, node.Type, node.Childs.Count, childCount), node); } for (var i = 0; childTypes != null && i < childTypes.Length && i < node.Childs.Count; i++) { if (childTypes[i] == TokenType.None) { continue; } if (node.Childs[i].Type != childTypes[i]) { throw new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_PARSER_INVALIDCHILDTYPESOFNODE, node.Type, node.Childs[i].Type, childTypes[i]), node.Childs[i]); } } }
private bool Expression(ParserNode op = default(ParserNode), TokenType[] term = null) { var ct = 0; var changed = false; while (this.tokens.Count > 0) { var token = this.tokens.Dequeue(); try { if (ct == 0 && UnaryReplacement.ContainsKey((int)token.Type)) { token = new Token((TokenType)UnaryReplacement[(int)token.Type], token.Value, token.LineNumber, token.ColumnNumber, token.TokenLength); } if ((token.Type == TokenType.Lparen && ct > 0) || token.Type == TokenType.Lbracket) { var callToken = new Token(TokenType.Call, token.Value, token.LineNumber, token.ColumnNumber, token.TokenLength); token = new Token(TokenType.Arguments, token.Value, token.LineNumber, token.ColumnNumber, token.TokenLength); this.tokens.Insert(0, token); this.tokens.Insert(0, callToken); continue; } if (term != null && Array.IndexOf(term, token.Type) >= 0) { this.tokens.Insert(0, token); break; } var node = new ParserNode(token); switch (token.Type) { case TokenType.Identifier: case TokenType.Literal: case TokenType.Number: this.stack.Push(node); changed = true; break; case TokenType.Compl: case TokenType.Not: case TokenType.Plus: case TokenType.Convert: case TokenType.Minus: case TokenType.New: this.stack.Push(node); if (!this.Expression(node, term)) { throw new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_PARSER_OPREQUIRESOPERAND, token.Type), token); } this.CombineUnary(node.Lexeme); changed = true; break; case TokenType.Add: case TokenType.Subtract: case TokenType.Div: case TokenType.Mul: case TokenType.Mod: case TokenType.And: case TokenType.Or: case TokenType.Xor: case TokenType.Lshift: case TokenType.Rshift: case TokenType.AndAlso: case TokenType.OrElse: case TokenType.Gt: case TokenType.Gte: case TokenType.Lt: case TokenType.Lte: case TokenType.Eq: case TokenType.Neq: case TokenType.Resolve: case TokenType.Coalesce: case TokenType.Colon: case TokenType.Is: case TokenType.As: case TokenType.Call: if (op.Type != TokenType.None && this.ComputePrecedence(node.Type, op.Type) <= 0) { this.tokens.Insert(0, token); return(changed); } this.stack.Push(node); if (!this.Expression(node, term)) { throw new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_PARSER_OPREQUIRESSECONDOPERAND, token.Type), token); } this.CombineBinary(node.Lexeme); if (token.Type == TokenType.Call && node.Childs.Count == 2 && node.Childs[0].Type == TokenType.Identifier && ( string.Equals(node.Childs[0].Value, "unchecked", StringComparison.Ordinal) || string.Equals(node.Childs[0].Value, "checked", StringComparison.Ordinal) || string.Equals(node.Childs[0].Value, "typeof", StringComparison.Ordinal) || string.Equals(node.Childs[0].Value, "default", StringComparison.Ordinal) ) && node.Childs[1].Childs.Count == 1) { var arguments = node.Childs[1]; var newType = string.Equals(node.Childs[0].Value, "unchecked", StringComparison.Ordinal) ? TokenType.UncheckedScope : string.Equals(node.Childs[0].Value, "checked", StringComparison.Ordinal) ? TokenType.CheckedScope : string.Equals(node.Childs[0].Value, "typeof", StringComparison.Ordinal) ? TokenType.Typeof : string.Equals(node.Childs[0].Value, "default", StringComparison.Ordinal) ? TokenType.Default : TokenType.Call; this.stack.Pop(); this.stack.Push(new ParserNode(newType, node.Lexeme, node.Value, arguments.Childs)); } changed = true; break; case TokenType.Cond: if (op.Type != TokenType.None && this.ComputePrecedence(node.Type, op.Type) <= 0) { this.tokens.Insert(0, token); return(changed); } this.stack.Push(node); var colonIdx = this.FindCondClosingToken(); if (colonIdx < 0) { throw new ExpressionParserException(Properties.Resources.EXCEPTION_PARSER_COLONISEXPRECTED, token); } this.Expression(term: CondTerm); this.CheckAndConsumeToken(token.Position, TokenType.Colon); this.Expression(term: DefaultTerm.Union(term ?? new TokenType[0]).ToArray()); this.CombineTernary(node.Lexeme); changed = true; break; case TokenType.Lbracket: case TokenType.Lparen: case TokenType.Arguments: if (token.Type == TokenType.Lparen) { node = new ParserNode(TokenType.Group, node.Lexeme, node.Value, node.Childs); } this.stack.Push(node); while (this.Expression(node, DefaultTerm)) { this.CombineUnary(node.Lexeme); if (this.tokens.Count == 0 || this.tokens[0].Type != TokenType.Comma) { break; } this.CheckAndConsumeToken(token.Position, TokenType.Comma); } this.CheckAndConsumeToken(token.Position, TokenType.Rparen, TokenType.Rbracket); if (token.Type == TokenType.Lparen && ct == 0 && node.Childs.Count == 1 && (node.Childs.First().Type == TokenType.Identifier || node.Childs.First().Type == TokenType.Resolve)) { node = new ParserNode(TokenType.Convert, node.Lexeme, node.Value, node.Childs); if (this.Expression(node, term) && this.stack.Any(n => n.Childs == node.Childs)) { this.CombineUnary(node.Lexeme); this.stack.Pop(); this.stack.Push(node); } } changed = true; break; default: throw new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_PARSER_UNEXPECTEDTOKEN, token), token); } ct++; } catch (ExpressionParserException) { throw; } catch (System.Threading.ThreadAbortException) { throw; } catch (Exception exception) { throw new ExpressionParserException(exception.Message, exception, token); } } return(changed); }