Skip to content

Commit 870fe2d

Browse files
committed
Fix recursive sppf
1 parent 3ba3284 commit 870fe2d

File tree

11 files changed

+87
-95
lines changed

11 files changed

+87
-95
lines changed

solver/src/main/kotlin/org/ucfs/descriptors/DescriptorsStorage.kt

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,16 @@ import org.ucfs.parser.ParsingException
66
* Collection of default descriptors
77
* @param VertexType - type of vertex in input graph
88
*/
9-
open class DescriptorsStorage<VertexType>{
9+
open class DescriptorsStorage<VertexType> {
1010
/**
1111
* Collection of already handled descriptors, accessible via descriptor's hashcode
1212
*/
13-
private val handledDescriptors = ArrayList<Descriptor<VertexType>>()
13+
private val handledDescriptors = HashSet<Descriptor<VertexType>>()
1414

1515
private val descriptorsToHandle = ArrayDeque<Descriptor<VertexType>>()
1616

1717
private fun isEmpty() = descriptorsToHandle.isEmpty()
1818

19-
private fun addToHandling(descriptor: Descriptor<VertexType>) {
20-
if (!isAlreadyHandled(descriptor)) {
21-
descriptorsToHandle.addLast(descriptor)
22-
}
23-
}
24-
2519
/**
2620
* @return next default descriptor to handle
2721
*/
@@ -32,23 +26,13 @@ open class DescriptorsStorage<VertexType>{
3226
return descriptorsToHandle.removeLast()
3327
}
3428

35-
/**
36-
* @param descriptor - descriptor to check
37-
* @return true if the descriptor was already processed, false otherwise
38-
*/
39-
private fun isAlreadyHandled(descriptor: Descriptor<VertexType>): Boolean {
40-
val handledDescriptor = handledDescriptors.find { descriptor.hashCode() == it.hashCode() }
41-
42-
return handledDescriptor != null
43-
}
44-
4529
fun addToHandled(descriptor: Descriptor<VertexType>) {
4630
handledDescriptors.add(descriptor)
4731
}
4832

4933
fun add(descriptor: Descriptor<VertexType>) {
50-
if(!isAlreadyHandled(descriptor)){
51-
addToHandling(descriptor)
34+
if(!handledDescriptors.contains(descriptor)){
35+
descriptorsToHandle.addLast(descriptor)
5236
}
5337
}
5438
/**

solver/src/main/kotlin/org/ucfs/gss/GraphStructuredStack.kt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,11 @@ import org.ucfs.rsm.RsmState
55
import org.ucfs.sppf.node.RangeSppfNode
66

77
class GraphStructuredStack<InputNode> {
8-
val nodes = ArrayList<GssNode<InputNode>>()
8+
val nodes = HashMap<GssNode<InputNode>, GssNode<InputNode>>()
99

1010
fun getOrCreateNode(input: InputNode, rsm: RsmState): GssNode<InputNode> {
11-
val node = findNode(input, rsm)
12-
return if (node == null) GssNode(rsm, input) else node
13-
}
14-
15-
fun findNode(input: InputNode, rsm: RsmState): GssNode<InputNode>? {
16-
return nodes.find { node -> node.inputPosition == input && node.rsm == rsm }
11+
val node = GssNode(rsm, input)
12+
return nodes.getOrPut(node, {node})
1713
}
1814

1915
fun addEdge(

solver/src/main/kotlin/org/ucfs/gss/GssNode.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.ucfs.gss
22

3-
import org.ucfs.descriptors.Descriptor
43
import org.ucfs.rsm.RsmState
54
import org.ucfs.sppf.node.RangeSppfNode
65
import java.util.*
@@ -20,9 +19,10 @@ data class GssNode<InputNodeType>(
2019
/**
2120
* Pointer to vertex in input graph
2221
*/
23-
val inputPosition: InputNodeType, val id: Int = lastId++
22+
val inputPosition: InputNodeType,
2423

2524
) {
25+
val id: Int = lastId++
2626
val popped = ArrayList<RangeSppfNode<InputNodeType>>()
2727

2828
val outgoingEdges = ArrayList<GssEdge<InputNodeType>>()
@@ -32,7 +32,6 @@ data class GssNode<InputNodeType>(
3232
*/
3333
fun addEdge(edge: GssEdge<InputNodeType>): ArrayList<RangeSppfNode<InputNodeType>> {
3434
outgoingEdges.add(edge)
35-
//TODO
3635
return popped
3736
}
3837

solver/src/main/kotlin/org/ucfs/parser/Gll.kt

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,30 +42,24 @@ class Gll<VertexType, LabelType : ILabel> private constructor(
4242
descriptor.rsmState,
4343
descriptor.rsmState,
4444
)
45-
val range = ctx.sppfStorage.addNode(RangeSppfNode(input, rsm, Range))
46-
val epsilon = ctx.sppfStorage.addNode(
47-
RangeSppfNode(input, rsm, EpsilonNonterminalType(descriptor.gssNode.rsm))
48-
)
49-
range.children.add(epsilon)
50-
return range
45+
return ctx.sppfStorage.addEpsilonNode(input, rsm, descriptor.gssNode.rsm)
5146
}
5247

5348
private fun handlePoppedGssEdge(
5449
poppedGssEdge: GssEdge<VertexType>, descriptor: Descriptor<VertexType>, childSppf: RangeSppfNode<VertexType>
5550
) {
5651
val leftRange = poppedGssEdge.matchedRange
57-
val startRsmState = if (poppedGssEdge.matchedRange.type == EmptyType) poppedGssEdge.gssNode.rsm
52+
val startRsmState = if (poppedGssEdge.matchedRange.type is EmptyType) poppedGssEdge.gssNode.rsm
5853
else poppedGssEdge.matchedRange.rsmRange!!.to
59-
val rightRange = ctx.sppfStorage.addNode(
54+
val rightRange = ctx.sppfStorage.addNonterminalNode(
6055
InputRange(
6156
descriptor.gssNode.inputPosition, descriptor.inputPosition
6257
), RsmRange(
6358
startRsmState,
6459
poppedGssEdge.state,
6560
), descriptor.gssNode.rsm, childSppf
6661
)
67-
ctx.sppfStorage.addNode(rightRange)
68-
val newRange = ctx.sppfStorage.addNode(leftRange, rightRange)
62+
val newRange = ctx.sppfStorage.addIntermediateNode(leftRange, rightRange)
6963
val newDescriptor = Descriptor(
7064
descriptor.inputPosition, poppedGssEdge.gssNode, poppedGssEdge.state, newRange
7165
)
@@ -78,9 +72,19 @@ class Gll<VertexType, LabelType : ILabel> private constructor(
7872
*/
7973
override fun handleDescriptor(descriptor: Descriptor<VertexType>) {
8074
ctx.descriptors.addToHandled(descriptor)
75+
println("input: ${descriptor.inputPosition}")
76+
println("gss: ${descriptor.gssNode.id}")
77+
println("rsm: ${descriptor.rsmState.id}")
78+
println("sppf: ${descriptor.sppfNode.id}")
8179
if (descriptor.rsmState.isFinal) {
82-
val matchedRange = if (descriptor.sppfNode.type == EmptyType) {
83-
getEpsilonRange(descriptor)
80+
val matchedRange = if (descriptor.sppfNode.type is EmptyType) {
81+
val node = getEpsilonRange(descriptor)
82+
//TODO fix
83+
// dirty hack: in fact it's equivavelnt descriptors
84+
// but only initial was added in handlet set
85+
ctx.descriptors.addToHandled(Descriptor(descriptor.inputPosition,
86+
descriptor.gssNode, descriptor.rsmState, node))
87+
node
8488
} else {
8589
descriptor.sppfNode
8690
}

solver/src/main/kotlin/org/ucfs/parser/IGll.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,13 @@ interface IGll<InputNodeType, LabelType : ILabel> {
7575

7676
for (rangeToPop in positionToPops) {
7777
val leftSubRange = descriptor.sppfNode
78-
val rightSubRange = ctx.sppfStorage.addNode(
79-
RangeSppfNode(
80-
rangeToPop.inputRange, RsmRange(
78+
val rightSubRange = ctx.sppfStorage.addNonterminalNode(
79+
rangeToPop.inputRange!!, RsmRange(
8180
descriptor.rsmState, destinationRsmState
82-
), NonterminalType(rsmStartState)
81+
), rsmStartState
8382
)
84-
)
85-
val newSppfNode = ctx.sppfStorage.addNode(leftSubRange, rightSubRange)
83+
84+
val newSppfNode = ctx.sppfStorage.addIntermediateNode(leftSubRange, rightSubRange)
8685

8786
//TODO why these parameters???
8887
newDescriptor = Descriptor(
@@ -108,7 +107,7 @@ interface IGll<InputNodeType, LabelType : ILabel> {
108107
destinationRsmState,
109108
), terminal
110109
)
111-
val intermediateOrTerminalSppf = ctx.sppfStorage.addNode(descriptor.sppfNode, terminalSppfNode)
110+
val intermediateOrTerminalSppf = ctx.sppfStorage.addIntermediateNode(descriptor.sppfNode, terminalSppfNode)
112111
val descriptorForTerminal = Descriptor(
113112
inputEdge.targetVertex, descriptor.gssNode, destinationRsmState, intermediateOrTerminalSppf
114113
)

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,30 @@ open class SppfStorage<InputEdgeType> {
1414
private val createdSppfNodes: HashMap<RangeSppfNode<InputEdgeType>, RangeSppfNode<InputEdgeType>> = HashMap()
1515

1616

17-
fun addNode(node: RangeSppfNode<InputEdgeType>): RangeSppfNode<InputEdgeType> {
17+
private fun addNode(node: RangeSppfNode<InputEdgeType>): RangeSppfNode<InputEdgeType> {
1818
return createdSppfNodes.getOrPut(node, { node })
1919
}
2020

2121
/**
2222
* Add nonterminal node after pop
2323
*/
24-
fun addNode(
25-
input: InputRange<InputEdgeType>, rsm: RsmRange, startState: RsmState, childSppf: RangeSppfNode<InputEdgeType>
24+
fun addNonterminalNode(
25+
input: InputRange<InputEdgeType>,
26+
rsm: RsmRange,
27+
startState: RsmState,
28+
childSppf: RangeSppfNode<InputEdgeType>? = null
2629
): RangeSppfNode<InputEdgeType> {
27-
return addNode(input, rsm, NonterminalType(startState), listOf(childSppf))
30+
return if (childSppf == null) addNode(input, rsm, NonterminalType(startState))
31+
else addNode(input, rsm, NonterminalType(startState), listOf(childSppf))
32+
}
33+
34+
fun addEpsilonNode(
35+
input: InputRange<InputEdgeType>,
36+
rsmRange: RsmRange,
37+
rsmState: RsmState
38+
): RangeSppfNode<InputEdgeType> {
39+
return addNode(
40+
input, rsmRange, EpsilonNonterminalType(rsmState))
2841
}
2942

3043
/**
@@ -36,11 +49,11 @@ open class SppfStorage<InputEdgeType> {
3649
return addNode(input, rsm, TerminalType(terminal))
3750
}
3851

39-
fun addNode(
52+
fun addIntermediateNode(
4053
leftSubtree: RangeSppfNode<InputEdgeType>,
4154
rightSubtree: RangeSppfNode<InputEdgeType>
4255
): RangeSppfNode<InputEdgeType> {
43-
if (leftSubtree.type == EmptyType) {
56+
if (leftSubtree.type is EmptyType) {
4457
return rightSubtree
4558
}
4659
return addNode(

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ data class RangeSppfNode<VertexType>(
2626
val children = ArrayList<RangeSppfNode<VertexType>>()
2727
}
2828

29-
fun <VertexType> getEmptyRange(): RangeSppfNode<VertexType> = RangeSppfNode(null, null, EmptyType)
29+
fun <VertexType> getEmptyRange(): RangeSppfNode<VertexType> = RangeSppfNode(null, null, EmptyType())
3030

3131
data class InputRange<VertexType>(
3232
val from: VertexType,
@@ -39,10 +39,10 @@ data class RsmRange(
3939
)
4040

4141
interface RangeType
42-
42+
var lastEmptyId = 0
4343
object Range : RangeType
4444
data class TerminalType<T : ITerminal>(val terminal: T) : RangeType
4545
data class NonterminalType(val startState: RsmState) : RangeType
4646
data class EpsilonNonterminalType(val startState: RsmState) : RangeType
4747
data class IntermediateType<VertexType>(val grammarSlot: RsmState, val inputPosition: VertexType) : RangeType
48-
object EmptyType : RangeType
48+
data class EmptyType(private val id: Int = lastEmptyId++) : RangeType

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@ fun <InputNode> getSppfDot(sppfNode: RangeSppfNode<InputNode>, label: String = "
2323
sb.appendLine("digraph g {")
2424
sb.appendLine("labelloc=\"t\"")
2525
sb.appendLine("label=\"$label\"")
26-
var nextNodeId = 0
2726
val nodeViews = HashMap<RangeSppfNode<InputNode>, String>()
2827
while (queue.isNotEmpty()) {
2928
node = queue.removeFirst()
3029
if (!visited.add(node.hashCode())) continue
3130

32-
nodeViews[node] = getNodeView(node)
31+
nodeViews[node] = getNodeView(node, )
3332

3433
node.children.forEach {
3534
queue.addLast(it)
@@ -66,51 +65,51 @@ enum class NodeShape(val view: String) {
6665
}
6766

6867
fun fillNodeTemplate(
69-
nodeInfo: String, inputRange: InputRange<*>?, shape: NodeShape, rsmRange: RsmRange? = null
68+
id: String? = null, nodeInfo: String, inputRange: InputRange<*>?, shape: NodeShape, rsmRange: RsmRange? = null
7069
): String {
7170
val inputRangeView = if (inputRange != null) "input: [${inputRange.from}, ${inputRange.to}]" else null
7271
val rsmRangeView = if (rsmRange != null) "rsm: [${rsmRange.from.id}, ${rsmRange.to.id}]" else null
7372
val view = listOfNotNull(nodeInfo, inputRangeView, rsmRangeView).joinToString(", ")
74-
return "[label = \"${shape.name} $view\", shape = ${shape.view}]"
73+
return "[label = \" ${id ?: ""} ${shape.name} $view\", shape = ${shape.view}]"
7574
}
7675

7776

78-
fun <InputNode> getNodeView(node: RangeSppfNode<InputNode>): String {
77+
fun <InputNode> getNodeView(node: RangeSppfNode<InputNode>, id: String? = null): String {
7978
val type = node.type
8079
return when (type) {
8180
is TerminalType<*> -> {
8281
fillNodeTemplate(
83-
"'${type.terminal}'", node.inputRange, NodeShape.Terminal
82+
id, "'${type.terminal}'", node.inputRange, NodeShape.Terminal
8483
)
8584
}
8685

8786
is NonterminalType -> {
8887
fillNodeTemplate(
89-
"${type.startState.nonterminal.name}", node.inputRange, NodeShape.Nonterminal
88+
id, "${type.startState.nonterminal.name}", node.inputRange, NodeShape.Nonterminal
9089
)
9190
}
9291

9392
is IntermediateType<*> -> {
9493
fillNodeTemplate(
95-
"input: ${type.inputPosition}, rsm: ${type.grammarSlot.id}", null, NodeShape.Intermediate
94+
id, "input: ${type.inputPosition}, rsm: ${type.grammarSlot.id}", null, NodeShape.Intermediate
9695
)
9796
}
9897

9998
is EmptyType -> {
10099
fillNodeTemplate(
101-
"", null, NodeShape.Empty
100+
id, "", null, NodeShape.Empty
102101
)
103102
}
104103

105104
is EpsilonNonterminalType -> {
106105
fillNodeTemplate(
107-
"RSM: ${type.startState.id}", node.inputRange, NodeShape.Epsilon
106+
id, "RSM: ${type.startState.id}", node.inputRange, NodeShape.Epsilon
108107
)
109108
}
110109

111110
is RangeType -> {
112111
fillNodeTemplate(
113-
"", node.inputRange, NodeShape.Range, node.rsmRange
112+
id, "", node.inputRange, NodeShape.Range, node.rsmRange
114113
)
115114
}
116115

test-shared/src/test/kotlin/grammars/SimpleDyck.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class LoopDyck : Grammar() {
1818
val S by Nt().asStart()
1919

2020
init {
21-
S /= Option("(" * S * ")")
21+
S /= Many( "(" * S * ")")
2222
}
2323
}
2424

test-shared/src/test/kotlin/solver/AbstractCorrectnessTest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ abstract class AbstractCorrectnessTest {
1313

1414
abstract fun getRootDataFolder(): Path
1515

16-
val grammars = listOf(SimplifiedDyck(), ABGrammar(), SALang(), Epsilon())
17-
//val grammars = listOf(LoopDyck())
16+
val grammars = listOf(SimplifiedDyck(), ABGrammar(), SALang(), Epsilon(), LoopDyck())
1817

1918
//@TestFactory
2019
//TODO make it abstract by used grammar

0 commit comments

Comments
 (0)