Ejemplo n.º 1
0
        public ExprOp ParseOrExpr(QueryLexerTokenKind tokContext)
        {
            ExprOp node = ParseAndExpr(tokContext);

            if (node != null)
            {
                while (true)
                {
                    QueryLexerToken tok = Lexer.NextToken(tokContext);
                    if (tok.Kind == QueryLexerTokenKind.TOK_OR)
                    {
                        ExprOp prev = node;
                        node       = new ExprOp(OpKindEnum.O_OR);
                        node.Left  = prev;
                        node.Right = ParseAndExpr(tokContext);
                        if (node.Right == null)
                        {
                            throw new ParseError(String.Format(ParseError.ParseError_OperatorNotFollowedByArgument, tok.Symbol()));
                        }
                    }
                    else
                    {
                        Lexer.PushToken(tok);
                        break;
                    }
                }
                return(node);
            }
            return(null); // new ExprOp();
        }
Ejemplo n.º 2
0
        public ExprOp ParseUnaryExpr(QueryLexerTokenKind tokContext)
        {
            ExprOp node = null;

            QueryLexerToken tok = Lexer.NextToken(tokContext);

            switch (tok.Kind)
            {
            case QueryLexerTokenKind.TOK_NOT:
            {
                ExprOp term = ParseQueryTerm(tokContext);
                if (term == null)
                {
                    throw new ParseError(String.Format(ParseError.ParseError_OperatorNotFollowedByArgument, tok.Symbol()));
                }

                node      = new ExprOp(OpKindEnum.O_NOT);
                node.Left = term;
                break;
            }

            default:
                Lexer.PushToken(tok);
                node = ParseQueryTerm(tokContext);
                break;
            }

            return(node);
        }
Ejemplo n.º 3
0
        public QueryLexerToken PeekToken(QueryLexerTokenKind tokContext = QueryLexerTokenKind.UNKNOWN)
        {
            if (TokenCache.Kind == QueryLexerTokenKind.UNKNOWN)
            {
                TokenCache = NextToken(tokContext);
            }

            return(TokenCache);
        }
Ejemplo n.º 4
0
        public void Unexpected()
        {
            QueryLexerTokenKind prevKind = Kind;

            Kind = QueryLexerTokenKind.UNKNOWN;

            switch (prevKind)
            {
            case QueryLexerTokenKind.END_REACHED:
                throw new ParseError(ParseError.ParseError_UnexpectedEndOfExpression);

            case QueryLexerTokenKind.TERM:
                throw new ParseError(String.Format(ParseError.ParseError_UnexpectedString, Value));

            default:
                throw new ParseError(String.Format(ParseError.ParseError_UnexpectedToken, Symbol()));
            }
        }
Ejemplo n.º 5
0
        public const char                                        InverseOne = (char)255; // -1

        public QueryLexerToken(QueryLexerTokenKind kind = QueryLexerTokenKind.UNKNOWN, string value = null) : this()
        {
            Kind  = kind;
            Value = value;
        }
