Created
May 11, 2019 03:39
-
-
Save tim-evans/6f404cba893f52c0f50c3819c6d2d5c2 to your computer and use it in GitHub Desktop.
atjson hir rewrite
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Tree { | |
label: string; | |
rank: number; | |
start: number; | |
end: number; | |
private children: Tree[]; | |
constructor(params: { | |
label: string, | |
start: number, | |
end: number, | |
rank: number | |
}) { | |
this.children = []; | |
this.label = params.label; | |
this.start = params.start; | |
this.end = params.end; | |
this.rank = params.rank; | |
} | |
// Currently assumes that nodes are sorted by rank | |
insert(node: Tree) { | |
for (let i = 0, len = this.children.length; i < len; i++) { | |
let child = this.children[i]; | |
if (node.start < child.start) { | |
// Splice in the full node and return if it's wholly | |
// before this child | |
if (node.end <= child.start) { | |
this.children.splice(i, 0, node); | |
i++; | |
return; | |
} | |
// Otherwise, we have a left branch to take care of | |
let [leftBranch, rest] = node.split(child.start); | |
// Insert the branch | |
this.children.splice(i, 0, leftBranch); | |
i++; | |
// Continue with partial node (to the next statement, | |
// since this may extend past this node) | |
if (rest == null) break; | |
node = rest; | |
} | |
if (node.start >= child.start && node.start < child.end) { | |
if (node.end <= child.end) { | |
child.insert(node); | |
return; | |
} | |
let [rightBranch, rest] = node.split(child.end); | |
// Insert the branch | |
child.insert(rightBranch); | |
if (rest == null) break; | |
// Continue with partial node | |
node = rest; | |
} | |
} | |
this.children.push(node); | |
} | |
split(at: number): [Tree, Tree] { | |
if (this.rank === Infinity) { | |
return [ | |
new Tree({ | |
label: this.label.slice(0, at - this.start), | |
start: this.start, | |
end: at, | |
rank: this.rank | |
}), | |
new Tree({ | |
label: this.label.slice(at - this.start), | |
start: at, | |
end: this.end, | |
rank: this.rank | |
}) | |
]; | |
} | |
return [ | |
new Tree({ | |
label: this.label, | |
start: this.start, | |
end: at, | |
rank: this.rank | |
}), | |
new Tree({ | |
label: this.label, | |
start: at, | |
end: this.end, | |
rank: this.rank | |
}) | |
]; | |
} | |
toJSON(): any { | |
return { | |
label: this.label, | |
start: this.start, | |
end: this.end, | |
children: this.children.map(child => child.toJSON()) | |
}; | |
} | |
trace(indent=0): any { | |
// @ts-ignore | |
let spacing = ' '.repeat(indent); | |
if (this.rank === Infinity) { | |
return `${spacing}${JSON.stringify(this.label)}`; | |
} | |
let children = this.children.map(child => child.trace(indent + 1)); | |
if (children.length === 0) { | |
return `${spacing}${this.label}[${this.start}, ${this.end}]()`; | |
} else { | |
return `${spacing}${this.label}[${this.start}, ${this.end}](\n${children.join('\n')}\n${spacing})`; | |
} | |
} | |
} | |
let tree = new Tree({ label: 'document', start: 0, end: 10, rank: 0 }); | |
tree.insert(new Tree({ label: 'ol', start: 4, end: 8, rank: 10 })); | |
tree.insert(new Tree({ label: 'li', start: 4, end: 8, rank: 10 })); | |
tree.insert(new Tree({ label: 'paragraph', start: 0, end: 4, rank: 15 })); | |
tree.insert(new Tree({ label: 'paragraph', start: 8, end: 10, rank: 15 })); | |
tree.insert(new Tree({ label: 'paragraph', start: 4, end: 8, rank: 15 })); | |
tree.insert(new Tree({ label: 'ab\n\nli\n\ncd', start: 0, end: 10, rank: Infinity })); | |
console.log(tree.trace()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment