Skip to content

Commit 4085fcc

Browse files
committed
Add tests & minor fixes
1 parent 5b15314 commit 4085fcc

17 files changed

Lines changed: 441 additions & 97 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66

77
group = "vadyushkins"
88

9-
version = "1.0.4"
9+
version = "1.0.5"
1010

1111
repositories { mavenCentral() }
1212

src/main/kotlin/org/kotgll/cfg/grammar/CFGWrite.kt

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,36 @@ import org.kotgll.cfg.grammar.symbol.Terminal
55
import java.io.File
66

77
fun writeCFGToTXT(cfg: Nonterminal, pathToTXT: String) {
8-
val alternatives: ArrayList<Alternative> = ArrayList()
9-
val nonterminals: HashSet<Nonterminal> = HashSet()
8+
val nonterminals: ArrayList<Nonterminal> = ArrayList()
109
val queue: ArrayDeque<Nonterminal> = ArrayDeque(listOf(cfg))
1110
while (!queue.isEmpty()) {
1211
val nonterminal = queue.removeFirst()
13-
nonterminals.add(nonterminal)
12+
if (!nonterminals.contains(nonterminal)) nonterminals.add(nonterminal)
1413
for (alternative in nonterminal.alternatives) {
15-
if (!alternatives.contains(alternative)) alternatives.add(alternative)
1614
for (symbol in alternative.elements) {
1715
if (symbol is Nonterminal) {
18-
if (!nonterminals.contains(symbol)) {
19-
queue.addLast(symbol)
20-
}
16+
if (!nonterminals.contains(symbol)) queue.addLast(symbol)
2117
}
2218
}
2319
}
2420
}
2521

2622
File(pathToTXT).printWriter().use { out ->
2723
out.println("""StartNonterminal("${cfg.name}")""")
28-
alternatives.forEach { alternative ->
29-
var alternativeString = """Nonterminal("${alternative.nonterminal.name}")"""
30-
alternativeString += " ->"
31-
alternative.elements.forEach { element ->
32-
alternativeString += " "
33-
if (element is Terminal) {
34-
alternativeString += """Terminal("${element.value}")"""
35-
} else if (element is Nonterminal) {
36-
alternativeString += """Nonterminal("${element.name}")"""
24+
nonterminals.forEach { nonterminal ->
25+
nonterminal.alternatives.forEach { alternative ->
26+
var alternativeString = """Nonterminal("${alternative.nonterminal.name}")"""
27+
alternativeString += " ->"
28+
alternative.elements.forEach { element ->
29+
alternativeString += " "
30+
if (element is Terminal) {
31+
alternativeString += """Terminal("${element.value}")"""
32+
} else if (element is Nonterminal) {
33+
alternativeString += """Nonterminal("${element.name}")"""
34+
}
3735
}
36+
out.println(alternativeString)
3837
}
39-
out.println(alternativeString)
4038
}
4139
}
4240
}

src/main/kotlin/org/kotgll/rsm/grammar/RSMState.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ class RSMState(
2727
override fun hashCode() = hashCode
2828

2929
fun addTerminalEdge(edge: RSMTerminalEdge) {
30-
outgoingTerminalEdges.add(edge)
30+
if (!outgoingTerminalEdges.contains(edge)) outgoingTerminalEdges.add(edge)
3131
}
3232

3333
fun addNonterminalEdge(edge: RSMNonterminalEdge) {
34-
outgoingNonterminalEdges.add(edge)
34+
if (!outgoingNonterminalEdges.contains(edge)) outgoingNonterminalEdges.add(edge)
3535
}
3636
}

src/main/kotlin/org/kotgll/rsm/grammar/RSMWrite.kt

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,17 @@ package org.kotgll.rsm.grammar
22

33
import java.io.File
44

5-
fun writeRSMToTXT(rsm: RSMState, pathToTXT: String) {
5+
fun writeRSMToTXT(startState: RSMState, pathToTXT: String) {
66
val states: ArrayList<RSMState> = ArrayList()
7-
val edges: HashMap<RSMState, ArrayList<RSMEdge>> = HashMap()
87

9-
val queue: ArrayDeque<RSMState> = ArrayDeque(listOf(rsm))
8+
val queue: ArrayDeque<RSMState> = ArrayDeque(listOf(startState))
109
while (!queue.isEmpty()) {
1110
val v = queue.removeFirst()
12-
states.add(v)
13-
if (!edges.containsKey(v)) edges[v] = ArrayList()
11+
if (!states.contains(v)) states.add(v)
1412
for (edge in v.outgoingTerminalEdges) {
15-
if (!edges[v]!!.contains(edge)) edges[v]!!.add(edge)
1613
if (!states.contains(edge.head)) queue.addLast(edge.head)
1714
}
1815
for (edge in v.outgoingNonterminalEdges) {
19-
if (!edges[v]!!.contains(edge)) edges[v]!!.add(edge)
2016
if (!states.contains(edge.head)) queue.addLast(edge.head)
2117
if (!states.contains(edge.nonterminal.startState)) queue.addLast(edge.nonterminal.startState)
2218
}
@@ -25,45 +21,44 @@ fun writeRSMToTXT(rsm: RSMState, pathToTXT: String) {
2521
File(pathToTXT).printWriter().use { out ->
2622
out.println(
2723
"""StartState(
28-
|id=${rsm.id},
29-
|nonterminal=Nonterminal("${rsm.nonterminal.name}"),
30-
|isStart=${rsm.isStart},
31-
|isFinal=${rsm.isFinal}
32-
|)"""
24+
|id=${startState.id},
25+
|nonterminal=Nonterminal("${startState.nonterminal.name}"),
26+
|isStart=${startState.isStart},
27+
|isFinal=${startState.isFinal}
28+
|)"""
3329
.trimMargin()
3430
.replace("\n", ""))
3531
states.forEach { state ->
3632
out.println(
3733
"""State(
38-
|id=${state.id},
39-
|nonterminal=Nonterminal("${state.nonterminal.name}"),
40-
|isStart=${state.isStart},
41-
|isFinal=${state.isFinal}
42-
|)"""
34+
|id=${state.id},
35+
|nonterminal=Nonterminal("${state.nonterminal.name}"),
36+
|isStart=${state.isStart},
37+
|isFinal=${state.isFinal}
38+
|)"""
4339
.trimMargin()
4440
.replace("\n", ""))
4541
}
4642
states.forEach { state ->
47-
edges[state]?.forEach { edge ->
48-
if (edge is RSMTerminalEdge) {
49-
out.println(
50-
"""TerminalEdge(
51-
|tail=${state.id},
52-
|head=${edge.head.id},
53-
|terminal=Terminal("${edge.terminal.value}")
54-
|)"""
55-
.trimMargin()
56-
.replace("\n", ""))
57-
} else if (edge is RSMNonterminalEdge) {
58-
out.println(
59-
"""NonterminalEdge(
60-
|tail=${state.id},
61-
|head=${edge.head.id},
62-
|nonterminal=Nonterminal("${edge.nonterminal.name}")
63-
|)"""
64-
.trimMargin()
65-
.replace("\n", ""))
66-
}
43+
state.outgoingTerminalEdges.forEach { edge ->
44+
out.println(
45+
"""TerminalEdge(
46+
|tail=${state.id},
47+
|head=${edge.head.id},
48+
|terminal=Terminal("${edge.terminal.value}")
49+
|)"""
50+
.trimMargin()
51+
.replace("\n", ""))
52+
}
53+
state.outgoingNonterminalEdges.forEach { edge ->
54+
out.println(
55+
"""NonterminalEdge(
56+
|tail=${state.id},
57+
|head=${edge.head.id},
58+
|nonterminal=Nonterminal("${edge.nonterminal.name}")
59+
|)"""
60+
.trimMargin()
61+
.replace("\n", ""))
6762
}
6863
}
6964
}

src/test/kotlin/cli/TestCFGReadWriteTXT.kt

Lines changed: 120 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,12 @@ class TestCFGReadWriteTXT {
5555
fun `'g1' cfg`() {
5656
val nonterminalS = Nonterminal("S")
5757
nonterminalS.addAlternative(
58-
Alternative(
59-
listOf(
60-
Terminal("subClassOf_r"),
61-
nonterminalS,
62-
Terminal("subClassOf"),
63-
)))
58+
Alternative(listOf(Terminal("subClassOf_r"), nonterminalS, Terminal("subClassOf"))))
6459
nonterminalS.addAlternative(
65-
Alternative(
66-
listOf(
67-
Terminal("subClassOf_r"),
68-
Terminal("subClassOf"),
69-
)))
70-
nonterminalS.addAlternative(
71-
Alternative(
72-
listOf(
73-
Terminal("type_r"),
74-
nonterminalS,
75-
Terminal("type"),
76-
)))
60+
Alternative(listOf(Terminal("subClassOf_r"), Terminal("subClassOf"))))
7761
nonterminalS.addAlternative(
78-
Alternative(
79-
listOf(
80-
Terminal("type_r"),
81-
Terminal("type"),
82-
)))
62+
Alternative(listOf(Terminal("type_r"), nonterminalS, Terminal("type"))))
63+
nonterminalS.addAlternative(Alternative(listOf(Terminal("type_r"), Terminal("type"))))
8364

8465
val pathToTXT = "src/test/resources/cli/TestCFGReadWriteTXT/g1.txt"
8566
writeCFGToTXT(nonterminalS, pathToTXT)
@@ -93,17 +74,8 @@ class TestCFGReadWriteTXT {
9374
fun `'g2' cfg`() {
9475
val nonterminalS = Nonterminal("S")
9576
nonterminalS.addAlternative(
96-
Alternative(
97-
listOf(
98-
Terminal("subClassOf_r"),
99-
nonterminalS,
100-
Terminal("subClassOf"),
101-
)))
102-
nonterminalS.addAlternative(
103-
Alternative(
104-
listOf(
105-
Terminal("subClassOf"),
106-
)))
77+
Alternative(listOf(Terminal("subClassOf_r"), nonterminalS, Terminal("subClassOf"))))
78+
nonterminalS.addAlternative(Alternative(listOf(Terminal("subClassOf"))))
10779

10880
val pathToTXT = "src/test/resources/cli/TestCFGReadWriteTXT/g2.txt"
10981
writeCFGToTXT(nonterminalS, pathToTXT)
@@ -137,4 +109,118 @@ class TestCFGReadWriteTXT {
137109
assertEquals(expected = nonterminalS, actual = actualNonterminal)
138110
assertEquals(expected = nonterminalS.alternatives, actual = actualNonterminal.alternatives)
139111
}
112+
113+
@Test
114+
fun `'c_analysis' rsm`() {
115+
val nonterminalS = Nonterminal("S")
116+
val nonterminalV = Nonterminal("V")
117+
val nonterminalV1 = Nonterminal("V1")
118+
val nonterminalV2 = Nonterminal("V2")
119+
val nonterminalV3 = Nonterminal("V3")
120+
121+
nonterminalS.addAlternative(Alternative(listOf(Terminal("d_r"), nonterminalV, Terminal("d"))))
122+
nonterminalV.addAlternative(Alternative(listOf(nonterminalV1, nonterminalV2, nonterminalV3)))
123+
nonterminalV1.addAlternative(Alternative(listOf()))
124+
nonterminalV1.addAlternative(Alternative(listOf(nonterminalV2, Terminal("a_r"), nonterminalV1)))
125+
nonterminalV2.addAlternative(Alternative(listOf()))
126+
nonterminalV2.addAlternative(Alternative(listOf(nonterminalS)))
127+
nonterminalV3.addAlternative(Alternative(listOf()))
128+
nonterminalV3.addAlternative(Alternative(listOf(Terminal("a"), nonterminalV2, nonterminalV3)))
129+
130+
val pathToTXT = "src/test/resources/cli/TestCFGReadWriteTXT/c_analysis.txt"
131+
writeCFGToTXT(nonterminalS, pathToTXT)
132+
val actualNonterminal = readCFGFromTXT(pathToTXT)
133+
134+
assertEquals(expected = nonterminalS, actual = actualNonterminal)
135+
assertEquals(expected = nonterminalS.alternatives, actual = actualNonterminal.alternatives)
136+
}
137+
138+
@Test
139+
fun `'reg1' cfg`() {
140+
val nonterminalS = Nonterminal("S")
141+
142+
nonterminalS.addAlternative(Alternative(listOf()))
143+
nonterminalS.addAlternative(Alternative(listOf(Terminal("type"))))
144+
nonterminalS.addAlternative(Alternative(listOf(Terminal("subClassOf"))))
145+
nonterminalS.addAlternative(Alternative(listOf(nonterminalS, nonterminalS)))
146+
147+
val pathToTXT = "src/test/resources/cli/TestCFGReadWriteTXT/reg1.txt"
148+
writeCFGToTXT(nonterminalS, pathToTXT)
149+
val actualNonterminal = readCFGFromTXT(pathToTXT)
150+
151+
assertEquals(expected = nonterminalS, actual = actualNonterminal)
152+
assertEquals(expected = nonterminalS.alternatives, actual = actualNonterminal.alternatives)
153+
}
154+
155+
@Test
156+
fun `'reg2' cfg`() {
157+
val nonterminalS = Nonterminal("S")
158+
159+
nonterminalS.addAlternative(Alternative(listOf()))
160+
nonterminalS.addAlternative(Alternative(listOf(Terminal("type"))))
161+
nonterminalS.addAlternative(Alternative(listOf(Terminal("type_r"))))
162+
nonterminalS.addAlternative(Alternative(listOf(Terminal("subClassOf"))))
163+
nonterminalS.addAlternative(Alternative(listOf(Terminal("subClassOf_r"))))
164+
nonterminalS.addAlternative(Alternative(listOf(nonterminalS, nonterminalS)))
165+
166+
val pathToTXT = "src/test/resources/cli/TestCFGReadWriteTXT/reg2.txt"
167+
writeCFGToTXT(nonterminalS, pathToTXT)
168+
val actualNonterminal = readCFGFromTXT(pathToTXT)
169+
170+
assertEquals(expected = nonterminalS, actual = actualNonterminal)
171+
assertEquals(expected = nonterminalS.alternatives, actual = actualNonterminal.alternatives)
172+
}
173+
174+
@Test
175+
fun `'reg3' cfg`() {
176+
val nonterminalS = Nonterminal("S")
177+
val nonterminalA = Nonterminal("A")
178+
val nonterminalB = Nonterminal("B")
179+
180+
nonterminalS.addAlternative(Alternative(listOf(nonterminalA, nonterminalB)))
181+
182+
nonterminalA.addAlternative(Alternative(listOf()))
183+
nonterminalA.addAlternative(Alternative(listOf(Terminal("type"), nonterminalA)))
184+
185+
nonterminalB.addAlternative(Alternative(listOf()))
186+
nonterminalB.addAlternative(Alternative(listOf(Terminal("subClassOf"), nonterminalB)))
187+
188+
val pathToTXT = "src/test/resources/cli/TestCFGReadWriteTXT/reg3.txt"
189+
writeCFGToTXT(nonterminalS, pathToTXT)
190+
val actualNonterminal = readCFGFromTXT(pathToTXT)
191+
192+
assertEquals(expected = nonterminalS, actual = actualNonterminal)
193+
assertEquals(expected = nonterminalS.alternatives, actual = actualNonterminal.alternatives)
194+
}
195+
196+
@Test
197+
fun `'reg5' cfg`() {
198+
val nonterminalS = Nonterminal("S")
199+
val nonterminalA = Nonterminal("A")
200+
val nonterminalB = Nonterminal("B")
201+
val nonterminalC = Nonterminal("C")
202+
val nonterminalD = Nonterminal("D")
203+
204+
nonterminalS.addAlternative(
205+
Alternative(listOf(nonterminalA, nonterminalB, nonterminalC, nonterminalD)))
206+
207+
nonterminalA.addAlternative(Alternative(listOf()))
208+
nonterminalA.addAlternative(Alternative(listOf(Terminal("type"), nonterminalA)))
209+
210+
nonterminalB.addAlternative(Alternative(listOf()))
211+
nonterminalB.addAlternative(Alternative(listOf(Terminal("subClassOf"), nonterminalB)))
212+
213+
nonterminalC.addAlternative(Alternative(listOf()))
214+
nonterminalC.addAlternative(Alternative(listOf(Terminal("subClassOf_r"), nonterminalC)))
215+
216+
nonterminalD.addAlternative(Alternative(listOf()))
217+
nonterminalD.addAlternative(Alternative(listOf(Terminal("type_r"), nonterminalD)))
218+
219+
val pathToTXT = "src/test/resources/cli/TestCFGReadWriteTXT/reg4.txt"
220+
writeCFGToTXT(nonterminalS, pathToTXT)
221+
val actualNonterminal = readCFGFromTXT(pathToTXT)
222+
223+
assertEquals(expected = nonterminalS, actual = actualNonterminal)
224+
assertEquals(expected = nonterminalS.alternatives, actual = actualNonterminal.alternatives)
225+
}
140226
}

0 commit comments

Comments
 (0)