Simplify parser syntax

This commit is contained in:
Guillaume Gomez 2022-02-09 20:56:37 +01:00
parent 99d552092c
commit 49297337b4
11 changed files with 50 additions and 205 deletions

View File

@ -129,17 +129,21 @@ window.initSearch = function(rawSearchIndex) {
}
function isSpecialStartCharacter(c) {
return "(<\"".indexOf(c) !== -1;
return "<\"".indexOf(c) !== -1;
}
function isEndCharacter(c) {
return "),>-".indexOf(c) !== -1;
return ",>-".indexOf(c) !== -1;
}
function isStopCharacter(c) {
return isWhitespace(c) || isEndCharacter(c);
}
function isErrorCharacter(c) {
return "()".indexOf(c) !== -1;
}
function itemTypeFromName(typename) {
for (var i = 0, len = itemTypes.length; i < len; ++i) {
if (itemTypes[i] === typename) {
@ -267,7 +271,9 @@ window.initSearch = function(rawSearchIndex) {
} else {
while (parserState.pos < parserState.length) {
var c = parserState.userQuery[parserState.pos];
if (isStopCharacter(c) || isSpecialStartCharacter(c)) {
if (isErrorCharacter(c)) {
throw new Error(`Unexpected \`${c}\``);
} else if (isStopCharacter(c) || isSpecialStartCharacter(c)) {
break;
}
// If we allow paths ("str::string" for example).
@ -285,6 +291,9 @@ window.initSearch = function(rawSearchIndex) {
if (parserState.pos < parserState.length &&
parserState.userQuery[parserState.pos] === "<")
{
if (isInGenerics) {
throw new Error("Unexpected `<` after `<`");
}
parserState.pos += 1;
getItemsBefore(query, parserState, generics, ">");
}
@ -317,12 +326,10 @@ window.initSearch = function(rawSearchIndex) {
continue;
} else if (c === ":" && isPathStart(parserState)) {
throw new Error("Unexpected `::`: paths cannot start with `::`");
} else if (c === "(" || c === ":" || isEndCharacter(c)) {
} else if (c === ":" || isEndCharacter(c)) {
var extra = "";
if (limit === ">") {
extra = "`<`";
} else if (limit === ")") {
extra = "`(`";
} else if (limit === "") {
extra = "`->`";
}
@ -356,8 +363,6 @@ window.initSearch = function(rawSearchIndex) {
} else if (c === "-" && isReturnArrow(parserState)) {
break;
}
} else if (c == "(") {
break;
} else if (c === ":" &&
parserState.typeFilter === null &&
!isPathStart(parserState))
@ -391,11 +396,7 @@ window.initSearch = function(rawSearchIndex) {
}
while (parserState.pos < parserState.length) {
c = parserState.userQuery[parserState.pos];
if (query.args.length === 0 && c === "(") {
parserState.pos += 1;
// Check for function/method arguments.
getItemsBefore(query, parserState, query.args, ")");
} else if (isReturnArrow(parserState)) {
if (isReturnArrow(parserState)) {
parserState.pos += 2;
// Get returned elements.
getItemsBefore(query, parserState, query.returned, "");
@ -419,7 +420,6 @@ window.initSearch = function(rawSearchIndex) {
userQuery: userQuery.toLowerCase(),
typeFilter: NO_TYPE_FILTER,
elems: [],
args: [],
returned: [],
// Total number of "top" elements (does not include generics).
foundElems: 0,
@ -466,19 +466,19 @@ window.initSearch = function(rawSearchIndex) {
*
* The supported syntax by this parser is as follow:
*
* ident = *1(ALPHA / DIGIT)
* path = ident *WS *(DOUBLE-COLON *WS ident)
* arg = path *WS [generics]
* ident = *(ALPHA / DIGIT)
* path = ident *(DOUBLE-COLON ident)
* arg = path [generics]
* arg-without-generic = path
* nonempty-arg-list = arg *WS *(COMMA *WS arg)
* generics = OPEN-ANGLE-BRACKET *WS nonempty-arg-list *WS CLOSE-ANGLE-BRACKET
* function-args = OPEN-PAREN *WS [nonempty-arg-list] *WS END-PAREN
* return-args = RETURN-ARROW *WS function-args
* nonempty-arg-list-without-generics = arg-without-generic *WS *(COMMA *WS arg-without-generic)
* generics = OPEN-ANGLE-BRACKET *WS nonempty-arg-list-without-generics *WS CLOSE-ANGLE-BRACKET
* return-args = RETURN-ARROW *WS nonempty-arg-list
*
* exact-search = [type-filter *WS COLON] *WS QUOTE ident QUOTE *WS [generics]
* type-search = [type-filter *WS COLON] *WS path *WS generics
* function-search = path *WS function-args *WS [return-args]
*
* query = *WS (exact-search / type-search / function-search / return-args) *WS
* query = *WS (exact-search / type-search / return-args) *WS
*
* type-filter = (
* "mod" /
@ -510,8 +510,6 @@ window.initSearch = function(rawSearchIndex) {
*
* OPEN-ANGLE-BRACKET = "<"
* CLOSE-ANGLE-BRACKET = ">"
* OPEN-PAREN = "("
* END-PAREN = ")"
* COLON = ":"
* DOUBLE-COLON = "::"
* QUOTE = %x22
@ -554,7 +552,7 @@ window.initSearch = function(rawSearchIndex) {
// case.
query.literalSearch = parserState.totalElems > 1;
}
query.foundElems = query.elems.length + query.args.length + query.returned.length;
query.foundElems = query.elems.length + query.returned.length;
if (query.foundElems === 0 && parserState.length !== 0) {
// In this case, we'll simply keep whatever was entered by the user...
createQueryElement(query, parserState, query.elems, userQuery, []);
@ -743,6 +741,11 @@ window.initSearch = function(rawSearchIndex) {
function checkGenerics(row, elem, defaultLev) {
if (row.length <= GENERICS_DATA || row[GENERICS_DATA].length === 0) {
return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
} else if (row[GENERICS_DATA].length > 0 && row[GENERICS_DATA][0][NAME] === "") {
if (row.length > GENERICS_DATA) {
return checkGenerics(row[GENERICS_DATA][0], elem, defaultLev);
}
return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
}
// The names match, but we need to be sure that all generics kinda
// match as well.
@ -751,7 +754,15 @@ window.initSearch = function(rawSearchIndex) {
var elems = {};
for (var x = 0, length = row[GENERICS_DATA].length; x < length; ++x) {
elem_name = row[GENERICS_DATA][x][NAME];
if (!elems[elem_name]) {
if (elem_name === "") {
// Pure generic, needs to check into it.
if (checkGenerics(
row[GENERICS_DATA][x], elem, MAX_LEV_DISTANCE + 1) !== 0) {
return MAX_LEV_DISTANCE + 1;
}
continue;
}
if (elems[elem_name] === undefined) {
elems[elem_name] = 0;
}
elems[elem_name] += 1;
@ -1216,9 +1227,6 @@ window.initSearch = function(rawSearchIndex) {
if (!checkArgs(parsedQuery.elems, findArg)) {
return;
}
if (!checkArgs(parsedQuery.args, findArg)) {
return;
}
if (!checkArgs(parsedQuery.returned, checkReturned)) {
return;
}
@ -1231,7 +1239,7 @@ window.initSearch = function(rawSearchIndex) {
}
function innerRunQuery() {
var elem, i, nSearchWords, in_args, in_returned, row;
var elem, i, nSearchWords, in_returned, row;
if (parsedQuery.foundElems === 1) {
if (parsedQuery.elems.length === 1) {
@ -1241,14 +1249,6 @@ window.initSearch = function(rawSearchIndex) {
// returned).
handleSingleArg(searchIndex[i], i, elem);
}
} else if (parsedQuery.args.length === 1) {
// We received one argument to check, so looking into args.
elem = parsedQuery.args[0];
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
row = searchIndex[i];
in_args = findArg(row, elem, parsedQuery.typeFilter);
addIntoResults(results_in_args, row.id, i, -1, in_args);
}
} else if (parsedQuery.returned.length === 1) {
// We received one returned argument to check, so looking into returned values.
elem = parsedQuery.returned[0];
@ -1262,9 +1262,7 @@ window.initSearch = function(rawSearchIndex) {
var container = results_others;
// In the special case where only a "returned" information is available, we want to
// put the information into the "results_returned" dict.
if (parsedQuery.returned.length !== 0 && parsedQuery.args.length === 0 &&
parsedQuery.elems.length === 0)
{
if (parsedQuery.returned.length !== 0 && parsedQuery.elems.length === 0) {
container = results_returned;
}
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {

View File

@ -19,7 +19,6 @@ const QUERY = [
const PARSED = [
{
args: [],
elems: [],
foundElems: 0,
original: "<\"P\">",
@ -29,7 +28,6 @@ const PARSED = [
error: "`\"` cannot be used in generics",
},
{
args: [],
elems: [],
foundElems: 0,
original: "\"P\" \"P\"",
@ -39,7 +37,6 @@ const PARSED = [
error: "Cannot have more than one literal search element",
},
{
args: [],
elems: [],
foundElems: 0,
original: "P \"P\"",
@ -49,7 +46,6 @@ const PARSED = [
error: "Cannot use literal search when there is more than one element",
},
{
args: [],
elems: [],
foundElems: 0,
original: "\"p\" p",
@ -59,7 +55,6 @@ const PARSED = [
error: "You cannot have more than one element if you use quotes",
},
{
args: [],
elems: [],
foundElems: 0,
original: "\"const\": p",
@ -69,7 +64,6 @@ const PARSED = [
error: "You cannot use quotes on type filter",
},
{
args: [],
elems: [],
foundElems: 0,
original: "<:a>",
@ -79,7 +73,6 @@ const PARSED = [
error: "Unexpected `:` after `<`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "<::a>",
@ -89,17 +82,15 @@ const PARSED = [
error: "Unexpected `::`: paths cannot start with `::`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "((a))",
returned: [],
typeFilter: -1,
userQuery: "((a))",
error: "Unexpected `(` after `(`",
error: "Unexpected `(`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "->,a",
@ -109,17 +100,15 @@ const PARSED = [
error: "Unexpected `,` after `->`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "(p -> p",
returned: [],
typeFilter: -1,
userQuery: "(p -> p",
error: "Unexpected `-` after `(`",
error: "Unexpected `(`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "::a::b",
@ -129,7 +118,6 @@ const PARSED = [
error: "Paths cannot start with `::`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "a::::b",
@ -139,7 +127,6 @@ const PARSED = [
error: "Unexpected `::::`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "a::b::",
@ -149,7 +136,6 @@ const PARSED = [
error: "Paths cannot end with `::`",
},
{
args: [],
elems: [],
foundElems: 0,
original: ":a",
@ -159,7 +145,6 @@ const PARSED = [
error: "Expected type filter before `:`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "a b:",
@ -169,17 +154,15 @@ const PARSED = [
error: "Unexpected `:`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "a (b:",
returned: [],
typeFilter: -1,
userQuery: "a (b:",
error: "Unexpected `:` after `(`",
error: "Unexpected `(`",
},
{
args: [],
elems: [],
foundElems: 0,
original: "{:",

View File

@ -2,7 +2,6 @@ const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo'];
const PARSED = [
{
args: [],
elems: [{
name: "foo",
fullPath: ["foo"],
@ -18,7 +17,6 @@ const PARSED = [
error: null,
},
{
args: [],
elems: [{
name: "foo",
fullPath: ["foo"],
@ -34,7 +32,6 @@ const PARSED = [
error: null,
},
{
args: [],
elems: [],
foundElems: 0,
original: "macro<f>:foo",

View File

@ -2,7 +2,6 @@ const QUERY = ['<P>', 'A<B<C<D>, E>', 'p<> u8'];
const PARSED = [
{
args: [],
elems: [{
name: "",
fullPath: [""],
@ -26,54 +25,15 @@ const PARSED = [
error: null,
},
{
args: [],
elems: [{
name: "a",
fullPath: ["a"],
pathWithoutLast: [],
pathLast: "a",
generics: [
{
name: "b",
fullPath: ["b"],
pathWithoutLast: [],
pathLast: "b",
generics: [
{
name: "c",
fullPath: ["c"],
pathWithoutLast: [],
pathLast: "c",
generics: [
{
name: "d",
fullPath: ["d"],
pathWithoutLast: [],
pathLast: "d",
generics: [],
},
],
},
{
name: "e",
fullPath: ["e"],
pathWithoutLast: [],
pathLast: "e",
generics: [],
},
],
},
],
}],
foundElems: 1,
elems: [],
foundElems: 0,
original: 'A<B<C<D>, E>',
returned: [],
typeFilter: -1,
userQuery: 'a<b<c<d>, e>',
error: null,
error: 'Unexpected `<` after `<`',
},
{
args: [],
elems: [
{
name: "p",

View File

@ -1,44 +0,0 @@
const QUERY = ['(whatever)', '(<P>)'];
const PARSED = [
{
args: [{
name: "whatever",
fullPath: ["whatever"],
pathWithoutLast: [],
pathLast: "whatever",
generics: [],
}],
elems: [],
foundElems: 1,
original: "(whatever)",
returned: [],
typeFilter: -1,
userQuery: "(whatever)",
error: null,
},
{
args: [{
name: "",
fullPath: [""],
pathWithoutLast: [],
pathLast: "",
generics: [
{
name: "p",
fullPath: ["p"],
pathWithoutLast: [],
pathLast: "p",
generics: [],
},
],
}],
elems: [],
foundElems: 1,
original: "(<P>)",
returned: [],
typeFilter: -1,
userQuery: "(<p>)",
error: null,
},
];

View File

@ -5,7 +5,6 @@ const QUERY = ['a b', 'a b', 'a,b(c)'];
const PARSED = [
{
args: [],
elems: [
{
name: "a",
@ -30,7 +29,6 @@ const PARSED = [
error: null,
},
{
args: [],
elems: [
{
name: "a",
@ -55,36 +53,12 @@ const PARSED = [
error: null,
},
{
args: [
{
name: "c",
fullPath: ["c"],
pathWithoutLast: [],
pathLast: "c",
generics: [],
},
],
elems: [
{
name: "a",
fullPath: ["a"],
pathWithoutLast: [],
pathLast: "a",
generics: [],
},
{
name: "b",
fullPath: ["b"],
pathWithoutLast: [],
pathLast: "b",
generics: [],
},
],
foundElems: 3,
elems: [],
foundElems: 0,
original: "a,b(c)",
returned: [],
typeFilter: -1,
userQuery: "a,b(c)",
error: null,
error: "Unexpected `(`",
},
];

View File

@ -2,7 +2,6 @@ const QUERY = ['R<P>'];
const PARSED = [
{
args: [],
elems: [{
name: "r",
fullPath: ["r"],

View File

@ -2,7 +2,6 @@ const QUERY = ['A::B', 'A::B,C', 'A::B<f>,C'];
const PARSED = [
{
args: [],
elems: [{
name: "a::b",
fullPath: ["a", "b"],
@ -18,7 +17,6 @@ const PARSED = [
error: null,
},
{
args: [],
elems: [
{
name: "a::b",
@ -43,7 +41,6 @@ const PARSED = [
error: null,
},
{
args: [],
elems: [
{
name: "a::b",

View File

@ -1,8 +1,7 @@
const QUERY = ['-> "p"', '("p")'];
const QUERY = ['-> "p"'];
const PARSED = [
{
args: [],
elems: [],
foundElems: 1,
original: "-> \"p\"",
@ -17,20 +16,4 @@ const PARSED = [
userQuery: "-> \"p\"",
error: null,
},
{
args: [{
name: "p",
fullPath: ["p"],
pathWithoutLast: [],
pathLast: "p",
generics: [],
}],
elems: [],
foundElems: 1,
original: "(\"p\")",
returned: [],
typeFilter: -1,
userQuery: "(\"p\")",
error: null,
},
];

View File

@ -2,7 +2,6 @@ const QUERY = ['-> <P>', '-> P'];
const PARSED = [
{
args: [],
elems: [],
foundElems: 1,
original: "-> <P>",
@ -26,7 +25,6 @@ const PARSED = [
error: null,
},
{
args: [],
elems: [],
foundElems: 1,
original: "-> P",

View File

@ -274,7 +274,7 @@ function loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate) {
"isWhitespace", "isSpecialStartCharacter", "isStopCharacter",
"parseInput", "getItemsBefore", "getNextElem", "createQueryElement",
"isReturnArrow", "isPathStart", "getStringElem", "newParsedQuery",
"itemTypeFromName", "isEndCharacter"];
"itemTypeFromName", "isEndCharacter", "isErrorCharacter"];
const functions = ["hasOwnPropertyRustdoc", "onEach"];
ALIASES = {};