target_tree.default_tree.DefaultTargetTreeNode.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Treepat Show documentation
Show all versions of Treepat Show documentation
Treepat is a language to recognise patterns in trees in a similar way as regular expressions recognize patterns in strings. Treepat includes analogous operators to regex union, concatenation, and closure, which are extended to the notion of trees.
package target_tree.default_tree
import target_tree.TargetTreeNode
data class MatchedResponse(val matchedString: String, val currentIndex: Int)
class DefaultTargetTreeNode(
override val name: String = "",
override val tag: String = "",
override val id: Int = -1,
override var children: List = mutableListOf()
) : TargetTreeNode, Comparable {
var parent: TargetTreeNode? = null
override fun moveToRightSibling(): TargetTreeNode? = (parent as? DefaultTargetTreeNode)?.getRightSibling(this)
override fun moveToLeftSibling(): TargetTreeNode? = (parent as? DefaultTargetTreeNode)?.getLeftSibling(this)
override fun moveToParent(): TargetTreeNode? = parent
override fun moveToFirstChild(): TargetTreeNode? = children.firstOrNull()
override fun matchedNodesString(selectedNodes: List): String =
matchedNodesString(selectedNodes.sortedBy { it.id }, 0, Int.MAX_VALUE).matchedString
override fun nextLeftmostPreorderNode(): TargetTreeNode? {
if (children.isNotEmpty()) {
return children.first()
}
return nextSiblingLeftmostChild()
}
fun nextSiblingLeftmostChild(): TargetTreeNode? {
val rightSibling = moveToRightSibling()
if (rightSibling != null) {
return rightSibling
}
return nextUpwardPreorderNode()
}
private fun nextUpwardPreorderNode(): TargetTreeNode? {
return (parent as DefaultTargetTreeNode?)?.nextSiblingLeftmostChild()
}
@Suppress("UNCHECKED_CAST")
fun matchedNodesString(
selectedNodes: List,
initialIndex: Int,
rightSiblingId: Int
): MatchedResponse {
var str = ""
var currentIndex = initialIndex
if (selectedNodes[initialIndex].id == id) {
str = "$name:$tag($id)"
currentIndex++
}
while (currentIndex < selectedNodes.size && selectedNodes[currentIndex].id < rightSiblingId) {
var goalInd = (children as List).binarySearch(
DefaultTargetTreeNode("", "", selectedNodes[currentIndex].id)
)
if (goalInd < 0 || (goalInd == 0 && selectedNodes[currentIndex].id != children[0].id)) {
goalInd *= -1
goalInd -= 2
}
val response = (children[goalInd] as DefaultTargetTreeNode).matchedNodesString(
selectedNodes,
currentIndex,
if (goalInd + 1 == children.size) rightSiblingId else children[goalInd + 1].id
)
str += END_LINE_STRING + response.matchedString.prependIndent(
INDENT_STRING
)
currentIndex = response.currentIndex
}
str = str.removePrefix(END_LINE_STRING)
return MatchedResponse(str, currentIndex)
}
override fun toString(): String {
var str = "$name:$tag"
if (children.isNotEmpty()) {
str += END_LINE_STRING
str += children.joinToString(separator = END_LINE_STRING).prependIndent(
INDENT_STRING
)
}
return str
}
@Suppress("UNCHECKED_CAST")
private fun getRightSibling(son: TargetTreeNode): TargetTreeNode? {
if (children.isNotEmpty()) {
val index = (children as List).binarySearch(son as DefaultTargetTreeNode)
if (index >= 0 && index + 1 < children.size) {
return children[index + 1]
}
}
return null
}
@Suppress("UNCHECKED_CAST")
private fun getLeftSibling(son: TargetTreeNode): TargetTreeNode? {
if (children.isNotEmpty()) {
val index = (children as List).binarySearch(son as DefaultTargetTreeNode)
if (index > 0) {
return children[index - 1]
}
}
return null
}
companion object {
const val INDENT_STRING = " "
const val END_LINE_STRING = "\n"
}
override fun compareTo(other: DefaultTargetTreeNode): Int = id.compareTo(other.id)
}