Ejemplo n.º 6
0
        public QueryLexerToken NextToken(QueryLexerTokenKind tokContext = QueryLexerTokenKind.UNKNOWN)
        {
            if (TokenCache.Kind != QueryLexerTokenKind.UNKNOWN)
            {
                QueryLexerToken tok = TokenCache;
                TokenCache = new QueryLexerToken();
                return(tok);
            }

            if (ArgI == ArgEnd)
            {
                if (!BeginEnumerator.MoveNext())
                {
                    return(new QueryLexerToken(QueryLexerTokenKind.END_REACHED));
                }
                else
                {
                    SetArg();
                }
            }

resume:

            switch (Arg[ArgI])
            {
            case '\0':
                throw new InvalidOperationException();

            case '\'':
            case '"':
            case '/':
            {
                string pat          = String.Empty;
                char   closing      = Arg[ArgI];
                bool   foundClosing = false;
                for (++ArgI; ArgI != ArgEnd; ++ArgI)
                {
                    if (Arg[ArgI] == '\\')
                    {
                        if (++ArgI == ArgEnd)
                        {
                            throw new ParseError(ParseError.ParseError_UnexpectedBackslashAtEndOfPattern);
                        }
                    }
                    else if (Arg[ArgI] == closing)
                    {
                        ++ArgI;
                        foundClosing = true;
                        break;
                    }
                    pat += Arg[ArgI];
                }
                if (!foundClosing)
                {
                    throw new ParseError(String.Format(ParseError.ParseError_ExpectedSmthAtEndOfPattern, closing));
                }
                if (String.IsNullOrEmpty(pat))
                {
                    throw new ParseError(ParseError.ParseError_MatchPatternIsEmpty);
                }

                return(new QueryLexerToken(QueryLexerTokenKind.TERM, pat));
            }
            }

            if (MultipleArgs && ConsumeNextArg)
            {
                ConsumeNextArg = false;
                QueryLexerToken tok = new QueryLexerToken(QueryLexerTokenKind.TERM, Arg.Substring(ArgI));
                PrevArgI = ArgI;
                ArgI     = ArgEnd;
                return(tok);
            }

            bool consumeNext = false;

            switch (Arg[ArgI])
            {
            case '\0':
                throw new InvalidOperationException();

            case ' ':
            case '\t':
            case '\r':
            case '\n':
                if (++ArgI == ArgEnd)
                {
                    return(NextToken(tokContext));
                }
                goto resume;

            case '(':
                ++ArgI;
                if (tokContext == QueryLexerTokenKind.TOK_EXPR)
                {
                    ConsumeWhitespace = true;
                }
                return(new QueryLexerToken(QueryLexerTokenKind.LPAREN));

            case ')':
                ++ArgI;
                if (tokContext == QueryLexerTokenKind.TOK_EXPR)
                {
                    ConsumeWhitespace = false;
                }
                return(new QueryLexerToken(QueryLexerTokenKind.RPAREN));

            case '&': ++ArgI; return(new QueryLexerToken(QueryLexerTokenKind.TOK_AND));

            case '|': ++ArgI; return(new QueryLexerToken(QueryLexerTokenKind.TOK_OR));

            case '!': ++ArgI; return(new QueryLexerToken(QueryLexerTokenKind.TOK_NOT));

            case '@': ++ArgI; return(new QueryLexerToken(QueryLexerTokenKind.TOK_PAYEE));

            case '#': ++ArgI; return(new QueryLexerToken(QueryLexerTokenKind.TOK_CODE));

            case '%': ++ArgI; return(new QueryLexerToken(QueryLexerTokenKind.TOK_META));

            case '=':
                ++ArgI;
                consumeNext = true;
                return(new QueryLexerToken(QueryLexerTokenKind.TOK_EQ));

            default:
            {
                if (Arg[ArgI] == '\\')
                {
                    ++ArgI;
                    consumeNext = true;
                }

                string ident = String.Empty;
                for (; ArgI != ArgEnd; ++ArgI)
                {
                    switch (Arg[ArgI])
                    {
                    case '\0':
                        throw new InvalidOperationException();

                    case ' ':
                    case '\t':
                    case '\n':
                    case '\r':
                        if (!MultipleArgs && !ConsumeWhitespace && !ConsumeNextArg)
                        {
                            goto test_ident;
                        }
                        else
                        {
                            ident += Arg[ArgI];
                        }
                        break;

                    case ')':
                        if (!consumeNext)              // DM - the second part of condition "... && tok_context == token_t::TOK_EXPR)" is redundant since it meets an opposite condition after falling through. See query.cc:166
                        {
                            goto test_ident;
                        }
                        ident += Arg[ArgI];
                        break;

                    case '(':
                    case '&':
                    case '|':
                    case '!':
                    case '@':
                    case '#':
                    case '%':
                    case '=':
                        if (!consumeNext && tokContext != QueryLexerTokenKind.TOK_EXPR)
                        {
                            goto test_ident;
                        }
                        ident += Arg[ArgI];
                        break;

                    default:
                        ident += Arg[ArgI];
                        break;
                    }
                }
                ConsumeWhitespace = false;

test_ident:

                QueryLexerTokenKind kind;
                if (Idents.TryGetValue(ident, out kind))
                {
                    if (kind == QueryLexerTokenKind.TOK_EXPR)
                    {
                        ConsumeNextArg = true;
                    }

                    return(new QueryLexerToken(kind));
                }
                return(new QueryLexerToken(QueryLexerTokenKind.TERM, ident));
            }
            }

            // Unreachable code... return new QueryLexerToken(QueryLexerTokenKind.UNKNOWN);
        }
