bolt/treegen/snippets/ast-before.js

115 lines
2.4 KiB
JavaScript
Raw Normal View History

2020-05-30 11:29:08 +02:00
export class NodeVisitor {
visit(node) {
for (const child of node.preorder()) {
const key = `visit${kindToString(child.kind)}`;
if (this[key] !== undefined) {
this[key](child);
}
}
}
}
2020-05-30 11:29:08 +02:00
let nextNodeId = 1;
class SyntaxBase {
2020-05-30 11:29:08 +02:00
constructor(span) {
this.id = nextNodeId++;
this.errors = [];
this.span = span;
}
*getChildNodes() {
for (const key of Object.keys(this)) {
2020-05-29 18:44:58 +02:00
if (key === 'span' || key === 'parentNode' || key === 'type') {
continue
}
const value = this[key];
if (Array.isArray(value)) {
for (const element of value) {
if (isSyntax(element)) {
yield element;
}
}
} else {
if (isSyntax(value)) {
yield value;
}
}
}
2020-05-30 11:29:08 +02:00
}
2020-05-26 20:59:44 +02:00
visit(visitors) {
const stack = [this];
while (stack.length > 0) {
const node = stack.pop();
const kindName = kindToString(node.kind);
const kindNamesToVisit = [kindName, ...NODE_TYPES[kindName].parents];
2020-05-26 20:59:44 +02:00
for (const visitor of visitors) {
for (const kindName of kindNamesToVisit) {
const key = `visit${kindName}`
if (visitor[key] !== undefined) {
visitor[key](node);
}
}
2020-05-26 20:59:44 +02:00
}
for (const childNode of node.getChildNodes()) {
stack.push(childNode);
}
}
2020-05-30 11:29:08 +02:00
}
2020-05-26 20:59:44 +02:00
*preorder() {
const stack = [this];
while (stack.length > 0) {
const node = stack.pop();
yield node
for (const childNode of node.getChildNodes()) {
stack.push(childNode);
}
}
2020-05-30 11:29:08 +02:00
}
mayContainKind(kind) {
// TODO
return true;
2020-05-30 11:29:08 +02:00
}
2020-05-26 20:59:44 +02:00
getParentOfKind(kind) {
let currNode = this.parentNode;
while (currNode !== null) {
if (currNode.kind === kind) {
return currNode;
}
currNode = currNode.parentNode;
}
return null;
2020-05-30 11:29:08 +02:00
}
*findAllChildrenOfKind(kind) {
for (const node of this.preorder()) {
if (!node.mayContainKind(kind)) {
break;
}
if (node.kind === kind) {
yield node
}
}
}
}
2020-05-30 11:29:08 +02:00
export function isSyntax(value) {
2020-05-10 15:56:34 +02:00
return typeof value === 'object'
&& value !== null
&& value.__NODE_TYPE !== undefined;
}
2020-05-30 11:29:08 +02:00
export function setParents(node, parentNode = null) {
2020-05-10 23:50:42 +02:00
node.parentNode = parentNode;
for (const child of node.getChildNodes()) {
2020-05-10 23:50:42 +02:00
setParents(child, node)
}
}