コード例 #1
0
        public void PushToken(LexerToken tok)
        {
            if (TokenCache.Kind != LexerTokenKindEnum.UNKNOWN)
            {
                throw new InvalidOperationException("Unexpected state");
            }

            TokenCache = tok;
        }
コード例 #2
0
ファイル: DateParser.cs プロジェクト: maznabili/nledger
        private void DetermineWhen(ref LexerToken tok, ref DateSpecifier specifier)
        {
            Date today = TimesCommon.Current.CurrentDate;

            specifier = specifier ?? new DateSpecifier();

            switch (tok.Kind)
            {
            case LexerTokenKindEnum.TOK_DATE:
                specifier = tok.Value.GetValue <DateSpecifier>();
                break;

            case LexerTokenKindEnum.TOK_INT:
            {
                int amount = tok.Value.GetValue <int>();
                int adjust = 0;

                tok = Lexer.PeekToken();
                LexerTokenKindEnum kind = tok.Kind;
                switch (kind)
                {
                case LexerTokenKindEnum.TOK_YEAR:
                case LexerTokenKindEnum.TOK_YEARS:
                case LexerTokenKindEnum.TOK_QUARTER:
                case LexerTokenKindEnum.TOK_QUARTERS:
                case LexerTokenKindEnum.TOK_MONTH:
                case LexerTokenKindEnum.TOK_MONTHS:
                case LexerTokenKindEnum.TOK_WEEK:
                case LexerTokenKindEnum.TOK_WEEKS:
                case LexerTokenKindEnum.TOK_DAY:
                case LexerTokenKindEnum.TOK_DAYS:
                    Lexer.NextToken();
                    tok = Lexer.NextToken();
                    switch (tok.Kind)
                    {
                    case LexerTokenKindEnum.TOK_AGO:
                        adjust = -1;
                        break;

                    case LexerTokenKindEnum.TOK_HENCE:
                        adjust = 1;
                        break;

                    default:
                        tok.Unexpected();
                        break;
                    }
                    break;

                default:
                    break;
                }

                Date when = today;

                switch (kind)
                {
                case LexerTokenKindEnum.TOK_YEAR:
                case LexerTokenKindEnum.TOK_YEARS:
                    when = when.AddYears(amount * adjust);
                    break;

                case LexerTokenKindEnum.TOK_QUARTER:
                case LexerTokenKindEnum.TOK_QUARTERS:
                    when = when.AddMonths(amount * 3 * adjust);
                    break;

                case LexerTokenKindEnum.TOK_MONTH:
                case LexerTokenKindEnum.TOK_MONTHS:
                    when = when.AddMonths(amount * adjust);
                    break;

                case LexerTokenKindEnum.TOK_WEEK:
                case LexerTokenKindEnum.TOK_WEEKS:
                    when = when.AddDays(amount * 7 * adjust);
                    break;

                case LexerTokenKindEnum.TOK_DAY:
                case LexerTokenKindEnum.TOK_DAYS:
                    when = when.AddDays(amount * adjust);
                    break;

                default:
                    if (amount > 31)
                    {
                        specifier.Year = amount;
                    }
                    else
                    {
                        specifier.Day = amount;
                    }
                    break;
                }

                if (adjust != 0)
                {
                    specifier = new DateSpecifier(when);
                }
                break;
            }

            case LexerTokenKindEnum.TOK_THIS:
            case LexerTokenKindEnum.TOK_NEXT:
            case LexerTokenKindEnum.TOK_LAST:
            {
                int adjust = 0;
                if (tok.Kind == LexerTokenKindEnum.TOK_NEXT)
                {
                    adjust = 1;
                }
                else if (tok.Kind == LexerTokenKindEnum.TOK_LAST)
                {
                    adjust = -1;
                }

                tok = Lexer.NextToken();
                switch (tok.Kind)
                {
                case LexerTokenKindEnum.TOK_A_MONTH:
                {
                    Date temp = new Date(today.Year, tok.Value.GetValue <int>(), 1);
                    temp      = temp.AddYears(adjust);
                    specifier = new DateSpecifier(temp.Year, (MonthEnum)temp.Month);
                    break;
                }

                case LexerTokenKindEnum.TOK_A_WDAY:
                {
                    Date temp = DateDuration.FindNearest(today, SkipQuantumEnum.WEEKS);
                    while (temp.DayOfWeek != tok.Value.GetValue <DayOfWeek>())
                    {
                        temp = temp.AddDays(1);
                    }
                    temp      = temp.AddDays(7 * adjust);
                    specifier = new DateSpecifier(temp);
                    break;
                }

                case LexerTokenKindEnum.TOK_YEAR:
                {
                    Date temp = today;
                    temp      = temp.AddYears(adjust);
                    specifier = new DateSpecifier(temp.Year);
                    break;
                }

                case LexerTokenKindEnum.TOK_QUARTER:
                {
                    Date baseDate = DateDuration.FindNearest(today, SkipQuantumEnum.QUARTERS);
                    Date temp     = default(Date);
                    if (adjust < 0)
                    {
                        temp = baseDate.AddMonths(3 * adjust);
                    }
                    else if (adjust == 0)
                    {
                        temp = baseDate.AddMonths(3);
                    }
                    else if (adjust > 0)
                    {
                        baseDate = baseDate.AddMonths(3 * adjust);
                        temp     = baseDate.AddMonths(3 * adjust);
                    }
                    specifier = new DateSpecifier(adjust < 0 ? temp : baseDate);
                    break;
                }

                case LexerTokenKindEnum.TOK_WEEK:
                {
                    Date baseDate = DateDuration.FindNearest(today, SkipQuantumEnum.WEEKS);
                    Date temp     = default(Date);
                    if (adjust < 0)
                    {
                        temp = baseDate.AddDays(7 * adjust);
                    }
                    else if (adjust == 0)
                    {
                        temp = baseDate.AddDays(7);
                    }
                    else if (adjust > 0)
                    {
                        baseDate = baseDate.AddDays(7 * adjust);
                        temp     = baseDate.AddDays(7 * adjust);
                    }
                    specifier = new DateSpecifier(adjust < 0 ? temp : baseDate);
                    break;
                }

                case LexerTokenKindEnum.TOK_DAY:
                {
                    Date temp = today;
                    temp      = temp.AddDays(adjust);
                    specifier = new DateSpecifier(temp);
                    break;
                }

                case LexerTokenKindEnum.TOK_MONTH:
                default:
                {
                    Date temp = today;
                    temp      = temp.AddMonths(adjust);
                    specifier = new DateSpecifier(temp.Year, (MonthEnum)temp.Month);
                    break;
                }
                }
                break;
            }

            case LexerTokenKindEnum.TOK_A_MONTH:
                specifier.Month = tok.Value.GetValue <MonthEnum>();
                tok             = Lexer.PeekToken();
                switch (tok.Kind)
                {
                case LexerTokenKindEnum.TOK_INT:
                    specifier.Year = tok.Value.GetValue <int>();
                    break;

                case LexerTokenKindEnum.END_REACHED:
                    break;

                default:
                    break;
                }
                break;

            case LexerTokenKindEnum.TOK_A_WDAY:
                specifier.WDay = tok.Value.GetValue <DayOfWeek>();
                break;

            case LexerTokenKindEnum.TOK_TODAY:
                specifier = new DateSpecifier(today);
                break;

            case LexerTokenKindEnum.TOK_TOMORROW:
                specifier = new DateSpecifier(today.AddDays(1));
                break;

            case LexerTokenKindEnum.TOK_YESTERDAY:
                specifier = new DateSpecifier(today.AddDays(-1));
                break;

            default:
                tok.Unexpected();
                break;
            }
        }
