UNPKG

antlr-ng

Version:

Next generation ANTLR Tool

329 lines (328 loc) 11.4 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); import { ANTLRv4Parser } from "../generated/ANTLRv4Parser.js"; import { disjoint } from "../support/helpers.js"; import { LeftRecursiveRule } from "../tool/LeftRecursiveRule.js"; import { Action } from "./model/Action.js"; import { AddToLabelList } from "./model/AddToLabelList.js"; import { AltBlock } from "./model/AltBlock.js"; import { CodeBlockForAlt } from "./model/CodeBlockForAlt.js"; import { CodeBlockForOuterMostAlt } from "./model/CodeBlockForOuterMostAlt.js"; import { InvokeRule } from "./model/InvokeRule.js"; import { LL1AltBlock } from "./model/LL1AltBlock.js"; import { LL1OptionalBlock } from "./model/LL1OptionalBlock.js"; import { LL1OptionalBlockSingleAlt } from "./model/LL1OptionalBlockSingleAlt.js"; import { LL1PlusBlockSingleAlt } from "./model/LL1PlusBlockSingleAlt.js"; import { LL1StarBlockSingleAlt } from "./model/LL1StarBlockSingleAlt.js"; import { LeftRecursiveRuleFunction } from "./model/LeftRecursiveRuleFunction.js"; import { MatchNotSet } from "./model/MatchNotSet.js"; import { MatchSet } from "./model/MatchSet.js"; import { MatchToken } from "./model/MatchToken.js"; import { OptionalBlock } from "./model/OptionalBlock.js"; import { Parser } from "./model/Parser.js"; import { ParserFile } from "./model/ParserFile.js"; import { PlusBlock } from "./model/PlusBlock.js"; import { RuleFunction } from "./model/RuleFunction.js"; import { SemPred } from "./model/SemPred.js"; import { StarBlock } from "./model/StarBlock.js"; import { TestSetInline } from "./model/TestSetInline.js"; import { Wildcard } from "./model/Wildcard.js"; import { RuleContextDecl } from "./model/decl/RuleContextDecl.js"; import { TokenDecl } from "./model/decl/TokenDecl.js"; import { TokenListDecl } from "./model/decl/TokenListDecl.js"; class ParserFactory { constructor(gen, forceAtn) { this.forceAtn = forceAtn; this.gen = gen; this.g = gen.g; } static { __name(this, "ParserFactory"); } g; controller; gen; parserFile(fileName, toolParameters) { return new ParserFile(this, fileName, toolParameters); } parser(file) { return new Parser(this, file); } lexerFile(fileName) { return void 0; } getGrammar() { return this.g; } lexer(file) { return void 0; } rule(r) { if (r instanceof LeftRecursiveRule) { return new LeftRecursiveRuleFunction(this, r); } return new RuleFunction(this, r); } epsilon(alt, outerMost) { return this.alternative(alt, outerMost); } alternative(alt, outerMost) { if (outerMost) { return new CodeBlockForOuterMostAlt(this, alt); } return new CodeBlockForAlt(this); } finishAlternative(blk, ops) { blk.ops = ops ?? []; return blk; } stringRef(id, label) { return this.tokenRef(id, label, null); } action(ast) { return [new Action(this, ast)]; } sempred(ast) { return [new SemPred(this, ast)]; } ruleRef(id, label, args) { const invokeOp = new InvokeRule(this, id, label); if (this.controller.needsImplicitLabel(id, invokeOp)) { this.defineImplicitLabel(id, invokeOp); } const listLabelOp = this.getAddToListOpIfListLabelPresent(invokeOp, label); return [invokeOp, listLabelOp]; } getCurrentRuleFunction() { return this.controller.currentRuleFunction; } tokenRef(id, labelAST, args) { const matchOp = new MatchToken(this, id); if (labelAST) { const label = labelAST.getText(); const rf = this.getCurrentRuleFunction(); if (labelAST.parent?.getType() === ANTLRv4Parser.PLUS_ASSIGN) { this.defineImplicitLabel(id, matchOp); const l = this.getTokenListLabelDecl(label); rf.addContextDecl(id.getAltLabel(), l); } else { const d = this.getTokenLabelDecl(label); matchOp.labels.push(d); rf.addContextDecl(id.getAltLabel(), d); } } if (this.controller.needsImplicitLabel(id, matchOp)) { this.defineImplicitLabel(id, matchOp); } const listLabelOp = this.getAddToListOpIfListLabelPresent(matchOp, labelAST); return [matchOp, listLabelOp]; } getTokenLabelDecl(label) { return new TokenDecl(this, label); } getTokenListLabelDecl(label) { return new TokenListDecl(this, this.gen.target.getListLabel(label)); } set(setAST, labelAST, invert) { let matchOp; if (invert) { matchOp = new MatchNotSet(this, setAST); } else { matchOp = new MatchSet(this, setAST); } if (labelAST !== null) { const label = labelAST.getText(); const rf = this.getCurrentRuleFunction(); if (labelAST.parent?.getType() === ANTLRv4Parser.PLUS_ASSIGN) { this.defineImplicitLabel(setAST, matchOp); const l = this.getTokenListLabelDecl(label); rf.addContextDecl(setAST.getAltLabel(), l); } else { const d = this.getTokenLabelDecl(label); matchOp.labels.push(d); rf.addContextDecl(setAST.getAltLabel(), d); } } if (this.controller.needsImplicitLabel(setAST, matchOp)) { this.defineImplicitLabel(setAST, matchOp); } const listLabelOp = this.getAddToListOpIfListLabelPresent(matchOp, labelAST); return [matchOp, listLabelOp]; } wildcard(ast, labelAST) { const wild = new Wildcard(this, ast); if (labelAST) { const label = labelAST.getText(); const d = this.getTokenLabelDecl(label); wild.labels.push(d); this.getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d); if (labelAST.parent?.getType() === ANTLRv4Parser.PLUS_ASSIGN) { const l = this.getTokenListLabelDecl(label); this.getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), l); } } if (this.controller.needsImplicitLabel(ast, wild)) { this.defineImplicitLabel(ast, wild); } const listLabelOp = this.getAddToListOpIfListLabelPresent(wild, labelAST); return [wild, listLabelOp]; } getChoiceBlock(blkAST, alts, labelAST) { const decision = blkAST.atnState.decision; let c; if (!this.forceAtn && disjoint(this.g.decisionLookahead[decision])) { c = this.getLL1ChoiceBlock(blkAST, alts); } else { c = this.getComplexChoiceBlock(blkAST, alts); } if (labelAST) { const label = labelAST.getText(); const d = this.getTokenLabelDecl(label); c.label = d; this.getCurrentRuleFunction().addContextDecl(labelAST.getAltLabel(), d); if (labelAST.parent?.getType() === ANTLRv4Parser.PLUS_ASSIGN) { const listLabel = this.gen.target.getListLabel(label); const l = new TokenListDecl(this, listLabel); this.getCurrentRuleFunction().addContextDecl(labelAST.getAltLabel(), l); } } return c; } getEBNFBlock(ebnfRoot, alts) { if (!this.forceAtn) { let decision; if (ebnfRoot.getType() === ANTLRv4Parser.POSITIVE_CLOSURE) { decision = ebnfRoot.atnState.decision; } else if (ebnfRoot.getType() === ANTLRv4Parser.CLOSURE) { decision = ebnfRoot.atnState.decision; } else { decision = ebnfRoot.atnState.decision; } if (disjoint(this.g.decisionLookahead[decision])) { return this.getLL1EBNFBlock(ebnfRoot, alts); } } return this.getComplexEBNFBlock(ebnfRoot, alts); } getLL1ChoiceBlock(blkAST, alts) { return new LL1AltBlock(this, blkAST, alts); } getComplexChoiceBlock(blkAST, alts) { return new AltBlock(this, blkAST, alts); } getLL1EBNFBlock(ebnfRoot, alts) { const ebnf = ebnfRoot.getType(); let c; switch (ebnf) { case ANTLRv4Parser.OPTIONAL: { if (alts.length === 1) { c = new LL1OptionalBlockSingleAlt(this, ebnfRoot, alts); } else { c = new LL1OptionalBlock(this, ebnfRoot, alts); } break; } case ANTLRv4Parser.CLOSURE: { if (alts.length === 1) { c = new LL1StarBlockSingleAlt(this, ebnfRoot, alts); } else { c = this.getComplexEBNFBlock(ebnfRoot, alts); } break; } case ANTLRv4Parser.POSITIVE_CLOSURE: { if (alts.length === 1) { c = new LL1PlusBlockSingleAlt(this, ebnfRoot, alts); } else { c = this.getComplexEBNFBlock(ebnfRoot, alts); } break; } default: } return c; } getComplexEBNFBlock(ebnfRoot, alts) { const ebnf = ebnfRoot.getType(); let c; switch (ebnf) { case ANTLRv4Parser.OPTIONAL: { c = new OptionalBlock(this, ebnfRoot, alts); break; } case ANTLRv4Parser.CLOSURE: { c = new StarBlock(this, ebnfRoot, alts); break; } case ANTLRv4Parser.POSITIVE_CLOSURE: { c = new PlusBlock(this, ebnfRoot, alts); break; } default: } return c; } getLL1Test(look, blkAST) { return [new TestSetInline(this, blkAST, look, this.gen.target.getInlineTestSetWordSize())]; } getGenerator() { return this.gen; } getCurrentOuterMostAlt() { return this.controller.currentOuterMostAlt; } getCurrentBlock() { return this.controller.currentBlock; } rulePostamble(ruleFunction, r) { if (r.namedActions.has("after") || r.namedActions.has("finally")) { const gen = this.getGenerator(); const codegenTemplates = gen.templates; const setStopTokenAST = codegenTemplates.getInstanceOf("recRuleSetStopToken"); const setStopTokenAction = new Action(this, ruleFunction.ruleCtx, setStopTokenAST); const ops = new Array(1); ops.push(setStopTokenAction); return ops; } return void 0; } needsImplicitLabel(id, op) { const currentOuterMostAlt = this.getCurrentOuterMostAlt(); const actionRefsAsToken = currentOuterMostAlt.tokenRefsInActions.has(id.getText()); const actionRefsAsRule = currentOuterMostAlt.ruleRefsInActions.has(id.getText()); return op.labels.length === 0 && (actionRefsAsToken || actionRefsAsRule); } defineImplicitLabel(ast, op) { let d; if (ast.getType() === ANTLRv4Parser.SET || ast.getType() === ANTLRv4Parser.WILDCARD) { const implLabel = this.gen.target.getImplicitSetLabel(String(ast.token.tokenIndex)); d = this.getTokenLabelDecl(implLabel); d.isImplicit = true; } else if (ast.getType() === ANTLRv4Parser.RULE_REF) { const r = this.g.getRule(ast.getText()); const implLabel = this.gen.target.getImplicitRuleLabel(ast.getText()); const ctxName = this.gen.target.getRuleFunctionContextStructName(r); d = new RuleContextDecl(this, implLabel, ctxName); d.isImplicit = true; } else { const implLabel = this.gen.target.getImplicitTokenLabel(ast.getText()); d = this.getTokenLabelDecl(implLabel); d.isImplicit = true; } op.labels.push(d); this.getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d); } getAddToListOpIfListLabelPresent(op, label) { let labelOp = null; if (label?.parent?.getType() === ANTLRv4Parser.PLUS_ASSIGN) { const target = this.gen.target; const listLabel = target.getListLabel(label.getText()); const listRuntimeName = target.escapeIfNeeded(listLabel); labelOp = new AddToLabelList(this, listRuntimeName, op.labels[0]); } return labelOp; } } export { ParserFactory };