antlr-ng
Version:
Next generation ANTLR Tool
112 lines (111 loc) • 3.93 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
import { GrammarTreeVisitor } from "../tree/walkers/GrammarTreeVisitor.js";
import { MultiMap } from "stringtemplate4ts";
import { LeftRecursiveRuleAnalyzer } from "../analysis/LeftRecursiveRuleAnalyzer.js";
import { DictType } from "../misc/types.js";
import { Utils } from "../misc/Utils.js";
import { ScopeParser } from "../parse/ScopeParser.js";
import { Grammar } from "../tool/Grammar.js";
import { LeftRecursiveRule } from "../tool/LeftRecursiveRule.js";
import { Rule } from "../tool/Rule.js";
class RuleCollector extends GrammarTreeVisitor {
static {
__name(this, "RuleCollector");
}
/** Which grammar are we checking? */
g;
nameToRuleMap = /* @__PURE__ */ new Map();
ruleToAltLabels = new MultiMap();
altLabelToRuleName = /* @__PURE__ */ new Map();
grammarCaseInsensitive = false;
constructor(g) {
super(g.tool.errorManager);
this.g = g;
}
process(ast) {
this.visitGrammar(ast);
}
discoverRule(rule, id, modifiers, arg, returns, thrws, options, locals, actions, block) {
const numAlts = block.children.length;
let r;
if (LeftRecursiveRuleAnalyzer.hasImmediateRecursiveRuleRefs(rule, id.getText())) {
r = new LeftRecursiveRule(this.g, id.getText(), rule);
} else {
r = new Rule(this.g, id.getText(), rule, numAlts);
}
this.nameToRuleMap.set(r.name, r);
if (arg !== void 0) {
r.args = ScopeParser.parseTypedArgList(arg, arg.getText(), this.g);
r.args.type = DictType.Argument;
r.args.ast = arg;
arg.resolver = r.alt[this.currentOuterAltNumber];
}
if (returns !== void 0) {
r.retvals = ScopeParser.parseTypedArgList(returns, returns.getText(), this.g);
r.retvals.type = DictType.Return;
r.retvals.ast = returns;
}
if (locals !== void 0) {
r.locals = ScopeParser.parseTypedArgList(locals, locals.getText(), this.g);
r.locals.type = DictType.Local;
r.locals.ast = locals;
}
for (const a of actions) {
const action = a.children[1];
r.namedActions.set(a.children[0].getText(), action);
action.resolver = r;
}
}
discoverOuterAlt(alt) {
if (alt.altLabel && this.currentRuleName) {
this.ruleToAltLabels.map(this.currentRuleName, alt.altLabel);
const altLabel = alt.altLabel.getText();
this.altLabelToRuleName.set(Utils.capitalize(altLabel), this.currentRuleName);
this.altLabelToRuleName.set(Utils.decapitalize(altLabel), this.currentRuleName);
}
}
grammarOption(id, valueAST) {
const caseInsensitive = this.getCaseInsensitiveValue(id, valueAST);
if (caseInsensitive !== null) {
this.grammarCaseInsensitive = caseInsensitive;
}
}
discoverLexerRule(rule, id, modifiers, options, block) {
let currentCaseInsensitive = this.grammarCaseInsensitive;
if (options !== null) {
for (const child of options.children) {
const childAST = child;
const caseInsensitive = this.getCaseInsensitiveValue(
childAST.children[0],
childAST.children[1]
);
if (caseInsensitive !== null) {
currentCaseInsensitive = caseInsensitive;
}
}
}
const numAlts = block.children.length;
const r = new Rule(this.g, id.getText(), rule, numAlts, this.currentModeName, currentCaseInsensitive);
if (modifiers.length != 0) {
r.modifiers = modifiers;
}
this.nameToRuleMap.set(r.name, r);
}
getCaseInsensitiveValue(optionID, valueAST) {
const optionName = optionID.getText();
if (optionName === Grammar.caseInsensitiveOptionName) {
const valueText = valueAST.getText();
if (valueText === "true") {
return true;
}
if (valueText === "false") {
return false;
}
}
return null;
}
}
export {
RuleCollector
};