mirror of
https://github.com/hi-language/transpiler.git
synced 2026-01-14 08:38:37 +00:00
57 lines
2.0 KiB
JavaScript
57 lines
2.0 KiB
JavaScript
import nearley from 'nearley';
|
|
import grammar from './grammar.js';
|
|
|
|
/**
|
|
* Generates JavaScript code from a Hi AST.
|
|
* @param {object} ast The Abstract Syntax Tree.
|
|
* @returns {string} The equivalent JavaScript code.
|
|
*/
|
|
function generate(ast) {
|
|
const generator = {
|
|
Program: (node) => node.body.map(generate).join('\n'),
|
|
Comment: (node) => node.value,
|
|
VariableDeclaration: (node) => `let ${node.identifier} = ${generate(node.value)};`,
|
|
Assignment: (node) => `${node.identifier} = ${generate(node.value)};`,
|
|
OutputCall: (node) => `console.log(${node.arguments.map(generate).join(', ')});`,
|
|
NumericLiteral: (node) => node.value,
|
|
StringLiteral: (node) => node.value,
|
|
};
|
|
|
|
if (!generator[ast.type]) {
|
|
throw new Error(`Unknown AST node type: ${ast.type}`);
|
|
}
|
|
return generator[ast.type](ast);
|
|
}
|
|
|
|
/**
|
|
* Transpiles a string of Hi source code into JavaScript using an AST.
|
|
* @param {string} sourceCode The Hi source code.
|
|
* @returns {string} The equivalent JavaScript code.
|
|
*/
|
|
export function hi2js(sourceCode) {
|
|
// 1. Create a nearley parser instance from our compiled grammar
|
|
const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));
|
|
|
|
try {
|
|
// 2. Feed the source code to the parser
|
|
parser.feed(sourceCode);
|
|
|
|
// 3. Check for ambiguity and get the AST
|
|
if (parser.results.length > 1) {
|
|
console.warn("Master, the grammar is ambiguous. Using the first parse tree.");
|
|
}
|
|
if (parser.results.length === 0) {
|
|
throw new Error("Unexpected end of input. The code is incomplete.");
|
|
}
|
|
const ast = parser.results[0];
|
|
|
|
// 4. Generate JavaScript from the AST
|
|
return generate(ast);
|
|
|
|
} catch (err) {
|
|
// Provide a more helpful error message
|
|
const message = err.message.replace(/ Instead, I found a "[^"]+" token here:/, ".");
|
|
throw new Error(`Parsing error: ${message}`);
|
|
}
|
|
}
|