UNPKG

@maniascript/api

Version:

Maniascript API generator

67 lines (66 loc) 2.66 kB
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 };