@ayanaware/bentocord
Version:
Bentocord is a Bento plugin designed to rapidly build fully functional Discord Bots.
101 lines • 3.94 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = void 0;
const Tokenizer_1 = require("./Tokenizer");
class Parser {
constructor(tokens) {
this.output = { all: [], options: [], phrases: [] };
this.postion = 0;
this.tokens = tokens;
}
parse() {
while (this.postion < this.tokens.length - 1)
this.parseNext();
return this.output;
}
expectToken(tokens, lookahead = 0) {
const token = this.tokens[this.postion + lookahead];
if (token == null)
return false;
return tokens.includes(token.type);
}
match(tokens, advance = false) {
const result = this.expectToken(tokens);
if (!result)
return false;
const token = this.tokens[this.postion];
if (advance)
this.postion++;
return token;
}
parseNext() {
for (const fn of [this.parseWhitespace.bind(this), this.parseOption.bind(this), this.parsePhrase.bind(this)])
fn();
}
parseWhitespace() {
// Consume whitespace
this.match([Tokenizer_1.TokenType.WHITESPACE], true);
}
parseOption() {
const optionToken = this.match([Tokenizer_1.TokenType.OPTION], true);
if (!optionToken)
return;
const optionKey = optionToken.value.replace(/[:= ]/g, '');
const option = { value: '', key: optionKey, raw: `${optionToken.value}` };
const collector = [];
let token = null;
// eslint-disable-next-line no-cond-assign
while (token = this.match([Tokenizer_1.TokenType.WORD, Tokenizer_1.TokenType.WHITESPACE, Tokenizer_1.TokenType.QUOTE_OPEN, Tokenizer_1.TokenType.QUOTE_CLOSE], true)) {
if (typeof token !== 'object')
continue;
option.raw += token.value;
if (token.type === Tokenizer_1.TokenType.WORD)
collector.push(token.value);
}
option.value = collector.join(' ');
this.output.all.push(option);
this.output.options.push(option);
}
parsePhrase(returnMode = false) {
// handle quotes
const quoteOpenToken = this.match([Tokenizer_1.TokenType.QUOTE_OPEN], true);
if (quoteOpenToken) {
// this is the start of a quoted phrase
let raw = quoteOpenToken.value;
const collector = [];
let token = null;
// eslint-disable-next-line no-cond-assign
while (token = this.match([Tokenizer_1.TokenType.WORD, Tokenizer_1.TokenType.WHITESPACE], true)) {
if (typeof token !== 'object')
continue; // make typescript happy
raw = `${raw}${token.value}`;
if (token.type === Tokenizer_1.TokenType.WORD)
collector.push(token.value);
}
let quoteCloseToken = this.match([Tokenizer_1.TokenType.QUOTE_CLOSE], true);
if (!quoteCloseToken) {
// Quoted Phrase was not closed :AWAUGERYY:
// Just close it ourself
quoteCloseToken = { type: Tokenizer_1.TokenType.QUOTE_CLOSE, value: '"' };
}
raw = `${raw}${quoteCloseToken.value}`;
const quotePhrase = { value: collector.join(' '), raw };
if (returnMode)
return quotePhrase;
this.output.all.push(quotePhrase);
this.output.phrases.push(quotePhrase);
return;
}
// word
const wordToken = this.match([Tokenizer_1.TokenType.WORD], true);
if (!wordToken)
return;
const phrase = { value: wordToken.value, raw: wordToken.value };
if (returnMode)
return phrase;
this.output.all.push(phrase);
this.output.phrases.push(phrase);
}
}
exports.Parser = Parser;
//# sourceMappingURL=Parser.js.map