public void DateParserLexer_PeekToken_CallsNextTokenIfCacheIsNull()
        {
            var dateParserLexer = new DateParserLexer("100");

            dateParserLexer.TokenCache = null;

            var token = dateParserLexer.PeekToken();

            Assert.Equal(LexerTokenKindEnum.TOK_INT, token.Kind);
            Assert.Equal(100, token.Value.GetValue <int>());

            Assert.Equal(token, dateParserLexer.TokenCache);
        }
Beispiel #2
0
        /// <summary>
        /// Ported from draft_t::parse_args
        /// </summary>
        protected void ParseArgs(Value args)
        {
            Match what         = Match.Empty;
            bool  checkForDate = true;

            Tmpl = new DraftXactTemplate();

            DayOfWeek?            weekday;
            DraftXactPostTemplate post = null;

            IList <Value> argsSequence = args.AsSequence;
            Value         endVal       = argsSequence.LastOrDefault();

            for (int index = 0; index < argsSequence.Count; index++)
            {
                Value val = argsSequence[index];

                if (checkForDate && (what = DateMask.Match(val.AsString)).Length > 0)
                {
                    Tmpl.Date    = TimesCommon.Current.ParseDate(what.Value);
                    checkForDate = false;
                }
                else if (checkForDate && (weekday = DateParserLexer.StringToDayOfWeek(what.Value)).HasValue)
                {
                    Date date = TimesCommon.Current.CurrentDate.AddDays(-1);
                    while (date.DayOfWeek != weekday)
                    {
                        date = date.AddDays(-1);
                    }
                    Tmpl.Date    = date;
                    checkForDate = false;
                }
                else
                {
                    string arg = val.AsString;

                    if (arg == "at")
                    {
                        if (val == endVal)
                        {
                            throw new RuntimeError(RuntimeError.ErrorMessageInvalidXactCommandArguments);
                        }
                        Tmpl.PayeeMask = new Mask(argsSequence[++index].AsString);
                    }
                    else if (arg == "to" || arg == "from")
                    {
                        if (post == null || post.AccountMask != null)
                        {
                            Tmpl.Posts.Add(post = new DraftXactPostTemplate());
                        }
                        if (val == endVal)
                        {
                            throw new RuntimeError(RuntimeError.ErrorMessageInvalidXactCommandArguments);
                        }
                        post.AccountMask = new Mask(argsSequence[++index].AsString);
                        post.From        = arg == "from";
                    }
                    else if (arg == "on")
                    {
                        if (val == endVal)
                        {
                            throw new RuntimeError(RuntimeError.ErrorMessageInvalidXactCommandArguments);
                        }
                        Tmpl.Date    = TimesCommon.Current.ParseDate(argsSequence[++index].AsString);
                        checkForDate = false;
                    }
                    else if (arg == "code")
                    {
                        if (val == endVal)
                        {
                            throw new RuntimeError(RuntimeError.ErrorMessageInvalidXactCommandArguments);
                        }
                        Tmpl.Code = argsSequence[++index].AsString;
                    }
                    else if (arg == "note")
                    {
                        if (val == endVal)
                        {
                            throw new RuntimeError(RuntimeError.ErrorMessageInvalidXactCommandArguments);
                        }
                        Tmpl.Note = argsSequence[++index].AsString;
                    }
                    else if (arg == "rest")
                    {
                        // just ignore this argument
                    }
                    else if (arg == "@" || arg == "@@")
                    {
                        Amount cost = new Amount();
                        post.CostOperator = arg;
                        if (val == endVal)
                        {
                            throw new RuntimeError(RuntimeError.ErrorMessageInvalidXactCommandArguments);
                        }
                        arg = argsSequence[++index].AsString;
                        if (!cost.Parse(ref arg, AmountParseFlagsEnum.PARSE_SOFT_FAIL | AmountParseFlagsEnum.PARSE_NO_MIGRATE))
                        {
                            throw new RuntimeError(RuntimeError.ErrorMessageInvalidXactCommandArguments);
                        }
                        post.Cost = cost;
                    }
                    else
                    {
                        // Without a preposition, it is either:
                        //
                        //  A payee, if we have not seen one
                        //  An account or an amount, if we have
                        //  An account if an amount has just been seen
                        //  An amount if an account has just been seen

                        if (Tmpl.PayeeMask == null)
                        {
                            Tmpl.PayeeMask = new Mask(arg);
                        }
                        else
                        {
                            Amount amt     = new Amount();
                            Mask   account = null;

                            string argToParse = arg;
                            if (!amt.Parse(ref argToParse, AmountParseFlagsEnum.PARSE_SOFT_FAIL | AmountParseFlagsEnum.PARSE_NO_MIGRATE))
                            {
                                account = new Mask(arg);
                            }

                            if (post == null || (account != null && post.AccountMask != null) || (account == null && post.Amount != null))
                            {
                                Tmpl.Posts.Add(post = new DraftXactPostTemplate());
                            }

                            if (account != null)
                            {
                                post.AccountMask = account;
                            }
                            else
                            {
                                post.Amount = amt;
                                post        = null; // an amount concludes this posting
                            }
                        }
                    }
                }
            }

            if (Tmpl.Posts.Any())
            {
                // A single account at the end of the line is the "from" account
                if (Tmpl.Posts.Count > 1 && Tmpl.Posts.Last().AccountMask != null && !(bool)Tmpl.Posts.Last().Amount)
                {
                    Tmpl.Posts.Last().From = true;
                }

                bool hasOnlyFrom = !Tmpl.Posts.Any(p => !p.From);
                bool hasOnlyTo   = !Tmpl.Posts.Any(p => p.From);

                if (hasOnlyFrom)
                {
                    Tmpl.Posts.Insert(0, new DraftXactPostTemplate());
                }
                else if (hasOnlyTo)
                {
                    Tmpl.Posts.Add(new DraftXactPostTemplate()
                    {
                        From = true
                    });
                }
            }
        }