lovelang
Version:
🖤 LoveLang: A romantic wrapper language over TypeScript/TSX
218 lines (213 loc) • 7.13 kB
JavaScript
;
(() => {
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// src/tokenizer.js
var require_tokenizer = __commonJS({
"src/tokenizer.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tokenize = tokenize2;
var KEYWORDS = [
"hi babe",
"remember",
"babe,",
"say",
"when babe thinks",
"if babe feels",
"then",
"else",
"whenever babe says",
"class",
"try",
"catch",
"stop thinking",
"render",
"component"
];
function tokenize2(src) {
var tokens = [];
var i = 0;
var _loop_1 = function() {
if (/\s/.test(src[i])) {
i++;
return "continue";
}
if (src[i] === '"') {
var j = i + 1;
while (src[j] !== '"' && j < src.length)
j++;
tokens.push({ type: "STRING", value: src.slice(i + 1, j) });
i = j + 1;
return "continue";
}
if (/\d/.test(src[i])) {
var j = i;
while (/\d/.test(src[j]))
j++;
tokens.push({ type: "NUMBER", value: src.slice(i, j) });
i = j;
return "continue";
}
var rest = src.slice(i);
var kw = KEYWORDS.find(function(k) {
return rest.startsWith(k);
});
if (kw) {
tokens.push({ type: "KEYWORD", value: kw });
i += kw.length;
return "continue";
}
if (/[A-Za-z_]/.test(src[i])) {
var j = i;
while (/[A-Za-z0-9_]/.test(src[j]))
j++;
tokens.push({ type: "IDENT", value: src.slice(i, j) });
i = j;
return "continue";
}
if (/[\=\;\{\}\,\<\>]/.test(src[i])) {
tokens.push({ type: "PUNCT", value: src[i] });
i++;
return "continue";
}
throw new Error("Unexpected character '".concat(src[i], "'"));
};
while (i < src.length) {
_loop_1();
}
return tokens;
}
}
});
// src/parser.js
var require_parser = __commonJS({
"src/parser.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parse = parse2;
function parse2(tokens) {
var pos = 0;
var peek = function() {
return tokens[pos];
};
var consume = function(type, value) {
var t2 = tokens[pos++];
if (type && t2.type !== type || value && t2.value !== value)
throw new Error("Expected ".concat(type, ":").concat(value, ", got ").concat(t2.type, ":").concat(t2.value));
return t2;
};
function parseVarDecl() {
consume("KEYWORD", "hi babe");
consume("PUNCT", "--");
consume("KEYWORD", "this is");
var name = consume("STRING").value;
consume("PUNCT", "=");
var expr = parseExpr();
consume("PUNCT", ";");
return { type: "VarDecl", name, expr };
}
function parsePrint() {
consume("KEYWORD", "babe,");
consume("KEYWORD", "say");
var expr = parseExpr();
consume("PUNCT", ";");
return { type: "PrintStmt", expr };
}
function parseExpr() {
var t2 = peek();
if (t2.type === "STRING") {
pos++;
return { type: "StringLiteral", value: t2.value };
}
if (t2.type === "NUMBER") {
pos++;
return { type: "NumberLiteral", value: t2.value };
}
if (t2.type === "IDENT") {
pos++;
return { type: "Identifier", value: t2.value };
}
throw new Error("Unexpected expr token ".concat(t2.value));
}
var ast = [];
while (pos < tokens.length) {
var t = peek();
if (t.type === "KEYWORD" && t.value === "hi babe")
ast.push(parseVarDecl());
else if (t.type === "KEYWORD" && t.value === "babe,")
ast.push(parsePrint());
else
throw new Error("Cannot parse statement at ".concat(t.value));
}
return ast;
}
}
});
// src/emitter.js
var require_emitter = __commonJS({
"src/emitter.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.emit = emit2;
function emit2(nodes) {
var out = "";
for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
var n = nodes_1[_i];
switch (n.type) {
case "VarDecl":
out += "let ".concat(n.name, " = ").concat(emitExpr(n.expr), ";\n");
break;
case "PrintStmt":
out += "console.log(".concat(emitExpr(n.expr), ");\n");
break;
}
}
return out;
}
function emitExpr(e) {
switch (e.type) {
case "StringLiteral":
return JSON.stringify(e.value);
case "NumberLiteral":
return e.value;
case "Identifier":
return e.value;
}
}
}
});
// playground-src/main.ts
var import_tokenizer = __toESM(require_tokenizer());
var import_parser = __toESM(require_parser());
var import_emitter = __toESM(require_emitter());
function compileLove(code) {
const tokens = (0, import_tokenizer.tokenize)(code);
const ast = (0, import_parser.parse)(tokens);
return (0, import_emitter.emit)(ast);
}
})();
//# sourceMappingURL=love-compiler.js.map