2024-03-18 13:20:47 +01:00
|
|
|
import { matchAll, matchAny, matchNone, matchNot } from './boolean';
|
|
|
|
import { AstMatcher, ParseError, TokenList } from './types';
|
|
|
|
|
|
|
|
export function parseTokens(lexicalArray: TokenList): AstMatcher {
|
|
|
|
const operandStack: AstMatcher[] = [];
|
|
|
|
|
2024-05-29 04:54:45 +02:00
|
|
|
for (let i = 0; i < lexicalArray.length; i += 1) {
|
|
|
|
const token = lexicalArray[i];
|
|
|
|
|
2024-03-18 13:20:47 +01:00
|
|
|
if (token === 'not_op') {
|
2024-05-29 04:54:45 +02:00
|
|
|
continue;
|
2024-03-18 13:20:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
let intermediate: AstMatcher;
|
|
|
|
|
|
|
|
if (typeof token === 'string') {
|
|
|
|
const op2 = operandStack.pop();
|
|
|
|
const op1 = operandStack.pop();
|
|
|
|
|
|
|
|
if (typeof op1 === 'undefined' || typeof op2 === 'undefined') {
|
|
|
|
throw new ParseError('Missing operand.');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (token === 'and_op') {
|
|
|
|
intermediate = matchAll(op1, op2);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
intermediate = matchAny(op1, op2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
intermediate = token;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lexicalArray[i + 1] === 'not_op') {
|
|
|
|
operandStack.push(matchNot(intermediate));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
operandStack.push(intermediate);
|
|
|
|
}
|
2024-05-29 04:54:45 +02:00
|
|
|
}
|
2024-03-18 13:20:47 +01:00
|
|
|
|
|
|
|
if (operandStack.length > 1) {
|
|
|
|
throw new ParseError('Missing operator.');
|
|
|
|
}
|
|
|
|
|
|
|
|
const op1 = operandStack.pop();
|
|
|
|
|
|
|
|
if (typeof op1 === 'undefined') {
|
|
|
|
return matchNone();
|
|
|
|
}
|
|
|
|
|
|
|
|
return op1;
|
|
|
|
}
|