initial ideas

This commit is contained in:
dylan
2023-04-28 17:57:35 -07:00
parent 3e7bf2dd80
commit 3390e9d50a
11 changed files with 1362 additions and 0 deletions

54
lang2/lexer.ts Normal file
View File

@ -0,0 +1,54 @@
type Token<T extends string> = {
type: T,
string: string,
}
type LexerProps<T extends string> = {
rules: {
[key in T]: RegExp;
},
// postprocess?: (token: Token<T>) =>
}
const entries = <K extends string, V>(obj: {[key in K]: V}) => {
return Object.entries(obj) as Array<[K, V]>;
}
const lexer = <T extends string>(props: LexerProps<T>) => {
const {rules} = props;
return (string: string): Array<Token<T>> => {
const tokens: Array<Token<T>> = [];
let str = string;
while (str.length) {
let matched = false;
for (const [type, matcher] of entries(rules)) {
const match = str.match(matcher);
if (match && match.index === 0) {
if (type !== "_skip") {
tokens.push({type, string: match[0]});
}
str = str.slice(match[0].length);
matched = true;
break;
}
}
if (!matched) {
console.log(tokens);
console.log(str);
throw 'Infinite Loop';
}
}
return tokens;
}
}
const my_lexer = lexer({
rules: {
symbol: /\w+/,
punctuation: /[\.,:;()[\]{}]/,
string_literal: /"([^"\\]|\\.)*"/,
_skip: /\s+/,
}
});
console.log(my_lexer(`abc def { ghi } "string literal!" "with \\"escaped\\" quote marks"`));

28
lang2/peg.js Normal file
View File

@ -0,0 +1,28 @@
const Expression = rule(
[{head: Term}, {tail: star([_, slash("+", "-"), _, Term])}],
({head, tail}) => {
return tail.reduce(function(result, element) {
if (element[1] === "+") { return result + element[3]; }
if (element[1] === "-") { return result - element[3]; }
}, head);
}
);
const Term = rule(
[{head: Factor}, {tail: star([_, slash("*", "/"), _, Factor])}],
({head, tail}) => {
return tail.reduce(function(result, element) {
if (element[1] === "*") { return result * element[3]; }
if (element[1] === "/") { return result / element[3]; }
}, head);
}
);
const Factor = slash(
rule(["(", _, {expr: Expression}, _, ")"], ({expr}) => expr),
Integer
);
const Integer = rule([_, /[0-9]+/], () => { return parseInt(text(), 10); });
const _ = /[ \t\n\r]*/;