mirror of
https://github.com/knex/knex.git
synced 2025-07-05 16:10:40 +00:00
162 lines
3.7 KiB
JavaScript
162 lines
3.7 KiB
JavaScript
// Sequence parser combinator
|
|
function s(sequence, post = (v) => v) {
|
|
return function ({ index = 0, input }) {
|
|
let position = index;
|
|
const ast = [];
|
|
|
|
for (const parser of sequence) {
|
|
const result = parser({ index: position, input });
|
|
|
|
if (result.success) {
|
|
position = result.index;
|
|
ast.push(result.ast);
|
|
} else {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return { success: true, ast: post(ast), index: position, input };
|
|
};
|
|
}
|
|
|
|
// Alternative parser combinator
|
|
function a(alternative, post = (v) => v) {
|
|
return function ({ index = 0, input }) {
|
|
for (const parser of alternative) {
|
|
const result = parser({ index, input });
|
|
|
|
if (result.success) {
|
|
return {
|
|
success: true,
|
|
ast: post(result.ast),
|
|
index: result.index,
|
|
input,
|
|
};
|
|
}
|
|
}
|
|
|
|
return { success: false, ast: null, index, input };
|
|
};
|
|
}
|
|
|
|
// Many parser combinator
|
|
function m(many, post = (v) => v) {
|
|
return function ({ index = 0, input }) {
|
|
let result = {};
|
|
let position = index;
|
|
const ast = [];
|
|
|
|
do {
|
|
result = many({ index: position, input });
|
|
|
|
if (result.success) {
|
|
position = result.index;
|
|
ast.push(result.ast);
|
|
}
|
|
} while (result.success);
|
|
|
|
if (ast.length > 0) {
|
|
return { success: true, ast: post(ast), index: position, input };
|
|
} else {
|
|
return { success: false, ast: null, index: position, input };
|
|
}
|
|
};
|
|
}
|
|
|
|
// Optional parser combinator
|
|
function o(optional, post = (v) => v) {
|
|
return function ({ index = 0, input }) {
|
|
const result = optional({ index, input });
|
|
|
|
if (result.success) {
|
|
return {
|
|
success: true,
|
|
ast: post(result.ast),
|
|
index: result.index,
|
|
input,
|
|
};
|
|
} else {
|
|
return { success: true, ast: post(null), index, input };
|
|
}
|
|
};
|
|
}
|
|
|
|
// Lookahead parser combinator
|
|
function l(lookahead, post = (v) => v) {
|
|
return function ({ index = 0, input }) {
|
|
const result = lookahead.do({ index, input });
|
|
|
|
if (result.success) {
|
|
const resultNext = lookahead.next({ index: result.index, input });
|
|
|
|
if (resultNext.success) {
|
|
return {
|
|
success: true,
|
|
ast: post(result.ast),
|
|
index: result.index,
|
|
input,
|
|
};
|
|
}
|
|
}
|
|
|
|
return { success: false, ast: null, index, input };
|
|
};
|
|
}
|
|
|
|
// Negative parser combinator
|
|
function n(negative, post = (v) => v) {
|
|
return function ({ index = 0, input }) {
|
|
const result = negative.do({ index, input });
|
|
|
|
if (result.success) {
|
|
const resultNot = negative.not({ index, input });
|
|
|
|
if (!resultNot.success) {
|
|
return {
|
|
success: true,
|
|
ast: post(result.ast),
|
|
index: result.index,
|
|
input,
|
|
};
|
|
}
|
|
}
|
|
|
|
return { success: false, ast: null, index, input };
|
|
};
|
|
}
|
|
|
|
// Token parser combinator
|
|
function t(token, post = (v) => v.text) {
|
|
return function ({ index = 0, input }) {
|
|
const result = input[index];
|
|
|
|
if (
|
|
result !== undefined &&
|
|
(token.type === undefined || token.type === result.type) &&
|
|
(token.text === undefined ||
|
|
token.text.toUpperCase() === result.text.toUpperCase())
|
|
) {
|
|
return {
|
|
success: true,
|
|
ast: post(result),
|
|
index: index + 1,
|
|
input,
|
|
};
|
|
} else {
|
|
return { success: false, ast: null, index, input };
|
|
}
|
|
};
|
|
}
|
|
|
|
// Empty parser constant
|
|
const e = function ({ index = 0, input }) {
|
|
return { success: true, ast: null, index, input };
|
|
};
|
|
|
|
// Finish parser constant
|
|
const f = function ({ index = 0, input }) {
|
|
return { success: index === input.length, ast: null, index, input };
|
|
};
|
|
|
|
module.exports = { s, a, m, o, l, n, t, e, f };
|