コード例 #3
0
ファイル: DateParser.cs プロジェクト: maznabili/nledger
        /// <summary>
        /// Ported from date_parser_t::parse()
        /// </summary>
        public DateInterval Parse()
        {
            DateSpecifier sinceSpecifier     = null;
            DateSpecifier untilSpecifier     = null;
            DateSpecifier inclusionSpecifier = null;

            DateInterval period       = new DateInterval();
            Date         today        = TimesCommon.Current.CurrentDate;
            bool         endInclusive = false;

            for (LexerToken tok = Lexer.NextToken(); tok.Kind != LexerTokenKindEnum.END_REACHED; tok = Lexer.NextToken())
            {
                switch (tok.Kind)
                {
                case LexerTokenKindEnum.TOK_DATE:
                case LexerTokenKindEnum.TOK_INT:
                case LexerTokenKindEnum.TOK_A_MONTH:
                case LexerTokenKindEnum.TOK_A_WDAY:
                    DetermineWhen(ref tok, ref inclusionSpecifier);
                    break;

                case LexerTokenKindEnum.TOK_DASH:
                    if (inclusionSpecifier != null)
                    {
                        sinceSpecifier     = inclusionSpecifier;
                        inclusionSpecifier = null;
                        tok = Lexer.NextToken();
                        DetermineWhen(ref tok, ref untilSpecifier);

                        // The dash operator is special: it has an _inclusive_ end.
                        endInclusive = true;
                    }
                    else
                    {
                        tok.Unexpected();
                    }
                    break;

                case LexerTokenKindEnum.TOK_SINCE:
                    if (sinceSpecifier != null)
                    {
                        tok.Unexpected();
                    }
                    else
                    {
                        tok = Lexer.NextToken();
                        DetermineWhen(ref tok, ref sinceSpecifier);
                    }
                    break;

                case LexerTokenKindEnum.TOK_UNTIL:
                    if (untilSpecifier != null)
                    {
                        tok.Unexpected();
                    }
                    else
                    {
                        tok = Lexer.NextToken();
                        DetermineWhen(ref tok, ref untilSpecifier);
                    }
                    break;

                case LexerTokenKindEnum.TOK_IN:
                    if (inclusionSpecifier != null)
                    {
                        tok.Unexpected();
                    }
                    else
                    {
                        tok = Lexer.NextToken();
                        DetermineWhen(ref tok, ref inclusionSpecifier);
                    }
                    break;

                case LexerTokenKindEnum.TOK_THIS:
                case LexerTokenKindEnum.TOK_NEXT:
                case LexerTokenKindEnum.TOK_LAST:
                {
                    int adjust = 0;
                    if (tok.Kind == LexerTokenKindEnum.TOK_NEXT)
                    {
                        adjust = 1;
                    }
                    else if (tok.Kind == LexerTokenKindEnum.TOK_LAST)
                    {
                        adjust = -1;
                    }

                    tok = Lexer.NextToken();
                    switch (tok.Kind)
                    {
                    case LexerTokenKindEnum.TOK_INT:
                    {
                        int amount = tok.Value.GetValue <int>();

                        Date baseDate = today;
                        Date end      = today;

                        if (adjust == 0)
                        {
                            adjust = 1;
                        }

                        tok = Lexer.NextToken();
                        switch (tok.Kind)
                        {
                        case LexerTokenKindEnum.TOK_YEARS:
                            baseDate = baseDate.AddYears(amount * adjust);
                            break;

                        case LexerTokenKindEnum.TOK_QUARTERS:
                            baseDate = baseDate.AddMonths(amount * adjust * 3);
                            break;

                        case LexerTokenKindEnum.TOK_MONTHS:
                            baseDate = baseDate.AddMonths(amount * adjust);
                            break;

                        case LexerTokenKindEnum.TOK_WEEKS:
                            baseDate = baseDate.AddDays(amount * adjust * 7);
                            break;

                        case LexerTokenKindEnum.TOK_DAYS:
                            baseDate = baseDate.AddDays(amount * adjust);
                            break;

                        default:
                            tok.Unexpected();
                            break;
                        }

                        if (adjust > 0)
                        {
                            Date temp = baseDate;
                            baseDate = end;
                            end      = temp;
                        }

                        sinceSpecifier = new DateSpecifier(baseDate);
                        untilSpecifier = new DateSpecifier(end);
                        break;
                    }

                    case LexerTokenKindEnum.TOK_A_MONTH:
                    {
                        DetermineWhen(ref tok, ref inclusionSpecifier);

                        Date temp = new Date(today.Year, (int)inclusionSpecifier.Month, 1);
                        temp = temp.AddYears(adjust);
                        inclusionSpecifier = new DateSpecifier(temp.Year, (MonthEnum)temp.Month);
                        break;
                    }

                    case LexerTokenKindEnum.TOK_A_WDAY:
                    {
                        DetermineWhen(ref tok, ref inclusionSpecifier);

                        Date temp = DateDuration.FindNearest(today, SkipQuantumEnum.WEEKS);
                        while (temp.DayOfWeek != inclusionSpecifier.WDay)
                        {
                            temp = temp.AddDays(1);
                        }
                        temp = temp.AddDays(7 * adjust);
                        inclusionSpecifier = new DateSpecifier(temp);
                        break;
                    }

                    case LexerTokenKindEnum.TOK_YEAR:
                    {
                        Date temp = today;
                        temp = temp.AddYears(adjust);
                        inclusionSpecifier = new DateSpecifier(temp.Year);
                        break;
                    }

                    case LexerTokenKindEnum.TOK_QUARTER:
                    {
                        Date baseDate = DateDuration.FindNearest(today, SkipQuantumEnum.QUARTERS);
                        Date temp;
                        if (adjust < 0)
                        {
                            temp = baseDate.AddMonths(3 * adjust);
                        }
                        else if (adjust == 0)
                        {
                            temp = baseDate.AddMonths(3);
                        }
                        else
                        {
                            baseDate = baseDate.AddMonths(3 * adjust);
                            temp     = baseDate.AddMonths(3 * adjust);
                        }
                        sinceSpecifier = new DateSpecifier(adjust < 0 ? temp : baseDate);
                        untilSpecifier = new DateSpecifier(adjust < 0 ? baseDate : temp);
                        break;
                    }

                    case LexerTokenKindEnum.TOK_WEEK:
                    {
                        Date baseDate = DateDuration.FindNearest(today, SkipQuantumEnum.WEEKS);
                        Date temp;
                        if (adjust < 0)
                        {
                            temp = baseDate.AddDays(7 * adjust);
                        }
                        else if (adjust == 0)
                        {
                            temp = baseDate.AddDays(7);
                        }
                        else
                        {
                            baseDate = baseDate.AddDays(7 * adjust);
                            temp     = baseDate.AddDays(7 * adjust);
                        }
                        sinceSpecifier = new DateSpecifier(adjust < 0 ? temp : baseDate);
                        untilSpecifier = new DateSpecifier(adjust < 0 ? baseDate : temp);
                        break;
                    }

                    case LexerTokenKindEnum.TOK_DAY:
                    {
                        Date temp = today;
                        temp = temp.AddDays(adjust);
                        inclusionSpecifier = new DateSpecifier(temp);
                        break;
                    }

                    case LexerTokenKindEnum.TOK_MONTH:
                    default:
                    {
                        Date temp = today;
                        temp = temp.AddMonths(adjust);
                        inclusionSpecifier = new DateSpecifier(temp.Year, (MonthEnum)temp.Month);
                        break;
                    }
                    }
                    break;
                }

                case LexerTokenKindEnum.TOK_TODAY:
                    inclusionSpecifier = new DateSpecifier(today);
                    break;

                case LexerTokenKindEnum.TOK_TOMORROW:
                    inclusionSpecifier = new DateSpecifier(today.AddDays(1));
                    break;

                case LexerTokenKindEnum.TOK_YESTERDAY:
                    inclusionSpecifier = new DateSpecifier(today.AddDays(-1));
                    break;

                case LexerTokenKindEnum.TOK_EVERY:
                    tok = Lexer.NextToken();
                    if (tok.Kind == LexerTokenKindEnum.TOK_INT)
                    {
                        int quantity = tok.Value.GetValue <int>();
                        tok = Lexer.NextToken();
                        switch (tok.Kind)
                        {
                        case LexerTokenKindEnum.TOK_YEARS:
                            period.Duration = new DateDuration(SkipQuantumEnum.YEARS, quantity);
                            break;

                        case LexerTokenKindEnum.TOK_QUARTERS:
                            period.Duration = new DateDuration(SkipQuantumEnum.QUARTERS, quantity);
                            break;

                        case LexerTokenKindEnum.TOK_MONTHS:
                            period.Duration = new DateDuration(SkipQuantumEnum.MONTHS, quantity);
                            break;

                        case LexerTokenKindEnum.TOK_WEEKS:
                            period.Duration = new DateDuration(SkipQuantumEnum.WEEKS, quantity);
                            break;

                        case LexerTokenKindEnum.TOK_DAYS:
                            period.Duration = new DateDuration(SkipQuantumEnum.DAYS, quantity);
                            break;

                        default:
                            tok.Unexpected();
                            break;
                        }
                    }
                    else
                    {
                        switch (tok.Kind)
                        {
                        case LexerTokenKindEnum.TOK_YEAR:
                            period.Duration = new DateDuration(SkipQuantumEnum.YEARS, 1);
                            break;

                        case LexerTokenKindEnum.TOK_QUARTER:
                            period.Duration = new DateDuration(SkipQuantumEnum.QUARTERS, 1);
                            break;

                        case LexerTokenKindEnum.TOK_MONTH:
                            period.Duration = new DateDuration(SkipQuantumEnum.MONTHS, 1);
                            break;

                        case LexerTokenKindEnum.TOK_WEEK:
                            period.Duration = new DateDuration(SkipQuantumEnum.WEEKS, 1);
                            break;

                        case LexerTokenKindEnum.TOK_DAY:
                            period.Duration = new DateDuration(SkipQuantumEnum.DAYS, 1);
                            break;

                        default:
                            tok.Unexpected();
                            break;
                        }
                    }
                    break;

                case LexerTokenKindEnum.TOK_YEARLY:
                    period.Duration = new DateDuration(SkipQuantumEnum.YEARS, 1);
                    break;

                case LexerTokenKindEnum.TOK_QUARTERLY:
                    period.Duration = new DateDuration(SkipQuantumEnum.QUARTERS, 1);
                    break;

                case LexerTokenKindEnum.TOK_BIMONTHLY:
                    period.Duration = new DateDuration(SkipQuantumEnum.MONTHS, 2);
                    break;

                case LexerTokenKindEnum.TOK_MONTHLY:
                    period.Duration = new DateDuration(SkipQuantumEnum.MONTHS, 1);
                    break;

                case LexerTokenKindEnum.TOK_BIWEEKLY:
                    period.Duration = new DateDuration(SkipQuantumEnum.WEEKS, 2);
                    break;

                case LexerTokenKindEnum.TOK_WEEKLY:
                    period.Duration = new DateDuration(SkipQuantumEnum.WEEKS, 1);
                    break;

                case LexerTokenKindEnum.TOK_DAILY:
                    period.Duration = new DateDuration(SkipQuantumEnum.DAYS, 1);
                    break;

                default:
                    tok.Unexpected();
                    break;
                }
            }

            if (sinceSpecifier != null || untilSpecifier != null)
            {
                DateRange range = new DateRange(sinceSpecifier, untilSpecifier)
                {
                    EndExclusive = endInclusive
                };
                period.Range = new DateSpecifierOrRange(range);
            }
            else if (inclusionSpecifier != null)
            {
                period.Range = new DateSpecifierOrRange(inclusionSpecifier);
            }
            else
            {
                /* otherwise, it's something like "monthly", with no date reference */
            }

            return(period);
        }
