Skip to content

Commit 6840a43

Browse files
committed
fix_sppf_bug: Dot create, without wrong nodes. We dot die on AmbiguiusAStart2
1 parent a22e1fb commit 6840a43

File tree

3 files changed

+76
-31
lines changed

3 files changed

+76
-31
lines changed

solver/src/main/kotlin/org/ucfs/sppf/SppfStorage.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ open class SppfStorage<InputEdgeType> {
1616

1717

1818
private fun addNode(node: RangeSppfNode<InputEdgeType>): RangeSppfNode<InputEdgeType> {
19-
20-
val sppfNode = createdSppfNodes.getOrPut(node) { node }
21-
return sppfNode
19+
return createdSppfNodes.getOrPut(node, { node })
2220
}
2321

2422
/**

solver/src/main/kotlin/org/ucfs/sppf/node/RangeSppfNode.kt

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,23 @@ import org.ucfs.rsm.symbol.ITerminal
1515
* May be used as extended packed sppfNode.
1616
* @param VertexType - type of vertex in input graph
1717
*/
18+
var lastId = 0
19+
1820
data class RangeSppfNode<VertexType>(
1921
val inputRange: InputRange<VertexType>?,
2022
val rsmRange: RsmRange?,
2123
val type: RangeType,
2224
) {
2325
val id: Int = lastId++
2426
val children = ArrayList<RangeSppfNode<VertexType>>()
25-
override fun toString(): String {
26-
return when (type) {
27-
is TerminalType<*> -> "Terminal `${type.terminal}` $inputRange"
28-
is Range -> "Range $inputRange $rsmRange"
29-
is NonterminalType -> "Nonterminal ${type.startState.nonterminal.name} $inputRange $rsmRange"
30-
is IntermediateType<*> -> "Intermediate input:${type.inputPosition} rsm:${type.grammarSlot.id}"
31-
is EpsilonNonterminalType -> "Epsilon ${type.startState.id}"
32-
is EmptyType -> "Empty node"
33-
else -> "Unknown sppf node type!"
34-
}
35-
}
3627
}
3728

38-
fun <VertexType> getEmptyRange(): RangeSppfNode<VertexType> {
39-
return RangeSppfNode(null, null, EmptyType())
29+
fun <VertexType> getEmptyRange(isStart: Boolean = false): RangeSppfNode<VertexType> {
30+
val type = EmptyType()
31+
if(isStart) {
32+
type.isStart = isStart
33+
}
34+
return RangeSppfNode(null, null, type)
4035
}
4136

4237
data class InputRange<VertexType>(
@@ -60,6 +55,16 @@ data class TerminalType<T : ITerminal>(val terminal: T) : RangeType
6055
data class NonterminalType(val startState: RsmState) : RangeType
6156
data class EpsilonNonterminalType(val startState: RsmState) : RangeType
6257
data class IntermediateType<VertexType>(val grammarSlot: RsmState, val inputPosition: VertexType) : RangeType
63-
class EmptyType : RangeType
58+
class EmptyType : RangeType {
59+
var isStart = false
6460

65-
var lastId = 0
61+
@Override
62+
override fun equals(other: Any?): Boolean {
63+
return other is EmptyType
64+
}
65+
66+
@Override
67+
override fun hashCode(): Int {
68+
return 12
69+
}
70+
}

solver/src/main/kotlin/org/ucfs/sppf/writeSppfToDot.kt

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,62 @@ enum class NodeShape(val view: String) {
8080
)
8181
}
8282

83-
fun getNodeView(node: RangeSppfNode<*>, id: String): String {
84-
val shape = getNodeShape(node.type)
85-
val idView = if (printWithId) "$id " else ""
86-
return "[label = \"$idView${node}\", shape = ${shape.view}]"
83+
fun fillNodeTemplate(
84+
id: String? = null, nodeInfo: String, inputRange: InputRange<*>?, shape: NodeShape, rsmRange: RsmRange? = null
85+
): String {
86+
val inputRangeView = if (inputRange != null) "input: [${inputRange.from}, ${inputRange.to}]" else null
87+
val rsmRangeView = if (rsmRange != null) "rsm: [${rsmRange.from.id}, ${rsmRange.to.id}]" else null
88+
val view = listOfNotNull(nodeInfo, inputRangeView, rsmRangeView).joinToString(", ")
89+
return "[label = \"${id?: ""}${shape.name} $view\", shape = ${shape.view}]"
8790
}
8891

89-
fun getNodeShape(rangeType: RangeType): NodeShape {
90-
return when (rangeType) {
91-
is TerminalType<*> -> NodeShape.Terminal
92-
is NonterminalType -> NodeShape.Nonterminal
93-
is IntermediateType<*> -> NodeShape.Intermediate
94-
is EmptyType -> NodeShape.Empty
95-
is EpsilonNonterminalType -> NodeShape.Epsilon
96-
is Range -> NodeShape.Range
97-
else -> throw IllegalStateException("Can't write node type $rangeType to DOT")
92+
fun <InputNode> getNodeView(node: RangeSppfNode<InputNode>, id: String? = null): String {
93+
val type = node.type
94+
return when (type) {
95+
is TerminalType<*> -> {
96+
fillNodeTemplate(
97+
id, "'${type.terminal}'", node.inputRange, NodeShape.Terminal
98+
)
99+
}
100+
101+
is NonterminalType -> {
102+
fillNodeTemplate(
103+
id, "${type.startState.nonterminal.name}", node.inputRange, NodeShape.Nonterminal
104+
)
105+
}
106+
107+
is IntermediateType<*> -> {
108+
fillNodeTemplate(
109+
id, "input: ${type.inputPosition}, rsm: ${type.grammarSlot.id}", node.inputRange, NodeShape.Intermediate
110+
)
111+
}
112+
113+
is EmptyType -> {
114+
fillNodeTemplate(
115+
id, "", null, NodeShape.Empty
116+
)
117+
}
118+
119+
is EpsilonNonterminalType -> {
120+
fillNodeTemplate(
121+
id, "RSM: ${type.startState.id}", node.inputRange, NodeShape.Epsilon
122+
)
123+
}
124+
125+
is RangeType -> {
126+
fillNodeTemplate(
127+
id, "", node.inputRange, NodeShape.Range, node.rsmRange
128+
)
129+
}
130+
131+
else -> throw IllegalStateException("Can't write node type $type to DOT")
132+
98133
}
134+
135+
136+
}
137+
138+
private fun getView(range: RsmRange?): String {
139+
if (range == null) return ""
140+
return "rsm: [(${range.from.nonterminal.name}:${range.from.numId}), " + "(${range.to.nonterminal.name}:${range.to.numId})]"
99141
}

0 commit comments

Comments
 (0)