예제 #1
0
        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);
        }
예제 #2
0
        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]);
                }
            }
        }
예제 #3
0
        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);
        }