150 lines
3.3 KiB
TypeScript
150 lines
3.3 KiB
TypeScript
|
|
|
|
// type Token = {
|
|
// type: "paren",
|
|
// value: 1 | -1,
|
|
// } | {
|
|
// type: "bracket",
|
|
// value: 1 | -1,
|
|
// } | {
|
|
// type: "brace",
|
|
// value: 1 | -1,
|
|
// } | {
|
|
// type: "number",
|
|
// value: number,
|
|
// } | {
|
|
// type: "keyword",
|
|
// value: (typeof KEYWORDS)[number],
|
|
// } | {
|
|
// type: "identifier",
|
|
// value: string,
|
|
// } | {
|
|
// type: "string",
|
|
// value: string,
|
|
// } | {
|
|
// type: "assignment-op",
|
|
// value: "=",
|
|
// }
|
|
|
|
|
|
// const KEYWORDS = [
|
|
// "let",
|
|
// "if",
|
|
// ] as const;
|
|
|
|
// const isKeyword = (str: string): str is (typeof KEYWORDS)[number] => {
|
|
// return KEYWORDS.includes(str as any);
|
|
// }
|
|
|
|
// const isMatchNestChar = (char: string): char is "(" | ")" | "[" | "]" | "{" | "}" => {
|
|
// return char === "(" || char === ")" || char === "[" || char === "]" || char === "{" || char === "}";
|
|
// }
|
|
|
|
// const matchNestType = {
|
|
// "(": "paren",
|
|
// ")": "paren",
|
|
// "[": "bracket",
|
|
// "]": "bracket",
|
|
// "{": "brace",
|
|
// "}": "brace",
|
|
// } as const
|
|
|
|
// const matchNestValue = {
|
|
// "(": 1,
|
|
// ")": -1,
|
|
// "[": 1,
|
|
// "]": -1,
|
|
// "{": 1,
|
|
// "}": -1,
|
|
// } as const
|
|
|
|
// const isSkippableChar = (char: string) => {
|
|
// return [" ", "\n", "\t", ";"].includes(char);
|
|
// }
|
|
|
|
// const isAlpha = (char: string) => {
|
|
// return /^[a-z]$/.test(char);
|
|
// }
|
|
|
|
// const isNumeric = (char: string) => {
|
|
// return /^\d$/.test(char);
|
|
// }
|
|
|
|
// const isAlphaNumeric = (char: string) => {
|
|
// return isAlpha(char) || isNumeric(char);
|
|
// }
|
|
|
|
// const tokenize = (source: string) => {
|
|
// const tokens: Array<Token> = [];
|
|
// let src = [...source];
|
|
// while (src.length) {
|
|
// const char = src[0];
|
|
// if (isMatchNestChar(char)) {
|
|
// const token = {type: matchNestType[char], value: matchNestValue[char]};
|
|
// tokens.push(token);
|
|
// src.shift();
|
|
// } else if (char === "=") {
|
|
// const token = {type: "assignment-op", value: "="} as const;
|
|
// tokens.push(token);
|
|
// src.shift();
|
|
// } else {
|
|
// if (isSkippableChar(char)) {
|
|
// src.shift();
|
|
// } else if (isNumeric(char)) {
|
|
// let num = "";
|
|
// while (src.length && isNumeric(src[0])) {
|
|
// num += src.shift();
|
|
// }
|
|
// const token = {type: "number" as const, value: Number(num)};
|
|
// tokens.push(token);
|
|
// } else if (isAlpha(char)) {
|
|
// let ident = "";
|
|
// while (src.length && isAlphaNumeric(src[0])) {
|
|
// ident += src.shift();
|
|
// }
|
|
// if (isKeyword(ident)) {
|
|
// const token = {type: "keyword" as const, value: ident};
|
|
// tokens.push(token);
|
|
// } else {
|
|
// const token = {type: "identifier" as const, value: ident};
|
|
// tokens.push(token);
|
|
// }
|
|
// } else if (char === '"' || char === "'") {
|
|
// console.log('lexing a string');
|
|
// const q = char;
|
|
// src.shift();
|
|
// let s = "";
|
|
// while (src.length && src[0] !== q) {
|
|
// const c = src.shift();
|
|
// console.log(`c: "${c}"`);
|
|
// if (c === "\\") {
|
|
// s += src.shift();
|
|
// } else {
|
|
// s += c;
|
|
// }
|
|
// }
|
|
// if (src.length) {
|
|
// src.shift();
|
|
// }
|
|
// const token = {type: "string" as const, value: s};
|
|
// tokens.push(token);
|
|
// } else {
|
|
// throw `Unrecognized character: '${char}'`
|
|
// }
|
|
// }
|
|
// }
|
|
// return tokens;
|
|
// }
|
|
|
|
|
|
// const code = `
|
|
// let x = 45;
|
|
// let y = ( 10 );
|
|
// if (y) {
|
|
// let z = (x = y);
|
|
// }
|
|
// let say = "Hello, \\"world\\"!";
|
|
|
|
// `
|
|
|
|
// console.log(tokenize(code));
|