antlr-ng
Version:
Next generation ANTLR Tool
255 lines (254 loc) • 7.1 kB
JavaScript
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
};