UNPKG

antlr-ng

Version:

Next generation ANTLR Tool

214 lines (213 loc) 7.1 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); import { writeFileSync } from "node:fs"; import { Token } from "antlr4ng"; import { AutoIndentWriter, ST, StringWriter } from "stringtemplate4ts"; import { Constants } from "../Constants.js"; import { IssueCode } from "../tool/Issues.js"; import { Grammar } from "../tool/Grammar.js"; import { OutputModelController } from "./OutputModelController.js"; import { OutputModelWalker } from "./OutputModelWalker.js"; import { ParserFactory } from "./ParserFactory.js"; import { CppTarget } from "./target/CppTarget.js"; import { CSharpTarget } from "./target/CSharpTarget.js"; import { DartTarget } from "./target/DartTarget.js"; import { GoTarget } from "./target/GoTarget.js"; import { JavaScriptTarget } from "./target/JavaScriptTarget.js"; import { JavaTarget } from "./target/JavaTarget.js"; import { PHPTarget } from "./target/PHPTarget.js"; import { Python3Target } from "./target/Python3Target.js"; import { SwiftTarget } from "./target/SwiftTarget.js"; import { TypeScriptTarget } from "./target/TypeScriptTarget.js"; const targetLanguages = [ "Cpp", "CSharp", "Dart", "Go", "JavaScript", "Java", "PHP", "Python3", "Swift", "TypeScript" ]; class CodeGenerator { static { __name(this, "CodeGenerator"); } static vocabFilePattern = "<tokens.keys:{t | <t>=<tokens.(t)>\n}><literals.keys:{t | <t>=<literals.(t)>\n}>"; static languageMap = /* @__PURE__ */ new Map([ ["Cpp", CppTarget], ["CSharp", CSharpTarget], ["Dart", DartTarget], ["Go", GoTarget], ["JavaScript", JavaScriptTarget], ["Java", JavaTarget], ["PHP", PHPTarget], ["Python3", Python3Target], ["Swift", SwiftTarget], ["TypeScript", TypeScriptTarget] ]); target; g; language; tool; lineWidth = 72; constructor(grammarOrLanguage) { this.g = grammarOrLanguage instanceof Grammar ? grammarOrLanguage : void 0; this.tool = this.g?.tool; this.language = grammarOrLanguage instanceof Grammar ? this.g.getLanguage() : grammarOrLanguage; this.target = new (CodeGenerator.languageMap.get(this.language))(this); } get templates() { return this.target.templates; } generateLexer(toolParameters, header) { header ??= false; return this.walk(this.createController(toolParameters.forceAtn).buildLexerOutputModel(header, toolParameters), header); } generateParser(toolParameters, header) { header ??= false; return this.walk(this.createController().buildParserOutputModel(header, toolParameters), header); } generateListener(header) { header ??= false; return this.walk(this.createController().buildListenerOutputModel(header), header); } generateBaseListener(header) { header ??= false; return this.walk(this.createController().buildBaseListenerOutputModel(header), header); } generateVisitor(header) { header ??= false; return this.walk(this.createController().buildVisitorOutputModel(header), header); } generateBaseVisitor(header) { header ??= false; return this.walk(this.createController().buildBaseVisitorOutputModel(header), header); } writeRecognizer(outputFileST, header) { this.target.genFile(this.g, outputFileST, this.getRecognizerFileName(header)); } writeListener(outputFileST, header) { this.target.genFile(this.g, outputFileST, this.getListenerFileName(header)); } writeBaseListener(outputFileST, header) { this.target.genFile(this.g, outputFileST, this.getBaseListenerFileName(header)); } writeVisitor(outputFileST, header) { this.target.genFile(this.g, outputFileST, this.getVisitorFileName(header)); } writeBaseVisitor(outputFileST, header) { this.target.genFile(this.g, outputFileST, this.getBaseVisitorFileName(header)); } writeVocabFile() { const tokenVocabSerialization = this.getTokenVocabOutput(); const fileName = this.getVocabFileName(); if (fileName !== void 0) { this.target.genFile(this.g, tokenVocabSerialization, fileName); } } write(code, fileName) { if (this.tool === void 0) { return; } try { fileName = this.tool.getOutputFile(this.g, fileName); const w = new StringWriter(); const wr = new AutoIndentWriter(w); wr.setLineWidth(this.lineWidth); code.write(wr); writeFileSync(fileName, w.toString(), "utf8"); } catch (cause) { if (cause instanceof Error) { this.g.tool.errorManager.toolError(IssueCode.CannotWriteFile, cause, fileName); } else { throw cause; } } } getRecognizerFileName(header) { header ??= false; return this.target.getRecognizerFileName(header); } getListenerFileName(header) { header ??= false; return this.target.getListenerFileName(header); } getVisitorFileName(header) { header ??= false; return this.target.getVisitorFileName(header); } getBaseListenerFileName(header) { header ??= false; return this.target.getBaseListenerFileName(header); } getBaseVisitorFileName(header) { header ??= false; return this.target.getBaseVisitorFileName(header); } /** * What is the name of the vocab file generated for this grammar? * * @returns undefined if no ".tokens" file should be generated. */ getVocabFileName() { return this.g.name + Constants.VocabFileExtension; } getHeaderFileName() { const extST = this.templates.getInstanceOf("headerFileExtension"); if (extST === null) { return void 0; } const recognizerName = this.g.getRecognizerName(); return recognizerName + extST.render(); } /** * Generates a token vocab file with all the token names/types. For example: * ``` * ID=7 * FOR=8 * 'for'=8 * ``` * This is independent of the target language and used by antlr internally. * * @returns The token vocab file as a string template. */ getTokenVocabOutput() { const vocabFileST = new ST(CodeGenerator.vocabFilePattern); const tokens = /* @__PURE__ */ new Map(); for (const [key, value] of this.g.tokenNameToTypeMap) { if (value >= Token.MIN_USER_TOKEN_TYPE) { tokens.set(key, value); } } vocabFileST.add("tokens", tokens); const literals = /* @__PURE__ */ new Map(); for (const [key, value] of this.g.stringLiteralToTypeMap) { if (value >= Token.MIN_USER_TOKEN_TYPE) { literals.set(key, value); } } vocabFileST.add("literals", literals); return vocabFileST; } // CREATE TEMPLATES BY WALKING MODEL createController(forceAtn) { const factory = new ParserFactory(this, forceAtn); const controller = new OutputModelController(factory); factory.controller = controller; return controller; } walk(outputModel, header) { if (this.tool === void 0) { throw new Error("Tool is undefined."); } const walker = new OutputModelWalker(this.tool, this.templates); return walker.walk(outputModel, header); } } export { CodeGenerator, targetLanguages };