diff --git a/query_language/grammar.js b/query_language/grammar.js --- a/query_language/grammar.js +++ b/query_language/grammar.js @@ -14,7 +14,7 @@ name: 'swh_search_ql', rules: { - query: $ => $.filters, + query: $ => seq($.filters, optional($.sortBy) ,optional($.limit)), filters: $ => choice( prec.left(PRECEDENCE.and, @@ -37,14 +37,30 @@ $.filter ), + sortBy: $ => seq($.sortByField, $.sortByOp, $.sortByVal), + sortByField: $ => token('sort_by'), + sortByOp: $ => $.equalOp, + sortByVal: $ => createArray(optionalWrapWith($.sortByOptions, ["'", '"'])), + sortByOptions: $ => seq(optional(token.immediate('-')) ,choice( + 'visits', + 'last_visit', + 'last_eventful_visit', + 'last_revision', + 'last_release', + 'created', + 'modified', + 'published' + )), + + limit: $ => seq('limit', $.equalOp, $.number), + filter: $ => choice( $.patternFilter, $.booleanFilter, $.numericFilter, $.boundedListFilter, $.unboundedListFilter, - $.dateFilter, - $.limitFilter + $.dateFilter ), patternFilter: $ => seq($.patternField, $.patternOp, $.patternVal), @@ -62,7 +78,7 @@ numericOp: $ => $.rangeOp, numberVal: $ => $.number, - boundedListFilter: $ => choice($.visitTypeFilter, $.sortByFilter), + boundedListFilter: $ => choice($.visitTypeFilter), visitTypeFilter: $ => seq($.visitTypeField, $.visitTypeOp, $.visitTypeVal), visitTypeField: $ => token(choice('visit_type')), @@ -83,7 +99,7 @@ "tar" ), // TODO: fetch this list dynamically from other swh services? - sortByFilter: $ => seq($.sortByField, $.sortByOp, $.sortByVal), + sortBy: $ => seq($.sortByField, $.sortByOp, $.sortByVal), sortByField: $ => token(choice('sort_by')), sortByOp: $ => $.equalOp, sortByVal: $ => createArray(optionalWrapWith($.sortByOptions, ["'", '"'])), @@ -119,7 +135,7 @@ dateOp: $ => $.rangeOp, dateVal: $ => $.isoDateTime, - limitFilter: $ => seq('limit', $.equalOp, $.number), + limit: $ => seq('limit', $.equalOp, $.number), rangeOp: $ => token(choice('<', '<=', '=', '!=', '>=', '>')), diff --git a/query_language/test/corpus/combinations.txt b/query_language/test/corpus/combinations.txt --- a/query_language/test/corpus/combinations.txt +++ b/query_language/test/corpus/combinations.txt @@ -19,18 +19,17 @@ ================== 10 origins with latest revision after 2020-01-01 ================== -last_revision > 2020-01-01 and limit = 10 +last_revision > 2020-01-01 limit = 10 --- - -(query (filters (filters (filter (dateFilter (dateField) (dateOp (rangeOp)) (dateVal (isoDateTime))))) (and) (filters (filter (limitFilter (equalOp) (number)))))) +(query (filters (filter (dateFilter (dateField) (dateOp (rangeOp)) (dateVal (isoDateTime))))) (limit (equalOp) (number))) ================== -Origins with last visit date not in 2020-2021 +Origins with last visit date not in 2020-2021 (sorted by number of visits) ================== -last_visit > 2021-01-01 or last_visit < 2020-01-01 +last_visit > 2021-01-01 or last_visit < 2020-01-01 sort_by = ["visits"] --- -(query (filters (filters (filter (dateFilter (dateField) (dateOp (rangeOp)) (dateVal (isoDateTime))))) (or) (filters (filter (dateFilter (dateField) (dateOp (rangeOp)) (dateVal (isoDateTime))))))) +(query (filters (filters (filter (dateFilter (dateField) (dateOp (rangeOp)) (dateVal (isoDateTime))))) (or) (filters (filter (dateFilter (dateField) (dateOp (rangeOp)) (dateVal (isoDateTime)))))) (sortBy (sortByField) (sortByOp (equalOp)) (sortByVal (sortByOptions)))) ================== Unvisited origins with kubernetes in metadata or minikube in url @@ -59,7 +58,7 @@ (query (filters (filters (filters (filters (filter (patternFilter (patternField) (patternOp (equalOp)) (patternVal (string (singleWord)))))) (or) (filters (filter (boundedListFilter (visitTypeFilter (visitTypeField) (visitTypeOp (equalOp)) (visitTypeVal (visitTypeOptions)))))))) (and) (filters (filter (unboundedListFilter (listField) (listOp (choiceOp)) (listVal (string (stringContent)))))))) ================== -Origins with 'and' and 'or' inside filter values +Origins with `and` and `or` inside filter values ================== (origin = "foo and bar or baz") ---