private static IQueryPart CreateQueryPart( IIndexedFieldLookup fieldLookup, QueryParserState state, QueryToken token, ITokenizer wordTokenizer, IQueryPart?currentQuery) { switch (token.TokenType) { case QueryTokenType.Text: return(ComposePart(currentQuery, CreateWordPart(token, wordTokenizer))); case QueryTokenType.FieldFilter: var(fieldId, tokenizer) = fieldLookup.GetFieldInfo(token.TokenText); var filteredPart = CreateQueryPart(fieldLookup, state, state.GetNextToken(), tokenizer, null); return(ComposePart( currentQuery, new FieldFilterQueryOperator(token.TokenText, fieldId, filteredPart))); case QueryTokenType.OrOperator: case QueryTokenType.AndOperator: case QueryTokenType.NearOperator: case QueryTokenType.PrecedingNearOperator: case QueryTokenType.PrecedingOperator: var rightPart = CreateQueryPart(fieldLookup, state, state.GetNextToken(), wordTokenizer, null); return(CombineParts(currentQuery, rightPart, token.TokenType, token.Tolerance)); case QueryTokenType.OpenBracket: var bracketedPart = state.GetTokensUntil(QueryTokenType.CloseBracket) .Aggregate((IQueryPart?)null, (current, next) => CreateQueryPart(fieldLookup, state, next, wordTokenizer, current)); if (bracketedPart == null) { throw new QueryParserException(ExceptionMessages.EmptyBracketedExpressionsAreNotSupported); } return(ComposePart(currentQuery, new BracketedQueryPart(bracketedPart))); case QueryTokenType.BeginAdjacentTextOperator: var words = state.GetTokensUntil(QueryTokenType.EndAdjacentTextOperator) .SelectMany(t => CreateWordParts(t, wordTokenizer)) .ToList(); if (words.Count == 0) { throw new QueryParserException(ExceptionMessages.EmptyAdjacentTextPartsAreNotSupported); } return(ComposePart(currentQuery, new AdjacentWordsQueryOperator(words))); default: throw new QueryParserException(ExceptionMessages.UnexpectedTokenEncountered, token.TokenType); } }
public IQuery Parse(IIndexedFieldLookup fieldLookup, string queryText, ITokenizer wordTokenizer) { if (fieldLookup is null) { throw new ArgumentNullException(nameof(fieldLookup)); } IQueryPart?rootPart = null; var state = new QueryParserState(queryText); while (state.TryGetNextToken(out var token)) { rootPart = CreateQueryPart(fieldLookup, state, token, wordTokenizer, rootPart); } return(new Query(rootPart ?? EmptyQueryPart.Instance)); }
private static IQueryPart CreateQueryPart( IIndexedFieldLookup fieldLookup, QueryParserState state, QueryToken token, ITokenizer wordTokenizer, IQueryPart rootPart) { switch (token.TokenType) { case QueryTokenType.Text: return(ComposePart(rootPart, CreateWordPart(token, wordTokenizer))); case QueryTokenType.FieldFilter: var filteredPart = CreateQueryPart(fieldLookup, state, state.GetNextToken(), wordTokenizer, null); if (fieldLookup.TryGetIdForField(token.TokenText, out var fieldId)) { return(ComposePart( rootPart, new FieldFilterQueryOperator(token.TokenText, fieldId, filteredPart))); } throw new QueryParserException(ExceptionMessages.UnknownFieldReference, token.TokenText); case QueryTokenType.OrOperator: case QueryTokenType.AndOperator: case QueryTokenType.NearOperator: case QueryTokenType.PrecedingNearOperator: case QueryTokenType.PrecedingOperator: var rightPart = CreateQueryPart(fieldLookup, state, state.GetNextToken(), wordTokenizer, null); return(CombineParts(rootPart, rightPart, token.TokenType, token.Tolerance)); case QueryTokenType.OpenBracket: var bracketedPart = state.GetTokensUntil(QueryTokenType.CloseBracket) .Aggregate((IQueryPart)null, (current, next) => CreateQueryPart(fieldLookup, state, next, wordTokenizer, current)); return(bracketedPart == null ? rootPart : ComposePart(rootPart, new BracketedQueryPart(bracketedPart))); default: throw new QueryParserException(ExceptionMessages.UnexpectedTokenEncountered, token.TokenType); } }