@maniascript/api
Version:
Maniascript API generator
67 lines (66 loc) • 2.66 kB
JavaScript
import { resolve, dirname, basename } from 'node:path';
import { readFile, writeFile } from 'node:fs/promises';
import { CharStream, CommonTokenStream, BaseErrorListener } from 'antlr4ng';
import { DocLexer } from '../antlr/DocLexer.js';
import { DocParser } from '../antlr/DocParser.js';
import { APIVisitor } from './api-visitor.js';
class MSAPIErrorListener extends BaseErrorListener {
errors = [];
syntaxError(_recognizer, _offendingSymbol, line, column, msg) {
this.errors.push({ message: msg, line, column });
}
}
function parse(input = '') {
const errorListener = new MSAPIErrorListener();
const inputStream = CharStream.fromString(input);
const lexer = new DocLexer(inputStream);
lexer.removeErrorListeners();
lexer.addErrorListener(errorListener);
const tokenStream = new CommonTokenStream(lexer);
const parser = new DocParser(tokenStream);
parser.removeErrorListeners();
parser.addErrorListener(errorListener);
const tree = parser.program();
return {
success: errorListener.errors.length === 0,
errors: errorListener.errors,
tree,
chars: inputStream,
lexer,
tokens: tokenStream,
parser: parser
};
}
function generateFromParseResult(result) {
const visitor = new APIVisitor(result.tokens);
return visitor.visit(result.tree);
}
function generateFromInput(input = '') {
return generateFromParseResult(parse(input));
}
async function generateFromFile(path = '') {
const input = await readFile(path, 'utf8');
return generateFromInput(input);
}
async function execute(inFile = '', outFile, format) {
const input = await readFile(inFile, 'utf8');
const result = parse(input);
if (!result.success) {
let errorList = '';
for (const error of result.errors) {
errorList += `${error.line.toString()}:${error.column.toString()} - ${error.message}\n`;
}
throw new Error(`Failed to parse file "${inFile}":\n${errorList}`);
}
const api = generateFromParseResult(result);
if (format === undefined || format === 'json') {
await writeFile(outFile ?? resolve(dirname(inFile), `${basename(inFile, '.h')}.json`), JSON.stringify(api, null, 2));
}
else if (format === 'ts') {
await writeFile(outFile ?? resolve(dirname(inFile), `${basename(inFile, '.h')}.ts`), `import type { API } from '../lib/api-visitor.js'\nexport const api: API = ${JSON.stringify(api, null, 2)}`);
}
else {
throw new Error('Format must be json or ts');
}
}
export { parse, generateFromParseResult, generateFromInput, generateFromFile, execute };