zoukankan      html  css  js  c++  java
  • 合肥工业大学编译原理实验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 + ":
    I" + 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:" + "
    " )
     292         displayRelations()
     293         staticStringBuilder.append( "**************" + "
    " )
     294         staticStringBuilder.append( "FIRST:" + "
    " )
     295         val testFIRST = FIRST()
     296         for( ex <- testFIRST ) {
     297             staticStringBuilder.append( "FIRST(" + ex._1 + ") = {" + ex._2.mkString(",") + "}" + "
    " )
     298         }
     299         staticStringBuilder.append( "**************" + "
    " )
     300         //test getItemGroup
     301         var cnt4 = 0
     302         for( ex <- itemGroup.toList.sortBy(_._2) ) {
     303             staticStringBuilder.append( "I" + ex._2 + ":" + "
    " )
     304                 for (tx <- ex._1 ) {
     305                     
     306                     staticStringBuilder.append( tx._1 + "->" + tx._2 + ", " + tx._3 + "
    " )
     307                 }
     308             staticStringBuilder.append( "^^^^^^^^^^^^^^^^^^^^^^^^" + "
    " )
     309             cnt4 += 1
     310         }
     311         staticStringBuilder.append( "**************" + "
    " )
     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 + "
    ")
     867                 if( ex != relations(0) ) {
     868                     staticStringBuilder2.append(ex._1 + "->" + ex._2 + "|" + ex._3 + "
    ")
     869                 }
     870             }
     871             else {
     872                 
     873                 staticStringBuilder.append( ex._1 + "->" + ex._2 + "
    ")
     874                 if( ex != relations(0) ) {
     875                     staticStringBuilder2.append(ex._1 + "->" + ex._2 + "
    ")
     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+"
    ");
    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)加个滚动条,表“分析步骤表”表格单元加宽些,我懒得整了。

  • 相关阅读:
    【数据结构】Trie树
    【算法】动态规划经典题之最长公共子序列
    【Leetcode】583. Delete Operation for Two Strings
    【Java】SpringBoot入门学习及基本使用
    【Java学习】调用ByteBuffer.getInt()方法得到808464432
    Install rapyuta Robot Cloud Engine on Ubuntu14.04
    Install rapyuta Robot Cloud Engine on Ubuntu12.04
    怎样下载youtube的字幕
    国内老版本ubuntu更新源地址以及sources.list的配置方法
    配置 ROS 的 apt 源
  • 原文地址:https://www.cnblogs.com/25th-engineer/p/11755764.html
Copyright © 2011-2022 走看看