合肥工业大学编译原理实验LR(1)文法分析完整Scala实现代码(Java封装GUI)与测试数据

 

  github地址:https://github.com/25thengineer/Compile_Experiment_LR_1

 

  测试数据:

  

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 }
View Code

 

 

  含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 }
View Code

 

  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 }
View Code

 

  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 }
View Code

 

  运行截图:

图 1 开始界面

 

图 2 选择文件

 

图 3 分析界面

 

图 4 显示初始文法

 

图 5 分析完成(输入表达死为“i+i*i”)

 

 

图 6  分析完成(输入表达死为“i+i*i”,手动把单元格拉长了些)

  可以改进的地方:給分析表(ACTION和GOTO)加个滚动条,表“分析步骤表”表格单元加宽些,我懒得整了。

 

posted on 2019-10-28 21:44  25th_engineer  阅读(668)  评论(0编辑  收藏  举报