Ejemplo n.º 7
0
        public ExprOp ParseQueryTerm(QueryLexerTokenKind tokContext)
        {
            ExprOp node = null;

            QueryLexerToken tok = Lexer.NextToken(tokContext);

            switch (tok.Kind)
            {
            case QueryLexerTokenKind.TOK_SHOW:
            case QueryLexerTokenKind.TOK_ONLY:
            case QueryLexerTokenKind.TOK_BOLD:
            case QueryLexerTokenKind.TOK_FOR:
            case QueryLexerTokenKind.TOK_SINCE:
            case QueryLexerTokenKind.TOK_UNTIL:
            case QueryLexerTokenKind.END_REACHED:
                Lexer.PushToken(tok);
                break;

            case QueryLexerTokenKind.TOK_CODE:
            case QueryLexerTokenKind.TOK_PAYEE:
            case QueryLexerTokenKind.TOK_NOTE:
            case QueryLexerTokenKind.TOK_ACCOUNT:
            case QueryLexerTokenKind.TOK_META:
            case QueryLexerTokenKind.TOK_EXPR:
                node = ParseQueryTerm(tok.Kind);
                if (node == null)
                {
                    throw new ParseError(String.Format(ParseError.ParseError_OperatorNotFollowedByArgument, tok.Symbol()));
                }
                break;

            case QueryLexerTokenKind.TERM:
                if (String.IsNullOrEmpty(tok.Value))
                {
                    throw new InvalidOperationException("term");
                }

                switch (tokContext)
                {
                case QueryLexerTokenKind.TOK_EXPR:
                    node = new Expr(tok.Value).Op;
                    break;

                case QueryLexerTokenKind.TOK_META:
                {
                    node = new ExprOp(OpKindEnum.O_CALL);

                    ExprOp ident = new ExprOp(OpKindEnum.IDENT);
                    ident.AsIdent = "has_tag";
                    node.Left     = ident;

                    ExprOp arg1 = new ExprOp(OpKindEnum.VALUE);
                    arg1.AsValue = Value.Get(new Mask(tok.Value));

                    tok = Lexer.PeekToken(tokContext);
                    if (tok.Kind == QueryLexerTokenKind.TOK_EQ)
                    {
                        tok = Lexer.NextToken(tokContext);
                        tok = Lexer.NextToken(tokContext);
                        if (tok.Kind != QueryLexerTokenKind.TERM)
                        {
                            throw new ParseError(ParseError.ParseError_MetadataEqualityOperatorNotFollowedByTerm);
                        }

                        ExprOp arg2 = new ExprOp(OpKindEnum.VALUE);
                        if (String.IsNullOrEmpty(tok.Value))
                        {
                            throw new InvalidOperationException();
                        }
                        arg2.AsValue = Value.Get(new Mask(tok.Value));

                        node.Right = ExprOp.NewNode(OpKindEnum.O_SEQ, ExprOp.NewNode(OpKindEnum.O_CONS, arg1, arg2));
                    }
                    else
                    {
                        node.Right = arg1;
                    }
                    break;
                }

                default:
                {
                    node = new ExprOp(OpKindEnum.O_MATCH);

                    ExprOp ident = new ExprOp(OpKindEnum.IDENT);
                    switch (tokContext)
                    {
                    case QueryLexerTokenKind.TOK_ACCOUNT:
                        ident.AsIdent = "account"; break;

                    case QueryLexerTokenKind.TOK_PAYEE:
                        ident.AsIdent = "payee"; break;

                    case QueryLexerTokenKind.TOK_CODE:
                        ident.AsIdent = "code"; break;

                    case QueryLexerTokenKind.TOK_NOTE:
                        ident.AsIdent = "note"; break;

                    default:
                        throw new InvalidOperationException();
                    }

                    ExprOp mask = new ExprOp(OpKindEnum.VALUE);
                    mask.AsValue = Value.Get(new Mask(tok.Value));

                    node.Left  = ident;
                    node.Right = mask;

                    break;
                }
                }
                break;

            case QueryLexerTokenKind.LPAREN:
                node = ParseQueryExpr(tokContext, true);
                tok  = Lexer.NextToken(tokContext);
                if (tok.Kind != QueryLexerTokenKind.RPAREN)
                {
                    tok.Expected(')');
                }
                break;

            default:
                Lexer.PushToken(tok);
                break;
            }

            return(node);
        }
