parser: use ast user data to store attribution

This commit is contained in:
2023-09-11 20:13:15 -04:00
parent a07e0fe672
commit b64c7fb259
11 changed files with 129 additions and 65 deletions

View File

@ -2,6 +2,7 @@ package gay.pizza.pork.parser
import gay.pizza.pork.ast.*
@Suppress("SameParameterValue")
class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
private val unsanitizedSource = source

View File

@ -0,0 +1,23 @@
package gay.pizza.pork.parser
import gay.pizza.pork.ast.Node
import gay.pizza.pork.ast.NodeCoalescer
import gay.pizza.pork.ast.data
import gay.pizza.pork.ast.visit
data class ParserAttributes(val tokens: List<Token>) {
companion object {
fun recallAllTokens(node: Node): List<Token> {
val all = mutableListOf<Token>()
val coalescer = NodeCoalescer { item ->
val attributes = item.data<ParserAttributes>()
if (attributes != null) {
all.addAll(attributes.tokens)
}
}
coalescer.visit(node)
all.sortBy { it.start }
return all
}
}
}

View File

@ -0,0 +1,37 @@
package gay.pizza.pork.parser
import gay.pizza.pork.ast.Node
import gay.pizza.pork.ast.data
class ParserNodeAttribution : NodeAttribution {
private val stack = mutableListOf<MutableList<Token>>()
private var current: MutableList<Token>? = null
override fun enter() {
val store = mutableListOf<Token>()
current = store
stack.add(store)
}
override fun push(token: Token) {
val store = current ?: throw RuntimeException("enter() not called!")
store.add(token)
}
override fun <T : Node> adopt(node: T) {
val attributes = node.data<ParserAttributes>()
if (attributes != null) {
for (token in attributes.tokens) {
push(token)
}
node.data = ParserAttributes(emptyList())
}
}
override fun <T: Node> exit(node: T): T {
val store = stack.removeLast()
current = stack.lastOrNull()
node.data = ParserAttributes(store)
return node
}
}

View File

@ -1,54 +0,0 @@
package gay.pizza.pork.parser
import gay.pizza.pork.ast.NodeCoalescer
import gay.pizza.pork.ast.Node
import gay.pizza.pork.ast.visit
import java.util.IdentityHashMap
class TokenNodeAttribution : NodeAttribution {
val nodes: MutableMap<Node, List<Token>> = IdentityHashMap()
private val stack = mutableListOf<MutableList<Token>>()
private var current: MutableList<Token>? = null
override fun enter() {
val store = mutableListOf<Token>()
current = store
stack.add(store)
}
override fun push(token: Token) {
val store = current ?: throw RuntimeException("enter() not called!")
store.add(token)
}
override fun <T : Node> adopt(node: T) {
val tokens = nodes.remove(node)
if (tokens != null) {
for (token in tokens) {
push(token)
}
}
}
override fun <T: Node> exit(node: T): T {
val store = stack.removeLast()
nodes[node] = store
current = stack.lastOrNull()
return node
}
fun tokensOf(node: Node): List<Token>? = nodes[node]
fun assembleTokens(node: Node): List<Token> {
val allTokens = mutableListOf<Token>()
val coalescer = NodeCoalescer { item ->
val tokens = tokensOf(item)
if (tokens != null) {
allTokens.addAll(tokens)
}
}
coalescer.visit(node)
return allTokens.asSequence().distinct().sortedBy { it.start }.toList()
}
}