antlr-ng
Version:
Next generation ANTLR Tool
82 lines (81 loc) • 2.83 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
import { Token } from "antlr4ng";
import { TreePatternLexer } from "./TreePatternLexer.js";
import { TreePatternParser } from "./TreePatternParser.js";
import { WildcardTreePattern } from "./WildcardTreePattern.js";
class TreeWizard {
static {
__name(this, "TreeWizard");
}
tokenNameToTypeMap;
constructor(tokenNames) {
this.tokenNameToTypeMap = this.computeTokenTypes(tokenNames);
}
/**
* Given a pattern like (ASSIGN %lhs:ID %rhs:.) with optional labels on the various nodes and '.' (dot) as
* the node/subtree wildcard, returns true if the pattern matches and fill the labels Map with the labels pointing
* at the appropriate nodes. Returns false if the pattern is malformed or the tree does not match.
*
* If a node specifies a text arg in pattern, then that must match for that node in t.
*/
parse(t, pattern, labels) {
const tokenizer = new TreePatternLexer(pattern);
const parser = new TreePatternParser(tokenizer, this);
const tpattern = parser.pattern();
const matched = this.doParse(t, tpattern, labels ?? null);
return matched;
}
/** Using the map of token names to token types, returns the type. */
getTokenType(tokenName) {
if (!this.tokenNameToTypeMap) {
return Token.INVALID_TYPE;
}
return this.tokenNameToTypeMap.get(tokenName) ?? Token.INVALID_TYPE;
}
/**
* Computes a map that is an inverted index of tokenNames (which maps int token types to names).
*/
computeTokenTypes(tokenNames) {
const m = /* @__PURE__ */ new Map();
for (let ttype = 0; ttype < tokenNames.length; ttype++) {
const name = tokenNames[ttype];
m.set(name, ttype);
}
return m;
}
/**
* Does the work for parse. Check to see if the t2 pattern fits the structure and token types in t1. Check text
* if the pattern has text arguments on nodes. Fill labels map with pointers to nodes in tree matched against
* nodes in pattern with labels.
*/
doParse(t1, tpattern, labels) {
if (!(tpattern instanceof WildcardTreePattern)) {
if (t1.getType() !== tpattern.getType()) {
return false;
}
if (tpattern.hasTextArg && t1.getText() !== tpattern.getText()) {
return false;
}
}
if (tpattern.label && labels !== null) {
labels.set(tpattern.label, t1);
}
const n1 = t1.children.length;
const n2 = tpattern.children.length;
if (n1 !== n2) {
return false;
}
for (let i = 0; i < n1; i++) {
const child1 = t1.children[i];
const child2 = tpattern.children[i];
if (!this.doParse(child1, child2, labels)) {
return false;
}
}
return true;
}
}
export {
TreeWizard
};