132 lines
3.5 KiB
TypeScript
132 lines
3.5 KiB
TypeScript
type TokenKind =
|
|
| "BinaryOperator"
|
|
| "UnaryOperator"
|
|
| "Identifier"
|
|
| "OpeningParenthesis"
|
|
| "ClosingParenthesis"
|
|
| "Pluss"
|
|
| "Semicolon";
|
|
|
|
export interface WildcardToken {
|
|
tokenKind: TokenKind;
|
|
value: string;
|
|
}
|
|
|
|
export class WildcardTokenizer {
|
|
private tokens: WildcardToken[] = [];
|
|
private current = -1; // Have to start at -1 because first iteration advances
|
|
private source: string[];
|
|
constructor(source: string) {
|
|
this.source = source.split("");
|
|
}
|
|
|
|
tokenize(): WildcardToken[] {
|
|
while (this.current < this.source.length - 1) {
|
|
this.scanToken();
|
|
}
|
|
return this.tokens;
|
|
}
|
|
|
|
private peek(): string | undefined {
|
|
return this.source[this.current + 1];
|
|
}
|
|
private getCurrent() {
|
|
return this.source[this.current];
|
|
}
|
|
private advance() {
|
|
this.current += 1;
|
|
}
|
|
|
|
private consumeToken(tokenKind: TokenKind, value: string) {
|
|
this.tokens.push({ tokenKind, value });
|
|
}
|
|
|
|
private scanToken() {
|
|
this.advance();
|
|
let char = this.getCurrent();
|
|
switch (char) {
|
|
case "(": {
|
|
this.consumeToken("OpeningParenthesis", char);
|
|
break;
|
|
}
|
|
case ")": {
|
|
this.consumeToken("ClosingParenthesis", char);
|
|
break;
|
|
}
|
|
case "|": {
|
|
if (this.peek() === "|") {
|
|
this.advance();
|
|
this.consumeToken("BinaryOperator", "||");
|
|
} else {
|
|
throw new Error(
|
|
"Invalid token given to tokenizer: " + char
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
case "!": {
|
|
this.consumeToken("UnaryOperator", char);
|
|
break;
|
|
}
|
|
case "&": {
|
|
if (this.peek() === "&") {
|
|
this.advance();
|
|
this.consumeToken("BinaryOperator", "&&");
|
|
} else {
|
|
throw new Error(
|
|
"Invalid token given to tokenizer: " + char
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
case "+": {
|
|
this.consumeToken("Pluss", char);
|
|
break;
|
|
}
|
|
case ":": {
|
|
this.consumeToken("Semicolon", char);
|
|
break;
|
|
}
|
|
case " ":
|
|
break;
|
|
default:
|
|
if (this.isAlpha(char)) {
|
|
this.consumeAlpha();
|
|
break;
|
|
} else {
|
|
throw new Error("Invalid token given: " + char);
|
|
}
|
|
}
|
|
}
|
|
private consumeAlpha() {
|
|
let word = "";
|
|
|
|
while (true) {
|
|
word += this.getCurrent();
|
|
|
|
let next = this.peek();
|
|
if (next && this.isAlpha(next)) {
|
|
this.advance();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
this.consumeToken("Identifier", word);
|
|
}
|
|
private isAlpha(val: string): boolean {
|
|
let alphabet = new Set(
|
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".split("")
|
|
);
|
|
return alphabet.has(val);
|
|
}
|
|
}
|
|
|
|
function testWildcardTokenizer() {
|
|
let tokenized = new WildcardTokenizer(
|
|
"aiaiai: ((LOL||!Smack)&&SomethingElse)*"
|
|
).tokenize();
|
|
|
|
console.log(tokenized);
|
|
}
|
|
//testWildcardTokenizer();
|