Ejemplo n.º 8
0
        public ExprOp ParseQueryExpr(QueryLexerTokenKind tokContext, bool subExpression = false)
        {
            ExprOp limiter = null;

            ExprOp next;

            while ((next = ParseOrExpr(tokContext)) != null)
            {
                if (limiter == null)
                {
                    limiter = next;
                }
                else
                {
                    ExprOp prev = limiter;
                    limiter       = new ExprOp(OpKindEnum.O_OR);
                    limiter.Left  = prev;
                    limiter.Right = next;
                }
            }

            if (!subExpression)
            {
                if (limiter != null)
                {
                    QueryMap.Add(QueryKindEnum.QUERY_LIMIT, new Predicate(limiter, WhatToKeep).PrintToStr());
                }

                QueryLexerToken tok = Lexer.PeekToken(tokContext);
                while (tok.Kind != QueryLexerTokenKind.END_REACHED)
                {
                    switch (tok.Kind)
                    {
                    case QueryLexerTokenKind.TOK_SHOW:
                    case QueryLexerTokenKind.TOK_ONLY:
                    case QueryLexerTokenKind.TOK_BOLD:
                    {
                        Lexer.NextToken(tokContext);

                        QueryKindEnum kind;
                        switch (tok.Kind)
                        {
                        case QueryLexerTokenKind.TOK_SHOW:
                            kind = QueryKindEnum.QUERY_SHOW;
                            break;

                        case QueryLexerTokenKind.TOK_ONLY:
                            kind = QueryKindEnum.QUERY_ONLY;
                            break;

                        case QueryLexerTokenKind.TOK_BOLD:
                            kind = QueryKindEnum.QUERY_BOLD;
                            break;

                        default:
                            throw new InvalidOperationException("To avoid using unassigned QueryKindEnum kind...");
                        }

                        ExprOp node = next = null;
                        while ((next = ParseOrExpr(tokContext)) != null)
                        {
                            if (node == null)
                            {
                                node = next;
                            }
                            else
                            {
                                ExprOp prev = node;
                                node       = new ExprOp(OpKindEnum.O_OR);
                                node.Left  = prev;
                                node.Right = next;
                            }
                        }

                        if (node != null)
                        {
                            QueryMap.Add(kind, new Predicate(node, WhatToKeep).PrintToStr());
                        }

                        break;
                    }

                    case QueryLexerTokenKind.TOK_FOR:
                    case QueryLexerTokenKind.TOK_SINCE:
                    case QueryLexerTokenKind.TOK_UNTIL:
                    {
                        tok = Lexer.NextToken(tokContext);

                        string forString = string.Empty;

                        if (tok.Kind == QueryLexerTokenKind.TOK_SINCE)
                        {
                            forString = "since";
                        }
                        else if (tok.Kind == QueryLexerTokenKind.TOK_UNTIL)
                        {
                            forString = "until";
                        }

                        Lexer.ConsumeNextArg = true;
                        tok = Lexer.PeekToken(tokContext);

                        while (tok.Kind != QueryLexerTokenKind.END_REACHED)
                        {
                            tok = Lexer.NextToken(tokContext);
                            if (tok.Kind != QueryLexerTokenKind.TERM)
                            {
                                throw new InvalidOperationException();
                            }

                            if (tok.Value == "show" || tok.Value == "bold" || tok.Value == "for" || tok.Value == "since" || tok.Value == "until")
                            {
                                Lexer.SetPrev();
                                Lexer.ConsumeNextArg = false;
                                break;
                            }

                            if (!String.IsNullOrEmpty(forString))
                            {
                                forString += " ";
                            }
                            forString += tok.Value;

                            Lexer.ConsumeNextArg = true;
                            tok = Lexer.PeekToken(tokContext);
                        }

                        if (!String.IsNullOrEmpty(forString))
                        {
                            QueryMap.Add(QueryKindEnum.QUERY_FOR, forString);
                        }
                        break;
                    }

                    default:
                        goto done;
                    }

                    tok = Lexer.PeekToken(tokContext);
                }

                done :;
            }

            return(limiter);
        }