Home Manual Reference Source

src/ast/materialize.js

import anyIterator from '../util/anyIterator.js';

export default async function materialize(root) {
	// Assert root.type === 'node'

	const parents = [
		{
			type: 'node',
			nonterminal: root.nonterminal,
			production: root.production,
			children: [],
		},
	];

	const children = [anyIterator(root.children)];

	while (true) {
		const todo = children.pop();

		// eslint-disable-next-line no-await-in-loop
		const {done, value} = await todo.next();

		if (done) {
			if (children.length === 0) return parents.pop();

			const tree = parents.pop();
			const parent = parents.pop();
			parent.children.push(tree);
			parents.push(parent);
		} else {
			const child = value;

			if (child.type === 'leaf') {
				const tree = parents.pop();
				tree.children.push(child);
				parents.push(tree);
				children.push(todo);
			} else {
				const grandchildren = anyIterator(child.children);

				const newchild = {
					type: 'node',
					nonterminal: child.nonterminal,
					production: child.production,
					children: [],
				};

				parents.push(newchild);
				children.push(todo, grandchildren);
			}
		}
	}
}