示例#1
0
 public Token([NotNull] string expr, IEnumerable <IToken> tokens, TokenType type)
 {
     ArgChk.NotNull(expr, nameof(expr));
     Expr     = expr;
     Type     = type;
     Children = tokens?.ToList();
 }
示例#2
0
 public Token([NotNull] string expr, TokenType type)
 {
     ArgChk.NotNull(expr, nameof(expr));
     Expr     = expr;
     Type     = type;
     Children = null;
 }
示例#3
0
 internal Expr([NotNull] IToken root, [NotNull] IExprContext context)
 {
     ArgChk.NotNull(root, nameof(root));
     ArgChk.NotNull(context, nameof(context));
     _root     = root;
     _context  = context;
     FuncNames = new HashSet <string>(GetFunctionName(_root));
     VarNames  = new HashSet <string>(GetVariableName(_root));
 }
示例#4
0
        internal IConvertible EvalToken([NotNull] IToken token)
        {
            ArgChk.NotNull(token, nameof(token));

            switch (token.Type)
            {
            case TokenType.LiteralNumber:
            {
                ArgChk.NullOrEmpty(token.Children, nameof(token.Children));
                return(double.Parse(token.Expr));
            }

            case TokenType.Identifier:
            {
                ArgChk.NullOrEmpty(token.Children, nameof(token.Children));
                return(_context.GetVar(token.Expr)(_context));
            }

            case TokenType.Func:
            {
                // parse child argument
                var args = new List <IConvertible>();
                if (token.Children?.Any() ?? false)
                {
                    var arg = new Queue <IToken>(token.Children);
                    while (arg.Count > 0)
                    {
                        var curArg = arg.Dequeue();
                        if (curArg.Type != TokenType.FuncArgs)
                        {
                            args.Add(EvalToken(curArg));
                        }
                        else
                        {
                            ArgChk.NotNullOrEmpty(curArg.Children, nameof(curArg.Children));
                            foreach (var c in curArg.Children)
                            {
                                arg.Enqueue(c);
                            }
                        }
                    }
                }
                return(_context.GetFunc(token.Expr)(_context, args));
            }

            case TokenType.FuncArgs:
                throw new Sprache.ParseException("unexpected comma");

            case TokenType.UnaryPlus:
            case TokenType.UnaryNoOp:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 1);
                return(Arg(token, 0));
            }

            case TokenType.UnaryMinus:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 1);
                return(-ArgDouble(token, 0));
            }

            case TokenType.UnaryNot:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 1);
                return(!ArgBool(token, 0));
            }

            case TokenType.BinaryPow:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(Math.Pow(ArgDouble(token, 0), ArgDouble(token, 1)));
            }

            case TokenType.BinaryMul:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                var arg0 = ArgDouble(token, 0);
                // short circuit!!
                if (_context.DoubleNearZero(arg0))
                {
                    return(0);
                }
                return(arg0 * ArgDouble(token, 1));
            }

            case TokenType.BinaryDiv:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgDouble(token, 0) / ArgDouble(token, 1));
            }

            case TokenType.BinaryDivInt:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                var arg1 = ArgInteger(token, 1);
                var arg0 = ArgInteger(token, 0);
                if (arg1 == 0)
                {
                    return((double)arg0 / arg1);
                }
                return(ArgInteger(token, 0) / arg1);
            }

            case TokenType.BinaryPlus:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgDouble(token, 0) + ArgDouble(token, 1));
            }

            case TokenType.BinaryMinus:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgDouble(token, 0) - ArgDouble(token, 1));
            }

            case TokenType.BinaryLt:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgDouble(token, 0) < ArgDouble(token, 1));
            }

            case TokenType.BinaryLe:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgDouble(token, 0) <= ArgDouble(token, 1));
            }

            case TokenType.BinaryGt:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgDouble(token, 0) > ArgDouble(token, 1));
            }

            case TokenType.BinaryGe:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgDouble(token, 0) >= ArgDouble(token, 1));
            }

            case TokenType.BinaryEq:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(_context.DoubleNearZero(ArgDouble(token, 0) - ArgDouble(token, 1)));
            }

            case TokenType.BinaryNe:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(!_context.DoubleNearZero(ArgDouble(token, 0) - ArgDouble(token, 1)));
            }

            case TokenType.BinaryAnd:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgBool(token, 0) && ArgBool(token, 1));
            }

            case TokenType.BinaryOr:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 2);
                return(ArgBool(token, 0) || ArgBool(token, 1));
            }

            case TokenType.TrinayCondition:
            {
                ExpectArgSize(token.Type.ToString(), token.Children, 3);
                return(ArgBool(token, 0) ? Arg(token, 1) : Arg(token, 2));
            }

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
示例#5
0
 internal IConvertible Arg([NotNull] IToken token, int idx)
 {
     ArgChk.NotNull(token, nameof(token));
     ArgChk.InBound(idx, nameof(idx), token.Children);
     return(EvalToken(token.Children[idx]));
 }
示例#6
0
 public void TestNotNull()
 {
     Assert.DoesNotThrow(() => ArgChk.NotNull(0, ArgName));
     Assert.Throws <ArgumentNullException>(() => ArgChk.NotNull(_nullObj, ArgName));
     Assert.Throws <ArgumentNullException>(() => ArgChk.NotNull(_nullInt, ArgName));
 }