mirror of
https://github.com/hi-language/transpiler.git
synced 2026-01-14 00:28:05 +00:00
Refactor: Replace Nearley with Chevrotain parser workflow
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import nearley from 'nearley';
|
import { HiLexer, parser, astBuilder } from './parser.js';
|
||||||
import grammar from './grammar.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates JavaScript code from a Hi AST.
|
* Generates JavaScript code from a Hi AST.
|
||||||
@@ -7,7 +6,7 @@ import grammar from './grammar.js';
|
|||||||
* @returns {string} The equivalent JavaScript code.
|
* @returns {string} The equivalent JavaScript code.
|
||||||
*/
|
*/
|
||||||
function generate(ast) {
|
function generate(ast) {
|
||||||
if (!ast) return ''; // Handle potential nulls from grammar
|
if (!ast) return '';
|
||||||
|
|
||||||
const generator = {
|
const generator = {
|
||||||
Program: (node) => node.body.map(generate).join('\n'),
|
Program: (node) => node.body.map(generate).join('\n'),
|
||||||
@@ -51,32 +50,26 @@ function generate(ast) {
|
|||||||
* @returns {string} The equivalent JavaScript code.
|
* @returns {string} The equivalent JavaScript code.
|
||||||
*/
|
*/
|
||||||
export function hi2js(sourceCode) {
|
export function hi2js(sourceCode) {
|
||||||
// 1. Create a nearley parser instance from our compiled grammar
|
if (!sourceCode.trim()) {
|
||||||
const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));
|
return "";
|
||||||
|
|
||||||
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) {
|
// 1. Lexing
|
||||||
// Throw an error only if the input was not empty.
|
const lexResult = HiLexer.tokenize(sourceCode);
|
||||||
if (sourceCode.trim().length > 0) {
|
if (lexResult.errors.length > 0) {
|
||||||
throw new Error("Unexpected end of input. The code is incomplete.");
|
throw new Error(`Lexing error: ${lexResult.errors[0].message}`);
|
||||||
}
|
}
|
||||||
return ""; // Return empty string for empty input.
|
|
||||||
}
|
|
||||||
const ast = parser.results[0];
|
|
||||||
|
|
||||||
// 4. Generate JavaScript from the AST
|
// 2. Parsing
|
||||||
|
parser.input = lexResult.tokens;
|
||||||
|
const cst = parser.program();
|
||||||
|
if (parser.errors.length > 0) {
|
||||||
|
const err = parser.errors[0];
|
||||||
|
throw new Error(`Parsing error: ${err.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Building AST from CST
|
||||||
|
const ast = astBuilder.visit(cst);
|
||||||
|
|
||||||
|
// 4. Generating JavaScript from AST
|
||||||
return generate(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}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user