コード例 #4
0
        public LexerToken NextToken()
        {
            if (TokenCache != null && TokenCache.Kind != LexerTokenKindEnum.UNKNOWN)
            {
                LexerToken tok = TokenCache;
                TokenCache = new LexerToken();
                return(tok);
            }

            Begin = Begin.TrimStart();

            if (String.IsNullOrEmpty(Begin))
            {
                return(new LexerToken(LexerTokenKindEnum.END_REACHED));
            }

            switch (Begin[0])
            {
            case '/': return(new LexerToken(LexerTokenKindEnum.TOK_SLASH));

            case '-': return(new LexerToken(LexerTokenKindEnum.TOK_DASH));

            case '.': return(new LexerToken(LexerTokenKindEnum.TOK_DOT));

            default: break;
            }

            // If the first character is a digit, try parsing the whole argument as a
            // date using the typical date formats.  This allows not only dates like
            // "2009/08/01", but also dates that fit the user's --input-date-format,
            // assuming their format fits in one argument and begins with a digit.
            if (Char.IsDigit(Begin[0]))
            {
                int    pos          = Begin.IndexOf(" ");
                string possibleDate = Begin.Substring(0, pos > 0 ? pos : Begin.Length);

                try
                {
                    DateTraits dateTraits;
                    Date       when = TimesCommon.Current.ParseDateMask(possibleDate, out dateTraits);
                    if (!when.IsNotADate())
                    {
                        Begin = Begin.Substring(possibleDate.Length);
                        return(new LexerToken(LexerTokenKindEnum.TOK_DATE, new BoostVariant(new DateSpecifier(when, dateTraits))));
                    }
                }
                catch (DateError)
                {
                    if (possibleDate.IndexOfAny(PossibleDateContains) >= 0)
                    {
                        throw;
                    }
                }
            }

            string start = Begin;

            bool alNul = Char.IsLetterOrDigit(Begin[0]);
            int  pos1  = 0;

            while (pos1 < Begin.Length && !Char.IsWhiteSpace(Begin[pos1]) &&
                   ((alNul && Char.IsLetterOrDigit(Begin[pos1])) || (!alNul && !Char.IsLetterOrDigit(Begin[pos1]))))
            {
                pos1++;
            }
            string term = Begin.Substring(0, pos1);

            Begin = Begin.Substring(pos1);

            if (!String.IsNullOrEmpty(term))
            {
                if (Char.IsDigit(term[0]))
                {
                    return(new LexerToken(LexerTokenKindEnum.TOK_INT, new BoostVariant(Int32.Parse(term))));
                }
                else if (Char.IsLetter(term[0]))
                {
                    term = term.ToLower();

                    MonthEnum?month = StringToMonthsOfYear(term);
                    if (month != null)
                    {
                        return(new LexerToken(LexerTokenKindEnum.TOK_A_MONTH, new BoostVariant(month.Value)));
                    }

                    DayOfWeek?wday = StringToDayOfWeek(term);
                    if (wday != null)
                    {
                        return(new LexerToken(LexerTokenKindEnum.TOK_A_WDAY, new BoostVariant(wday.Value)));
                    }

                    LexerTokenKindEnum stringTokenEnum;
                    if (StringTokens.TryGetValue(term, out stringTokenEnum))
                    {
                        return(new LexerToken(stringTokenEnum));
                    }
                }
                else
                {
                    LexerToken.Expected(default(char), term[0]);
                    Begin = start.Substring(1);
                }
            }
            else
            {
                LexerToken.Expected(default(char), term[0]);
            }

            return(new LexerToken(LexerTokenKindEnum.UNKNOWN, new BoostVariant(term)));
        }