测试数据:
1 E->E+T
2 E->T
3 T->T*F
4 T->F
5 F->(E)
6 F->i
代码:
无GUI代码(Scala):
1 import scala.collection.immutable.Stack
2 import scala.collection.mutable
3 import scala.collection.mutable.{ArrayBuffer, Map}
4 import scala.util.matching.Regex
5
6
7
8
9 object LR_1 {
10 private final var allCharacters = new String()
11 private final var relations = new ArrayBuffer[ (String, String, String) ]()
12 private final var VN = new String()
13 private final var VT = new String()
14 private final var rowLength = 0
15 private final var columnLength = 0
16 private final val itemGroup = Map[ ArrayBuffer[ (String, String, String) ], Int ]()
17 private final var LL1_G = new ArrayBuffer[ (String, String) ]()
18 //private val allCandidateLetters = "αΑβΒγΓδΔεΕζΖηΗθΘιΙκΚλΛμΜνΝξΞοΟπΠρΡσΣτΤυΥφΦχΧψΨωΩ" + "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
19 private val allCandidateLetters = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩABCDEFGHIJKLMNOPQRSTUVWXYZ"
20 private final var usedCharacters = ""
21 // private val LL1_G = ArrayBuffer( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"),
22 // ("S", "ε"), ("F", "(E)"), ("F", "i") )//, ("Y", "*FS|/FS"), ("Y", "+TG|-TG"), ("Y", "x"), ("Y", "M"), ("M", "i"), ("M", "ε") )
23 // test data 1:
24 // ( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"),
25 // ("S", "ε"), ("F", "(E)"), ("F", "i"), ("Y", "S"), ("Y", "Gx"), ("Y", "x"), ("Y", "M"), ("M", "i"), ("M", "ε") )
26 // test data 2:
27 // ( ("D", "*FD"), ("D", "ε"), ("T", "FD"), ("E", "TC"), ("F", "(E)"), ("F", "i"), ("C", "+TC"), ("C", "ε") )
28 // test data 3:
29 // ( ("E", "E+T|T"), ("T", "T*F|T"), ("F", "(E)|i") )
30 // stand test data:
31 // ( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"), ("S", "ε"), ("F", "(E)"), ("F", "i") )
32
33 def main(args: Array[String]): Unit = {
34
35 //test parseFile
36 val result = parseFile("/home/hadoop001/Documents/code/Scala/LR(1)/testData/test.data")
37 println( "the original language rules:" )
38 for( rs <- result ) {
39 println( rs._1 + "->" + rs._2 )
40 }
41 initiate("/home/hadoop001/Documents/code/Scala/LR(1)/testData/test.data")
42 utility()
43 println("**************")
44 analyse("i+i*i#")
45
46 }
47
48 /*
49 * Function name: utility
50 * Function description: 辅助输出函数
51 * Input parameters: 无
52 * Return value: 无
53 * Exception: 未处理
54 * Author: 来自高山
55 * Created date: Mon Oct 28 2019 +0800
56 * Editor: 来自高山
57 * Edited Date: Mon Oct 28 2019 +0800
58 */
59 def utility(): Unit = {
60 println( "after expanding the language rules:" )
61 displayRelations()
62
63 println("**************")
64 //test FIRST
65 println("FIRST:")
66 val testFIRST = FIRST()
67 for( ex <- testFIRST ) {
68 println( "FIRST(" + ex._1 + ") = {" + ex._2.mkString(",") + "}" )
69 }
70 println("**************")
71
72 var cnt4 = 0
73 for( ex <- itemGroup.toList.sortBy(_._2) ) {
74 println( cnt4 + ":\nI" + ex._2 + ":" )
75 for (tx <- ex._1 ) {
76 println( tx._1 + "->" + tx._2 + ", " + tx._3 )
77 }
78 println("^^^^^^^^^^^^^^^^^^^^^^^^")
79 cnt4 += 1
80 }
81
82 println("**************")
83 val test_createMatrix = createMatrix
84 for ( i <- 0 to test_createMatrix.length - 1 ) {
85 for ( j <- 0 to test_createMatrix(i).length - 1 ) {
86 print( test_createMatrix(i)(j) + " " )
87 }
88 println()
89 }
90 }
91
92 /*
93 * Function name: analyse
94 * Function description: 对指定的字符串进行LR(1)分析
95 * Input parameters: -String(输入的指定字符串)
96 * Return value: -Boolean(分析成功则返回true,否则false)
97 * Exception: 未处理(有出错提示)
98 * Author: 来自高山
99 * Created date: Mon Oct 28 2019 +0800
100 * Editor: 来自高山
101 * Edited Date: Mon Oct 28 2019 +0800
102 */
103 def analyse( expression: String ): Boolean = {
104 val statusStack = new mutable.Stack[String]()
105 val characterStack = new mutable.Stack[String]()
106 val analyseTable = createMatrix()
107 // val analyseTable = ArrayBuffer(ArrayBuffer(null, "+", "*", "(", ")", "i", "#", "E", "T", "F", "A"),
108 // ArrayBuffer("0", null, null, "S4", null, "S5", null, "1", "2", "3", null),
109 // ArrayBuffer("1", "S6", null, null, null, null, "acc", null, null, null, null),
110 // ArrayBuffer("2", "r2", "S7", null, null, null, "r2", null, null, null, null),
111 // ArrayBuffer("3", "r4", "r4", null, null, null, "r4", null, null, null, null),
112 // ArrayBuffer("4", null, null, "S4", null, "S11", null, "8", "9", "10", null),
113 // ArrayBuffer("5", "r6", "r6", null, null, null, "r6", null, null, null, null),
114 // ArrayBuffer("6", null, null, "S4", null, "S5", null, null, "12", "13", null),
115 // ArrayBuffer("7", null, null, "S4", null, "S5", null, null, null, "14", null),
116 // ArrayBuffer("8", "S15", null, null, "S16", null, null, null, null, null, null),
117 // ArrayBuffer("9", "r2", "S17", null, "r2", null, null, null, null, null, null),
118 // ArrayBuffer("10", "r4", "r4", null, "r4", null, null, null, null, null, null),
119 // ArrayBuffer("11", "r6", "r6", null, "r6", null, null, null, null, null, null),
120 // ArrayBuffer("12", "r1", "S18", null, null, null, "r1", null, null, null, null),
121 // ArrayBuffer("13", "r4", "r4", null, null, null, "r4",null, null, null, null),
122 // ArrayBuffer("14", "r3", "r3", null, null, null, "r3", null, null, null, null),
123 // ArrayBuffer("15", null, null, "S4", null, "S11", null, null, "19", "20", null),
124 // ArrayBuffer("16", "r5", "r5", null, null, null, "r5", null, null, null, null),
125 // ArrayBuffer("17", null, null, "S4", null, "S11", null, null, null, "21", null),
126 // ArrayBuffer("18", null, null, "S4", null, "S5", null, null, null, "14", null),
127 // ArrayBuffer("19", "r1", "S17", null, "r1", null, null, null, null, null, null),
128 // ArrayBuffer("20", "r4", "r4", null, "r4", null, null, null, null, null, null),
129 // ArrayBuffer("21", "r3", "r3", null, "r3", null, null, null, null, null, null)
130 // )
131 var expr = expression
132 var flag = false
133 var repeat = true
134 statusStack.push("0")
135 characterStack.push("#")
136 var tot = 0
137 case class characterToColumn(a: String) {
138 var ans = -1
139 for( j <- 1 to (columnLength - 1) ) {
140 if( analyseTable(0)(j) == a ) {
141 ans = j
142 }
143 }
144 //ans
145 }
146 while ( repeat == true ) {
147 // s = statusTop
148 val statusTop = statusStack.top
149 val a = expr(0)
150
151 val aColumn = characterToColumn(a.toString).ans
152 var sRow = statusTop.toInt
153 if(sRow == 0 ) sRow += 1 else sRow += 1
154
155 if( analyseTable(sRow)(aColumn)(0) == 'S' ) {
156 val newStatus = analyseTable(sRow)(aColumn).drop(1)
157 statusStack.push(newStatus)
158 characterStack.push(a.toString)
159 expr = expr.drop(1)
160
161 println( tot + "状态栈: [" + displayStack(statusStack.reverse).mkString(",") + "],符号栈:[" +
162 displayStack(characterStack.reverse) + "],剩余字符串:" + expr + ",动作:ACTION[" +
163 statusTop + ", " + a + "]," + "状态 " + aColumn + " 与符号 " + a + " 分别入栈")
164 tot += 1
165 }
166 else if( analyseTable(sRow)(aColumn)(0) == 'r' ) {
167 val exprLineNO = analyseTable(sRow)(aColumn).drop(1).toInt
168 val currentRelation = relations(exprLineNO)
169
170 var popLength = 0
171 if( currentRelation._3 != "א" ) {
172 popLength = currentRelation._2.length + currentRelation._3.length
173 }
174 else {
175 popLength = currentRelation._2.length
176 }
177 var cnt = popLength
178 val tmpCharacter = characterStack.reverse.toString.replace("Stack(", "").replace(")", "").replace(",", "").replace(" ", "") //.substring() //.substring(characterStack.length - popLength - 1, characterStack.length - 1 )
179 val reduceCharacter = tmpCharacter.drop(tmpCharacter.length - popLength)
180 while ( cnt >= 1 ) {
181 statusStack.pop()
182 characterStack.pop()
183 cnt -= 1
184 }
185 // s' = characterTop
186 val statusTop2 = statusStack.top.toInt
187
188 var sRow2 = -1
189 if( statusTop2 == 0 ) sRow2 = statusTop2 + 1 else sRow2 = statusTop2 + 1
190
191 val A = currentRelation._1
192 characterStack.push(A)
193 val tmp = analyseTable(sRow2)( characterToColumn(A).ans )
194 statusStack.push(tmp)
195
196 println( tot + "状态栈: [" + displayStack(statusStack.reverse).mkString(",") + "],符号栈:[" +
197 displayStack(characterStack.reverse) + "],剩余字符串:" + expr + ",动作:GOTO[" +
198 statusTop2 + ", " + A + "]" + ",用产生式 " + A + "->" + reduceCharacter + " 进行规约")
199 tot += 1
200 }
201 else if( analyseTable(sRow)(aColumn) == "acc" ) {
202 println("succeed")
203 flag = true
204 repeat = false
205 }
206 else {
207 println("error")
208 println( "error in, sRow = " + sRow + ", aColumn = " + aColumn + ", analyseTable(" + sRow + ")(" + aColumn + ") = " + analyseTable(sRow)(aColumn) )
209 flag = true
210 repeat = false
211 }
212 //cnt += 1
213 }
214 if(flag) true else false
215 }
216
217 /*
218 * Function name: createMatrix
219 * Function description: 构造ACTION与GOTO分析表
220 * Input parameters: 无
221 * Return value: -Array[ Array[String] ](分析表矩阵元素构成的二维数组)
222 * Exception: 未处理
223 * Author: 来自高山
224 * Created date: Mon Oct 28 2019 +0800
225 * Editor: 来自高山
226 * Edited Date: Mon Oct 28 2019 +0800
227 */
228 def createMatrix(): Array[ Array[String] ] = {
229 val result = initiateMatrix()
230 val localVT = VT
231 val localVN = VN
232
233 case class getColumn( ch: String ) {
234 val matrix = initiateMatrix()
235 var ans = -1
236 for( j <- 0 to (columnLength - 1) ) {
237 if( matrix(0)(j) == ch ) {
238 ans = j
239 }
240 }
241 }
242
243
244 for( ex <- itemGroup ) {
245 for( tx <- ex._1 ) {
246 val pointPosition = tx._2.indexOf("·")
247 //· 不在最右边
248 //若项目[A->α·aβ] ∈ Ik,且GO(Ik, a) = Ij,a为终结符,则置ACTION[k, a]为“sj”
249 if (pointPosition < tx._2.length - 1) {
250 val a = tx._2( pointPosition + 1 )
251 if( localVT.contains(a) == true && findItemOrder(ex._1, a.toString) != -1 ) {
252 val j = findItemOrder(ex._1, a.toString)
253 var tmpRow = -1
254 tmpRow = ex._2 + 1
255 result(tmpRow)( getColumn(a.toString).ans ) = "S" + j.toString
256 }
257 }
258 if (pointPosition == tx._2.length - 1 ) {
259 val a = tx._3
260 var tmpRow = -1
261 tmpRow = ex._2 + 1
262 result(tmpRow)(getColumn(a).ans) = "r" + ( findRelationOrder( (tx._1,
263 tx._2.replace("·", "") ) ) )
264 }
265 if( tx._1 == relations(0)._1 && tx._2 == relations(0)._2 + "·" && tx._3 == "#" ) {
266 var tmpRow = -1
267 tmpRow = ex._2 + 1
268 result(tmpRow)( getColumn("#").ans ) = "acc"
269 }
270 }
271 for( ch <- localVN ) {
272 if( findItemOrder(ex._1, ch.toString) != -1 ) {
273 val gotoNumber = findItemOrder(ex._1, ch.toString)
274 var tmpRow = -1
275 tmpRow = ex._2 + 1
276 //A = ch
277 result(tmpRow)( getColumn(ch.toString).ans ) = gotoNumber.toString
278 }
279 }
280 }
281 result
282 }
283
284 /*
285 * Function name: findRelationOrder
286 * Function description: 获取产生式的位于文法的第几行,从0开始
287 * Input parameters: -(String, String)(給定的产生式)
288 * Return value: -Int(給定的产生式在給定文法中的行数)
289 * Exception: 未处理
290 * Author: 来自高山
291 * Created date: Mon Oct 28 2019 +0800
292 * Editor: 来自高山
293 * Edited Date: Mon Oct 28 2019 +0800
294 */
295 def findRelationOrder( expression: (String, String) ): Int ={
296 var ans = -1
297 var cnt = 0
298 val localRelations = relations
299 for( ex <- localRelations ) {
300 var expr = ""
301 if( ex._3 != "א" ) {
302 expr = ex._1 + ex._2 + ex._3
303 }
304 else {
305 expr = ex._1 + ex._2
306 }
307 if( expr.equals(expression._1 + expression._2) ) {
308 ans = cnt
309 }
310 cnt += 1
311 }
312 ans
313 }
314
315 /*
316 * Function name: findItemOrder
317 * Function description: 获取特定项目对于指定字符在项目集族中的编号,从0开始
318 * Input parameters: -ArrayBuffer[ (String, String, String) ](給定项目), -String(給定字符)
319 * Return value: -Int(給定的项目对于指定字符在项目集族中的编号)
320 * Exception: 未处理
321 * Author: 来自高山
322 * Created date: Mon Oct 28 2019 +0800
323 * Editor: 来自高山
324 * Edited Date: Mon Oct 28 2019 +0800
325 */
326 def findItemOrder( item: ArrayBuffer[ (String, String, String) ], a: String ): Int = {
327 var ans = -1
328 val givenItem = go( item, a).sorted
329 val localItemGroup = itemGroup
330 for( ex <- localItemGroup ) {
331 if( ex._1.sorted.equals(givenItem) ) {
332 ans = ex._2
333 }
334 }
335 ans
336 }
337
338 /*
339 * Function name: initiateMatrix
340 * Function description: 初始化分析表,即ACTION表与GOTO表
341 * Input parameters: 无
342 * Return value: -Array[ Array[ String] ](已完成初始的分析表)
343 * Exception: 未处理
344 * Author: 来自高山
345 * Created date: Sun Oct 27 2019 +0800
346 * Editor: 来自高山
347 * Edited Date: Sun Oct 27 2019 +0800
348 */
349 def initiateMatrix(): Array[ Array[ String] ] = {
350 val localVN = VN
351 val localVT = VT
352 val tableRowLength = rowLength
353 val tableColumnLength = columnLength
354 val result = Array.ofDim[String](tableRowLength, tableColumnLength)
355 for( j <- 1 to localVT.length ) {
356 result(0)(j) = localVT(j - 1).toString
357 }
358 for( j <- localVT.length + 1 to tableColumnLength - 1 ) {
359 result(0)(j) = localVN(j - localVT.length - 1).toString
360 }
361 for( i <- 1 to ( tableRowLength - 1 ) ) {
362 result(i)(0) = (i - 1).toString
363 }
364 for( i <- 0 to (tableRowLength - 1) ) {
365 for( j <- 0 to (tableColumnLength - 1) ) {
366 if( result.isEmpty != false ) {
367 result(i)(j) = null
368 }
369 }
370 }
371
372 result
373 }
374
375 /*
376 * Function name: getItemGroup
377 * Function description: 对于输入的文法,建立初始化的项目集
378 * Input parameters: 无
379 * Return value: -Unit
380 * Exception: 未处理
381 * Author: 来自高山
382 * Created date: Wed Oct 23 2019 +0800
383 * Editor: 来自高山
384 * Edited Date: Sun Oct 27 2019 +0800
385 */
386 def getItemGroup(): Unit = {
387 val ldx = ( relations(0)._1, "·" + relations(0)._2, "#" )
388 val I0 = getClosure( ArrayBuffer(ldx) )
389 val wholeCharacters = allCharacters
390 var tot = 0
391 // var cnt = 0
392 itemGroup(I0) = tot
393 var appendFlag = true
394 while (appendFlag == true) {
395 var originalAns = Map[ ArrayBuffer[ (String, String, String) ], Int ]()
396 originalAns = itemGroup.clone()
397 //为什么用I作为遍历变量不行?!
398 for(item <- itemGroup.keys) {
399 for (ch <- wholeCharacters) {
400 val newItem = go(item, ch.toString).sorted
401 if (newItem.isEmpty == false && itemGroup.contains(newItem) == false) {
402 tot += 1
403 itemGroup(newItem) = tot
404 }
405 }
406 }
407 if( originalAns.equals(itemGroup) == true ) {
408 appendFlag = false
409 // println( cnt + ", all same" )
410 // cnt += 1
411 }
412 else {
413 originalAns.clear()
414 originalAns = itemGroup.clone()
415 // println( cnt + ", changed" )
416 // cnt += 1
417 }
418 }
419 }
420
421 /*
422 * Function name: getItems
423 * Function description: 返回文法的初始项目集I0
424 * Input parameters: 无
425 * Return value: -ArrayBuffer[String](文法的项目集,第一个元素是文法产生式左边符号,第二个是对应的右边字符串所生成的项目)
426 * Exception: 未处理
427 * Author: 来自高山
428 * Created date: Wed Oct 23 2019 +0800
429 * Editor: 来自高山
430 * Edited Date: Sar Oct 26 2019 +0800
431 */
432 def getItems(): ArrayBuffer[ (String, String, String) ] = {
433 val result = new ArrayBuffer[ (String, String, String) ]()
434 val localRelations = relations
435 //initiate
436 for (ex <- localRelations) {
437 if (ex._3 != "א") {
438 result += ((ex._1, "·" + ex._2, "#"))
439 result += ((ex._1, "·" + ex._3, "#"))
440 }
441 else {
442 result += ((ex._1, "·" + ex._2, "#"))
443 }
444 }
445 result
446 }
447
448 /*
449 * Function name: go
450 * Function description: 求給定项目对于特定字符的下一状态
451 * Input parameters: -ArrayBuffer[ (String, String, String) ](給定项目), String(特定字符)
452 * Return value: -ArrayBuffer[ (String, String, String) ](給定项目对于特定字符的下一状态)
453 * Exception: 未处理
454 * Author: 来自高山
455 * Created date: Sat Oct 26 2019 +0800
456 * Editor: 来自高山
457 * Edited Date: Sat Oct 26 2019 +0800
458 */
459 def go( I: ArrayBuffer[ (String, String, String) ], X: String ): ArrayBuffer[ (String, String, String) ] = {
460 //GO(I, X) = CLOSURE(J)
461 //J = {任何形如[A->αX·β, a]的项目|[A->α·Xβ, a]∈I}
462 val ans = new ArrayBuffer[ (String, String, String) ]()
463 val items = new ArrayBuffer[ (String, String, String) ]()
464
465 for( ex <- I ) {
466 val pointPosition = ex._2.indexOf("·")
467 //· 不在最右边
468 if (pointPosition < ex._2.length - 1) {
469 val A = ex._1
470 val possibleX = ex._2( pointPosition + 1)
471 // αXβ
472 val noPointExpressionPart2 = ex._2.replace("·", "")
473 if( X == possibleX.toString ) {
474 // αX·β
475 val newPart2 = noPointExpressionPart2.substring(0, pointPosition + 1) + "·" +
476 noPointExpressionPart2.substring(pointPosition + 1, noPointExpressionPart2.length)
477 val a = ex._3
478 items += ( (A, newPart2, a) )
479 }
480 }
481 }
482 ans.appendAll( getClosure(items) )
483 ans
484 }
485
486 /*
487 * Function name: getClosure
488 * Function description: 求給定项目集的闭包
489 * Input parameters: -ArrayBuffer[ (String, String, String) ](給定的项目集)
490 * Return value: -ArrayBuffer[ (String, String, String) ](給定项目集的闭包)
491 * Exception: 未处理
492 * Author: 来自高山
493 * Created date: Sat Oct 26 2019 +0800
494 * Editor: 来自高山
495 * Edited Date: Sun Oct 27 2019 +0800
496 */
497 def getClosure( items: ArrayBuffer[ (String, String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
498 val result = new ArrayBuffer[ (String, String, String) ]()
499 result.appendAll(items)
500 val localFIRST = FIRST()
501 var addFlag = true
502 var cnt = 1
503 while (addFlag == true ) {
504 val originalResult = new ArrayBuffer[(String, String, String)]()
505 originalResult.appendAll(result)
506 for (ex <- result) {
507
508 val pointPosition = ex._2.indexOf("·")
509 //· 不在最右边
510 if (pointPosition < ex._2.length - 1) {
511 //B在 · 的右边
512 val B = ex._2(pointPosition + 1)
513 val a = ex._3
514
515 // case 1: β != Φ and a != # or
516 // case 2: β != Φ and a = #
517 if (pointPosition < ex._2.length - 2) {
518 val β = ex._2(pointPosition + 2)
519 // ξ
520 val rightExpressionsOfB = getRightExpressions(B.toString)
521 val FIRST_Of_βa = localFIRST(β.toString)
522 for (b <- FIRST_Of_βa) {
523 for (ksi <- rightExpressionsOfB) {
524 val tmp = ((B.toString, "·" + ksi, b.toString))
525
526 if (result.contains(tmp) == false) {
527 result += tmp
528 }
529 }
530 }
531 }
532 // case 3: β = Φ and a equals any character
533 if (pointPosition == ex._2.length - 2) {
534 val rightExpressionsOfB = getRightExpressions(B.toString)
535 val FIRST_Of_βa = localFIRST(a.toString)
536 for (b <- FIRST_Of_βa) {
537 for (ksi <- rightExpressionsOfB) {
538 val tmp = ((B.toString, "·" + ksi, b.toString))
539 if (result.contains(tmp) == false) {
540 result += tmp
541 }
542 }
543 }
544 }
545 }
546 }
547 if (result != originalResult) {
548 originalResult.remove(0, originalResult.length)
549 originalResult.appendAll(result)
550 cnt += 1
551 }
552 else {
553 addFlag = false
554 cnt += 1
555 }
556 }
557 result
558 }
559
560 /*
561 * Function name: getRightExpressions
562 * Function description: 获取給定非终结符所在产生式的右部,可能不止一个,因此返回值是String类型的ArrayBuffer数组
563 * Input parameters: -String(給定的非终结符)
564 * Return value: -ArrayBuffer[String](給定非终结符所在产生式的右部)
565 * Exception: 未处理
566 * Author: 来自高山
567 * Created date: Fri Oct 25 2019 +0800
568 * Editor: 来自高山
569 * Edited Date: Fri Oct 25 2019 +0800
570 */
571 def getRightExpressions(ch: String): ArrayBuffer[String] = {
572 val result = new ArrayBuffer[String]()
573 val localRelations = relations
574 for( ex <- localRelations ) {
575 if( ex._1 == ch ) {
576 if( ex._3 != "א" ) {
577 result += ex._2
578 result += ex._3
579 }
580 else {
581 result += ex._2
582 }
583 }
584 }
585 result
586 }
587
588 def getSingleRelation( ch: String ): ArrayBuffer[ (String, String, String) ] = {
589 val result = new ArrayBuffer[ (String, String, String) ]()
590 val localRelations = relations
591 for( ex<- localRelations ) {
592 if(ex._1 == ch ) {
593 result += ex
594 }
595 }
596 result
597 }
598
599 /*
600 * Function name: splitString
601 * Function description: 从字符串的首字符的左边到尾字符的右边,依次插入点“·”;每插入一个点即将其作为元素加入待返回String类型的ArrayBuffer数组
602 * Input parameters: -String(待处理的String类型的字符串)
603 * Return value: -ArrayBuffer[String](输入字符串依次添加点“·”为元素的字符串数组)
604 * Exception: 未处理
605 * Author: 来自高山
606 * Created date: Wed Oct 23 2019 +0800
607 * Editor: 来自高山
608 * Edited Date: Wed Oct 23 2019 +0800
609 */
610 def splitString( string: String ): ArrayBuffer[String] = {
611 val result = new ArrayBuffer[String]()
612 val stringLength = string.length
613 for( i <- 0 to stringLength ) {
614 result += string.substring(0, i) + "·" + string.substring(i, stringLength)
615 }
616 result
617 }
618
619 /*
620 * Function name: displayStack
621 * Function description: 输出栈的所有元素
622 * Input parameters: -mutable.Stack[String](待处理的String类型的栈)
623 * Return value: -String(栈所有元素组成的字符串)
624 * Exception: 未处理
625 * Author: 来自高山
626 * Created date: Mon Oct 21 2019 +0800
627 * Editor: 来自高山
628 * Edited Date: Mon Oct 21 2019 +0800
629 */
630 def displayStack( stack: mutable.Stack[String] ): String = {
631 var result = ""
632 for( ex <- stack ) {
633 result += ex
634 }
635 result
636 }
637
638 /*
639 * Function name: initiate
640 * Function description: 初始化全局变量
641 * Input parameters: the absolute path of the language-rule source file
642 * Return value: 无
643 * Exception: 未处理
644 * Author: 来自高山
645 * Created date: Sat Oct 19 2019 +0800
646 * Editor: 来自高山
647 * Edited Date: Sun Oct 27 2019 +0800
648 */
649 def initiate( filePath: String ): Unit = {
650 LL1_G = parseFile(filePath)
651 allCharacters = getWholeCharacters(LL1_G)
652 usedCharacters = allCharacters
653 relations = getRelation(LL1_G)
654 VN = getVN(allCharacters)
655 VT = getVT(allCharacters)
656 val leftCharacters = subString(allCandidateLetters, VN)
657 //relations += ( ( leftCharacters(0).toString, (relations(0)._1), "א" ) )
658 relations.insert(0, ( leftCharacters(0).toString, (relations(0)._1), "א" ) )
659 VN += leftCharacters(0).toString
660 usedCharacters += leftCharacters(0).toString
661 allCharacters += leftCharacters(0).toString
662
663 allCharacters += "#"
664 usedCharacters += "#"
665 VT += "#"
666 getItemGroup
667 columnLength = VN.length + VT.length + 1
668 rowLength = itemGroup.size + 1
669 }
670
671 /*
672 * Function name: subString
673 * Function description: 获取两输入字符串的差集(要求两者均非空)
674 * Input parameters: 无
675 * Return value: -String(两输入字符串的差集)
676 * Exception: 未处理
677 * Author: 来自高山
678 * Created date: Sat Oct 19 2019 +0800
679 * Editor: 来自高山
680 * Edited Date: Sat Oct 19 2019 +0800
681 */
682 def subString( usedCharacters: String, localCandidateLetters: String ): String = {
683 require( usedCharacters.length != 0 && localCandidateLetters.length != 0 )
684 var ans = ""
685 var A = usedCharacters
686 var B = localCandidateLetters
687 if( A.length < B.length ) {
688 val tmp = A
689 A = B
690 B = tmp
691 }
692 for( i <- 0 to (A.length - 1) ) {
693 var j = 0
694 while( j < B.length && B(j) != A(i) ) {
695 j += 1
696 }
697 if( j == B.length ) {
698 ans += A(i)
699 }
700 }
701 ans
702 }
703
704 /*
705 * Function name: displayRelations
706 * Function description: display all he language rules
707 * Input parameters: 无
708 * Return value: 无
709 * Exception: 未处理
710 * Author: 来自高山
711 * Created date: Sat Oct 19 2019 +0800
712 * Editor: 来自高山
713 * Edited Date: Sat Oct 19 2019 +0800
714 */
715 def displayRelations(): Unit = {
716 for( ex <- relations ) {
717 if( ex._3 != "א" ) {
718 println( ex._1 + "->" + ex._2 + "|" + ex._3 )
719 }
720 else {
721 println( ex._1 + "->" + ex._2 )
722 }
723 }
724 }
725
726 /*
727 * Function name: parseFile
728 * Function description: 解析文本文件,保存在数组中
729 * Input parameters: 文本绝对路径
730 * Return value: -ArrayBuffer[ ( String, String ) ](String类型的元组ArrayBuffer数组)
731 * Exception: 未处理
732 * Author: 来自高山
733 * Created date: Fri Oct 18 2019 +0800
734 * Editor: 来自高山
735 * Edited Date: Fri Oct 18 2019 +0800
736 */
737 def parseFile( filePath: String ): ArrayBuffer[ ( String, String ) ] = {
738 val result = new ArrayBuffer[ ( String, String ) ]( countLines( readFromTxtByLine(filePath) ) )
739 val sourceFile = readFromTxtByLine(filePath) //filePath
740 for( line <- sourceFile ) {
741 val tmp = line.split( "->", 2 )
742 result += ( ( tmp.head, tmp.last ) )
743 }
744 result
745 }
746
747 /*
748 * Function name: countLines
749 * Function description: 计算文本行数,用于创建接收数组时开辟相应空间
750 * Input parameters: -Array[String](文本文件数据构成的数组)
751 * Return value: -Int(文本行数)
752 * Exception: 未处理
753 * Author: 来自高山
754 * Created date: Fri Oct 18 2019 +0800
755 * Editor: 来自高山
756 * Edited Date: Sat Oct 19 2019 +0800
757 */
758 def countLines( sourceFile: Array[String] ): Int = {
759 var cnt = 0
760 for( line <- sourceFile ) {
761 cnt += 1
762 }
763 cnt
764 }
765
766 /*
767 * Function name: readFromTxtByLine
768 * Function description: 读取文本文件
769 * Input parameters: -String(文本文件绝对路径)
770 * Return value: -Array[String](文本文件构成的数组,每行数据占一个数组元素)
771 * Exception: -未处理
772 * Author: 来自高山
773 * Created date: Fri Oct 18 2019 +0800
774 * Editor: 来自高山
775 * Edited Date: Fri Oct 18 2019 +0800
776 */
777 def readFromTxtByLine(filePath: String): Array[String] = {
778 import scala.io.Source
779 val source = Source.fromFile(filePath, "UTF-8")
780 //val lineIterator = source.getLines()
781 //lineIterator.foreach()
782 val lines = source.getLines().toArray
783 source.close()
784 //println(lines.size)
785 lines
786 }
787
788 /*
789 * Function name: getWholeCharacters
790 * Function description: 获取文法的除“|”之外的所有字符
791 * Input parameters: -ArrayBuffer[ (String, String) ](由文法左右两部分字符构成一个元组的数组,筛掉“|”)
792 * Return value: -String(文法的除“|”之外的所有字符)
793 * Exception: 未处理(有出错提示)
794 * Author: 来自高山
795 * Created date: Fri Oct 11 2019 +0800
796 * Editor: 来自高山
797 * Edited Date: Fri Oct 11 2019 +0800
798 */
799 def getWholeCharacters( string: ArrayBuffer[ (String, String) ] ): String = {
800 var wholeCharacters = ""
801 for( expression <- string ) {
802 wholeCharacters += expression._1 + expression._2
803 }
804 val pattern = new Regex("\\|")
805 val result = pattern replaceAllIn( wholeCharacters, "" )
806 if( result.isEmpty )
807 "function getWholeCharacters failed"
808 else
809 result.distinct
810 }
811 /*
812 * Function name: getVN
813 * Function description: 获取文法的所有非终结符(non-terminal character),默认大写字母为非终结符,使用正则表达式匹配
814 * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
815 * Return value: -String(文法的所有非终结符)
816 * Exception: 未处理(有出错提示)
817 * Author: 来自高山
818 * Created date: Fri Oct 11 2019 +0800
819 * Editor: 来自高山
820 * Edited Date: Fri Oct 11 2019 +0800
821 */
822 def getVN( string: String ): String = {
823 //match big letter:
824 //^[A-Z]+$
825 val pattern = new Regex("[A-Z]")//("^[A-Z]+$")
826 if( (pattern findAllIn string) != null )
827 (pattern findAllIn string).mkString("")
828 else
829 "function getVN failed"
830 }
831
832 /*
833 * Function name: getVT
834 * Function description: 获取文法的所有非终结符(terminal character),默认大写字母外的字符为终结符,使用正则表达式匹配
835 * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
836 * Return value: -String(文法的所有终结符)
837 * Exception: 未处理(有出错提示)
838 * Author: 来自高山
839 * Created date: Fri Oct 11 2019 +0800
840 * Editor: 来自高山
841 * Edited Date: Fri Oct 11 2019 +0800
842 */
843 def getVT( string: String ): String = {
844 val pattern1 = new Regex("[A-Z]")
845 val pattern2 = new Regex("\\|")
846 val firstFilter = pattern1 replaceAllIn( string, "" )
847 val result = pattern2 replaceAllIn( firstFilter, "" )
848 if( result.isEmpty == false )
849 result
850 else
851 return "function getVT failed"
852 }
853 /*
854 * Function name: getRelation
855 * Function description: 获取文法每一行对应的推导关系,若文法只推出了1项(即没有符号“|”),则返回元组的第三个用希伯来字母“א”示空
856 * Input parameters: -ArrayBuffer[ (String, String)(已经分割好的文法左右部分构成的数组)
857 * Return value: -ArrayBuffer[ (String, String, String) ](元组第一个元素为推导式左边符号,第二为右边第二个符号串,第三为右边(若有)第三个符号串)
858 * Exception: 未处理
859 * Author: 来自高山
860 * Created date: Fri Oct 11 2019 +0800
861 * Editor: 来自高山
862 * Edited Date: Fri Oct 11 2019 +0800
863 */
864 def getRelation( string: ArrayBuffer[ (String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
865 val relation = new ArrayBuffer[ (String, String, String) ]()
866 for( expression <- string ) {
867 if( expression._2.contains("|") == false ) {
868 relation += ( ( expression._1, expression._2, "א" ) )
869 }
870 else {
871 val tmp = expression._2.split("\\|", 2 )
872 relation += ( ( expression._1, tmp.head, tmp.last ) )
873 }
874 }
875 relation
876 }
877
878 /*
879 * Function name: findFirst
880 * Function description: 获取指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串
881 * Input parameters: -String(指定字符)
882 * Return value: -String(指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串)
883 * Exception: 未处理
884 * Author: 来自高山
885 * Created date: Fri Oct 11 2019 +0800
886 * Editor: 来自高山
887 * Edited Date: Fri Oct 11 2019 +0800
888 */
889 def findFirst( ch: String ): String = {
890
891 val localRelations = relations
892 var result = ""
893 for( ex <- localRelations ) {
894 if( ch == ex._1 ) {
895 if( ex._3 != "א" ) {
896 if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
897 result += ex._2(0).toString
898 }
899 if( VT.contains( ex._3(0) ) && ex._3(0) != 'ε' ) {
900 result += ex._3(0).toString
901 }
902 }
903 else {
904 if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
905 result += ex._2(0).toString
906 }
907 }
908 }
909 }
910 result
911 }
912
913 /*
914 * Function name: judgeOnlyOneVoidSuccession
915 * Function description: 判断指定字符是否可推出唯一的字符ε
916 * Input parameters: -String(指定字符串)
917 * Return value: -Boolean(存在则true,否则false)
918 * Exception: 未处理
919 * Author: 来自高山
920 * Created date: Fri Oct 11 2019 +0800
921 * Editor: 来自高山
922 * Edited Date: Fri Oct 11 2019 +0800
923 */
924 def judgeOnlyOneVoidSuccession( ch: String ): Boolean = {
925 val localRelations = relations
926 var result = 1
927 for( ex <- localRelations ) {
928 if( ch == ex._1 ) {
929 if( ex._3 != "א" ) {
930 if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) || (ex._3.length == 1 && ex._3(0) == 'ε') ) {
931 result = 1
932 }
933 else {
934 result = 0
935 }
936 }
937 else {
938 if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) ) {
939 result = 1
940 }
941 else {
942 result = 0
943 }
944 }
945 }
946 }
947 if( result == 1 ) true else false
948 }
949
950 /*
951 * Function name: judgeCaseXY
952 * Function description: 判断构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)
953 * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
954 * Return value: -Boolean(满足则true,否则false)
955 * Exception: 未处理
956 * Author: 来自高山
957 * Created date: Sat Oct 12 2019 +0800
958 * Editor: 来自高山
959 * Edited Date: Sat Oct 12 2019 +0800
960 */
961 def judgeCaseXY( ch: Char ): Boolean = {
962 val localVN = VN
963 val localRelations = relations
964 var result = 0
965 if( localVN.contains(ch) == true ) {
966 for( ex <- localRelations ) {
967 if( ex._1(0) == ch ) {
968 if( localVN.contains( ex._2(0) ) || localVN.contains( ex._3(0) ) ) {
969 result += 1
970 }
971 }
972 }
973 }
974 if( result > 0 )
975 true
976 else
977 false
978 }
979
980 /*
981 * Function name: findCase_Y_In_XY
982 * Function description: 获取构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)时的Y
983 * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
984 * Return value: -String(Y构成的String字符串,无则为空)
985 * Exception: 未处理
986 * Author: 来自高山
987 * Created date: Sat Oct 12 2019 +0800
988 * Editor: 来自高山
989 * Edited Date: Sat Oct 12 2019 +0800
990 */
991 def findCase_Y_In_XY( ch: Char ): String = {
992 val localVN = VN
993 val localRelations = relations
994 var result = ""
995 if( localVN.contains(ch) == true ) {
996 for( ex <- localRelations ) {
997 if( ex._1(0) == ch ) {
998 if( ex._3 != "א" ) {
999 if( localVN.contains( ex._2(0) ) == true ) {
1000 result += ex._2(0).toString
1001 }
1002 if( localVN.contains( ex._3(0) ) == true ) {
1003 result += ex._3(0).toString
1004 }
1005 }
1006 else {
1007 if( localVN.contains( ex._2(0) ) == true ) {
1008 result += ex._2(0).toString
1009 }
1010 }
1011 }
1012 }
1013 }
1014 result
1015 }
1016
1017 /*
1018 * Function name: findCase_Y_In_nY
1019 * Function description: 获取构造FIRST集时可能的第3种情况的(2)时的FIRST(Yi)中所有的非ε-元素(省略描述若干字)
1020 * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
1021 * Return value: -String(FIRST(Yi)中所有的非ε-元素构成的String字符串,无则为空)
1022 * Exception: 未处理
1023 * Author: 来自高山
1024 * Created date: Sat Oct 12 2019 +0800
1025 * Editor: 来自高山
1026 * Edited Date: Sat Oct 12 2019 +0800
1027 */
1028 def findCase_Y_In_nY( ch: Char ): String = {
1029 val localVN = VN
1030 val localRelations = relations
1031 var result = ""
1032 for( ex <- localRelations ) {
1033 if (ex._1 == ch.toString) {
1034 var tmp = ""
1035
1036 if (ex._3 != 'א') {
1037 var cnt = 0
1038 for (tx <- ex._2) {
1039 // add the element belongs to tmp
1040 if (localVN.contains(tx)) {
1041 tmp += tx.toString
1042 cnt += 1
1043 }
1044 // otherwise, reset tmp as empty string
1045 else {
1046 tmp = ""
1047 }
1048 }
1049 if (cnt == ex._2.length) {
1050 result += tmp
1051 }
1052
1053 // reset
1054 cnt = 0
1055 tmp = ""
1056 for (tx <- ex._3) {
1057 // add the element belongs to tmp
1058 if (localVN.contains(tx)) {
1059 tmp += tx.toString
1060 cnt += 1
1061 }
1062 // otherwise, reset result as empty string
1063 else {
1064 tmp = ""
1065 }
1066 }
1067 if (cnt == ex._3.length) {
1068 result += tmp
1069 }
1070 }
1071 else {
1072 tmp = ""
1073 var cnt = 0
1074 for (tx <- ex._2) {
1075 // add the element belongs to tmp
1076 if (localVN.contains(tx)) {
1077 tmp += tx.toString
1078 cnt += 1
1079 }
1080 // otherwise, reset tmp as empty string
1081 else {
1082 tmp = ""
1083 }
1084 }
1085 if (cnt == ex._2.length) {
1086 result += tmp
1087 }
1088 }
1089 }
1090 }
1091 result = result.distinct
1092 result
1093 }
1094
1095 /*
1096 * Function name: FIRST
1097 * Function description: 按照教材P78左下角的算法描述实现求解指定文法FIRST集;因用的是循环迭代求解,因此代码较长
1098 * Input parameters: -ArrayBuffer[ (String, String) ](产生式左右两部分分别构成元组的第1个和第2个元素)
1099 * Return value: -Map[ String, String ](Map的key是非终结符,value是其FIRST元素)
1100 * Exception: 未处理
1101 * Author: 来自高山
1102 * Created date: Mon Oct 14 2019 +0800
1103 * Editor: 来自高山
1104 * Edited Date: Sat Oct 19 2019 +0800
1105 */
1106 def FIRST(): Map[ String, String ] = {
1107 val FIRST_Group = Map[ String, String ]()
1108 val wholeCharacters = allCharacters
1109 val localVT = VT
1110 val localVN = VN
1111
1112 for( character <- wholeCharacters ) {
1113 // case 1
1114 if( localVT.contains(character) ) {
1115 //if there exist the original key that equals the current one
1116 if( FIRST_Group.contains(character.toString) == true ) {
1117 val tmp = character.toString + FIRST_Group(character.toString)
1118 FIRST_Group(character.toString) = tmp.distinct
1119 }
1120 //otherwise
1121 else {
1122 FIRST_Group(character.toString) = character.toString
1123 }
1124 }
1125
1126 // case 2
1127 if( localVN.contains(character.toString) == true ) {
1128 // case 2.1
1129 val value = findFirst(character.toString)
1130 if ( value.length != 0 ) {
1131 if ( FIRST_Group.contains(character.toString) == true ) {
1132 for( ch <- value ) {
1133 val tmp = ch + FIRST_Group(character.toString)
1134 FIRST_Group(character.toString) = tmp.distinct
1135 }
1136 }
1137 else {
1138 FIRST_Group(character.toString) = value.toString
1139 }
1140 }
1141
1142 // case 2.2
1143 if( judgeOnlyOneVoidSuccession(character.toString) == true ) {
1144 if ( FIRST_Group.contains(character.toString) == true ) {
1145 val tmp = "ε" + FIRST_Group(character.toString)
1146 FIRST_Group(character.toString) = tmp.distinct
1147 }
1148 else {
1149 FIRST_Group(character.toString) = "ε"
1150 }
1151 }
1152 }
1153
1154 for( character <- wholeCharacters ) {
1155 // case 3
1156 // case 3.1
1157 if( judgeCaseXY(character) == true ) {
1158 val tmpReply = findCase_Y_In_XY(character)
1159 for( eachTmpReply <- tmpReply ) {
1160 if( FIRST_Group.contains(eachTmpReply.toString) == true ) {
1161 for (ex <- FIRST_Group(eachTmpReply.toString)) {
1162 if (ex != 'ε') {
1163 if (FIRST_Group.contains(character.toString) == true) {
1164 val tmp = ex.toString + FIRST_Group(character.toString)
1165 FIRST_Group(character.toString) = tmp.distinct
1166 }
1167 else {
1168 FIRST_Group(character.toString) = ex.toString
1169 }
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 // case 3.2
1177 if( findCase_Y_In_nY(character).length > 0 ) {
1178 var flag = true
1179 val tmpReply = findCase_Y_In_nY(character)
1180
1181 for( ex <- tmpReply ) {
1182 if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true ) {
1183 if( FIRST_Group(ex.toString).contains("ε") == false ) {
1184 flag = false
1185 }
1186 }
1187 else {
1188 flag = false
1189 }
1190 if( flag == true ) {
1191 if (FIRST_Group.contains(character.toString) == true) {
1192 val tmp = FIRST_Group(ex.toString).replace( "ε", "" ) + FIRST_Group(character.toString)
1193 FIRST_Group(character.toString) = tmp.distinct
1194 }
1195 else {
1196 FIRST_Group(character.toString) = FIRST_Group(ex.toString).replace( "ε", "" )
1197 }
1198
1199 }
1200 }
1201 }
1202 // case 3.3
1203 if( findCase_Y_In_nY(character).length > 0 ) {
1204 var flag = true
1205 val tmpReply = findCase_Y_In_nY(character)
1206 for( ex <- tmpReply ) {
1207 if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true ) {
1208 if( FIRST_Group(ex.toString).contains("ε") == false ) {
1209 flag = false
1210 }
1211 }
1212 else {
1213 flag = false
1214 }
1215 if( flag == true ) {
1216
1217 if (FIRST_Group.contains(character.toString) == true) {
1218 val tmp = "ε" + FIRST_Group(character.toString)
1219 FIRST_Group(character.toString) = tmp.distinct
1220 }
1221 else {
1222 FIRST_Group(character.toString) = "ε"
1223 }
1224 }
1225 }
1226 }
1227 }
1228 }
1229 FIRST_Group
1230 }
1231
1232 }
含GUI代码:
LR_1_try_GUI类(Scala):
1 import java.awt.{Color}
2 import java.awt.event.{ActionEvent, ActionListener}
3
4 import javax.swing.table.{AbstractTableModel}
5 import javax.swing.{JButton, JFileChooser, JFrame, JPanel, JScrollPane, JTable, JTextField, JTextPane}
6 import pojo.Analyse
7
8 import scala.collection.mutable
9 import scala.collection.mutable.{ArrayBuffer, Map}
10 import scala.util.matching.Regex
11
12
13 object LR_1_try_GUI {
14 private final var allCharacters = new String()
15 private final var relations = new ArrayBuffer[ (String, String, String) ]()
16 private final var VN = new String()
17 private final var VT = new String()
18 private final var rowLength = 0
19 private final var columnLength = 0
20 private final val itemGroup = Map[ ArrayBuffer[ (String, String, String) ], Int ]()
21 private final var LL1_G = new ArrayBuffer[ (String, String) ]()
22 private val allCandidateLetters = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩABCDEFGHIJKLMNOPQRSTUVWXYZ"
23 private final var usedCharacters = ""
24
25 val staticAnalyseList : ArrayBuffer[Analyse] = new ArrayBuffer[Analyse]();
26 var staticTestMatrix : Array[ Array[String] ] = new Array[Array[String]](0)
27 var staticStringBuilder : StringBuilder = new StringBuilder();
28 var staticStringBuilder2 : StringBuilder = new StringBuilder();
29
30 def main(args: Array[String]): Unit = {
31 GUI1
32 }
33
34 /*
35 * Function name: GUI1
36 * Function description: 实现图形化界面展示,开始界面
37 * Input parameters: 无
38 * Return value: 无
39 * Exception: 未处理
40 * Author: 来自高山
41 * Created date: Sun Oct 20 2019 +0800
42 * Editor: 来自高山
43 * Edited Date: Mon Oct 28 2019 +0800
44 */
45 def GUI1(): Unit = {
46 val jFrame = new JFrame("LR(1)词法分析");
47 val jPanel = new JPanel();
48 jFrame.setBounds( 0, 10,1000,90);
49
50 val appendFileJButton2 = new JButton("开始分析");
51 appendFileJButton2.setBounds( 100, 400,200,30);
52 appendFileJButton2.addActionListener(new ActionListener {
53 override def actionPerformed(e: ActionEvent): Unit = {
54 GUI2
55 jFrame.dispose()
56 }
57 })
58
59 //添加文件按钮
60 val appendFileJButton = new JButton("添加文件");
61 appendFileJButton.setBounds( 300, 400,200,30);
62 appendFileJButton.addActionListener(new ActionListener {
63 override def actionPerformed(e: ActionEvent): Unit = {
64 val fileChooser = new JFileChooser();
65 fileChooser.showOpenDialog(jFrame);
66 val filePath = fileChooser.getSelectedFile.getAbsolutePath
67 initiate(filePath)
68 utility
69 }
70 })
71
72 val appendFileJButton3 = new JButton("退出程序")
73 appendFileJButton3.setBounds(500, 400, 200, 30)
74 appendFileJButton3.addActionListener(new ActionListener {
75 override def actionPerformed(e: ActionEvent): Unit = {
76 jFrame.dispose()
77 }
78 })
79
80 jPanel.add(appendFileJButton)
81 jPanel.add(appendFileJButton2)
82 jPanel.add(appendFileJButton3)
83 jPanel.setBackground(Color.gray)
84 jFrame.add(jPanel)
85 import java.awt.FlowLayout
86 jPanel.setLayout(new FlowLayout(FlowLayout.LEADING, 200, 20))
87 jFrame.setResizable(false);
88 jFrame.setVisible(true);
89 }
90
91 /*
92 * Function name: GUI2
93 * Function description: 实现图形化界面展示,分析界面
94 * Input parameters: 无
95 * Return value: 无
96 * Exception: 未处理
97 * Author: 菊花侠
98 * Created date: Sat Oct 19 2019 +0800
99 * Editor: 来自高山
100 * Edited Date: Mon Oct 28 2019 +0800
101 */
102 def GUI2(): Unit = {
103 val jFrame = new JFrame("LR(1)词法分析");
104 jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
105 jFrame.setResizable(false)
106 jFrame.setBounds(0,0,1000,1000);
107 jFrame.setLayout(null)
108
109 //输入行
110 val inputJPanel = new JPanel();
111 inputJPanel.setBounds(0,0,1000,30);
112 inputJPanel.setLayout(null);
113
114 val inputJTextField = new JTextField();
115 inputJTextField.setBounds(0,0,300,30);
116 val inputJButton = new JButton("确认");
117 inputJButton.setBounds(320,0,60,30);
118 inputJPanel.add(inputJTextField)
119 inputJPanel.add(inputJButton)
120 jFrame.add(inputJPanel);
121
122
123 val displayFileJTextPane = new JTextPane();
124 displayFileJTextPane.setEditable(false);
125
126 val displayFileJScrollPane = new JScrollPane();
127 displayFileJScrollPane.setBounds(0,64,1000,300);
128 displayFileJScrollPane.setViewportView(displayFileJTextPane);
129 jFrame.add(displayFileJScrollPane)
130
131 val appendFileJButton = new JButton("显示初始文法")
132 appendFileJButton.setBounds(0, 32,120,30)
133 appendFileJButton.addActionListener(new ActionListener {
134 override def actionPerformed(e: ActionEvent): Unit = {
135 displayFileJTextPane.setText(staticStringBuilder2.toString());
136 }
137 })
138
139 val appendFileJButton2 = new JButton("返回")
140 appendFileJButton2.setBounds(220, 32, 120, 30)
141 appendFileJButton2.addActionListener(new ActionListener {
142 override def actionPerformed(e: ActionEvent): Unit = {
143 GUI1
144 jFrame.dispose()
145 }
146 })
147
148 val appendFileJButton3 = new JButton("退出")
149 appendFileJButton3.setBounds(440, 32, 120, 30)
150 appendFileJButton3.addActionListener(new ActionListener {
151 override def actionPerformed(e: ActionEvent): Unit = {
152 jFrame.dispose()
153 }
154 })
155
156 jFrame.add(appendFileJButton)
157 jFrame.add(appendFileJButton2)
158 jFrame.add(appendFileJButton3)
159
160 val dataMode1 = new AbstractTableModel() {
161
162 override def getColumnCount = 5
163
164 override
165
166 def getRowCount = staticAnalyseList.length
167
168 override
169
170 def getValueAt(row: Int, col: Int): String = {
171 val a = staticAnalyseList(row);
172 if(col == 0){
173 return a.getStep();
174 }
175 if(col == 1){
176 return a.getAnalysisStack;
177 }
178 if(col == 2){
179 return a.getRemainingString;
180 }
181 if(col == 3){
182 return a.getProductionType;
183 }
184 if(col == 4){
185 return a.getAction;
186 }
187 return new String();
188 }
189 }
190
191 val table1JScrollPane = new JScrollPane();
192 val table1JTable = new JTable(dataMode1);
193
194
195
196 table1JScrollPane.setBounds(0,370,690,300)
197 table1JScrollPane.setViewportView(table1JTable);
198
199 val table1JTextPaneScrollPan = new JScrollPane();
200 table1JTextPaneScrollPan.setBounds(692,370,300,300);
201
202
203 val table1JTextPane = new JTextPane();
204 table1JTextPane.setEditable(false);
205 table1JTextPaneScrollPan.setViewportView(table1JTextPane);
206 jFrame.add(table1JTextPaneScrollPan);
207 jFrame.add(table1JScrollPane);
208
209 val table2JTable = new JTable();
210 table2JTable.setBounds(0,682,1000,300);
211
212 val table2JScrollPane = new JScrollPane();
213
214 table2JScrollPane.setBounds(0,682,1000,300)
215 table2JScrollPane.setViewportView(table2JTable);//ryr
216
217 table2JScrollPane.add(table2JTable)
218 jFrame.add(table2JTable);
219
220 jFrame.setVisible(true);
221
222 inputJButton.addActionListener(new ActionListener {
223 override def actionPerformed(e: ActionEvent): Unit = {
224 staticAnalyseList.clear();
225 staticTestMatrix = createMatrix();
226 analyse( inputJTextField.getText() + "#" );
227 val dataMode1 = new AbstractTableModel() {
228
229 override def getColumnCount = 5
230
231 override
232
233 def getRowCount = staticAnalyseList.length
234
235 override
236
237 def getValueAt(row: Int, col: Int): String = {
238 val a = staticAnalyseList(row);
239 if(col == 0){
240 return a.getStep();
241 }
242 if(col == 1){
243 return a.getAnalysisStack;
244 }
245 if(col == 2){
246 return a.getRemainingString;
247 }
248 if(col == 3){
249 return a.getProductionType;
250 }
251 if(col == 4){
252 return a.getAction;
253 }
254 return new String();
255 }
256
257 }
258 table1JTable.setModel(dataMode1);
259
260 val dataMode2 = new AbstractTableModel() {
261
262 override def getColumnCount = columnLength
263
264 override
265
266 def getRowCount = rowLength
267
268 override
269
270 def getValueAt(row: Int, col: Int) = staticTestMatrix(row)(col)
271 }
272 table2JTable.setModel(dataMode2);
273 table1JTextPane.setText(staticStringBuilder.toString())
274 }
275 })
276 }
277
278 /*
279 * Function name: utility
280 * Function description: 辅助输出函数
281 * Input parameters: 无
282 * Return value: 无
283 * Exception: 未处理
284 * Author: 来自高山
285 * Created date: Mon Oct 28 2019 +0800
286 * Editor: 来自高山
287 * Edited Date: Mon Oct 28 2019 +0800
288 */
289 def utility(): Unit = {
290
291 staticStringBuilder.append( "after expanding the language rules:" + "\r\n" )
292 displayRelations()
293 staticStringBuilder.append( "**************" + "\r\n" )
294 staticStringBuilder.append( "FIRST:" + "\r\n" )
295 val testFIRST = FIRST()
296 for( ex <- testFIRST ) {
297 staticStringBuilder.append( "FIRST(" + ex._1 + ") = {" + ex._2.mkString(",") + "}" + "\r\n" )
298 }
299 staticStringBuilder.append( "**************" + "\r\n" )
300 //test getItemGroup
301 var cnt4 = 0
302 for( ex <- itemGroup.toList.sortBy(_._2) ) {
303 staticStringBuilder.append( "I" + ex._2 + ":" + "\r\n" )
304 for (tx <- ex._1 ) {
305
306 staticStringBuilder.append( tx._1 + "->" + tx._2 + ", " + tx._3 + "\r\n" )
307 }
308 staticStringBuilder.append( "^^^^^^^^^^^^^^^^^^^^^^^^" + "\r\n" )
309 cnt4 += 1
310 }
311 staticStringBuilder.append( "**************" + "\r\n" )
312 val test_createMatrix = createMatrix
313 staticTestMatrix = test_createMatrix
314 for ( i <- 0 to test_createMatrix.length - 1 ) {
315 for ( j <- 0 to test_createMatrix(i).length - 1 ) {
316 print( test_createMatrix(i)(j) + " " )
317 }
318
319 }
320 }
321
322 /*
323 * Function name: analyse
324 * Function description: 对指定的字符串进行LR(1)分析
325 * Input parameters: -String(输入的指定字符串)
326 * Return value: -Boolean(分析成功则返回true,否则false)
327 * Exception: 未处理(有出错提示)
328 * Author: 来自高山
329 * Created date: Mon Oct 28 2019 +0800
330 * Editor: 来自高山
331 * Edited Date: Mon Oct 28 2019 +0800
332 */
333 def analyse( expression: String ): Boolean = {
334 val statusStack = new mutable.Stack[String]()
335 val characterStack = new mutable.Stack[String]()
336 val analyseTable = createMatrix()
337 var expr = expression
338 var flag = false
339 var repeat = true
340 statusStack.push("0")
341 characterStack.push("#")
342 var tot = 0
343 staticAnalyseList.append(new Analyse("步骤","状态栈","符号栈","剩余字符串","动作"));
344 staticAnalyseList.append( new Analyse( tot.toString, statusStack.reverse.mkString(","),
345 characterStack.reverse.mkString(""), expr, "initiate") )
346 tot += 1
347 case class characterToColumn(a: String) {
348 var ans = -1
349 for( j <- 1 to (columnLength - 1) ) {
350 if( analyseTable(0)(j) == a ) {
351 ans = j
352 }
353 }
354 //ans
355 }
356 while ( repeat == true ) {
357 // s = statusTop
358 val statusTop = statusStack.top
359 val a = expr(0)
360
361 val aColumn = characterToColumn(a.toString).ans
362 var sRow = statusTop.toInt
363 if(sRow == 0 ) sRow += 1 else sRow += 1
364
365 if( analyseTable(sRow)(aColumn)(0) == 'S' ) {
366 val newStatus = analyseTable(sRow)(aColumn).drop(1)
367 statusStack.push(newStatus)
368 characterStack.push(a.toString)
369 expr = expr.drop(1)
370 staticAnalyseList.append( new Analyse( tot.toString,statusStack.reverse.mkString(","),
371 characterStack.reverse.mkString(""), expr, "ACTION[" + statusTop + ", " + a + "]," + "状态 " + aColumn +
372 " 与符号 " + a + " 分别入栈") )
373 tot += 1
374 }
375 else if( analyseTable(sRow)(aColumn)(0) == 'r' ) {
376 val exprLineNO = analyseTable(sRow)(aColumn).drop(1).toInt
377 val currentRelation = relations(exprLineNO)
378
379 var popLength = 0
380 if( currentRelation._3 != "א" ) {
381 popLength = currentRelation._2.length + currentRelation._3.length
382 }
383 else {
384 popLength = currentRelation._2.length
385 }
386 var cnt = popLength
387 val tmpCharacter = characterStack.reverse.toString.replace("Stack(", "").replace(")",
388 "").replace(",", "").replace(" ", "")
389 val reduceCharacter = tmpCharacter.drop(tmpCharacter.length - popLength)
390 while ( cnt >= 1 ) {
391 statusStack.pop()
392 characterStack.pop()
393 cnt -= 1
394 }
395 // s' = characterTop
396 val statusTop2 = statusStack.top.toInt
397
398 var sRow2 = -1
399 if( statusTop2 == 0 ) sRow2 = statusTop2 + 1 else sRow2 = statusTop2 + 1
400
401 val A = currentRelation._1
402 characterStack.push(A)
403 val tmp = analyseTable(sRow2)( characterToColumn(A).ans )
404 statusStack.push(tmp)
405
406 staticAnalyseList.append( new Analyse( tot.toString, statusStack.reverse.mkString(","),
407 characterStack.reverse.mkString(""), expr, "GOTO[" + statusTop2 + ", " + A + "]" +
408 ",用产生式 " + A + "->" + reduceCharacter + " 进行规约") )
409 tot += 1
410 }
411 else if( analyseTable(sRow)(aColumn) == "acc" ) {
412
413 staticAnalyseList.append( new Analyse( tot.toString,statusStack.reverse.mkString(","),
414 characterStack.reverse.mkString(""), expr, "ACTION[" + statusTop + ", " + a + "] = " + "acc, succeeded") )
415 flag = true
416 repeat = false
417 }
418 else {
419 staticAnalyseList.append( new Analyse( tot.toString,statusStack.reverse.mkString(","),
420 characterStack.reverse.toString(), expr, "ACTION[" + statusTop + ", " + a + "] = " +
421 "error in " + "analyseTable[" + sRow + ", " + aColumn + "]") )
422 flag = true
423 repeat = false
424 }
425 }
426 if(flag) true else false
427 }
428
429 /*
430 * Function name: createMatrix
431 * Function description: 构造ACTION与GOTO分析表
432 * Input parameters: 无
433 * Return value: -Array[ Array[String] ](分析表矩阵元素构成的二维数组)
434 * Exception: 未处理
435 * Author: 来自高山
436 * Created date: Mon Oct 28 2019 +0800
437 * Editor: 来自高山
438 * Edited Date: Mon Oct 28 2019 +0800
439 */
440 def createMatrix(): Array[ Array[String] ] = {
441 val result = initiateMatrix()
442 val localVT = VT
443 val localVN = VN
444
445 case class getColumn( ch: String ) {
446 val matrix = initiateMatrix()
447 var ans = -1
448 for( j <- 0 to (columnLength - 1) ) {
449 if( matrix(0)(j) == ch ) {
450 ans = j
451 }
452 }
453 }
454
455 for( ex <- itemGroup ) {
456 for( tx <- ex._1 ) {
457 val pointPosition = tx._2.indexOf("·")
458 //· 不在最右边
459 //若项目[A->α·aβ] ∈ Ik,且GO(Ik, a) = Ij,a为终结符,则置ACTION[k, a]为“sj”
460 if (pointPosition < tx._2.length - 1) {
461 val a = tx._2( pointPosition + 1 )
462 if( localVT.contains(a) == true && findItemOrder(ex._1, a.toString) != -1 ) {
463 val j = findItemOrder(ex._1, a.toString)
464 var tmpRow = -1
465 tmpRow = ex._2 + 1
466 result(tmpRow)( getColumn(a.toString).ans ) = "S" + j.toString
467 }
468 }
469 if (pointPosition == tx._2.length - 1 ) {
470 val a = tx._3
471 var tmpRow = -1
472 tmpRow = ex._2 + 1
473 result(tmpRow)(getColumn(a).ans) = "r" + ( findRelationOrder( (tx._1,
474 tx._2.replace("·", "") ) ) )
475 }
476 if( tx._1 == relations(0)._1 && tx._2 == relations(0)._2 + "·" && tx._3 == "#" ) {
477 var tmpRow = -1
478 tmpRow = ex._2 + 1
479 result(tmpRow)( getColumn("#").ans ) = "acc"
480 }
481 }
482 for( ch <- localVN ) {
483 if( findItemOrder(ex._1, ch.toString) != -1 ) {
484 val gotoNumber = findItemOrder(ex._1, ch.toString)
485 var tmpRow = -1
486 tmpRow = ex._2 + 1
487 //A = ch
488 result(tmpRow)( getColumn(ch.toString).ans ) = gotoNumber.toString
489 }
490 }
491 }
492 result
493 }
494
495 /*
496 * Function name: findRelationOrder
497 * Function description: 获取产生式的位于文法的第几行,从0开始
498 * Input parameters: -(String, String)(給定的产生式)
499 * Return value: -Int(給定的产生式在給定文法中的行数)
500 * Exception: 未处理
501 * Author: 来自高山
502 * Created date: Mon Oct 28 2019 +0800
503 * Editor: 来自高山
504 * Edited Date: Mon Oct 28 2019 +0800
505 */
506 def findRelationOrder( expression: (String, String) ): Int ={
507 var ans = -1
508 var cnt = 0
509 val localRelations = relations
510 for( ex <- localRelations ) {
511 var expr = ""
512 if( ex._3 != "א" ) {
513 expr = ex._1 + ex._2 + ex._3
514 }
515 else {
516 expr = ex._1 + ex._2
517 }
518 if( expr.equals(expression._1 + expression._2) ) {
519 ans = cnt
520 }
521 cnt += 1
522 }
523 ans
524 }
525
526 /*
527 * Function name: findItemOrder
528 * Function description: 获取特定项目对于指定字符在项目集族中的编号,从0开始
529 * Input parameters: -ArrayBuffer[ (String, String, String) ](給定项目), -String(給定字符)
530 * Return value: -Int(給定的项目对于指定字符在项目集族中的编号)
531 * Exception: 未处理
532 * Author: 来自高山
533 * Created date: Mon Oct 28 2019 +0800
534 * Editor: 来自高山
535 * Edited Date: Mon Oct 28 2019 +0800
536 */
537 def findItemOrder( item: ArrayBuffer[ (String, String, String) ], a: String ): Int = {
538 var ans = -1
539 val givenItem = go( item, a).sorted
540 val localItemGroup = itemGroup
541 for( ex <- localItemGroup ) {
542 if( ex._1.sorted.equals(givenItem) ) {
543 ans = ex._2
544 }
545 }
546 ans
547 }
548
549 /*
550 * Function name: initiateMatrix
551 * Function description: 初始化分析表,即ACTION表与GOTO表
552 * Input parameters: 无
553 * Return value: -Array[ Array[ String] ](已完成初始的分析表)
554 * Exception: 未处理
555 * Author: 来自高山
556 * Created date: Sun Oct 27 2019 +0800
557 * Editor: 来自高山
558 * Edited Date: Sun Oct 27 2019 +0800
559 */
560 def initiateMatrix(): Array[ Array[ String] ] = {
561 val localVN = VN
562 val localVT = VT
563 val tableRowLength = rowLength
564 val tableColumnLength = columnLength
565 val result = Array.ofDim[String](tableRowLength, tableColumnLength)
566 for( j <- 1 to localVT.length ) {
567 result(0)(j) = localVT(j - 1).toString
568 }
569 for( j <- localVT.length + 1 to tableColumnLength - 1 ) {
570 result(0)(j) = localVN(j - localVT.length - 1).toString
571 }
572 for( i <- 1 to ( tableRowLength - 1 ) ) {
573 result(i)(0) = (i - 1).toString
574 }
575 for( i <- 0 to (tableRowLength - 1) ) {
576 for( j <- 0 to (tableColumnLength - 1) ) {
577 if( result.isEmpty != false ) {
578 result(i)(j) = null
579 }
580 }
581 }
582
583 result
584 }
585
586 /*
587 * Function name: getItemGroup
588 * Function description: 对于输入的文法,建立初始化的项目集
589 * Input parameters: 无
590 * Return value: -Unit
591 * Exception: 未处理
592 * Author: 来自高山
593 * Created date: Wed Oct 23 2019 +0800
594 * Editor: 来自高山
595 * Edited Date: Sun Oct 27 2019 +0800
596 */
597 def getItemGroup(): Unit = {
598 val ldx = ( relations(0)._1, "·" + relations(0)._2, "#" )
599 val I0 = getClosure( ArrayBuffer(ldx) )
600 val wholeCharacters = allCharacters
601 var tot = 0
602 itemGroup(I0) = tot
603 var appendFlag = true
604 while (appendFlag == true) {
605 var originalAns = Map[ ArrayBuffer[ (String, String, String) ], Int ]()
606 originalAns = itemGroup.clone()
607 //为什么用I作为遍历变量不行?!
608 for(item <- itemGroup.keys) {
609 for (ch <- wholeCharacters) {
610 val newItem = go(item, ch.toString).sorted
611 if (newItem.isEmpty == false && itemGroup.contains(newItem) == false) {
612 tot += 1
613 itemGroup(newItem) = tot
614 }
615 }
616 }
617 if( originalAns.equals(itemGroup) == true ) {
618 appendFlag = false
619 }
620 else {
621 originalAns.clear()
622 originalAns = itemGroup.clone()
623 }
624 }
625 }
626
627 /*
628 * Function name: go
629 * Function description: 求給定项目对于特定字符的下一状态
630 * Input parameters: -ArrayBuffer[ (String, String, String) ](給定项目), String(特定字符)
631 * Return value: -ArrayBuffer[ (String, String, String) ](給定项目对于特定字符的下一状态)
632 * Exception: 未处理
633 * Author: 来自高山
634 * Created date: Sat Oct 26 2019 +0800
635 * Editor: 来自高山
636 * Edited Date: Sat Oct 26 2019 +0800
637 */
638 def go( I: ArrayBuffer[ (String, String, String) ], X: String ): ArrayBuffer[ (String, String, String) ] = {
639 //GO(I, X) = CLOSURE(J)
640 //J = {任何形如[A->αX·β, a]的项目|[A->α·Xβ, a]∈I}
641 val ans = new ArrayBuffer[ (String, String, String) ]()
642 val items = new ArrayBuffer[ (String, String, String) ]()
643
644 for( ex <- I ) {
645 val pointPosition = ex._2.indexOf("·")
646 //· 不在最右边
647 if (pointPosition < ex._2.length - 1) {
648 val A = ex._1
649 val possibleX = ex._2( pointPosition + 1)
650 // αXβ
651 val noPointExpressionPart2 = ex._2.replace("·", "")
652 if( X == possibleX.toString ) {
653 // αX·β
654 val newPart2 = noPointExpressionPart2.substring(0, pointPosition + 1) + "·" +
655 noPointExpressionPart2.substring(pointPosition + 1, noPointExpressionPart2.length)
656 val a = ex._3
657 items += ( (A, newPart2, a) )
658 }
659 }
660 }
661 ans.appendAll( getClosure(items) )
662 ans
663 }
664
665 /*
666 * Function name: getClosure
667 * Function description: 求給定项目集的闭包
668 * Input parameters: -ArrayBuffer[ (String, String, String) ](給定的项目集)
669 * Return value: -ArrayBuffer[ (String, String, String) ](給定项目集的闭包)
670 * Exception: 未处理
671 * Author: 来自高山
672 * Created date: Sat Oct 26 2019 +0800
673 * Editor: 来自高山
674 * Edited Date: Sun Oct 27 2019 +0800
675 */
676 def getClosure( items: ArrayBuffer[ (String, String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
677 val result = new ArrayBuffer[ (String, String, String) ]()
678 result.appendAll(items)
679 val localFIRST = FIRST()
680 var addFlag = true
681 var cnt = 1
682 while (addFlag == true ) {
683 val originalResult = new ArrayBuffer[(String, String, String)]()
684 originalResult.appendAll(result)
685 for (ex <- result) {
686
687 val pointPosition = ex._2.indexOf("·")
688 //· 不在最右边
689 if (pointPosition < ex._2.length - 1) {
690 //B在 · 的右边
691 val B = ex._2(pointPosition + 1)
692 val a = ex._3
693
694 // case 1: β != Φ and a != # or
695 // case 2: β != Φ and a = #
696 if (pointPosition < ex._2.length - 2) {
697 val β = ex._2(pointPosition + 2)
698 // ξ
699 val rightExpressionsOfB = getRightExpressions(B.toString)
700 val FIRST_Of_βa = localFIRST(β.toString)
701 for (b <- FIRST_Of_βa) {
702 for (ksi <- rightExpressionsOfB) {
703 val tmp = ((B.toString, "·" + ksi, b.toString))
704
705 if (result.contains(tmp) == false) {
706 result += tmp
707 }
708 }
709 }
710 }
711 // case 3: β = Φ and a equals any character
712 if (pointPosition == ex._2.length - 2) {
713 val rightExpressionsOfB = getRightExpressions(B.toString)
714 val FIRST_Of_βa = localFIRST(a.toString)
715 for (b <- FIRST_Of_βa) {
716 for (ksi <- rightExpressionsOfB) {
717 val tmp = ((B.toString, "·" + ksi, b.toString))
718 if (result.contains(tmp) == false) {
719 result += tmp
720 }
721 }
722 }
723 }
724 }
725 }
726 if (result != originalResult) {
727 originalResult.remove(0, originalResult.length)
728 originalResult.appendAll(result)
729 cnt += 1
730 }
731 else {
732 addFlag = false
733 cnt += 1
734 }
735 }
736 result
737 }
738
739 /*
740 * Function name: getRightExpressions
741 * Function description: 获取給定非终结符所在产生式的右部,可能不止一个,因此返回值是String类型的ArrayBuffer数组
742 * Input parameters: -String(給定的非终结符)
743 * Return value: -ArrayBuffer[String](給定非终结符所在产生式的右部)
744 * Exception: 未处理
745 * Author: 来自高山
746 * Created date: Fri Oct 25 2019 +0800
747 * Editor: 来自高山
748 * Edited Date: Fri Oct 25 2019 +0800
749 */
750 def getRightExpressions(ch: String): ArrayBuffer[String] = {
751 val result = new ArrayBuffer[String]()
752 val localRelations = relations
753 for( ex <- localRelations ) {
754 if( ex._1 == ch ) {
755 if( ex._3 != "א" ) {
756 result += ex._2
757 result += ex._3
758 }
759 else {
760 result += ex._2
761 }
762 }
763 }
764 result
765 }
766
767 /*
768 * Function name: displayStack
769 * Function description: 输出栈的所有元素
770 * Input parameters: -mutable.Stack[String](待处理的String类型的栈)
771 * Return value: -String(栈所有元素组成的字符串)
772 * Exception: 未处理
773 * Author: 来自高山
774 * Created date: Mon Oct 21 2019 +0800
775 * Editor: 来自高山
776 * Edited Date: Mon Oct 21 2019 +0800
777 */
778 def displayStack( stack: mutable.Stack[String] ): String = {
779 var result = ""
780 for( ex <- stack ) {
781 result += ex
782 }
783 result
784 }
785
786 /*
787 * Function name: initiate
788 * Function description: 初始化全局变量
789 * Input parameters: the absolute path of the language-rule source file
790 * Return value: 无
791 * Exception: 未处理
792 * Author: 来自高山
793 * Created date: Sat Oct 19 2019 +0800
794 * Editor: 来自高山
795 * Edited Date: Sun Oct 27 2019 +0800
796 */
797 def initiate( filePath: String ): Unit = {
798 LL1_G = parseFile(filePath)
799 allCharacters = getWholeCharacters(LL1_G)
800 usedCharacters = allCharacters
801 relations = getRelation(LL1_G)
802 VN = getVN(allCharacters)
803 VT = getVT(allCharacters)
804 val leftCharacters = subString(allCandidateLetters, VN)
805 relations.insert(0, ( leftCharacters(0).toString, (relations(0)._1), "א" ) )
806 VN += leftCharacters(0).toString
807 usedCharacters += leftCharacters(0).toString
808 allCharacters += leftCharacters(0).toString
809
810 allCharacters += "#"
811 usedCharacters += "#"
812 VT += "#"
813 getItemGroup
814 columnLength = VN.length + VT.length + 1
815 rowLength = itemGroup.size + 1
816 }
817
818 /*
819 * Function name: subString
820 * Function description: 获取两输入字符串的差集(要求两者均非空)
821 * Input parameters: 无
822 * Return value: -String(两输入字符串的差集)
823 * Exception: 未处理
824 * Author: 来自高山
825 * Created date: Sat Oct 19 2019 +0800
826 * Editor: 来自高山
827 * Edited Date: Sat Oct 19 2019 +0800
828 */
829 def subString( usedCharacters: String, localCandidateLetters: String ): String = {
830 require( usedCharacters.length != 0 && localCandidateLetters.length != 0 )
831 var ans = ""
832 var A = usedCharacters
833 var B = localCandidateLetters
834 if( A.length < B.length ) {
835 val tmp = A
836 A = B
837 B = tmp
838 }
839 for( i <- 0 to (A.length - 1) ) {
840 var j = 0
841 while( j < B.length && B(j) != A(i) ) {
842 j += 1
843 }
844 if( j == B.length ) {
845 ans += A(i)
846 }
847 }
848 ans
849 }
850
851 /*
852 * Function name: displayRelations
853 * Function description: display all he language rules
854 * Input parameters: 无
855 * Return value: 无
856 * Exception: 未处理
857 * Author: 来自高山
858 * Created date: Sat Oct 19 2019 +0800
859 * Editor: 来自高山
860 * Edited Date: Mon Oct 28 2019 +0800
861 */
862 def displayRelations(): Unit = {
863 for( ex <- relations ) {
864 if( ex._3 != "א" ) {
865
866 staticStringBuilder.append( ex._1 + "->" + ex._2 + "|" + ex._3 + "\r\n")
867 if( ex != relations(0) ) {
868 staticStringBuilder2.append(ex._1 + "->" + ex._2 + "|" + ex._3 + "\r\n")
869 }
870 }
871 else {
872
873 staticStringBuilder.append( ex._1 + "->" + ex._2 + "\r\n")
874 if( ex != relations(0) ) {
875 staticStringBuilder2.append(ex._1 + "->" + ex._2 + "\r\n")
876 }
877 }
878 }
879 }
880
881 /*
882 * Function name: parseFile
883 * Function description: 解析文本文件,保存在数组中
884 * Input parameters: 文本绝对路径
885 * Return value: -ArrayBuffer[ ( String, String ) ](String类型的元组ArrayBuffer数组)
886 * Exception: 未处理
887 * Author: 来自高山
888 * Created date: Fri Oct 18 2019 +0800
889 * Editor: 来自高山
890 * Edited Date: Fri Oct 18 2019 +0800
891 */
892 def parseFile( filePath: String ): ArrayBuffer[ ( String, String ) ] = {
893 val result = new ArrayBuffer[ ( String, String ) ]( countLines( readFromTxtByLine(filePath) ) )
894 val sourceFile = readFromTxtByLine(filePath) //filePath
895 for( line <- sourceFile ) {
896 val tmp = line.split( "->", 2 )
897 result += ( ( tmp.head, tmp.last ) )
898 }
899 result
900 }
901
902 /*
903 * Function name: countLines
904 * Function description: 计算文本行数,用于创建接收数组时开辟相应空间
905 * Input parameters: -Array[String](文本文件数据构成的数组)
906 * Return value: -Int(文本行数)
907 * Exception: 未处理
908 * Author: 来自高山
909 * Created date: Fri Oct 18 2019 +0800
910 * Editor: 来自高山
911 * Edited Date: Sat Oct 19 2019 +0800
912 */
913 def countLines( sourceFile: Array[String] ): Int = {
914 var cnt = 0
915 for( line <- sourceFile ) {
916 cnt += 1
917 }
918 cnt
919 }
920
921 /*
922 * Function name: readFromTxtByLine
923 * Function description: 读取文本文件
924 * Input parameters: -String(文本文件绝对路径)
925 * Return value: -Array[String](文本文件构成的数组,每行数据占一个数组元素)
926 * Exception: -未处理
927 * Author: 来自高山
928 * Created date: Fri Oct 18 2019 +0800
929 * Editor: 来自高山
930 * Edited Date: Fri Oct 18 2019 +0800
931 */
932 def readFromTxtByLine(filePath: String): Array[String] = {
933 import scala.io.Source
934 val source = Source.fromFile(filePath, "UTF-8")
935 //val lineIterator = source.getLines()
936 //lineIterator.foreach()
937 val lines = source.getLines().toArray
938 source.close()
939 //
940 lines
941 }
942
943 /*
944 * Function name: getWholeCharacters
945 * Function description: 获取文法的除“|”之外的所有字符
946 * Input parameters: -ArrayBuffer[ (String, String) ](由文法左右两部分字符构成一个元组的数组,筛掉“|”)
947 * Return value: -String(文法的除“|”之外的所有字符)
948 * Exception: 未处理(有出错提示)
949 * Author: 来自高山
950 * Created date: Fri Oct 11 2019 +0800
951 * Editor: 来自高山
952 * Edited Date: Fri Oct 11 2019 +0800
953 */
954 def getWholeCharacters( string: ArrayBuffer[ (String, String) ] ): String = {
955 var wholeCharacters = ""
956 for( expression <- string ) {
957 wholeCharacters += expression._1 + expression._2
958 }
959 val pattern = new Regex("\\|")
960 val result = pattern replaceAllIn( wholeCharacters, "" )
961 if( result.isEmpty )
962 "function getWholeCharacters failed"
963 else
964 result.distinct
965 }
966 /*
967 * Function name: getVN
968 * Function description: 获取文法的所有非终结符(non-terminal character),默认大写字母为非终结符,使用正则表达式匹配
969 * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
970 * Return value: -String(文法的所有非终结符)
971 * Exception: 未处理(有出错提示)
972 * Author: 来自高山
973 * Created date: Fri Oct 11 2019 +0800
974 * Editor: 来自高山
975 * Edited Date: Fri Oct 11 2019 +0800
976 */
977 def getVN( string: String ): String = {
978 //match big letter:
979 //^[A-Z]+$
980 val pattern = new Regex("[A-Z]")//("^[A-Z]+$")
981 if( (pattern findAllIn string) != null )
982 (pattern findAllIn string).mkString("")
983 else
984 "function getVN failed"
985 }
986
987 /*
988 * Function name: getVT
989 * Function description: 获取文法的所有非终结符(terminal character),默认大写字母外的字符为终结符,使用正则表达式匹配
990 * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
991 * Return value: -String(文法的所有终结符)
992 * Exception: 未处理(有出错提示)
993 * Author: 来自高山
994 * Created date: Fri Oct 11 2019 +0800
995 * Editor: 来自高山
996 * Edited Date: Fri Oct 11 2019 +0800
997 */
998 def getVT( string: String ): String = {
999 val pattern1 = new Regex("[A-Z]")
1000 val pattern2 = new Regex("\\|")
1001 val firstFilter = pattern1 replaceAllIn( string, "" )
1002 val result = pattern2 replaceAllIn( firstFilter, "" )
1003 if( result.isEmpty == false )
1004 result
1005 else
1006 return "function getVT failed"
1007 }
1008 /*
1009 * Function name: getRelation
1010 * Function description: 获取文法每一行对应的推导关系,若文法只推出了1项(即没有符号“|”),则返回元组的第三个用希伯来字母“א”示空
1011 * Input parameters: -ArrayBuffer[ (String, String)(已经分割好的文法左右部分构成的数组)
1012 * Return value: -ArrayBuffer[ (String, String, String) ](元组第一个元素为推导式左边符号,第二为右边第二个符号串,第三为右边(若有)第三个符号串)
1013 * Exception: 未处理
1014 * Author: 来自高山
1015 * Created date: Fri Oct 11 2019 +0800
1016 * Editor: 来自高山
1017 * Edited Date: Fri Oct 11 2019 +0800
1018 */
1019 def getRelation( string: ArrayBuffer[ (String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
1020 val relation = new ArrayBuffer[ (String, String, String) ]()
1021 for( expression <- string ) {
1022 if( expression._2.contains("|") == false ) {
1023 relation += ( ( expression._1, expression._2, "א" ) )
1024 }
1025 else {
1026 val tmp = expression._2.split("\\|", 2 )
1027 relation += ( ( expression._1, tmp.head, tmp.last ) )
1028 }
1029 }
1030 relation
1031 }
1032
1033 /*
1034 * Function name: findFirst
1035 * Function description: 获取指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串
1036 * Input parameters: -String(指定字符)
1037 * Return value: -String(指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串)
1038 * Exception: 未处理
1039 * Author: 来自高山
1040 * Created date: Fri Oct 11 2019 +0800
1041 * Editor: 来自高山
1042 * Edited Date: Fri Oct 11 2019 +0800
1043 */
1044 def findFirst( ch: String ): String = {
1045
1046 val localRelations = relations
1047 var result = ""
1048 for( ex <- localRelations ) {
1049 if( ch == ex._1 ) {
1050 if( ex._3 != "א" ) {
1051 if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
1052 result += ex._2(0).toString
1053 }
1054 if( VT.contains( ex._3(0) ) && ex._3(0) != 'ε' ) {
1055 result += ex._3(0).toString
1056 }
1057 }
1058 else {
1059 if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
1060 result += ex._2(0).toString
1061 }
1062 }
1063 }
1064 }
1065 result
1066 }
1067
1068 /*
1069 * Function name: judgeOnlyOneVoidSuccession
1070 * Function description: 判断指定字符是否可推出唯一的字符ε
1071 * Input parameters: -String(指定字符串)
1072 * Return value: -Boolean(存在则true,否则false)
1073 * Exception: 未处理
1074 * Author: 来自高山
1075 * Created date: Fri Oct 11 2019 +0800
1076 * Editor: 来自高山
1077 * Edited Date: Fri Oct 11 2019 +0800
1078 */
1079 def judgeOnlyOneVoidSuccession( ch: String ): Boolean = {
1080 val localRelations = relations
1081 var result = 1
1082 for( ex <- localRelations ) {
1083 if( ch == ex._1 ) {
1084 if( ex._3 != "א" ) {
1085 if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) || (ex._3.length == 1 && ex._3(0) == 'ε') ) {
1086 result = 1
1087 }
1088 else {
1089 result = 0
1090 }
1091 }
1092 else {
1093 if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) ) {
1094 result = 1
1095 }
1096 else {
1097 result = 0
1098 }
1099 }
1100 }
1101 }
1102 if( result == 1 ) true else false
1103 }
1104
1105 /*
1106 * Function name: judgeCaseXY
1107 * Function description: 判断构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)
1108 * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
1109 * Return value: -Boolean(满足则true,否则false)
1110 * Exception: 未处理
1111 * Author: 来自高山
1112 * Created date: Sat Oct 12 2019 +0800
1113 * Editor: 来自高山
1114 * Edited Date: Sat Oct 12 2019 +0800
1115 */
1116 def judgeCaseXY( ch: Char ): Boolean = {
1117 val localVN = VN
1118 val localRelations = relations
1119 var result = 0
1120 if( localVN.contains(ch) == true ) {
1121 for( ex <- localRelations ) {
1122 if( ex._1(0) == ch ) {
1123 if( localVN.contains( ex._2(0) ) || localVN.contains( ex._3(0) ) ) {
1124 result += 1
1125 }
1126 }
1127 }
1128 }
1129 if( result > 0 )
1130 true
1131 else
1132 false
1133 }
1134
1135 /*
1136 * Function name: findCase_Y_In_XY
1137 * Function description: 获取构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)时的Y
1138 * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
1139 * Return value: -String(Y构成的String字符串,无则为空)
1140 * Exception: 未处理
1141 * Author: 来自高山
1142 * Created date: Sat Oct 12 2019 +0800
1143 * Editor: 来自高山
1144 * Edited Date: Sat Oct 12 2019 +0800
1145 */
1146 def findCase_Y_In_XY( ch: Char ): String = {
1147 val localVN = VN
1148 val localRelations = relations
1149 var result = ""
1150 if( localVN.contains(ch) == true ) {
1151 for( ex <- localRelations ) {
1152 if( ex._1(0) == ch ) {
1153 if( ex._3 != "א" ) {
1154 if( localVN.contains( ex._2(0) ) == true ) {
1155 result += ex._2(0).toString
1156 }
1157 if( localVN.contains( ex._3(0) ) == true ) {
1158 result += ex._3(0).toString
1159 }
1160 }
1161 else {
1162 if( localVN.contains( ex._2(0) ) == true ) {
1163 result += ex._2(0).toString
1164 }
1165 }
1166 }
1167 }
1168 }
1169 result
1170 }
1171
1172 /*
1173 * Function name: findCase_Y_In_nY
1174 * Function description: 获取构造FIRST集时可能的第3种情况的(2)时的FIRST(Yi)中所有的非ε-元素(省略描述若干字)
1175 * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
1176 * Return value: -String(FIRST(Yi)中所有的非ε-元素构成的String字符串,无则为空)
1177 * Exception: 未处理
1178 * Author: 来自高山
1179 * Created date: Sat Oct 12 2019 +0800
1180 * Editor: 来自高山
1181 * Edited Date: Sat Oct 12 2019 +0800
1182 */
1183 def findCase_Y_In_nY( ch: Char ): String = {
1184 val localVN = VN
1185 val localRelations = relations
1186 var result = ""
1187 for( ex <- localRelations ) {
1188 if (ex._1 == ch.toString) {
1189 var tmp = ""
1190
1191 if (ex._3 != 'א') {
1192 var cnt = 0
1193 for (tx <- ex._2) {
1194 // add the element belongs to tmp
1195 if (localVN.contains(tx)) {
1196 tmp += tx.toString
1197 cnt += 1
1198 }
1199 // otherwise, reset tmp as empty string
1200 else {
1201 tmp = ""
1202 }
1203 }
1204 if (cnt == ex._2.length) {
1205 result += tmp
1206 }
1207
1208 // reset
1209 cnt = 0
1210 tmp = ""
1211 for (tx <- ex._3) {
1212 // add the element belongs to tmp
1213 if (localVN.contains(tx)) {
1214 tmp += tx.toString
1215 cnt += 1
1216 }
1217 // otherwise, reset result as empty string
1218 else {
1219 tmp = ""
1220 }
1221 }
1222 if (cnt == ex._3.length) {
1223 result += tmp
1224 }
1225 }
1226 else {
1227 tmp = ""
1228 var cnt = 0
1229 for (tx <- ex._2) {
1230 // add the element belongs to tmp
1231 if (localVN.contains(tx)) {
1232 tmp += tx.toString
1233 cnt += 1
1234 }
1235 // otherwise, reset tmp as empty string
1236 else {
1237 tmp = ""
1238 }
1239 }
1240 if (cnt == ex._2.length) {
1241 result += tmp
1242 }
1243 }
1244 }
1245 }
1246 result = result.distinct
1247 result
1248 }
1249
1250 /*
1251 * Function name: FIRST
1252 * Function description: 按照教材P78左下角的算法描述实现求解指定文法FIRST集;因用的是循环迭代求解,因此代码较长
1253 * Input parameters: -ArrayBuffer[ (String, String) ](产生式左右两部分分别构成元组的第1个和第2个元素)
1254 * Return value: -Map[ String, String ](Map的key是非终结符,value是其FIRST元素)
1255 * Exception: 未处理
1256 * Author: 来自高山
1257 * Created date: Mon Oct 14 2019 +0800
1258 * Editor: 来自高山
1259 * Edited Date: Sat Oct 19 2019 +0800
1260 */
1261 def FIRST(): Map[ String, String ] = {
1262 val FIRST_Group = Map[ String, String ]()
1263 val wholeCharacters = allCharacters
1264 val localVT = VT
1265 val localVN = VN
1266
1267 for( character <- wholeCharacters ) {
1268 // case 1
1269 if( localVT.contains(character) ) {
1270 //if there exist the original key that equals the current one
1271 if( FIRST_Group.contains(character.toString) == true ) {
1272 val tmp = character.toString + FIRST_Group(character.toString)
1273 FIRST_Group(character.toString) = tmp.distinct
1274 }
1275 //otherwise
1276 else {
1277 FIRST_Group(character.toString) = character.toString
1278 }
1279 }
1280
1281 // case 2
1282 if( localVN.contains(character.toString) == true ) {
1283 // case 2.1
1284 val value = findFirst(character.toString)
1285 if ( value.length != 0 ) {
1286 if ( FIRST_Group.contains(character.toString) == true ) {
1287 for( ch <- value ) {
1288 val tmp = ch + FIRST_Group(character.toString)
1289 FIRST_Group(character.toString) = tmp.distinct
1290 }
1291 }
1292 else {
1293 FIRST_Group(character.toString) = value.toString
1294 }
1295 }
1296
1297 // case 2.2
1298 if( judgeOnlyOneVoidSuccession(character.toString) == true ) {
1299 if ( FIRST_Group.contains(character.toString) == true ) {
1300 val tmp = "ε" + FIRST_Group(character.toString)
1301 FIRST_Group(character.toString) = tmp.distinct
1302 }
1303 else {
1304 FIRST_Group(character.toString) = "ε"
1305 }
1306 }
1307 }
1308
1309 for( character <- wholeCharacters ) {
1310 // case 3
1311 // case 3.1
1312 if( judgeCaseXY(character) == true ) {
1313 val tmpReply = findCase_Y_In_XY(character)
1314 for( eachTmpReply <- tmpReply ) {
1315 if( FIRST_Group.contains(eachTmpReply.toString) == true ) {
1316 for (ex <- FIRST_Group(eachTmpReply.toString)) {
1317 if (ex != 'ε') {
1318 if (FIRST_Group.contains(character.toString) == true) {
1319 val tmp = ex.toString + FIRST_Group(character.toString)
1320 FIRST_Group(character.toString) = tmp.distinct
1321 }
1322 else {
1323 FIRST_Group(character.toString) = ex.toString
1324 }
1325 }
1326 }
1327 }
1328 }
1329 }
1330
1331 // case 3.2
1332 if( findCase_Y_In_nY(character).length > 0 ) {
1333 var flag = true
1334 val tmpReply = findCase_Y_In_nY(character)
1335
1336 for( ex <- tmpReply ) {
1337 if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true ) {
1338 if( FIRST_Group(ex.toString).contains("ε") == false ) {
1339 flag = false
1340 }
1341 }
1342 else {
1343 flag = false
1344 }
1345 if( flag == true ) {
1346 if (FIRST_Group.contains(character.toString) == true) {
1347 val tmp = FIRST_Group(ex.toString).replace( "ε", "" ) + FIRST_Group(character.toString)
1348 FIRST_Group(character.toString) = tmp.distinct
1349 }
1350 else {
1351 FIRST_Group(character.toString) = FIRST_Group(ex.toString).replace( "ε", "" )
1352 }
1353
1354 }
1355 }
1356 }
1357 // case 3.3
1358 if( findCase_Y_In_nY(character).length > 0 ) {
1359 var flag = true
1360 val tmpReply = findCase_Y_In_nY(character)
1361 for( ex <- tmpReply ) {
1362 if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true ) {
1363 if( FIRST_Group(ex.toString).contains("ε") == false ) {
1364 flag = false
1365 }
1366 }
1367 else {
1368 flag = false
1369 }
1370 if( flag == true ) {
1371
1372 if (FIRST_Group.contains(character.toString) == true) {
1373 val tmp = "ε" + FIRST_Group(character.toString)
1374 FIRST_Group(character.toString) = tmp.distinct
1375 }
1376 else {
1377 FIRST_Group(character.toString) = "ε"
1378 }
1379 }
1380 }
1381 }
1382 }
1383 }
1384 FIRST_Group
1385 }
1386
1387 }
FileUtil类(Java):
1 import java.io.*; 2 import java.util.Vector; 3 4 /** 5 * 文件工具类 6 */ 7 public class FileUtil { 8 public static void main(String[] args) throws FileNotFoundException { 9 String s = readFile( new FileInputStream("/home/hadoop001/Desktop/test.data") ); 10 System.out.println(s); 11 } 12 /** 13 * 读取文件内容 14 * 15 * @param is 16 * @return 17 */ 18 public static String readFile(InputStream is) { 19 BufferedReader br = null; 20 StringBuffer sb = new StringBuffer(); 21 try { 22 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); 23 String readLine = null; 24 while ((readLine = br.readLine()) != null) { 25 sb.append(readLine+"\r\n"); 26 } 27 } catch (Exception e) { 28 e.printStackTrace(); 29 } finally { 30 try { 31 br.close(); 32 is.close(); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } 36 } 37 return sb.toString(); 38 } 39 }
Analyse类(Java):
1 package pojo;
2
3 public class Analyse {
4 private String step;
5 private String analysisStack;
6 private String remainingString;
7 private String productionType;
8 private String action;
9
10 public Analyse(){
11
12 }
13
14 public Analyse(String step, String analysisStack, String remainingString, String productionType, String action) {
15 this.step = step;
16 this.analysisStack = analysisStack;
17 this.remainingString = remainingString;
18 this.productionType = productionType;
19 this.action = action;
20 }
21
22 public String getStep() {
23 return step;
24 }
25
26 public void setStep(String step) {
27 this.step = step;
28 }
29
30 public String getAnalysisStack() {
31 return analysisStack;
32 }
33
34 public void setAnalysisStack(String analysisStack) {
35 this.analysisStack = analysisStack;
36 }
37
38 public String getRemainingString() {
39 return remainingString;
40 }
41
42 public void setRemainingString(String remainingString) {
43 this.remainingString = remainingString;
44 }
45
46 public String getProductionType() {
47 return productionType;
48 }
49
50 public void setProductionType(String productionType) {
51 this.productionType = productionType;
52 }
53
54 public String getAction() {
55 return action;
56 }
57
58 public void setAction(String action) {
59 this.action = action;
60 }
61 }
运行截图:
图 1 开始界面
图 2 选择文件
图 3 分析界面
图 4 显示初始文法
图 5 分析完成(输入表达死为“i+i*i”)