mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 21:21:33 +00:00
parser: use ast user data to store attribution
This commit is contained in:
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user