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(); }
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); }
public QueryLexerToken PeekToken(QueryLexerTokenKind tokContext = QueryLexerTokenKind.UNKNOWN) { if (TokenCache.Kind == QueryLexerTokenKind.UNKNOWN) { TokenCache = NextToken(tokContext); } return(TokenCache); }
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())); } }
public const char InverseOne = (char)255; // -1 public QueryLexerToken(QueryLexerTokenKind kind = QueryLexerTokenKind.UNKNOWN, string value = null) : this() { Kind = kind; Value = value; }
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); }
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); }
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); }