UNPKG

antlr-ng

Version:

Next generation ANTLR Tool

255 lines (254 loc) 7.1 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); import { CharStream } from "antlr4ng"; import { ActionSplitter } from "../generated/ActionSplitter.js"; import { Alternative } from "../tool/Alternative.js"; import { IssueCode } from "../tool/Issues.js"; import { Grammar } from "../tool/Grammar.js"; import { LabelType } from "../tool/LabelType.js"; import { Rule } from "../tool/Rule.js"; class AttributeChecks { static { __name(this, "AttributeChecks"); } g; /** `null` if action outside of rule */ r; /** `null` if action outside of alt; could be in rule. */ alt; node; actionToken; constructor(g, r, alt, node, actionToken) { this.g = g; this.r = r; this.alt = alt; this.node = node; this.actionToken = actionToken; } static checkAllAttributeExpressions(g) { for (const act of g.namedActions.values()) { const checker = new AttributeChecks(g, null, null, act, act.token); checker.examineAction(); } for (const r of g.rules.values()) { for (const a of r.namedActions.values()) { const checker = new AttributeChecks(g, r, null, a, a.token); checker.examineAction(); } for (let i = 1; i <= r.numberOfAlts; i++) { const alt = r.alt[i]; for (const a of alt.actions) { const checker = new AttributeChecks(g, r, alt, a, a.token); checker.examineAction(); } } for (const e of r.exceptions) { const a = e.children[1]; const checker = new AttributeChecks(g, r, null, a, a.token); checker.examineAction(); } if (r.finallyAction) { const checker = new AttributeChecks(g, r, null, r.finallyAction, r.finallyAction.token); checker.examineAction(); } } } examineAction() { const input = CharStream.fromString(this.actionToken.text); const splitter = new ActionSplitter(input); this.node.chunks = splitter.getActionTokens(this, this.actionToken); } // `$x.y` qualifiedAttr(expr, x, y) { if (this.g.isLexer()) { this.g.tool.errorManager.grammarError( IssueCode.AttributeInLexerAction, this.g.fileName, x, x.text + "." + y.text, expr ); return; } if (this.node.resolver.resolveToAttribute(x.text, this.node) !== null) { this.attr(expr, x); return; } if (this.node.resolver.resolveToAttribute(x.text, y.text, this.node) === null) { const ruleRef = this.isolatedRuleRef(x.text); if (ruleRef) { if (ruleRef.args?.get(y.text) !== null) { this.g.tool.errorManager.grammarError( IssueCode.InvalidRuleParameterRef, this.g.fileName, y, y.text, ruleRef.name, expr ); } else { this.g.tool.errorManager.grammarError( IssueCode.UnknownRuleAttribute, this.g.fileName, y, y.text, ruleRef.name, expr ); } } else if (!this.node.resolver.resolvesToAttributeDict(x.text, this.node)) { this.g.tool.errorManager.grammarError( IssueCode.UnknownSimpleAttribute, this.g.fileName, x, x.text, expr ); } else { this.g.tool.errorManager.grammarError( IssueCode.UnknownAtrributeInScopoe, this.g.fileName, y, y.text, expr ); } } } setAttr(expr, x, rhs) { if (this.g.isLexer()) { this.g.tool.errorManager.grammarError( IssueCode.AttributeInLexerAction, this.g.fileName, x, x.text, expr ); return; } if (this.node.resolver.resolveToAttribute(x.text, this.node) === null) { let errorType = IssueCode.UnknownSimpleAttribute; if (this.node.resolver.resolvesToListLabel(x.text, this.node)) { errorType = IssueCode.AssignmentToListLabel; } this.g.tool.errorManager.grammarError(errorType, this.g.fileName, x, x.text, expr); } new AttributeChecks(this.g, this.r, this.alt, this.node, rhs).examineAction(); } attr(expr, x) { if (this.g.isLexer()) { this.g.tool.errorManager.grammarError( IssueCode.AttributeInLexerAction, this.g.fileName, x, x.text, expr ); return; } if (this.node.resolver.resolveToAttribute(x.text, this.node) === null) { if (this.node.resolver.resolvesToToken(x.text, this.node)) { return; } if (this.node.resolver.resolvesToListLabel(x.text, this.node)) { return; } if (this.isolatedRuleRef(x.text) !== null) { this.g.tool.errorManager.grammarError(IssueCode.IsloatedRuleRef, this.g.fileName, x, x.text, expr); return; } this.g.tool.errorManager.grammarError( IssueCode.UnknownSimpleAttribute, this.g.fileName, x, x.text, expr ); } } nonLocalAttr(expr, x, y) { const r = this.g.getRule(x.text); if (r === null) { this.g.tool.errorManager.grammarError( IssueCode.UndefinedRuleInNonlocalRef, this.g.fileName, x, x.text, y, expr ); } else if (r.resolveToAttribute(y.text, null) === null) { this.g.tool.errorManager.grammarError( IssueCode.UnknownRuleAttribute, this.g.fileName, y, y.text, x.text, expr ); } } setNonLocalAttr(expr, x, y, rhs) { const r = this.g.getRule(x.text); if (r === null) { this.g.tool.errorManager.grammarError( IssueCode.UndefinedRuleInNonlocalRef, this.g.fileName, x, x.text, y.text, expr ); } else if (r.resolveToAttribute(y.text, null) === null) { this.g.tool.errorManager.grammarError( IssueCode.UnknownRuleAttribute, this.g.fileName, y, y.text, x.text, expr ); } } text(text) { } templateInstance(expr) { } indirectTemplateInstance(expr) { } setExprAttribute(expr) { } setSTAttribute(expr) { } templateExpr(expr) { } isolatedRuleRef(x) { if (this.node.resolver instanceof Grammar) { return null; } if (x === this.r?.name) { return this.r; } let labels = null; if (this.node.resolver instanceof Rule) { labels = this.r.getElementLabelDefs().get(x); } else if (this.node.resolver instanceof Alternative) { labels = this.node.resolver.labelDefs.get(x); } if (labels) { const anyLabelDef = labels[0]; if (anyLabelDef.type === LabelType.RuleLabel) { return this.g.getRule(anyLabelDef.element.getText()); } } if (this.node.resolver instanceof Alternative) { if (this.node.resolver.ruleRefs.get(x)) { return this.g.getRule(x); } } return null; } } export { AttributeChecks };