UNPKG

t3-lang

Version:

T3 brings a smoother, cleaner experience to JavaScript with TypeScript's power—minus the clutter.

134 lines (129 loc) • 4.87 kB
#!/usr/bin/env node // src/t3.ts import fs2 from "fs"; import path2 from "path"; // src/parser.ts import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; import peggy from "peggy"; var __filename = fileURLToPath(import.meta.url); var __dirname = path.dirname(__filename); var grammarPath = path.resolve(__dirname, "./grammar.pegjs"); var grammar = fs.readFileSync(grammarPath, "utf-8"); var parser = peggy.generate(grammar); function parseT3(code) { return parser.parse(code); } // src/transpiler.ts function transpile(ast2) { return ast2.map((node) => emit(node)).filter((node) => node.trim() !== "").join("\n").trim(); } function replaceComparisonOperators(text) { let result2 = text; result2 = result2.replace(/([^=!><%])[ \t]*==[ \t]*([^=])/g, "$1 === $2"); result2 = result2.replace(/([^=!><%])[ \t]*!=[ \t]*([^=])/g, "$1 !== $2"); return result2; } function emit(node, indent = "") { if (typeof node === "string") { const match = node.match(/^(\s*)\(/); if (match) { const leading = match[1]; return indent + leading + ";" + node.trimStart(); } const processedString = replaceComparisonOperators(node); return indent + processedString; } const innerIndent = indent + (node.indent || ""); if (node.type === "IfStatement") { const condition = replaceComparisonOperators(node.condition); const bodyContent = Array.isArray(node.body) ? node.body.map((stmt) => emit(stmt, innerIndent + " ")).join("\n") : emit(node.body, innerIndent + " "); return `${innerIndent}if (${condition}) { ${bodyContent} ${innerIndent}}`; } if (node.type === "ForStatement") { const condition = replaceComparisonOperators(node.condition); const bodyContent = Array.isArray(node.body) ? node.body.map((stmt) => emit(stmt, innerIndent + " ")).join("\n") : emit(node.body, innerIndent + " "); return `${innerIndent}for (${condition}) { ${bodyContent} ${innerIndent}}`; } if (node.type === "WhileStatement") { const condition = replaceComparisonOperators(node.condition); const bodyContent = Array.isArray(node.body) ? node.body.map((stmt) => emit(stmt, innerIndent + " ")).join("\n") : emit(node.body, innerIndent + " "); return `${innerIndent}while (${condition}) { ${bodyContent} ${innerIndent}}`; } if (node.type === "TernaryExpression") { const processedExpression = replaceComparisonOperators(node.expression); return `${innerIndent}${processedExpression}`; } if (node.type === "AssignmentStatement") { const processedExpression = replaceComparisonOperators(node.expression); return `${innerIndent}${processedExpression}`; } if (node.type === "SwitchStatement") { const condition = node.condition; const body = emit(node.body, innerIndent); return `${innerIndent}switch (${condition}) { ${body} ${innerIndent}}`; } if (node.type === "CaseStatement") { const label = node.label; const caseIndent = innerIndent + " "; const blockIndent = caseIndent + " "; if (node.hasBlock) { const blockLines = node.block.body.map( (item) => emit(item, blockIndent) ); const blockContent = blockLines.join("\n"); return `${caseIndent}${label} { ${blockContent} ${caseIndent}}`; } else if (node.block && node.block.type === "CaseBlockContent") { if (node.block.body && node.block.body.length > 0) { const blockContent = node.block.body.map((lines) => { return lines.map((line) => emit(line, blockIndent)).filter((line) => line !== "").join("\n"); }).join("\n"); return `${caseIndent}${label} ${blockContent}`; } return `${caseIndent}${label}`; } else { return `${caseIndent}${label}`; } } if (node.type === "BlockStatement") { return node.body.map((stmt) => emit(stmt, indent + " ")).join("\n"); } if (node.type === "SwitchBlockStatement") { return node.body.map((stmt) => emit(stmt, indent)).join("\n"); } if (node.type === "CaseBlockContent") { return node.lines ? node.lines.map((line) => emit(line, indent)).join("\n") : node.body ? node.body.map((line) => emit(line[0], indent)).join("\n") : ""; } return ""; } // src/t3.ts var args = process.argv.slice(2); var inputPath = args[0]; if (!inputPath) { console.error("Usage: t3 <input-file> [--outDir <dir>]"); process.exit(1); } var outDirIndex = args.indexOf("--outDir"); var outDir = outDirIndex !== -1 ? args[outDirIndex + 1] : null; var inputCode = fs2.readFileSync(inputPath, "utf-8"); var ast = parseT3(inputCode); var result = transpile(ast); var inputName = path2.basename(inputPath, path2.extname(inputPath)); var outputPath = path2.join( outDir || path2.dirname(inputPath), `${inputName}.ts` ); fs2.mkdirSync(path2.dirname(outputPath), { recursive: true }); fs2.writeFileSync(outputPath, result, "utf-8");