public Token([NotNull] string expr, IEnumerable <IToken> tokens, TokenType type) { ArgChk.NotNull(expr, nameof(expr)); Expr = expr; Type = type; Children = tokens?.ToList(); }
public Token([NotNull] string expr, TokenType type) { ArgChk.NotNull(expr, nameof(expr)); Expr = expr; Type = type; Children = null; }
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)); }
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(); } }
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])); }
public void TestNotNull() { Assert.DoesNotThrow(() => ArgChk.NotNull(0, ArgName)); Assert.Throws <ArgumentNullException>(() => ArgChk.NotNull(_nullObj, ArgName)); Assert.Throws <ArgumentNullException>(() => ArgChk.NotNull(_nullInt, ArgName)); }