const highlight = (map, source) => { let output = ""; let i = 0; while (i < source.length) { for (f of map.rules) { let p = f((j) => source[i + j], (j) => { i += j }); if (p != undefined) output += p; } output += source[i++]; } return output; } const match = (m) => (peek, take) => { for (let i = 0; i < m.length; i++) if (peek(i) != m[i]) return false; take(m.length); return true; } const match_identifier = (m) => (peek, take) => { try { if (peek(-1).match(/[0-9a-z_]/)) return false; } catch {} if (match(m)(peek, take)) { if (peek(0).match(/[0-9a-z]/)) { take(-m.length); return false } return true; } return false; } const take_until = (p) => (peek, take) => { let b = ""; while (!p()) { b += peek(0); take(1); } return b; } const simpleHighlight = (c) => (keyword) => (peek, take) => { if (match_identifier(keyword)(peek, take)) return `${keyword}`; } const keyword = simpleHighlight("keyword"); const altKeyword = simpleHighlight("keyword-alt"); const comment = (prefix) => (peek, take) => { if (match(prefix)(peek, take)) { let b = prefix; b += take_until(() => peek(0) == "\n")(peek, take); return `${b}` } } const multiline_comment = (prefix, suffix) => (peek, take) => { if (match(prefix)(peek, take)) { let b = prefix; b += take_until(() => match(suffix)(peek, take))(peek, take); b += suffix; return `${b}` } } const string = (c) => (peek, take) => { if (match(c)(peek, take)) { let b = c; b += take_until(() => match(c)(peek, take))(peek, take); b += c; return `${b}` } } // keywords: [ // "auto", // "void", // "struct" // ], // altkeywords: [ // "const", // "static", // "int", // "std::string", // "std::unique_ptr", // "char", // "public", // "private", // "protected" // ], const maps = { cpp: { rules: [ comment("//"), multiline_comment("/*", "*/"), string("\""), // single char (peek, take) => { if (peek(0) == "'") { let b = peek(1); take(3); return `'${b}'`; } }, keyword("auto"), keyword("void"), keyword("class"), keyword("struct"), keyword("std::string"), altKeyword("const"), altKeyword("static"), altKeyword("int"), altKeyword("char"), altKeyword("private"), altKeyword("public"), altKeyword("protected"), altKeyword("abstract"), altKeyword("override"), altKeyword("return"), ], }, nix: { rules: [ comment("#"), string("\""), string("''"), keyword("@"), keyword("nixpkgs"), keyword("builtins"), altKeyword("let"), altKeyword("in"), altKeyword("with"), altKeyword("inherit"), altKeyword("import"), ], }, rust: { rules: [ comment("//"), string("\""), // single char (peek, take) => { if (peek(0) == "'") { let b = peek(1); take(3); return `'${b}'`; } }, keyword("fn"), keyword("struct"), keyword("enum"), keyword("trait"), keyword("Option"), keyword("Some"), keyword("None"), keyword("Result"), keyword("Ok"), keyword("Err"), keyword("in"), keyword("Self"), keyword("mut"), altKeyword("if"), altKeyword("else"), altKeyword("match"), altKeyword("loop"), altKeyword("for"), altKeyword("while"), altKeyword("return"), altKeyword("async"), altKeyword("await"), altKeyword("mod"), altKeyword("use"), altKeyword("pub"), altKeyword("impl"), altKeyword("crate"), altKeyword("let"), altKeyword("const"), altKeyword("static"), ] } };