• 合肥工业大学编译原理实验LL(1)完整Scala实现代码与测试数据


      github项目地址:https://github.com/25thengineer/Compile_Experiment_LL_1

      完成了形式上的消除左递归,但是还存在bug,不能直接用于求解实际问题,但过实验指导书的样例是没问题的。先上几组测试数据。

      测试数据:

      test.data(指导书上的样例):

    1 E->TG
    2 G->+TG|-TG
    3 G->ε
    4 T->FS
    5 S->*FS|/FS
    6 S->ε
    7 F->(E)
    8 F->i

      test2.data:

    1 E->E+T|T
    2 T->T-T|F
    3 T->T+T|x
    4 F->(E)|i

       test3.data:

    1 E->TG
    2 G->+TG|-TG
    3 G->ε
    4 S->*FS|/FS
    5 S->ε
    6 F->(E)
    7 F->i
    8 T->α
    9 α->Sα|ε

      test4.data:

    1 E->EG|HR
    2 G->+TG|-TG
    3 G->ε
    4 T->FS
    5 E->ES|HR
    6 S->*FS|/FS
    7 S->ε
    8 F->(E)
    9 F->i

      test5.data(书上的例子):

    1 E->E+T|T
    2 T->T*F|F
    3 F->(E)|i

      下面直接上代码,如果后面有时间而且心情好的话再修修补补下。老师要求有个界面,我因为对Scala的GUI编程不熟悉,没有弄;虽说Scala的GUI编程与Java的一脉相承,但差别还是有的,如果直接把Java的代码放在Scala里面跑铁定是一堆error和warnning。

       无GUI的代码:

       1 import scala.collection.mutable
       2 import scala.collection.mutable.{ArrayBuffer, Map}
       3 import scala.util.matching.Regex
       4  
       5  
       6  
       7  
       8 object LL1_try_GUI {
       9     private final var allCharacters = new String()
      10     private final var relations = new ArrayBuffer[ (String, String, String) ]()
      11     private final var VN = new String()
      12     private final var VT = new String()
      13     private final var LL1_G = new ArrayBuffer[ (String, String) ]()
      14     //private val allCandidateLetters = "αΑβΒγΓδΔεΕζΖηΗθΘιΙκΚλΛμΜνΝξΞοΟπΠρΡσΣτΤυΥφΦχΧψΨωΩ" + "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
      15     private val allCandidateLetters = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩABCDEFGHIJKLMNOPQRSTUVWXYZ"
      16     private final var usedCharacters = ""
      17 //    private val LL1_G = ArrayBuffer( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"),
      18 //        ("S", "ε"), ("F", "(E)"), ("F", "i") )//, ("Y", "*FS|/FS"), ("Y", "+TG|-TG"), ("Y", "x"), ("Y", "M"), ("M", "i"), ("M", "ε") )
      19     //     test data 1:
      20     //     ( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"),
      21     //            ("S", "ε"), ("F", "(E)"), ("F", "i"), ("Y", "S"), ("Y", "Gx"), ("Y", "x"), ("Y", "M"), ("M", "i"), ("M", "ε") )
      22     //     test data 2:
      23     //            ( ("D", "*FD"), ("D", "ε"), ("T", "FD"), ("E", "TC"), ("F", "(E)"), ("F", "i"), ("C", "+TC"), ("C", "ε") )
      24     //     test data 3:
      25     //            ( ("E", "E+T|T"), ("T", "T*F|T"), ("F", "(E)|i") )
      26     //     stand test data:
      27     //            ( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"), ("S", "ε"), ("F", "(E)"), ("F", "i") )
      28  
      29     def main(args: Array[String]): Unit = {
      30  
      31         //test countLines
      32         //println( "cnt = " + countLines( readFromTxtByLine("/home/hadoop001/Desktop/test.data") ) )
      33         //test parseFile
      34         val result = parseFile("/home/hadoop001/Desktop/test.data")
      35         println( "the original language rules:" )
      36         for( rs <- result ) {
      37             println( rs._1 + "->" + rs._2 )
      38         }
      39         initiate("/home/hadoop001/Desktop/test.data")
      40         println( "after eliminating the all the left recursion in the language rules:" )
      41         displayRelations()
      42  
      43         println( "VT = " + VT )
      44         println( "VN = " + VN )
      45         println( "allCharacters = " + allCharacters )
      46  
      47         println("*************")
      48  
      49         val testMatrix1 = initiateMatrix()
      50         for( i <- 0 to (testMatrix1.length - 1) ) {
      51             for( j <- 0 to (testMatrix1(0).length - 1) ) {
      52                 print(testMatrix1(i)(j) + "   ")
      53             }
      54             println()
      55         }
      56  
      57         println("*************")
      58  
      59         // test FIRST
      60         val tx = FIRST(LL1_G)
      61         println( "FIRST: " )
      62         for( t <- tx ) {
      63             if( allCharacters.contains( t._1 ) ) {
      64                 println(t)
      65             }
      66         }
      67         // test FOLLOW
      68         val ex = FOLLOW(LL1_G)
      69         println( "FOLLOW: " )
      70         for( t <- ex ) {
      71             if( VN.contains( t._1 ) ) {
      72                 println(t)
      73             }
      74         }
      75  
      76  
      77  
      78         println("*************")
      79  
      80         val testMatrix2 = createMatrix()
      81         for( i <- 0 to (testMatrix2.length - 1) ) {
      82             for( j <- 0 to (testMatrix2(0).length - 1) ) {
      83                 print(testMatrix2(i)(j) + "   ")
      84             }
      85             println()
      86         }
      87  
      88         println("*************")
      89  
      90         for( i <- 0 to (testMatrix1.length - 1) ) {
      91             for( j <- 0 to (testMatrix1(0).length - 1) ) {
      92                 if( i == 0 && j == 0 ) {
      93                     testMatrix1(i)(j) = "   "
      94                 }
      95             }
      96         }
      97         println()
      98         for( i <- 0 to (testMatrix1.length - 1) ) {
      99             for( j <- 0 to (testMatrix1(0).length - 1) ) {
     100                 if( testMatrix1(i)(j) == null && i != 0 && j != 0 ) {
     101                     print("   ")
     102                 }
     103                 else {
     104                     print(testMatrix1(i)(j) + "      ")
     105                 }
     106             }
     107             println()
     108         }
     109  
     110         analyse("i+i*i#")
     111     }
     112  
     113     /*
     114     * Function name: initiate
     115     * Function description: 初始化全局变量
     116     * Input parameters: the absolute path of the language-rule source file
     117     * Return value: 无
     118     * Exception: 未处理
     119     * Author: 来自高山
     120     * Created date: Sat Oct 19 2019 +0800
     121     * Editor: 来自高山
     122     * Edited Date: Sat Oct 19 2019 +0800
     123      */
     124     def initiate( filePath: String ): Unit = {
     125         LL1_G = parseFile(filePath)
     126         allCharacters = getWholeCharacters(LL1_G)
     127         usedCharacters = allCharacters
     128         relations = getRelation(LL1_G)
     129         VN = getVN(allCharacters)
     130         VT = getVT(allCharacters)
     131         eliminateLeftRecursion      // eliminate all the left recursion at first
     132     }
     133  
     134     /*
     135     * Function name: displayRelations
     136     * Function description: display all he language rules
     137     * Input parameters: 无
     138     * Return value: 无
     139     * Exception: 未处理
     140     * Author: 来自高山
     141     * Created date: Sat Oct 19 2019 +0800
     142     * Editor: 来自高山
     143     * Edited Date: Sat Oct 19 2019 +0800
     144      */
     145     def displayRelations(): Unit = {
     146         for( ex <- relations ) {
     147             if( ex._3 != "א" ) {
     148                 println( ex._1 + "->" + ex._2 + "|" + ex._3 )
     149             }
     150             else {
     151                 println( ex._1 + "->" + ex._2 )
     152             }
     153         }
     154     }
     155  
     156     /*
     157     * Function name: parseFile
     158     * Function description: 解析文本文件,保存在数组中
     159     * Input parameters: 文本绝对路径
     160     * Return value: -ArrayBuffer[ ( String, String ) ](String类型的元组ArrayBuffer数组)
     161     * Exception: 未处理
     162     * Author: 来自高山
     163     * Created date: Fri Oct 18 2019 +0800
     164     * Editor: 来自高山
     165     * Edited Date: Fri Oct 18 2019 +0800
     166      */
     167     def parseFile( filePath: String ): ArrayBuffer[ ( String, String ) ] = {
     168         val result = new ArrayBuffer[ ( String, String ) ]( countLines( readFromTxtByLine(filePath) ) )
     169         val sourceFile = readFromTxtByLine(filePath) //filePath
     170         for( line <- sourceFile ) {
     171             val tmp = line.split( "->", 2 )
     172             result += ( ( tmp.head, tmp.last ) )
     173         }
     174         result
     175     }
     176  
     177     /*
     178     * Function name: countLines
     179     * Function description: 计算文本行数,用于创建接收数组时开辟相应空间
     180     * Input parameters: -Array[String](文本文件数据构成的数组)
     181     * Return value: -Int(文本行数)
     182     * Exception: 未处理
     183     * Author: 来自高山
     184     * Created date: Fri Oct 18 2019 +0800
     185     * Editor: 来自高山
     186     * Edited Date: Sat Oct 19 2019 +0800
     187      */
     188     def countLines( sourceFile: Array[String] ): Int = {
     189         var cnt = 0
     190         for( line <- sourceFile ) {
     191             cnt += 1
     192         }
     193         cnt
     194     }
     195  
     196     /*
     197     * Function name: readFromTxtByLine
     198     * Function description: 读取文本文件
     199     * Input parameters: -String(文本文件绝对路径)
     200     * Return value: -Array[String](文本文件构成的数组,每行数据占一个数组元素)
     201     * Exception: -未处理
     202     * Author: 来自高山
     203     * Created date: Fri Oct 18 2019 +0800
     204     * Editor: 来自高山
     205     * Edited Date: Fri Oct 18 2019 +0800
     206      */
     207     def readFromTxtByLine(filePath: String): Array[String] = {
     208         import scala.io.Source
     209         val source = Source.fromFile(filePath, "UTF-8")
     210         //val lineIterator = source.getLines()
     211         //lineIterator.foreach()
     212         val lines = source.getLines().toArray
     213         source.close()
     214         //println(lines.size)
     215         lines
     216     }
     217  
     218     /*
     219     * Function name: getWholeCharacters
     220     * Function description: 获取文法的除“|”之外的所有字符
     221     * Input parameters: -ArrayBuffer[ (String, String) ](由文法左右两部分字符构成一个元组的数组,筛掉“|”)
     222     * Return value: -String(文法的除“|”之外的所有字符)
     223     * Exception: 未处理(有出错提示)
     224     * Author: 来自高山
     225     * Created date: Fri Oct 11 2019 +0800
     226     * Editor: 来自高山
     227     * Edited Date: Fri Oct 11 2019 +0800
     228      */
     229     def getWholeCharacters( string: ArrayBuffer[ (String, String) ] ): String = {
     230         var wholeCharacters = ""
     231         for( expression <- string ) {
     232             wholeCharacters += expression._1 + expression._2
     233         }
     234         val pattern = new Regex("\|")
     235         val result = pattern replaceAllIn( wholeCharacters, "" )
     236         if( result.isEmpty )
     237             "function getWholeCharacters failed"
     238         else
     239             result.distinct
     240     }
     241     /*
     242     * Function name: getVN
     243     * Function description: 获取文法的所有非终结符(non-terminal character),默认大写字母为非终结符,使用正则表达式匹配
     244     * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
     245     * Return value: -String(文法的所有非终结符)
     246     * Exception: 未处理(有出错提示)
     247     * Author: 来自高山
     248     * Created date: Fri Oct 11 2019 +0800
     249     * Editor: 来自高山
     250     * Edited Date: Fri Oct 11 2019 +0800
     251      */
     252     def getVN( string: String ): String = {
     253         //match big letter:
     254         //^[A-Z]+$
     255         val pattern = new Regex("[A-Z]")//("^[A-Z]+$")
     256         if( (pattern findAllIn string) != null )
     257             (pattern findAllIn string).mkString("")
     258         else
     259             "function getVN failed"
     260     }
     261  
     262     /*
     263     * Function name: getVT
     264     * Function description: 获取文法的所有非终结符(terminal character),默认大写字母外的字符为终结符,使用正则表达式匹配
     265     * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
     266     * Return value: -String(文法的所有终结符)
     267     * Exception: 未处理(有出错提示)
     268     * Author: 来自高山
     269     * Created date: Fri Oct 11 2019 +0800
     270     * Editor: 来自高山
     271     * Edited Date: Fri Oct 11 2019 +0800
     272      */
     273     def getVT( string: String ): String = {
     274         val pattern1 = new Regex("[A-Z]")
     275         val pattern2 = new Regex("\|")
     276         val firstFilter = pattern1 replaceAllIn( string, "" )
     277         val result = pattern2 replaceAllIn( firstFilter, "" )
     278         if( result.isEmpty == false )
     279             result
     280         else
     281             return "function getVT failed"
     282     }
     283     /*
     284     * Function name: getRelation
     285     * Function description: 获取文法每一行对应的推导关系,若文法只推出了1项(即没有符号“|”),则返回元组的第三个用希伯来字母“א”示空
     286     * Input parameters: -ArrayBuffer[ (String, String)(已经分割好的文法左右部分构成的数组)
     287     * Return value: -ArrayBuffer[ (String, String, String) ](元组第一个元素为推导式左边符号,第二为右边第二个符号串,第三为右边(若有)第三个符号串)
     288     * Exception: 未处理
     289     * Author: 来自高山
     290     * Created date: Fri Oct 11 2019 +0800
     291     * Editor: 来自高山
     292     * Edited Date: Fri Oct 11 2019 +0800
     293      */
     294     def getRelation( string: ArrayBuffer[ (String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
     295         val relation = new ArrayBuffer[ (String, String, String) ]()
     296         for( expression <- string ) {
     297             if( expression._2.contains("|") == false ) {
     298                 relation += ( ( expression._1, expression._2, "א" ) )
     299             }
     300             else {
     301                 val tmp = expression._2.split("\|", 2 )
     302                 relation += ( ( expression._1, tmp.head, tmp.last ) )
     303             }
     304         }
     305         relation
     306     }
     307  
     308     /*
     309     * Function name: findFirst
     310     * Function description: 获取指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串
     311     * Input parameters: -String(指定字符)
     312     * Return value: -String(指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串)
     313     * Exception: 未处理
     314     * Author: 来自高山
     315     * Created date: Fri Oct 11 2019 +0800
     316     * Editor: 来自高山
     317     * Edited Date: Fri Oct 11 2019 +0800
     318      */
     319     def findFirst( ch: String ): String = {
     320  
     321         val localRelations = relations
     322         var result = ""
     323         for( ex <- localRelations ) {
     324             if( ch == ex._1 ) {
     325                 if( ex._3 != "א" ) {
     326                     if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
     327                         result += ex._2(0).toString
     328                     }
     329                     if( VT.contains( ex._3(0) ) && ex._3(0) != 'ε' ) {
     330                         result += ex._3(0).toString
     331                     }
     332                 }
     333                 else {
     334                     if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
     335                         result += ex._2(0).toString
     336                     }
     337                 }
     338             }
     339         }
     340         result
     341     }
     342  
     343     /*
     344     * Function name: judgeOnlyOneVoidSuccession
     345     * Function description: 判断指定字符是否可推出唯一的字符ε
     346     * Input parameters: -String(指定字符串)
     347     * Return value: -Boolean(存在则true,否则false)
     348     * Exception: 未处理
     349     * Author: 来自高山
     350     * Created date: Fri Oct 11 2019 +0800
     351     * Editor: 来自高山
     352     * Edited Date: Fri Oct 11 2019 +0800
     353      */
     354     def judgeOnlyOneVoidSuccession( ch: String ): Boolean = {
     355         val localRelations = relations
     356         var result = 1
     357         for( ex <- localRelations ) {
     358             if( ch == ex._1 ) {
     359                 if( ex._3 != "א" ) {
     360                     if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) || (ex._3.length == 1 && ex._3(0) == 'ε') ) {
     361                         result = 1
     362                     }
     363                     else {
     364                         result = 0
     365                     }
     366                 }
     367                 else {
     368                     if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) ) {
     369                         result = 1
     370                     }
     371                     else {
     372                         result = 0
     373                     }
     374                 }
     375             }
     376         }
     377         if( result == 1 ) true else false
     378     }
     379  
     380     /*
     381     * Function name: judgeCaseXY
     382     * Function description: 判断构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)
     383     * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
     384     * Return value: -Boolean(满足则true,否则false)
     385     * Exception: 未处理
     386     * Author: 来自高山
     387     * Created date: Sat Oct 12 2019 +0800
     388     * Editor: 来自高山
     389     * Edited Date: Sat Oct 12 2019 +0800
     390      */
     391     def judgeCaseXY( ch: Char ): Boolean = {
     392         val localVN = VN
     393         val localRelations = relations
     394         var result = 0
     395         if( localVN.contains(ch) == true ) {
     396             for( ex <- localRelations ) {
     397                 if( ex._1(0) == ch ) {
     398                     if( localVN.contains( ex._2(0) ) || localVN.contains( ex._3(0) ) ) {
     399                         result += 1
     400                     }
     401                 }
     402             }
     403         }
     404         if( result > 0 )
     405             true
     406         else
     407             false
     408     }
     409  
     410     /*
     411     * Function name: findCase_Y_In_XY
     412     * Function description: 获取构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)时的Y
     413     * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
     414     * Return value: -String(Y构成的String字符串,无则为空)
     415     * Exception: 未处理
     416     * Author: 来自高山
     417     * Created date: Sat Oct 12 2019 +0800
     418     * Editor: 来自高山
     419     * Edited Date: Sat Oct 12 2019 +0800
     420      */
     421     def findCase_Y_In_XY( ch: Char ): String = {
     422         val localVN = VN
     423         val localRelations = relations
     424         var result = ""
     425         if( localVN.contains(ch) == true ) {
     426             for( ex <- localRelations ) {
     427                 if( ex._1(0) == ch ) {
     428                     if( ex._3 != "א" ) {
     429                         if( localVN.contains( ex._2(0) ) == true ) {
     430                             result += ex._2(0).toString
     431                         }
     432                         if( localVN.contains( ex._3(0) ) == true ) {
     433                             result += ex._3(0).toString
     434                         }
     435                     }
     436                     else {
     437                         if( localVN.contains( ex._2(0) ) == true ) {
     438                             result += ex._2(0).toString
     439                         }
     440                     }
     441                 }
     442             }
     443         }
     444         result
     445     }
     446  
     447     /*
     448     * Function name: findCase_Y_In_nY
     449     * Function description: 获取构造FIRST集时可能的第3种情况的(2)时的FIRST(Yi)中所有的非ε-元素(省略描述若干字)
     450     * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
     451     * Return value: -String(FIRST(Yi)中所有的非ε-元素构成的String字符串,无则为空)
     452     * Exception: 未处理
     453     * Author: 来自高山
     454     * Created date: Sat Oct 12 2019 +0800
     455     * Editor: 来自高山
     456     * Edited Date: Sat Oct 12 2019 +0800
     457      */
     458     def findCase_Y_In_nY( ch: Char ): String = {
     459         val localVN = VN
     460         val localRelations = relations
     461         var result = ""
     462         for( ex <- localRelations ) {
     463             if (ex._1 == ch.toString) {
     464                 var tmp = ""
     465  
     466                 if (ex._3 != 'א') {
     467                     var cnt = 0
     468                     for (tx <- ex._2) {
     469                         // add the element belongs to tmp
     470                         if (localVN.contains(tx)) {
     471                             tmp += tx.toString
     472                             cnt += 1
     473                         }
     474                         // otherwise, reset tmp as empty string
     475                         else {
     476                             tmp = ""
     477                         }
     478                     }
     479                     if (cnt == ex._2.length) {
     480                         result += tmp
     481                     }
     482  
     483                     // reset
     484                     cnt = 0
     485                     tmp = ""
     486                     for (tx <- ex._3) {
     487                         // add the element belongs to tmp
     488                         if (localVN.contains(tx)) {
     489                             tmp += tx.toString
     490                             cnt += 1
     491                         }
     492                         // otherwise, reset result as empty string
     493                         else {
     494                             tmp = ""
     495                         }
     496                     }
     497                     if (cnt == ex._3.length) {
     498                         result += tmp
     499                     }
     500                 }
     501                 else {
     502                     tmp = ""
     503                     var cnt = 0
     504                     for (tx <- ex._2) {
     505                         // add the element belongs to tmp
     506                         if (localVN.contains(tx)) {
     507                             tmp += tx.toString
     508                             cnt += 1
     509                         }
     510                         // otherwise, reset tmp as empty string
     511                         else {
     512                             tmp = ""
     513                         }
     514                     }
     515                     if (cnt == ex._2.length) {
     516                         result += tmp
     517                     }
     518                 }
     519             }
     520         }
     521         result = result.distinct
     522         result
     523     }
     524  
     525     /*
     526     * Function name: FIRST
     527     * Function description: 按照教材P78左下角的算法描述实现求解指定文法FIRST集;因用的是循环迭代求解,因此代码较长
     528     * Input parameters: -ArrayBuffer[ (String, String) ](产生式左右两部分分别构成元组的第1个和第2个元素)
     529     * Return value: -Map[ String, String ](Map的key是非终结符,value是其FIRST元素)
     530     * Exception: 未处理
     531     * Author: 来自高山
     532     * Created date: Mon Oct 14 2019 +0800
     533     * Editor: 来自高山
     534     * Edited Date: Sat Oct 19 2019 +0800
     535      */
     536     def FIRST( string: ArrayBuffer[ (String, String) ] ): Map[ String, String ] = {
     537         val FIRST_Group = Map[ String, String ]()
     538  
     539         val wholeCharacters = allCharacters
     540         val localVT = VT
     541         val localVN = VN
     542  
     543         for( character <- wholeCharacters ) {
     544             // case 1
     545             if( localVT.contains(character) ) {
     546                 //if there exist the original key that equals the current one
     547                 if( FIRST_Group.contains(character.toString) == true ) {
     548                     val tmp = character.toString + FIRST_Group(character.toString)
     549                     FIRST_Group(character.toString) = tmp.distinct
     550                 }
     551                 //otherwise
     552                 else {
     553                     FIRST_Group(character.toString) = character.toString
     554                 }
     555             }
     556  
     557             // case 2
     558             if( localVN.contains(character.toString) == true ) {
     559                 // case 2.1
     560                 val value = findFirst(character.toString)
     561                 if ( value.length != 0 ) {
     562                     if ( FIRST_Group.contains(character.toString) == true ) {
     563                         for( ch <- value ) {
     564                             val tmp = ch + FIRST_Group(character.toString)
     565                             FIRST_Group(character.toString) = tmp.distinct
     566                         }
     567                     }
     568                     else {
     569                         FIRST_Group(character.toString) = value.toString
     570                     }
     571                 }
     572  
     573                 // case 2.2
     574                 if( judgeOnlyOneVoidSuccession(character.toString) == true ) {
     575                     if ( FIRST_Group.contains(character.toString) == true ) {
     576                         val tmp = "ε" + FIRST_Group(character.toString)
     577                         FIRST_Group(character.toString) = tmp.distinct
     578                     }
     579                     else {
     580                         FIRST_Group(character.toString) = "ε"
     581                     }
     582                 }
     583             }
     584  
     585             for( character <- wholeCharacters ) {
     586                 // case 3
     587                 // case 3.1
     588                 if( judgeCaseXY(character) == true ) {
     589                     val tmpReply = findCase_Y_In_XY(character)
     590                     for( eachTmpReply <- tmpReply ) {
     591                         if( FIRST_Group.contains(eachTmpReply.toString) == true ) {
     592                             for (ex <- FIRST_Group(eachTmpReply.toString)) {
     593                                 if (ex != 'ε') {
     594                                     if (FIRST_Group.contains(character.toString) == true) {
     595                                         val tmp = ex.toString + FIRST_Group(character.toString)
     596                                         FIRST_Group(character.toString) = tmp.distinct
     597                                     }
     598                                     else {
     599                                         FIRST_Group(character.toString) = ex.toString
     600                                     }
     601                                 }
     602                             }
     603                         }
     604                     }
     605                 }
     606  
     607                 // case 3.2
     608                 if( findCase_Y_In_nY(character).length > 0 ) {
     609                     var flag = true
     610                     val tmpReply = findCase_Y_In_nY(character)
     611  
     612                     for( ex <- tmpReply ) {
     613                         if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true )  {
     614                             if( FIRST_Group(ex.toString).contains("ε") == false ) {
     615                                 flag = false
     616                             }
     617                         }
     618                         else {
     619                             flag = false
     620                         }
     621                         if( flag == true ) {
     622                             if (FIRST_Group.contains(character.toString) == true) {
     623                                 val tmp = FIRST_Group(ex.toString).replace( "ε", "" ) + FIRST_Group(character.toString)
     624                                 FIRST_Group(character.toString) = tmp.distinct
     625                             }
     626                             else {
     627                                 FIRST_Group(character.toString) = FIRST_Group(ex.toString).replace( "ε", "" )
     628                             }
     629  
     630                         }
     631                     }
     632                 }
     633                 // case 3.3
     634                 if( findCase_Y_In_nY(character).length > 0 ) {
     635                     var flag = true
     636                     val tmpReply = findCase_Y_In_nY(character)
     637                     for( ex <- tmpReply ) {
     638                         if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true )  {
     639                             if( FIRST_Group(ex.toString).contains("ε") == false ) {
     640                                 flag = false
     641                             }
     642                         }
     643                         else {
     644                             flag = false
     645                         }
     646                         if( flag == true ) {
     647  
     648                             if (FIRST_Group.contains(character.toString) == true) {
     649                                 val tmp = "ε" + FIRST_Group(character.toString)
     650                                 FIRST_Group(character.toString) = tmp.distinct
     651                             }
     652                             else {
     653                                 FIRST_Group(character.toString) = "ε"
     654                             }
     655                         }
     656                     }
     657                 }
     658             }
     659         }
     660         FIRST_Group
     661     }
     662  
     663     /*
     664     * Function name: FOLLOW
     665     * Function description: 根据dfsFOLLOW函数,获取各个非终结符的FOLLOW集元素
     666     * Input parameters: -ArrayBuffer[ (String, String) ](产生式左右两部分分别构成元组的第1个和第2个元素)
     667     * Return value: -Map[ String, String ](Map的key是非终结符,value是其FOLLOW集元素)
     668     * Exception: 未处理
     669     * Author: 来自高山
     670     * Created date: Sat Oct 19 2019 +0800
     671     * Editor: 来自高山
     672     * Edited Date: Sat Oct 19 2019 +0800
     673      */
     674     def FOLLOW( string: ArrayBuffer[ (String, String) ] ): Map[ String, String ] = {
     675         val localVN = VN
     676         val FOLLOW_Group = Map[ String, String ]()
     677         for( ch <- localVN ) {
     678             FOLLOW_Group(ch.toString) = dfsFOLLOW(ch.toString)
     679         }
     680         FOLLOW_Group
     681     }
     682  
     683     /*
     684     * Function name: dfsFOLLOW
     685     * Function description: 使用深度优先搜索(DFS)寻找各个非终结符的FOLLOW集元素
     686     * Input parameters: -String(指定的非终结符)
     687     * Return value: -String(指定终结符的FOLLOW集元素)
     688     * Exception: 未处理
     689     * Author: 来自高山
     690     * Created date: Sat Oct 19 2019 +0800
     691     * Editor: 来自高山
     692     * Edited Date: Sat Oct 19 2019 +0800
     693      */
     694     def dfsFOLLOW( ch: String ): String = {
     695         val FOLLOWPositions = Map[ String, String ]()
     696         val FOLLOW_Group = Map[ String, String ]()
     697         val localLL1_G = LL1_G
     698         val FIRST_Group = FIRST(localLL1_G)
     699         val localVN = VN
     700         for( ch <- localVN ) {
     701             FOLLOWPositions(ch.toString) = findGivenValueFOLLOWPosition(ch.toString)
     702             FOLLOW_Group(ch.toString) = "#"
     703         }
     704         var result = ""
     705  
     706         if( FOLLOWPositions(ch).length == 4 ) {
     707             if( FOLLOWPositions(ch)(1).toString == "T" ) {
     708                 result += FIRST_Group( FOLLOWPositions(ch)(0).toString )
     709                 FOLLOW_Group(ch) += result.distinct
     710             }
     711             else if( FOLLOWPositions(ch)(3).toString == "T" ) {
     712                 result += FIRST_Group( FOLLOWPositions(ch)(2).toString )
     713                 FOLLOW_Group(ch) += result.distinct
     714             }
     715             if( FOLLOWPositions(ch)(1).toString == "W" ) {
     716                 result += dfsFOLLOW( FOLLOWPositions(ch)(0).toString )
     717                 FOLLOW_Group(ch) = result.distinct
     718             }
     719             else if( FOLLOWPositions(ch)(3).toString == "W" ) {
     720                 result += dfsFOLLOW( FOLLOWPositions(ch)(2).toString )
     721                 FOLLOW_Group(ch) = result.distinct
     722             }
     723         }
     724  
     725         if( FOLLOWPositions(ch).length == 2 ) {
     726             if( FOLLOWPositions(ch)(1).toString == "T" ) {
     727                 result += FIRST_Group( FOLLOWPositions(ch)(0).toString )
     728                 FOLLOW_Group(ch) = result.distinct
     729             }
     730             else if( FOLLOWPositions(ch)(1).toString == "W" ) {
     731                 result += dfsFOLLOW( FOLLOWPositions(ch)(0).toString )
     732                 FOLLOW_Group(ch) = result.distinct
     733             }
     734         }
     735         FOLLOW_Group(ch).replace("ε", "")
     736     }
     737  
     738     /*
     739     * Function name: findGivenValueFOLLOWPosition
     740     * Function description: 按照教材P79右上角的算法描述,求解构成每个非终结符的FOLLOW集的“依赖”(因为实现了这个函数,节省了我原先用循环叠加求解FOLLOW集的700+代码)
     741     * Input parameters: -String(指定终结符)
     742     * Return value: -String(指定终结符的FOLLOW集元素,无则为空)
     743     * Exception: 未处理
     744     * Author: 来自高山
     745     * Created date: Sat Oct 19 2019 +0800
     746     * Editor: 来自高山
     747     * Edited Date: Sat Oct 19 2019 +0800
     748      */
     749     def findGivenValueFOLLOWPosition( ch: String ): String = {
     750         var result = ""
     751         val cnt = new ArrayBuffer[String]()
     752         val localRelations = relations
     753  
     754         for( ex <- localRelations ) {
     755             if( ex._3 != "א" ) {
     756                 if( ex._2.contains(ch) ) {
     757                     // מ
     758                     if( ex._2.length == 3 ) {
     759                             // B                                    A       α                 B         β
     760                         if( ex._2(1).toString == ch && judgeCase2( ex._1, ex._2(0).toString, ch, ex._2(2).toString ) ) {
     761                             val value = ex._2(2).toString + "T"
     762                             if( cnt.contains(value) == false ) {
     763                                 cnt += value
     764                                 result += value
     765                             }
     766                         }
     767                             // B                                    A       α                 B         β
     768                         if( ex._2(1).toString == ch && judgeCase3( ex._1, ex._2(0).toString, ch, ex._2(2).toString ) ) {
     769                             val value = ex._1.toString + "W"
     770                             if( cnt.contains(value) == false ) {
     771                                 cnt += value
     772                                 result += value
     773                             }
     774                         }
     775                     }
     776                     if( ex._2.length == 2 ) {
     777                             // B                                    A       α                 B
     778                         if( ex._2(1).toString == ch && judgeCase3( ex._1, ex._2(0).toString, ch, "" ) ) {
     779                             val value = ex._1 + "W"
     780                             if( cnt.contains(value) == false ) {
     781                                 cnt += value
     782                                 result += value
     783                             }
     784                         }
     785                     }
     786                 }
     787                 if( ex._3.contains(ch) ) {
     788                     if( ex._3.length == 3 ) {
     789                             // B                                      A       α                 B         β
     790                         if( ex._3(1).toString == ch && judgeCase2( ex._1, ex._3(0).toString, ch, ex._3(2).toString ) ) {
     791                             val value = ex._3(2).toString + "T"
     792                             if( cnt.contains(value) == false ) {
     793                                 cnt += value
     794                                 result += value
     795                             }
     796                         }
     797                         if( ex._3(1).toString == ch && judgeCase3( ex._1, ex._3(0).toString, ch, ex._3(2).toString ) ) {
     798                             val value = ex._1 + "W"
     799                             if( cnt.contains(value) == false ) {
     800                                 cnt += value
     801                                 result += value
     802                             }
     803                         }
     804                     }
     805                     if( ex._3.length == 2 ) {
     806                             // B                                    A       α                 B
     807                         if( ex._3(1).toString == ch && judgeCase3( ex._1, ex._3(0).toString, ch, "" ) ) {
     808                             val value = ex._1 + "W"
     809                             if( cnt.contains(value) == false ) {
     810                                 cnt += value
     811                                 result += value
     812                             }
     813                         }
     814                     }
     815                 }
     816             }
     817             else {
     818                 if( ex._2.contains(ch) ) {
     819                     if( ex._2.length == 3 ) {
     820                             // B                                      A       α              B         β
     821                         if( ex._2(1).toString == ch && judgeCase2( ex._1, ex._2(0).toString, ch, ex._2(2).toString ) ) {
     822                             val value = ex._2(2).toString + "T"
     823                             if( cnt.contains(value) == false ) {
     824                                 cnt += value
     825                                 result += value
     826                             }
     827                         }
     828                         if( ex._2(1).toString == ch && judgeCase3( ex._1, ex._2(0).toString, ch, ex._2(2).toString ) ) {
     829                             val value = ex._1 + "T"
     830                             if( cnt.contains(value) == false ) {
     831                                 cnt += value
     832                                 result += value
     833                             }
     834                         }
     835                     }
     836                     if( ex._2.length == 2 ) {
     837                             // B                                    A       α                 B
     838                         if( ex._2(1).toString == ch && judgeCase3( ex._1, ex._2(0).toString, ch, "" ) ) {
     839                             val value = ex._1 + "W"
     840                             if( cnt.contains(value) == false ) {
     841                                 cnt += value
     842                                 result += value
     843                             }
     844                         }
     845                     }
     846                 }
     847             }
     848         }
     849         result
     850     }
     851  
     852     /*
     853     * Function name: judgeCase2
     854     * Function description: 按照教材P79右下角的算法描述,判断是否填充满足条件(2)的矩阵元素
     855     * Input parameters: -String, String, String, String[分别代表条件(2)的四个字符]
     856     * Return value: -Boolean(满足条件(2)则返回true,否则返回false)
     857     * Exception: 未处理
     858     * Author: 来自高山
     859     * Created date: Tue Oct 15 2019 +0800
     860     * Editor: 来自高山
     861     * Edited Date: Tue Oct 15 2019 +0800
     862      */
     863     def judgeCase2( A: String, α: String, B: String, β: String ): Boolean = {
     864         val localVN = VN
     865         val wholeCharacters = allCharacters
     866         val localLL1_G = LL1_G
     867         val localFIRST = FIRST(localLL1_G)
     868         if( localVN.contains(A) == true && wholeCharacters.contains(α) == true && localVN.contains(B) == true &&
     869                 wholeCharacters.contains(β) && localFIRST.contains(β) == true ) {
     870             true
     871         }
     872         else {
     873             false
     874         }
     875     }
     876  
     877     /*
     878     * Function name: judgeCase3
     879     * Function description: 按照教材P79右下角的算法描述,判断是否填充满足条件(3)的矩阵元素
     880     * Input parameters: -String, String, String, String[分别代表条件(3)的四个字符]
     881     * Return value: -Boolean(满足条件(3)则返回true,否则返回false)
     882     * Exception: 未处理
     883     * Author: 来自高山
     884     * Created date: Wed Oct 16 2019 +0800
     885     * Editor: 来自高山
     886     * Edited Date: Wed Oct 16 2019 +0800
     887      */
     888     def judgeCase3( A: String, α: String, B: String, β: String ): Boolean = {
     889         val localVN = VN
     890         val wholeCharacters = allCharacters
     891         val localLL1_G = LL1_G
     892         val localFIRST = FIRST(localLL1_G)
     893         if( ( localVN.contains(A) == true && wholeCharacters.contains(α) == true && localVN.contains(B) == true ) ||
     894                 ( localVN.contains(A) == true && wholeCharacters.contains(α) == true && localVN.contains(B) == true && localFIRST(β).contains("ε") == true ) ) {
     895             true
     896         }
     897         else {
     898             false
     899         }
     900     }
     901  
     902     /*
     903     * Function name: initiateMatrix
     904     * Function description: 初始化分析表(为了在控制台打印方便,表长为非终结符个数加一,表宽为终结符个数加一)
     905     * Input parameters: 无
     906     * Return value: -Array[ Array[ String] ](分析表矩阵元素构成的二维数组,除了第0行和第0列,其它列与行的元素均为null)
     907     * Exception: 未处理
     908     * Author: 来自高山
     909     * Created date: Wed Oct 16 2019 +0800
     910     * Editor: 来自高山
     911     * Edited Date: Wed Oct 16 2019 +0800
     912      */
     913     def initiateMatrix(): Array[ Array[ String] ] = {
     914         val localVN = VN
     915         val localVT = VT
     916         val result = Array.ofDim[String](localVN.length + 1, localVT.length + 1)
     917         for( i <- 1 to localVN.length ) {
     918             result(i)(0) = localVN(i - 1).toString
     919         }
     920         for( j <- 1 to localVT.length ) {
     921             if( localVT(j - 1).toString == "ε" ) {
     922                 result(0)(j) = "#"
     923             }
     924             else {
     925                 result(0)(j) = localVT(j - 1).toString
     926             }
     927         }
     928         result
     929     }
     930  
     931     /*
     932     * Function name: createMatrix
     933     * Function description: 按照教材P79右下角的算法描述,构造分析表
     934     * Input parameters: 无
     935     * Return value: -Array[ Array[String] ](分析表矩阵元素构成的二维数组)
     936     * Exception: 未处理
     937     * Author: 来自高山
     938     * Created date: Wed Oct 16 2019 +0800
     939     * Editor: 来自高山
     940     * Edited Date: Wed Oct 16 2019 +0800
     941      */
     942     def createMatrix(): Array[ Array[String] ] = {
     943         val result = initiateMatrix()
     944         val localVT = VT
     945         val localRelations = relations
     946         val localLL1_G = LL1_G
     947         val localFIRST = FIRST(localLL1_G)
     948         val localFOLLOW = FOLLOW(localLL1_G)
     949  
     950         for( ex <- localRelations ) {
     951  
     952             if( ex._3 !=  "א" ) {
     953                 for( a <- localVT ) {
     954                     val ex2Length = ex._2.length
     955                     var range = ""
     956                     var α = ""
     957                     var flag = false
     958                     for( x <- 0 to (ex2Length - 1) ) {
     959                         if( localFIRST( ex._2(x).toString ).contains("ε") == false && flag == false ) {
     960                             α = ex._2(x).toString
     961                             range = localFIRST( α )
     962                             flag = true
     963                         }
     964                     }
     965                     if( range.contains(a) == true && flag == true ) {
     966                         result(getRow(ex._1))(getColumn(a.toString)) = ex._1 + "->" + ex._2
     967                     }
     968                     if( flag == false ) {
     969                         range = "ε"
     970                         result( getRow(ex._1) )( getColumn("ε") ) = ex._1 + "->" + "ε"
     971                     }
     972  
     973                     // case 3
     974                     if( range.contains("ε") == true && flag == false ) {
     975                         for( b <- localFOLLOW(α) ) {
     976                             result( getRow(ex._1.toString) )( getColumn(b.toString) ) = ex._1 + "->" + ex._2  // t --> tx
     977                         }
     978                     }
     979  
     980                     val ex3Length = ex._3.length
     981                     range = ""
     982                     flag = false
     983                     for( x <- 0 to (ex3Length - 1) ) {
     984                         if( localFIRST( ex._3(x).toString ).contains("ε") == false && flag == false ) {
     985                             α = ex._3(x).toString
     986                             range = localFIRST( α )
     987                             flag = true
     988                         }
     989                     }
     990                     if( range.contains(a) == true && flag == true ) {
     991                         result( getRow(ex._1) )( getColumn(a.toString) ) = ex._1 + "->" + ex._3
     992                     }
     993                     if( flag == false ) {
     994                         range = "ε"
     995                         result(getRow(ex._1))(getColumn("ε")) = ex._1 + "->" + "ε"
     996                     }
     997  
     998                     // case 3
     999                     if( range.contains("ε") == true && flag == false ) {
    1000                         for( b <- localFOLLOW(ex._1) ) {
    1001                             result( getRow(ex._1.toString) )( getColumn(b.toString) ) = ex._1 + "->" + ex._3  // t --> tx
    1002                         }
    1003                     }
    1004                 }
    1005             }
    1006  
    1007             else {
    1008                 for( a <- localVT ) {
    1009                     val ex2Length = ex._2.length
    1010                     var range = ""
    1011                     var α = ""
    1012                     var flag = false
    1013                     for( x <- 0 to (ex2Length - 1) ) {
    1014                         if( localFIRST( ex._2(x).toString ).contains("ε") == false && flag == false ) {
    1015                             α = ex._2(x).toString
    1016                             range = localFIRST(α)
    1017                             flag = true
    1018                         }
    1019                     }
    1020                     if( range.contains(a) == true && flag == true ) {
    1021                         result( getRow(ex._1) )( getColumn(a.toString) ) = ex._1 + "->" + ex._2
    1022                     }
    1023                     if( flag == false ) {
    1024                         range = "ε"
    1025                         result( getRow(ex._1) )( getColumn("ε") ) = ex._1 + "->" + "ε"
    1026                     }
    1027  
    1028                     // case 3
    1029                     if( range.contains("ε") == true && flag == false ) {
    1030                         for( b <- localFOLLOW(ex._1) ) {
    1031                             result( getRow(ex._1.toString) )( getColumn(b.toString) ) = ex._1 + "->" + ex._2
    1032                         }
    1033                     }
    1034                 }
    1035             }
    1036         }
    1037         result
    1038     }
    1039  
    1040     /*
    1041     * Function name: getRow
    1042     * Function description: 获取指定字符在分析表中的行数
    1043     * Input parameters: -String(指定字符)
    1044     * Return value: -Int(指定字符所在的行数)
    1045     * Exception: 未处理
    1046     * Author: 来自高山
    1047     * Created date: Wed Oct 16 2019 +0800
    1048     * Editor: 来自高山
    1049     * Edited Date: Wed Oct 16 2019 +0800
    1050      */
    1051     def getRow( ch: String ): Int = {
    1052         val matrix = initiateMatrix()
    1053         var result = -1
    1054         if( ch == "α" ) {
    1055             println( "1 --- getRow, ch == " + ch )
    1056         }
    1057         for( i <- 0 to (matrix.length - 1) ) {
    1058             if( matrix(i)(0) == ch ) {
    1059                 result = i
    1060             }
    1061         }
    1062         result
    1063     }
    1064  
    1065     /*
    1066     * Function name: getColumn
    1067     * Function description: 获取指定字符在分析表中的列数
    1068     * Input parameters: -String(指定字符)
    1069     * Return value: -Int(指定字符所在的列数)
    1070     * Exception: 未处理
    1071     * Author: 来自高山
    1072     * Created date: Wed Oct 16 2019 +0800
    1073     * Editor: 来自高山
    1074     * Edited Date: Wed Oct 16 2019 +0800
    1075      */
    1076     def getColumn( ch: String ): Int = {
    1077         val matrix = initiateMatrix()
    1078         var result = -1
    1079         for( i <- 0 to (matrix.length - 1) ) {
    1080             for( j <- 0 to (matrix(i).length - 1) ) {
    1081                 if( matrix(0)(j) == ch ) {
    1082                     result = j
    1083                 }
    1084                 if( matrix(0)(j) == "#" && ch == "ε" ) {
    1085                     result = j
    1086                 }
    1087             }
    1088         }
    1089         result
    1090     }
    1091  
    1092     /*
    1093     * Function name: analyse
    1094     * Function description: 对指定的字符串进行LL(1)分析
    1095     * Input parameters: -String(输入的指定字符串)
    1096     * Return value: -Boolean(分析成功则返回true,否则false)
    1097     * Exception: 未处理(有出错提示)
    1098     * Author: 来自高山
    1099     * Created date: Wed Oct 16 2019 +0800
    1100     * Editor: 来自高山
    1101     * Edited Date: Wed Oct 16 2019 +0800
    1102      */
    1103     def analyse( expression: String ): Boolean = {
    1104         val stack = new mutable.Stack[String]()
    1105         var localExpression = expression
    1106         val table = createMatrix()
    1107         val localVT = VT
    1108         val localVN = VN
    1109         val localRelations = relations
    1110  
    1111         stack.push("#")
    1112         stack.push( localRelations(0)._1 )
    1113  
    1114         var cnt = 0
    1115         println( cnt + " " + " stack = " + stack + ", expression = " + localExpression + "  initiate" )
    1116  
    1117         while( stack.isEmpty == false ) {
    1118             val stackTop = stack.top
    1119             stack.pop()
    1120             // 栈顶符号属于  非终结符
    1121             if( localVN.contains(stackTop) == true ) {
    1122                 // 栈顶符号与表达式左端首字符  存在  关系
    1123                 if( table( getRow(stackTop) )( getColumn( localExpression(0).toString ) ) != null ) {
    1124                     val lastHalf = table( getRow(stackTop) )( getColumn( localExpression(0).toString ) ).split( "->", 2 ).last
    1125                     val length = lastHalf.length
    1126                     for( i <- 0 to (length - 1) ) {
    1127                         if( lastHalf != "ε" ) {
    1128                             stack.push(lastHalf(length - 1 - i).toString)
    1129                         }
    1130                     }
    1131                     cnt += 1
    1132                     println( cnt + " " + " stack = " + stack + ", expression = " + localExpression +
    1133                             ",  analyse expression = " + table( getRow(stackTop) )( getColumn( localExpression(0).toString ) ) + ",  POP, PUSH(" + lastHalf.reverse + ")")
    1134                 }
    1135                 // 栈顶符号与表达式左端首字符  不存在  关系
    1136                 else {
    1137                     // 栈顶符号 等于 表达式左端首字符
    1138                     if( stackTop == "#" && localExpression(0).toString == "#" ) {
    1139                         println("11111")
    1140                         return true
    1141                     }
    1142                     // 栈顶符号 不等于 表达式左端首字符
    1143                     else {
    1144                         println("1 - error")
    1145                         //stack.push( localExpression(0).toString )
    1146                         println( cnt + " " + " stack = " + stack + ", expression = " + localExpression )
    1147                         return false
    1148                     }
    1149                 }
    1150             }
    1151             // 栈顶符号属于  终结符
    1152             if( localVT.contains(stackTop) == true ) {
    1153                 // 栈顶符号 等于 表达式左端首字符
    1154                 if( stackTop == localExpression(0).toString ) {
    1155                     if( stackTop == localExpression(0).toString ) {
    1156                         //stack.pop()
    1157                         localExpression = localExpression.drop(1)
    1158                         cnt += 1
    1159                         println( cnt + " " + " stack = " + stack + ", expression = " + localExpression + ",  GETNEXT(" + stackTop + ")" )
    1160                     }
    1161                     // 栈顶符号 不等于 表达式左端首字符
    1162                     else {
    1163                         println("2 - error")
    1164                         return false
    1165                     }
    1166                 }
    1167             }
    1168         }
    1169         true
    1170     }
    1171  
    1172     /*
    1173     * Function name: judgeLeftRecursion
    1174     * Function description: 判断是否存在形式上的左递归
    1175     * Input parameters: -(String, String, String)(产生式的左端与右端的两个(或为1个)元素)
    1176     * Return value: -Int(0表示无,1表示右端第1个元素存在形式上的左递归,2表示右端第2个元素)
    1177     * Exception: 未处理
    1178     * Author: 来自高山
    1179     * Created date: Sat Oct 19 2019 +0800
    1180     * Editor: 来自高山
    1181     * Edited Date: Sat Oct 19 2019 +0800
    1182      */
    1183     def judgeLeftRecursion( expression: (String, String, String) ): Int = {
    1184         var ans = 0             // ans = 0 means the current expression is not involved left-recursion
    1185         if( expression._2.length >= 2 && expression._1 == expression._2(0).toString && expression._2.drop(1) != "ε" ) {
    1186             ans += 1            // ans = 1 means the left recursion involves the expression._2
    1187         }
    1188         if( expression._3.length >= 2 && expression._1 == expression._3(0).toString && expression._3.drop(1) != "ε" ) {
    1189             ans += 2            // ans = 2 means the left recursion involves the expression._3
    1190         }
    1191         ans                     // ans = 3 means the given expression is false since both exp(2) and exp(3) involved
    1192     }
    1193  
    1194     /*
    1195     * Function name: eliminateLeftRecursion
    1196     * Function description: 消除形式上的左递归
    1197     * Input parameters: 无
    1198     * Return value: -ArrayBuffer[ (String, String, String) ](消除左递归后的新文法)
    1199     * Exception: 未处理
    1200     * Author: 来自高山
    1201     * Created date: Sat Oct 19 2019 +0800
    1202     * Editor: 来自高山
    1203     * Edited Date: Sat Oct 19 2019 +0800
    1204      */
    1205     def eliminateLeftRecursion(): ArrayBuffer[ (String, String, String) ] = {
    1206         var localRelations = relations
    1207         var invalidRelations = new ArrayBuffer[ (String, String, String) ]()
    1208         val localCandidateLetters = allCandidateLetters
    1209         val VN1 = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩABCDEFGHIJKLMNOPQRSTUVWXYZ"
    1210         val VT1 = "αβγδεζηθικλμνξοπρστυφχψωabcdefghijklmnopqrstuvwxyz"
    1211         for( ex <- localRelations ) {
    1212             if( ex._3 != "א" ) {
    1213                 if( judgeLeftRecursion( ex._1, ex._2, ex._3 ) == 1 ) {
    1214                     // P = ex._1, α = ex._2 - ex._1, β = ex._3,  P' = newValue
    1215                     invalidRelations += ( ( ex._1, ex._2, ex._3 ) )
    1216                     val newValue = subString( usedCharacters, localCandidateLetters )(0)
    1217                     usedCharacters += newValue
    1218                     if( VN1.contains(newValue) && !VN.contains(newValue) ) {
    1219                         VN += newValue.toString
    1220                         allCharacters += newValue.toString
    1221                     }
    1222                     if( VT1.contains(newValue) && !VT.contains(newValue) ) {
    1223                         VT += newValue.toString
    1224                         allCharacters += newValue.toString
    1225                     }
    1226                     val α = ex._2.drop(1)
    1227                     val exp1 = ( ex._1, ex._3 + newValue.toString, "א" )
    1228                     val exp2 = ( newValue.toString, α.toString + newValue.toString, "ε" )
    1229 //                    println( "1 -- exp1._1 = " + exp1._1 + ", exp1._2 = " + exp1._2 + ", exp1._3 = " + exp1._3 )
    1230 //                    println( "1 -- exp2._1 = " + exp2._1 + ", exp2._2 = " + exp2._2 + ", exp2._3 = " + exp2._3 )
    1231                     localRelations += exp1
    1232                     localRelations += exp2
    1233                 }
    1234                 else if( judgeLeftRecursion( ex._1, ex._2, ex._3 ) == 2 ) {
    1235                     // P = ex._1, α = ex._3 - ex._1, β = ex._3,  P' = newValue
    1236                     invalidRelations += ( ( ex._1, ex._2, ex._3 ) )
    1237                     val newValue = subString( usedCharacters, localCandidateLetters )(0)
    1238                     if( VN1.contains(newValue) && !VN.contains(newValue) ) {
    1239                         VN += newValue.toString
    1240                         allCharacters += newValue.toString
    1241                     }
    1242                     if( VT1.contains(newValue) && !VT.contains(newValue) ) {
    1243                         VT += newValue.toString
    1244                         allCharacters += newValue.toString
    1245                     }
    1246                     usedCharacters += newValue
    1247                     val α = ex._3.drop(1)
    1248                     val exp1 = ( ex._1, ex._3 + newValue.toString, "א" )
    1249                     val exp2 = ( newValue.toString, α.toString + newValue.toString, "ε" )
    1250 //                    println( "2 -- exp1._1 = " + exp1._1 + ", exp1._2 = " + exp1._2 + ", exp1._3 = " + exp1._3 )
    1251 //                    println( "2 -- exp2._1 = " + exp2._1 + ", exp2._2 = " + exp2._2 + ", exp2._3 = " + exp2._3 )
    1252                     localRelations += exp1
    1253                     localRelations += exp2
    1254                 }
    1255                 else if( judgeLeftRecursion( ex._1, ex._2, ex._3 ) == 3 ){
    1256                     println( "error in the function eliminateLeftRecursion" )
    1257                 }
    1258             }
    1259             else {
    1260                 if( judgeLeftRecursion( ex._1, ex._2, ex._3 ) == 1 ) {
    1261                     // P = ex._1, α = ex._2 - ex._1, β = ex._3,  P' = newValue
    1262                     invalidRelations += ( ( ex._1, ex._2, ex._3 ) )
    1263                     val newValue = subString( usedCharacters, localCandidateLetters )(0)
    1264                     if( VN1.contains(newValue) && !VN.contains(newValue) ) {
    1265                         VN += newValue.toString
    1266                         allCharacters += newValue.toString
    1267                     }
    1268                     if( VT1.contains(newValue) && !VT.contains(newValue) ) {
    1269                         VT += newValue.toString
    1270                         allCharacters += newValue.toString
    1271                     }
    1272                     usedCharacters += newValue
    1273                     val α = ex._2.drop(1)
    1274                     val exp1 = ( ex._1, newValue.toString, "א" )
    1275                     val exp2 = ( newValue.toString, α.toString + newValue.toString, "ε" )
    1276 //                    println( "3 -- exp1._1 = " + exp1._1 + ", exp1._2 = " + exp1._2 + ", exp1._3 = " + exp1._3 )
    1277 //                    println( "3 -- exp2._1 = " + exp2._1 + ", exp2._2 = " + exp2._2 + ", exp2._3 = " + exp2._3 )
    1278                     localRelations += exp1
    1279                     localRelations += exp2
    1280                 }
    1281             }
    1282         }
    1283         for( ex <- invalidRelations ) {
    1284             localRelations = localRelations.-(ex)
    1285         }
    1286         relations = localRelations
    1287         localRelations
    1288     }
    1289  
    1290     /*
    1291     * Function name: subString
    1292     * Function description: 获取两输入字符串的差集(要求两者均非空)
    1293     * Input parameters: 无
    1294     * Return value: -String(两输入字符串的差集)
    1295     * Exception: 未处理
    1296     * Author: 来自高山
    1297     * Created date: Sat Oct 19 2019 +0800
    1298     * Editor: 来自高山
    1299     * Edited Date: Sat Oct 19 2019 +0800
    1300      */
    1301     def subString( usedCharacters: String, localCandidateLetters: String ): String = {
    1302         require( usedCharacters.length != 0 && localCandidateLetters.length != 0 )
    1303         var ans = ""
    1304         var A = usedCharacters
    1305         var B = localCandidateLetters
    1306         if( A.length < B.length ) {
    1307             val tmp = A
    1308             A = B
    1309             B = tmp
    1310         }
    1311         for( i <- 0 to (A.length - 1) ) {
    1312             var j = 0
    1313             while( j < B.length && B(j) != A(i) ) {
    1314                 j += 1
    1315             }
    1316             if( j == B.length ) {
    1317                 ans += A(i)
    1318             }
    1319         }
    1320         ans
    1321     }
    1322 }

      含GUI的代码:

      LL1_try_GUI object(Scala):

       1 import java.awt.{BorderLayout, Color}
       2 import java.awt.event.{ActionEvent, ActionListener}
       3 import java.io.FileInputStream
       4  
       5 import javax.swing.table.{AbstractTableModel, DefaultTableCellRenderer, DefaultTableColumnModel, DefaultTableModel, TableColumn, TableModel}
       6 import javax.swing.{JButton, JFileChooser, JFrame, JPanel, JScrollPane, JTable, JTextField, JTextPane}
       7 import pojo.Analyse
       8  
       9 import scala.collection.mutable
      10 import scala.collection.mutable.{ArrayBuffer, Map}
      11 import scala.util.matching.Regex
      12  
      13  
      14 object LL1_try_GUI {
      15     private final var allCharacters = new String()
      16     private final var relations = new ArrayBuffer[ (String, String, String) ]()
      17     private final var VN = new String()
      18     private final var VT = new String()
      19     private val allCandidateLetters = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩABCDEFGHIJKLMNOPQRSTUVWXYZ"
      20     private final var usedCharacters = ""
      21  
      22  
      23     private var LL1_G = new ArrayBuffer[ (String, String) ]()//ArrayBuffer( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"),
      24     //("S", "ε"), ("F", "(E)"), ("F", "i") )//, ("Y", "*FS|/FS"), ("Y", "+TG|-TG"), ("Y", "x"), ("Y", "M"), ("M", "i"), ("M", "ε") )
      25     //     test data 1:
      26     //     ( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"),
      27     //            ("S", "ε"), ("F", "(E)"), ("F", "i"), ("Y", "S"), ("Y", "Gx"), ("Y", "x"), ("Y", "M"), ("M", "i"), ("M", "ε") )
      28     //     test data 2:
      29     //            ( ("D", "*FD"), ("D", "ε"), ("T", "FD"), ("E", "TC"), ("F", "(E)"), ("F", "i"), ("C", "+TC"), ("C", "ε") )
      30     //     test data 3:
      31     //            ( ("E", "E+T|T"), ("T", "T*F|T"), ("F", "(E)|i") )
      32     //     stand test data:
      33     //            ( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"), ("S", "ε"), ("F", "(E)"), ("F", "i") )
      34  
      35     val staticAnalyseList : ArrayBuffer[Analyse] = new ArrayBuffer[Analyse]();
      36     var staticTestMatrix : Array[ Array[String] ] = new Array[Array[String]](0)
      37     var staticStringBuilder : StringBuilder = new StringBuilder();
      38     var staticStringBuilder2 : StringBuilder = new StringBuilder();
      39  
      40     def main(args: Array[String]): Unit = {
      41         GUI1
      42     }
      43  
      44     /*
      45     * Function name: displayStack
      46     * Function description: 输出栈的所有元素
      47     * Input parameters: -mutable.Stack[String](待处理的String类型的栈)
      48     * Return value: -String(栈所有元素组成的字符串)
      49     * Exception: 未处理
      50     * Author: 来自高山
      51     * Created date: Mon Oct 21 2019 +0800
      52     * Editor: 来自高山
      53     * Edited Date: Mon Oct 21 2019 +0800
      54      */
      55     def displayStack( stack: mutable.Stack[String] ): String = {
      56         var result = ""
      57         for( ex <- stack ) {
      58             result += ex
      59         }
      60         result
      61     }
      62  
      63     /*
      64     * Function name: utility
      65     * Function description: 辅助输出函数
      66     * Input parameters: 无
      67     * Return value: 无
      68     * Exception: 未处理
      69     * Author: 来自高山
      70     * Created date: Sun Oct 20 2019 +0800
      71     * Editor: 来自高山
      72     * Edited Date: Sun Oct 20 2019 +0800
      73      */
      74     def utility(): Unit = {
      75         staticStringBuilder.append("VT = " + VT +"
    ");
      76         staticStringBuilder.append("VN = " + VN +"
    ");
      77         staticStringBuilder.append( "allCharacters = " + allCharacters +"
    ");
      78         val tx = FIRST(LL1_G)
      79         staticStringBuilder.append(  "FIRST集: " +"
    ");
      80         for( t <- tx ) {
      81             if( allCharacters.contains( t._1 ) ) {
      82                 staticStringBuilder.append( "FIRST("+ t._1 + ") = {" + t._2.mkString(",") + "}
    ");
      83             }
      84         }
      85         val ex = FOLLOW(LL1_G)
      86         staticStringBuilder.append("FOLLOW集: "+"
    ");
      87         for( t <- ex ) {
      88             if( VN.contains( t._1 ) ) {
      89                 staticStringBuilder.append( "FOLLOW("+ t._1 + ") = {" + t._2.mkString(",") + "}
    ");
      90             }
      91         }
      92         val testMatrix1 = createMatrix()
      93         staticTestMatrix = testMatrix1;
      94         for( ex <- LL1_G ) {
      95             staticStringBuilder2.append( ex._1 + "->" + ex._2 + "
    ")
      96         }
      97     }
      98  
      99     /*
     100     * Function name: GUI1
     101     * Function description: 实现图形化界面展示,开始界面
     102     * Input parameters: 无
     103     * Return value: 无
     104     * Exception: 未处理
     105     * Author: 来自高山
     106     * Created date: Sun Oct 20 2019 +080
     107     * Editor: 来自高山
     108     * Edited Date: Sun Oct 20 2019 +0800
     109      */
     110     def GUI1(): Unit = {
     111         val jFrame = new JFrame("LL(1)文法分析");
     112         val jPanel = new JPanel();
     113         jFrame.setBounds( 0, 10,1000,90);
     114  
     115         val appendFileJButton2 = new JButton("开始分析");
     116         appendFileJButton2.setBounds( 100, 400,200,30);
     117         appendFileJButton2.addActionListener(new ActionListener {
     118             override def actionPerformed(e: ActionEvent): Unit = {
     119                 GUI2
     120                 jFrame.dispose()
     121             }
     122         })
     123  
     124         //添加文件按钮
     125         val appendFileJButton = new JButton("添加文件");
     126         appendFileJButton.setBounds( 300, 400,200,30);
     127         appendFileJButton.addActionListener(new ActionListener {
     128             override def actionPerformed(e: ActionEvent): Unit = {
     129                 val fileChooser = new JFileChooser();
     130                 fileChooser.showOpenDialog(jFrame);
     131                 val filePath = fileChooser.getSelectedFile.getAbsolutePath
     132                 initiate(filePath)
     133                 utility
     134             }
     135         })
     136         val appendFileJButton3 = new JButton("退出程序")
     137         appendFileJButton3.setBounds(500, 400, 200, 30)
     138         appendFileJButton3.addActionListener(new ActionListener {
     139             override def actionPerformed(e: ActionEvent): Unit = {
     140                 jFrame.dispose()
     141             }
     142         })
     143  
     144         jPanel.add(appendFileJButton)
     145         jPanel.add(appendFileJButton2)
     146         jPanel.add(appendFileJButton3)
     147         jPanel.setBackground(Color.gray)
     148         jFrame.add(jPanel)
     149         import java.awt.FlowLayout
     150         jPanel.setLayout(new FlowLayout(FlowLayout.LEADING, 200, 20))
     151         jFrame.setResizable(false);
     152         jFrame.setVisible(true);
     153     }
     154  
     155     /*
     156     * Function name: GUI2
     157     * Function description: 实现图形化界面展示,分析界面
     158     * Input parameters: 无
     159     * Return value: 无
     160     * Exception: 未处理
     161     * Author: 菊花侠
     162     * Created date: Sat Oct 19 2019 +0800
     163     * Editor: 来自高山
     164     * Edited Date: Sun Oct 20 2019 +0800
     165      */
     166     def GUI2(): Unit = {
     167         val jFrame = new JFrame("LL(1)文法分析");
     168         jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
     169         jFrame.setResizable(false)
     170         jFrame.setBounds(0,0,1000,810);
     171         jFrame.setLayout(null)
     172  
     173         //输入行
     174         val inputJPanel = new JPanel();
     175         inputJPanel.setBounds(0,0,1000,30);
     176         inputJPanel.setLayout(null);
     177  
     178         val inputJTextField = new JTextField();
     179         inputJTextField.setBounds(0,0,300,30);
     180         //    inputJTextField.setText("i+i*i*i#");
     181         //    inputJTextField.setPreferredSize(new Dimension(300,30));
     182         val inputJButton = new JButton("确认");
     183         inputJButton.setBounds(320,0,60,30);
     184         //    inputJButton.setPreferredSize(new Dimension(30,30));
     185         inputJPanel.add(inputJTextField)
     186         inputJPanel.add(inputJButton)
     187         jFrame.add(inputJPanel);
     188  
     189  
     190         val displayFileJTextPane = new JTextPane();
     191         displayFileJTextPane.setEditable(false);
     192  
     193         val displayFileJScrollPane = new JScrollPane();
     194         displayFileJScrollPane.setBounds(0,64,1000,300);
     195         displayFileJScrollPane.setViewportView(displayFileJTextPane);
     196         jFrame.add(displayFileJScrollPane)
     197  
     198         //添加文件按钮
     199         //        val appendFileJButton = new JButton("添加文件");
     200         val appendFileJButton = new JButton("显示当前文法")
     201         appendFileJButton.setBounds(0, 32,120,30)
     202         appendFileJButton.addActionListener(new ActionListener {
     203             override def actionPerformed(e: ActionEvent): Unit = {
     204                 displayFileJTextPane.setText(staticStringBuilder2.toString());
     205             }
     206         })
     207  
     208         val appendFileJButton2 = new JButton("返回")
     209         appendFileJButton2.setBounds(220, 32, 120, 30)
     210         appendFileJButton2.addActionListener(new ActionListener {
     211             override def actionPerformed(e: ActionEvent): Unit = {
     212                 GUI1
     213                 jFrame.dispose()
     214             }
     215         })
     216  
     217         val appendFileJButton3 = new JButton("退出")
     218         appendFileJButton3.setBounds(440, 32, 120, 30)
     219         appendFileJButton3.addActionListener(new ActionListener {
     220             override def actionPerformed(e: ActionEvent): Unit = {
     221                 jFrame.dispose()
     222             }
     223         })
     224  
     225         jFrame.add(appendFileJButton)
     226         jFrame.add(appendFileJButton2)
     227         jFrame.add(appendFileJButton3)
     228  
     229         val dataMode1 = new AbstractTableModel() {
     230  
     231             override def getColumnCount = 5
     232  
     233             override
     234  
     235             def getRowCount = staticAnalyseList.length
     236             override
     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         val table1JScrollPane = new JScrollPane();
     259         val table1JTable = new JTable(dataMode1);
     260         table1JScrollPane.setBounds(0,370,690,300)
     261         //    table1JTable.setBounds(0,170,500,300);
     262         table1JScrollPane.setViewportView(table1JTable);
     263         val table1JTextPaneScrollPan = new JScrollPane();
     264         table1JTextPaneScrollPan.setBounds(692,370,300,300);
     265         val table1JTextPane = new JTextPane();
     266         table1JTextPane.setEditable(false);
     267         table1JTextPaneScrollPan.setViewportView(table1JTextPane);
     268         jFrame.add(table1JTextPaneScrollPan);
     269         jFrame.add(table1JScrollPane);
     270  
     271         val table2JScrollPane = new JScrollPane();
     272         table2JScrollPane.setBounds(0,682,300,300)
     273         //    table2JScrollPane.setBounds(0,482);
     274  
     275         val table2JTable = new JTable();
     276         table2JTable.setBounds(0,682,1000,300);
     277         val r = new DefaultTableCellRenderer();
     278         r.setHorizontalAlignment(0)
     279         table2JTable.setDefaultRenderer(classOf[Any],r);
     280         table2JScrollPane.add(table2JTable)
     281         jFrame.add(table2JTable);
     282  
     283         jFrame.setVisible(true);
     284  
     285         inputJButton.addActionListener(new ActionListener {
     286             override def actionPerformed(e: ActionEvent): Unit = {
     287                 staticAnalyseList.clear();
     288                 //        staticTestMatrix : Array[ Array[String] ] = new Array[Array[String]](0)
     289                 staticTestMatrix = createMatrix();
     290                 analyse( inputJTextField.getText() + "#" );
     291                 val dataMode1 = new AbstractTableModel() {
     292  
     293                     override def getColumnCount = 5
     294  
     295                     override
     296  
     297                     def getRowCount = staticAnalyseList.length
     298                     override
     299                     def getValueAt(row: Int, col: Int): String = {
     300                         val a = staticAnalyseList(row);
     301                         if(col == 0){
     302                             return a.getStep();
     303                         }
     304                         if(col == 1){
     305                             return a.getAnalysisStack;
     306                         }
     307                         if(col == 2){
     308                             return a.getRemainingString;
     309                         }
     310                         if(col == 3){
     311                             return a.getProductionType;
     312                         }
     313                         if(col == 4){
     314                             return a.getAction;
     315                         }
     316                         return new String();
     317                     }
     318  
     319                 }
     320                 table1JTable.setModel(dataMode1);
     321  
     322                 val dataMode2 = new AbstractTableModel() {
     323  
     324                     override def getColumnCount = 9
     325  
     326                     override
     327  
     328                     def getRowCount = staticTestMatrix.length
     329                     override
     330                     def getValueAt(row: Int, col: Int) = staticTestMatrix(row)(col)
     331                 }
     332                 table2JTable.setModel(dataMode2);
     333                 table1JTextPane.setText(staticStringBuilder.toString())
     334             }
     335         })
     336     }
     337  
     338     /*
     339     * Function name: initiate
     340     * Function description: 初始化全局变量
     341     * Input parameters: the absolute path of the language-rule source file
     342     * Return value: 无
     343     * Exception: 未处理
     344     * Author: 来自高山
     345     * Created date: Sat Oct 19 2019 +0800
     346     * Editor: 来自高山
     347     * Edited Date: Sat Oct 19 2019 +0800
     348      */
     349     def initiate( filePath: String ): Unit = {
     350         LL1_G = parseFile(filePath)
     351         allCharacters = getWholeCharacters(LL1_G)
     352         usedCharacters = allCharacters
     353         relations = getRelation(LL1_G)
     354         VN = getVN(allCharacters)
     355         VT = getVT(allCharacters)
     356         eliminateLeftRecursion      // eliminate all the left recursion at first
     357     }
     358  
     359     /*
     360     * Function name: displayRelations
     361     * Function description: display all he language rules
     362     * Input parameters: 无
     363     * Return value: 无
     364     * Exception: 未处理
     365     * Author: 来自高山
     366     * Created date: Sat Oct 19 2019 +0800
     367     * Editor: 来自高山
     368     * Edited Date: Sat Oct 19 2019 +0800
     369      */
     370     def displayRelations(): Unit = {
     371         for( ex <- relations ) {
     372             if( ex._3 != "א" ) {
     373                 println( ex._1 + "->" + ex._2 + "|" + ex._3 )
     374             }
     375             else {
     376                 println( ex._1 + "->" + ex._2 )
     377             }
     378         }
     379     }
     380  
     381     /*
     382     * Function name: parseFile
     383     * Function description: 解析文本文件,保存在数组中
     384     * Input parameters: 文本绝对路径
     385     * Return value: -ArrayBuffer[ ( String, String ) ](String类型的元组ArrayBuffer数组)
     386     * Exception: 未处理
     387     * Author: 来自高山
     388     * Created date: Fri Oct 18 2019 +0800
     389     * Editor: 来自高山
     390     * Edited Date: Fri Oct 18 2019 +0800
     391      */
     392     def parseFile( filePath: String ): ArrayBuffer[ ( String, String ) ] = {
     393         val result = new ArrayBuffer[ ( String, String ) ]( countLines( readFromTxtByLine(filePath) ) )
     394         val sourceFile = readFromTxtByLine(filePath) //filePath
     395         for( line <- sourceFile ) {
     396             val tmp = line.split( "->", 2 )
     397             result += ( ( tmp.head, tmp.last ) )
     398         }
     399         result
     400     }
     401  
     402     /*
     403     * Function name: countLines
     404     * Function description: 计算文本行数,用于创建接收数组时开辟相应空间
     405     * Input parameters: -Array[String](文本文件数据构成的数组)
     406     * Return value: -Int(文本行数)
     407     * Exception: 未处理
     408     * Author: 来自高山
     409     * Created date: Fri Oct 18 2019 +0800
     410     * Editor: 来自高山
     411     * Edited Date: Sat Oct 19 2019 +0800
     412      */
     413     def countLines( sourceFile: Array[String] ): Int = {
     414         var cnt = 0
     415         for( line <- sourceFile ) {
     416             cnt += 1
     417         }
     418         cnt
     419     }
     420  
     421     /*
     422     * Function name: readFromTxtByLine
     423     * Function description: 读取文本文件
     424     * Input parameters: -String(文本文件绝对路径)
     425     * Return value: -Array[String](文本文件构成的数组,每行数据占一个数组元素)
     426     * Exception: -未处理
     427     * Author: 来自高山
     428     * Created date: Fri Oct 18 2019 +0800
     429     * Editor: 来自高山
     430     * Edited Date: Fri Oct 18 2019 +0800
     431      */
     432     def readFromTxtByLine(filePath: String): Array[String] = {
     433         import scala.io.Source
     434         val source = Source.fromFile(filePath, "UTF-8")
     435         //val lineIterator = source.getLines()
     436         //lineIterator.foreach()
     437         val lines = source.getLines().toArray
     438         source.close()
     439         //println(lines.size)
     440         lines
     441     }
     442  
     443     /*
     444     * Function name: getWholeCharacters
     445     * Function description: 获取文法的除“|”之外的所有字符
     446     * Input parameters: -ArrayBuffer[ (String, String) ](由文法左右两部分字符构成一个元组的数组,筛掉“|”)
     447     * Return value: -String(文法的除“|”之外的所有字符)
     448     * Exception: 未处理(有出错提示)
     449     * Author: 来自高山
     450     * Created date: Fri Oct 11 2019 +0800
     451     * Editor: 来自高山
     452     * Edited Date: Fri Oct 11 2019 +0800
     453      */
     454     def getWholeCharacters( string: ArrayBuffer[ (String, String) ] ): String = {
     455         var wholeCharacters = ""
     456         for( expression <- string ) {
     457             wholeCharacters += expression._1 + expression._2
     458         }
     459         val pattern = new Regex("\|")
     460         val result = pattern replaceAllIn( wholeCharacters, "" )
     461         if( result.isEmpty )
     462             "function getWholeCharacters failed"
     463         else
     464             result.distinct
     465     }
     466     /*
     467     * Function name: getVN
     468     * Function description: 获取文法的所有非终结符(non-terminal character),默认大写字母为非终结符,使用正则表达式匹配
     469     * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
     470     * Return value: -String(文法的所有非终结符)
     471     * Exception: 未处理(有出错提示)
     472     * Author: 来自高山
     473     * Created date: Fri Oct 11 2019 +0800
     474     * Editor: 来自高山
     475     * Edited Date: Fri Oct 11 2019 +0800
     476      */
     477     def getVN( string: String ): String = {
     478         //match big letter:
     479         //^[A-Z]+$
     480         val pattern = new Regex("[A-Z]")//("^[A-Z]+$")
     481         if( (pattern findAllIn string) != null )
     482             (pattern findAllIn string).mkString("")
     483         else
     484             "function getVN failed"
     485     }
     486  
     487     /*
     488     * Function name: getVT
     489     * Function description: 获取文法的所有非终结符(terminal character),默认大写字母外的字符为终结符,使用正则表达式匹配
     490     * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
     491     * Return value: -String(文法的所有终结符)
     492     * Exception: 未处理(有出错提示)
     493     * Author: 来自高山
     494     * Created date: Fri Oct 11 2019 +0800
     495     * Editor: 来自高山
     496     * Edited Date: Fri Oct 11 2019 +0800
     497      */
     498     def getVT( string: String ): String = {
     499         val pattern1 = new Regex("[A-Z]")
     500         val pattern2 = new Regex("\|")
     501         val firstFilter = pattern1 replaceAllIn( string, "" )
     502         val result = pattern2 replaceAllIn( firstFilter, "" )
     503         if( result.isEmpty == false )
     504             result
     505         else
     506             return "function getVT failed"
     507     }
     508     /*
     509     * Function name: getRelation
     510     * Function description: 获取文法每一行对应的推导关系,若文法只推出了1项(即没有符号“|”),则返回元组的第三个用希伯来字母“א”示空
     511     * Input parameters: -ArrayBuffer[ (String, String)(已经分割好的文法左右部分构成的数组)
     512     * Return value: -ArrayBuffer[ (String, String, String) ](元组第一个元素为推导式左边符号,第二为右边第二个符号串,第三为右边(若有)第三个符号串)
     513     * Exception: 未处理
     514     * Author: 来自高山
     515     * Created date: Fri Oct 11 2019 +0800
     516     * Editor: 来自高山
     517     * Edited Date: Fri Oct 11 2019 +0800
     518      */
     519     def getRelation( string: ArrayBuffer[ (String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
     520         val relation = new ArrayBuffer[ (String, String, String) ]()
     521         for( expression <- string ) {
     522             if( expression._2.contains("|") == false ) {
     523                 relation += ( ( expression._1, expression._2, "א" ) )
     524             }
     525             else {
     526                 val tmp = expression._2.split("\|", 2 )
     527                 relation += ( ( expression._1, tmp.head, tmp.last ) )
     528             }
     529         }
     530         relation
     531     }
     532  
     533     /*
     534     * Function name: findFirst
     535     * Function description: 获取指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串
     536     * Input parameters: -String(指定字符)
     537     * Return value: -String(指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串)
     538     * Exception: 未处理
     539     * Author: 来自高山
     540     * Created date: Fri Oct 11 2019 +0800
     541     * Editor: 来自高山
     542     * Edited Date: Fri Oct 11 2019 +0800
     543      */
     544     def findFirst( ch: String ): String = {
     545  
     546         val localRelations = relations
     547         var result = ""
     548         for( ex <- localRelations ) {
     549             if( ch == ex._1 ) {
     550                 if( ex._3 != "א" ) {
     551                     if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
     552                         result += ex._2(0).toString
     553                     }
     554                     if( VT.contains( ex._3(0) ) && ex._3(0) != 'ε' ) {
     555                         result += ex._3(0).toString
     556                     }
     557                 }
     558                 else {
     559                     if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
     560                         result += ex._2(0).toString
     561                     }
     562                 }
     563             }
     564         }
     565         result
     566     }
     567  
     568     /*
     569     * Function name: judgeOnlyOneVoidSuccession
     570     * Function description: 判断指定字符是否可推出唯一的字符ε
     571     * Input parameters: -String(指定字符串)
     572     * Return value: -Boolean(存在则true,否则false)
     573     * Exception: 未处理
     574     * Author: 来自高山
     575     * Created date: Fri Oct 11 2019 +0800
     576     * Editor: 来自高山
     577     * Edited Date: Fri Oct 11 2019 +0800
     578      */
     579     def judgeOnlyOneVoidSuccession( ch: String ): Boolean = {
     580         val localRelations = relations
     581         var result = 1
     582         for( ex <- localRelations ) {
     583             if( ch == ex._1 ) {
     584                 if( ex._3 != "א" ) {
     585                     if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) || (ex._3.length == 1 && ex._3(0) == 'ε') ) {
     586                         result = 1
     587                     }
     588                     else {
     589                         result = 0
     590                     }
     591                 }
     592                 else {
     593                     if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) ) {
     594                         result = 1
     595                     }
     596                     else {
     597                         result = 0
     598                     }
     599                 }
     600             }
     601         }
     602         if( result == 1 ) true else false
     603     }
     604  
     605     /*
     606     * Function name: judgeCaseXY
     607     * Function description: 判断构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)
     608     * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
     609     * Return value: -Boolean(满足则true,否则false)
     610     * Exception: 未处理
     611     * Author: 来自高山
     612     * Created date: Sat Oct 12 2019 +0800
     613     * Editor: 来自高山
     614     * Edited Date: Sat Oct 12 2019 +0800
     615      */
     616     def judgeCaseXY( ch: Char ): Boolean = {
     617         val localVN = VN
     618         val localRelations = relations
     619         var result = 0
     620         if( localVN.contains(ch) == true ) {
     621             for( ex <- localRelations ) {
     622                 if( ex._1(0) == ch ) {
     623                     if( localVN.contains( ex._2(0) ) || localVN.contains( ex._3(0) ) ) {
     624                         result += 1
     625                     }
     626                 }
     627             }
     628         }
     629         if( result > 0 )
     630             true
     631         else
     632             false
     633     }
     634  
     635     /*
     636     * Function name: findCase_Y_In_XY
     637     * Function description: 获取构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)时的Y
     638     * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
     639     * Return value: -String(Y构成的String字符串,无则为空)
     640     * Exception: 未处理
     641     * Author: 来自高山
     642     * Created date: Sat Oct 12 2019 +0800
     643     * Editor: 来自高山
     644     * Edited Date: Sat Oct 12 2019 +0800
     645      */
     646     def findCase_Y_In_XY( ch: Char ): String = {
     647         val localVN = VN
     648         val localRelations = relations
     649         var result = ""
     650         if( localVN.contains(ch) == true ) {
     651             for( ex <- localRelations ) {
     652                 if( ex._1(0) == ch ) {
     653                     if( ex._3 != "א" ) {
     654                         if( localVN.contains( ex._2(0) ) == true ) {
     655                             result += ex._2(0).toString
     656                         }
     657                         if( localVN.contains( ex._3(0) ) == true ) {
     658                             result += ex._3(0).toString
     659                         }
     660                     }
     661                     else {
     662                         if( localVN.contains( ex._2(0) ) == true ) {
     663                             result += ex._2(0).toString
     664                         }
     665                     }
     666                 }
     667             }
     668         }
     669         result
     670     }
     671  
     672     /*
     673     * Function name: findCase_Y_In_nY
     674     * Function description: 获取构造FIRST集时可能的第3种情况的(2)时的FIRST(Yi)中所有的非ε-元素(省略描述若干字)
     675     * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
     676     * Return value: -String(FIRST(Yi)中所有的非ε-元素构成的String字符串,无则为空)
     677     * Exception: 未处理
     678     * Author: 来自高山
     679     * Created date: Sat Oct 12 2019 +0800
     680     * Editor: 来自高山
     681     * Edited Date: Sat Oct 12 2019 +0800
     682      */
     683     def findCase_Y_In_nY( ch: Char ): String = {
     684         val localVN = VN
     685         val localRelations = relations
     686         var result = ""
     687         for( ex <- localRelations ) {
     688             if (ex._1 == ch.toString) {
     689                 var tmp = ""
     690  
     691                 if (ex._3 != 'א') {
     692                     var cnt = 0
     693                     for (tx <- ex._2) {
     694                         // add the element belongs to tmp
     695                         if (localVN.contains(tx)) {
     696                             tmp += tx.toString
     697                             cnt += 1
     698                         }
     699                         // otherwise, reset tmp as empty string
     700                         else {
     701                             tmp = ""
     702                         }
     703                     }
     704                     if (cnt == ex._2.length) {
     705                         result += tmp
     706                     }
     707  
     708                     // reset
     709                     cnt = 0
     710                     tmp = ""
     711                     for (tx <- ex._3) {
     712                         // add the element belongs to tmp
     713                         if (localVN.contains(tx)) {
     714                             tmp += tx.toString
     715                             cnt += 1
     716                         }
     717                         // otherwise, reset result as empty string
     718                         else {
     719                             tmp = ""
     720                         }
     721                     }
     722                     if (cnt == ex._3.length) {
     723                         result += tmp
     724                     }
     725                 }
     726                 else {
     727                     tmp = ""
     728                     var cnt = 0
     729                     for (tx <- ex._2) {
     730                         // add the element belongs to tmp
     731                         if (localVN.contains(tx)) {
     732                             tmp += tx.toString
     733                             cnt += 1
     734                         }
     735                         // otherwise, reset tmp as empty string
     736                         else {
     737                             tmp = ""
     738                         }
     739                     }
     740                     if (cnt == ex._2.length) {
     741                         result += tmp
     742                     }
     743                 }
     744             }
     745         }
     746         result = result.distinct
     747         result
     748     }
     749  
     750     /*
     751     * Function name: FIRST
     752     * Function description: 按照教材P78左下角的算法描述实现求解指定文法FIRST集;因用的是循环迭代求解,因此代码较长
     753     * Input parameters: -ArrayBuffer[ (String, String) ](产生式左右两部分分别构成元组的第1个和第2个元素)
     754     * Return value: -Map[ String, String ](Map的key是非终结符,value是其FIRST元素)
     755     * Exception: 未处理
     756     * Author: 来自高山
     757     * Created date: Mon Oct 14 2019 +0800
     758     * Editor: 来自高山
     759     * Edited Date: Sat Oct 19 2019 +0800
     760      */
     761     def FIRST( string: ArrayBuffer[ (String, String) ] ): Map[ String, String ] = {
     762         val FIRST_Group = Map[ String, String ]()
     763  
     764         val wholeCharacters = allCharacters
     765         val localVT = VT
     766         val localVN = VN
     767  
     768         for( character <- wholeCharacters ) {
     769             // case 1
     770             if( localVT.contains(character) ) {
     771                 //if there exist the original key that equals the current one
     772                 if( FIRST_Group.contains(character.toString) == true ) {
     773                     val tmp = character.toString + FIRST_Group(character.toString)
     774                     FIRST_Group(character.toString) = tmp.distinct
     775                 }
     776                 //otherwise
     777                 else {
     778                     FIRST_Group(character.toString) = character.toString
     779                 }
     780             }
     781  
     782             // case 2
     783             if( localVN.contains(character.toString) == true ) {
     784                 // case 2.1
     785                 val value = findFirst(character.toString)
     786                 if ( value.length != 0 ) {
     787                     if ( FIRST_Group.contains(character.toString) == true ) {
     788                         for( ch <- value ) {
     789                             val tmp = ch + FIRST_Group(character.toString)
     790                             FIRST_Group(character.toString) = tmp.distinct
     791                         }
     792                     }
     793                     else {
     794                         FIRST_Group(character.toString) = value.toString
     795                     }
     796                 }
     797  
     798                 // case 2.2
     799                 if( judgeOnlyOneVoidSuccession(character.toString) == true ) {
     800                     if ( FIRST_Group.contains(character.toString) == true ) {
     801                         val tmp = "ε" + FIRST_Group(character.toString)
     802                         FIRST_Group(character.toString) = tmp.distinct
     803                     }
     804                     else {
     805                         FIRST_Group(character.toString) = "ε"
     806                     }
     807                 }
     808             }
     809  
     810             for( character <- wholeCharacters ) {
     811                 // case 3
     812                 // case 3.1
     813                 if( judgeCaseXY(character) == true ) {
     814                     val tmpReply = findCase_Y_In_XY(character)
     815                     for( eachTmpReply <- tmpReply ) {
     816                         if( FIRST_Group.contains(eachTmpReply.toString) == true ) {
     817                             for (ex <- FIRST_Group(eachTmpReply.toString)) {
     818                                 if (ex != 'ε') {
     819                                     if (FIRST_Group.contains(character.toString) == true) {
     820                                         val tmp = ex.toString + FIRST_Group(character.toString)
     821                                         FIRST_Group(character.toString) = tmp.distinct
     822                                     }
     823                                     else {
     824                                         FIRST_Group(character.toString) = ex.toString
     825                                     }
     826                                 }
     827                             }
     828                         }
     829                     }
     830                 }
     831  
     832                 // case 3.2
     833                 if( findCase_Y_In_nY(character).length > 0 ) {
     834                     var flag = true
     835                     val tmpReply = findCase_Y_In_nY(character)
     836  
     837                     for( ex <- tmpReply ) {
     838                         if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true )  {
     839                             if( FIRST_Group(ex.toString).contains("ε") == false ) {
     840                                 flag = false
     841                             }
     842                         }
     843                         else {
     844                             flag = false
     845                         }
     846                         if( flag == true ) {
     847                             if (FIRST_Group.contains(character.toString) == true) {
     848                                 val tmp = FIRST_Group(ex.toString).replace( "ε", "" ) + FIRST_Group(character.toString)
     849                                 FIRST_Group(character.toString) = tmp.distinct
     850                             }
     851                             else {
     852                                 FIRST_Group(character.toString) = FIRST_Group(ex.toString).replace( "ε", "" )
     853                             }
     854  
     855                         }
     856                     }
     857                 }
     858                 // case 3.3
     859                 if( findCase_Y_In_nY(character).length > 0 ) {
     860                     var flag = true
     861                     val tmpReply = findCase_Y_In_nY(character)
     862                     for( ex <- tmpReply ) {
     863                         if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true )  {
     864                             if( FIRST_Group(ex.toString).contains("ε") == false ) {
     865                                 flag = false
     866                             }
     867                         }
     868                         else {
     869                             flag = false
     870                         }
     871                         if( flag == true ) {
     872  
     873                             if (FIRST_Group.contains(character.toString) == true) {
     874                                 val tmp = "ε" + FIRST_Group(character.toString)
     875                                 FIRST_Group(character.toString) = tmp.distinct
     876                             }
     877                             else {
     878                                 FIRST_Group(character.toString) = "ε"
     879                             }
     880                         }
     881                     }
     882                 }
     883             }
     884         }
     885         FIRST_Group
     886     }
     887  
     888     /*
     889     * Function name: FOLLOW
     890     * Function description: 根据dfsFOLLOW函数,获取各个非终结符的FOLLOW集元素
     891     * Input parameters: -ArrayBuffer[ (String, String) ](产生式左右两部分分别构成元组的第1个和第2个元素)
     892     * Return value: -Map[ String, String ](Map的key是非终结符,value是其FOLLOW集元素)
     893     * Exception: 未处理
     894     * Author: 来自高山
     895     * Created date: Sat Oct 19 2019 +0800
     896     * Editor: 来自高山
     897     * Edited Date: Sat Oct 19 2019 +0800
     898      */
     899     def FOLLOW( string: ArrayBuffer[ (String, String) ] ): Map[ String, String ] = {
     900         val localVN = VN
     901         val FOLLOW_Group = Map[ String, String ]()
     902         for( ch <- localVN ) {
     903             FOLLOW_Group(ch.toString) = dfsFOLLOW(ch.toString)
     904         }
     905         FOLLOW_Group
     906     }
     907  
     908     /*
     909     * Function name: dfsFOLLOW
     910     * Function description: 使用深度优先搜索(DFS)寻找各个非终结符的FOLLOW集元素
     911     * Input parameters: -String(指定的非终结符)
     912     * Return value: -String(指定终结符的FOLLOW集元素)
     913     * Exception: 未处理
     914     * Author: 来自高山
     915     * Created date: Sat Oct 19 2019 +0800
     916     * Editor: 来自高山
     917     * Edited Date: Sat Oct 19 2019 +0800
     918      */
     919     def dfsFOLLOW( ch: String ): String = {
     920         val FOLLOWPositions = Map[ String, String ]()
     921         val FOLLOW_Group = Map[ String, String ]()
     922         val localLL1_G = LL1_G
     923         val FIRST_Group = FIRST(localLL1_G)
     924         val localVN = VN
     925         for( ch <- localVN ) {
     926             FOLLOWPositions(ch.toString) = findGivenValueFOLLOWPosition(ch.toString)
     927             FOLLOW_Group(ch.toString) = "#"
     928         }
     929         var result = ""
     930  
     931         if( FOLLOWPositions(ch).length == 4 ) {
     932             if( FOLLOWPositions(ch)(1).toString == "T" ) {
     933                 result += FIRST_Group( FOLLOWPositions(ch)(0).toString )
     934                 FOLLOW_Group(ch) += result.distinct
     935             }
     936             else if( FOLLOWPositions(ch)(3).toString == "T" ) {
     937                 result += FIRST_Group( FOLLOWPositions(ch)(2).toString )
     938                 FOLLOW_Group(ch) += result.distinct
     939             }
     940             if( FOLLOWPositions(ch)(1).toString == "W" ) {
     941                 result += dfsFOLLOW( FOLLOWPositions(ch)(0).toString )
     942                 FOLLOW_Group(ch) = result.distinct
     943             }
     944             else if( FOLLOWPositions(ch)(3).toString == "W" ) {
     945                 result += dfsFOLLOW( FOLLOWPositions(ch)(2).toString )
     946                 FOLLOW_Group(ch) = result.distinct
     947             }
     948         }
     949  
     950         if( FOLLOWPositions(ch).length == 2 ) {
     951             if( FOLLOWPositions(ch)(1).toString == "T" ) {
     952                 result += FIRST_Group( FOLLOWPositions(ch)(0).toString )
     953                 FOLLOW_Group(ch) = result.distinct
     954             }
     955             else if( FOLLOWPositions(ch)(1).toString == "W" ) {
     956                 result += dfsFOLLOW( FOLLOWPositions(ch)(0).toString )
     957                 FOLLOW_Group(ch) = result.distinct
     958             }
     959         }
     960         FOLLOW_Group(ch).replace("ε", "")
     961     }
     962  
     963     /*
     964     * Function name: findGivenValueFOLLOWPosition
     965     * Function description: 按照教材P79右上角的算法描述,求解构成每个非终结符的FOLLOW集的“依赖”(因为实现了这个函数,节省了我原先用循环叠加求解FOLLOW集的700+代码)
     966     * Input parameters: -String(指定终结符)
     967     * Return value: -String(指定终结符的FOLLOW集元素,无则为空)
     968     * Exception: 未处理
     969     * Author: 来自高山
     970     * Created date: Sat Oct 19 2019 +0800
     971     * Editor: 来自高山
     972     * Edited Date: Sat Oct 19 2019 +0800
     973      */
     974     def findGivenValueFOLLOWPosition( ch: String ): String = {
     975         var result = ""
     976         val cnt = new ArrayBuffer[String]()
     977         val localRelations = relations
     978  
     979         for( ex <- localRelations ) {
     980             if( ex._3 != "א" ) {
     981                 if( ex._2.contains(ch) ) {
     982                     // מ
     983                     if( ex._2.length == 3 ) {
     984                         // B                                    A       α                 B         β
     985                         if( ex._2(1).toString == ch && judgeCase2( ex._1, ex._2(0).toString, ch, ex._2(2).toString ) ) {
     986                             val value = ex._2(2).toString + "T"
     987                             if( cnt.contains(value) == false ) {
     988                                 cnt += value
     989                                 result += value
     990                             }
     991                         }
     992                         // B                                    A       α                 B         β
     993                         if( ex._2(1).toString == ch && judgeCase3( ex._1, ex._2(0).toString, ch, ex._2(2).toString ) ) {
     994                             val value = ex._1.toString + "W"
     995                             if( cnt.contains(value) == false ) {
     996                                 cnt += value
     997                                 result += value
     998                             }
     999                         }
    1000                     }
    1001                     if( ex._2.length == 2 ) {
    1002                         // B                                    A       α                 B
    1003                         if( ex._2(1).toString == ch && judgeCase3( ex._1, ex._2(0).toString, ch, "" ) ) {
    1004                             val value = ex._1 + "W"
    1005                             if( cnt.contains(value) == false ) {
    1006                                 cnt += value
    1007                                 result += value
    1008                             }
    1009                         }
    1010                     }
    1011                 }
    1012                 if( ex._3.contains(ch) ) {
    1013                     if( ex._3.length == 3 ) {
    1014                         // B                                      A       α                 B         β
    1015                         if( ex._3(1).toString == ch && judgeCase2( ex._1, ex._3(0).toString, ch, ex._3(2).toString ) ) {
    1016                             val value = ex._3(2).toString + "T"
    1017                             if( cnt.contains(value) == false ) {
    1018                                 cnt += value
    1019                                 result += value
    1020                             }
    1021                         }
    1022                         if( ex._3(1).toString == ch && judgeCase3( ex._1, ex._3(0).toString, ch, ex._3(2).toString ) ) {
    1023                             val value = ex._1 + "W"
    1024                             if( cnt.contains(value) == false ) {
    1025                                 cnt += value
    1026                                 result += value
    1027                             }
    1028                         }
    1029                     }
    1030                     if( ex._3.length == 2 ) {
    1031                         // B                                    A       α                 B
    1032                         if( ex._3(1).toString == ch && judgeCase3( ex._1, ex._3(0).toString, ch, "" ) ) {
    1033                             val value = ex._1 + "W"
    1034                             if( cnt.contains(value) == false ) {
    1035                                 cnt += value
    1036                                 result += value
    1037                             }
    1038                         }
    1039                     }
    1040                 }
    1041             }
    1042             else {
    1043                 if( ex._2.contains(ch) ) {
    1044                     if( ex._2.length == 3 ) {
    1045                         // B                                      A       α              B         β
    1046                         if( ex._2(1).toString == ch && judgeCase2( ex._1, ex._2(0).toString, ch, ex._2(2).toString ) ) {
    1047                             val value = ex._2(2).toString + "T"
    1048                             if( cnt.contains(value) == false ) {
    1049                                 cnt += value
    1050                                 result += value
    1051                             }
    1052                         }
    1053                         if( ex._2(1).toString == ch && judgeCase3( ex._1, ex._2(0).toString, ch, ex._2(2).toString ) ) {
    1054                             val value = ex._1 + "T"
    1055                             if( cnt.contains(value) == false ) {
    1056                                 cnt += value
    1057                                 result += value
    1058                             }
    1059                         }
    1060                     }
    1061                     if( ex._2.length == 2 ) {
    1062                         // B                                    A       α                 B
    1063                         if( ex._2(1).toString == ch && judgeCase3( ex._1, ex._2(0).toString, ch, "" ) ) {
    1064                             val value = ex._1 + "W"
    1065                             if( cnt.contains(value) == false ) {
    1066                                 cnt += value
    1067                                 result += value
    1068                             }
    1069                         }
    1070                     }
    1071                 }
    1072             }
    1073         }
    1074         result
    1075     }
    1076  
    1077     /*
    1078     * Function name: judgeCase2
    1079     * Function description: 按照教材P79右下角的算法描述,判断是否填充满足条件(2)的矩阵元素
    1080     * Input parameters: -String, String, String, String[分别代表条件(2)的四个字符]
    1081     * Return value: -Boolean(满足条件(2)则返回true,否则返回false)
    1082     * Exception: 未处理
    1083     * Author: 来自高山
    1084     * Created date: Tue Oct 15 2019 +0800
    1085     * Editor: 来自高山
    1086     * Edited Date: Tue Oct 15 2019 +0800
    1087      */
    1088     def judgeCase2( A: String, α: String, B: String, β: String ): Boolean = {
    1089         val localVN = VN
    1090         val wholeCharacters = allCharacters
    1091         val localLL1_G = LL1_G
    1092         val localFIRST = FIRST(localLL1_G)
    1093         if( localVN.contains(A) == true && wholeCharacters.contains(α) == true && localVN.contains(B) == true &&
    1094                 wholeCharacters.contains(β) && localFIRST.contains(β) == true ) {
    1095             true
    1096         }
    1097         else {
    1098             false
    1099         }
    1100     }
    1101  
    1102     /*
    1103     * Function name: judgeCase3
    1104     * Function description: 按照教材P79右下角的算法描述,判断是否填充满足条件(3)的矩阵元素
    1105     * Input parameters: -String, String, String, String[分别代表条件(3)的四个字符]
    1106     * Return value: -Boolean(满足条件(3)则返回true,否则返回false)
    1107     * Exception: 未处理
    1108     * Author: 来自高山
    1109     * Created date: Wed Oct 16 2019 +0800
    1110     * Editor: 来自高山
    1111     * Edited Date: Wed Oct 16 2019 +0800
    1112      */
    1113     def judgeCase3( A: String, α: String, B: String, β: String ): Boolean = {
    1114         val localVN = VN
    1115         val wholeCharacters = allCharacters
    1116         val localLL1_G = LL1_G
    1117         val localFIRST = FIRST(localLL1_G)
    1118         if( ( localVN.contains(A) == true && wholeCharacters.contains(α) == true && localVN.contains(B) == true ) ||
    1119                 ( localVN.contains(A) == true && wholeCharacters.contains(α) == true && localVN.contains(B) == true && localFIRST(β).contains("ε") == true ) ) {
    1120             true
    1121         }
    1122         else {
    1123             false
    1124         }
    1125     }
    1126  
    1127     /*
    1128     * Function name: initiateMatrix
    1129     * Function description: 初始化分析表(为了在控制台打印方便,表长为非终结符个数加一,表宽为终结符个数加一)
    1130     * Input parameters: 无
    1131     * Return value: -Array[ Array[ String] ](分析表矩阵元素构成的二维数组,除了第0行和第0列,其它列与行的元素均为null)
    1132     * Exception: 未处理
    1133     * Author: 来自高山
    1134     * Created date: Wed Oct 16 2019 +0800
    1135     * Editor: 来自高山
    1136     * Edited Date: Wed Oct 16 2019 +0800
    1137      */
    1138     def initiateMatrix(): Array[ Array[ String] ] = {
    1139         val localVN = VN
    1140         val localVT = VT
    1141         val result = Array.ofDim[String](localVN.length + 1, localVT.length + 1)
    1142         for( i <- 1 to localVN.length ) {
    1143             result(i)(0) = localVN(i - 1).toString
    1144         }
    1145         for( j <- 1 to localVT.length ) {
    1146             if( localVT(j - 1).toString == "ε" ) {
    1147                 result(0)(j) = "#"
    1148             }
    1149             else {
    1150                 result(0)(j) = localVT(j - 1).toString
    1151             }
    1152         }
    1153         result
    1154     }
    1155  
    1156     /*
    1157     * Function name: createMatrix
    1158     * Function description: 按照教材P79右下角的算法描述,构造分析表
    1159     * Input parameters: 无
    1160     * Return value: -Array[ Array[String] ](分析表矩阵元素构成的二维数组)
    1161     * Exception: 未处理
    1162     * Author: 来自高山
    1163     * Created date: Wed Oct 16 2019 +0800
    1164     * Editor: 来自高山
    1165     * Edited Date: Wed Oct 16 2019 +0800
    1166      */
    1167     def createMatrix(): Array[ Array[String] ] = {
    1168         val result = initiateMatrix()
    1169         val localVT = VT
    1170         val localRelations = relations
    1171         val localLL1_G = LL1_G
    1172         val localFIRST = FIRST(localLL1_G)
    1173         val localFOLLOW = FOLLOW(localLL1_G)
    1174  
    1175         for( ex <- localRelations ) {
    1176  
    1177             if( ex._3 !=  "א" ) {
    1178                 for( a <- localVT ) {
    1179                     val ex2Length = ex._2.length
    1180                     var range = ""
    1181                     var α = ""
    1182                     var flag = false
    1183                     for( x <- 0 to (ex2Length - 1) ) {
    1184                         if( localFIRST( ex._2(x).toString ).contains("ε") == false && flag == false ) {
    1185                             α = ex._2(x).toString
    1186                             range = localFIRST( α )
    1187                             flag = true
    1188                         }
    1189                     }
    1190                     if( range.contains(a) == true && flag == true ) {
    1191                         result(getRow(ex._1))(getColumn(a.toString)) = ex._1 + "->" + ex._2
    1192                     }
    1193                     if( flag == false ) {
    1194                         range = "ε"
    1195                         result( getRow(ex._1) )( getColumn("ε") ) = ex._1 + "->" + "ε"
    1196                     }
    1197  
    1198                     // case 3
    1199                     if( range.contains("ε") == true && flag == false ) {
    1200                         for( b <- localFOLLOW(α) ) {
    1201                             result( getRow(ex._1.toString) )( getColumn(b.toString) ) = ex._1 + "->" + ex._2  // t --> tx
    1202                         }
    1203                     }
    1204  
    1205                     val ex3Length = ex._3.length
    1206                     range = ""
    1207                     flag = false
    1208                     for( x <- 0 to (ex3Length - 1) ) {
    1209                         if( localFIRST( ex._3(x).toString ).contains("ε") == false && flag == false ) {
    1210                             α = ex._3(x).toString
    1211                             range = localFIRST( α )
    1212                             flag = true
    1213                         }
    1214                     }
    1215                     if( range.contains(a) == true && flag == true ) {
    1216                         result( getRow(ex._1) )( getColumn(a.toString) ) = ex._1 + "->" + ex._3
    1217                     }
    1218                     if( flag == false ) {
    1219                         range = "ε"
    1220                         result(getRow(ex._1))(getColumn("ε")) = ex._1 + "->" + "ε"
    1221                     }
    1222  
    1223                     // case 3
    1224                     if( range.contains("ε") == true && flag == false ) {
    1225                         for( b <- localFOLLOW(ex._1) ) {
    1226                             result( getRow(ex._1.toString) )( getColumn(b.toString) ) = ex._1 + "->" + ex._3  // t --> tx
    1227                         }
    1228                     }
    1229                 }
    1230             }
    1231  
    1232             else {
    1233                 for( a <- localVT ) {
    1234                     val ex2Length = ex._2.length
    1235                     var range = ""
    1236                     var α = ""
    1237                     var flag = false
    1238                     for( x <- 0 to (ex2Length - 1) ) {
    1239                         if( localFIRST( ex._2(x).toString ).contains("ε") == false && flag == false ) {
    1240                             α = ex._2(x).toString
    1241                             range = localFIRST(α)
    1242                             flag = true
    1243                         }
    1244                     }
    1245                     if( range.contains(a) == true && flag == true ) {
    1246                         result( getRow(ex._1) )( getColumn(a.toString) ) = ex._1 + "->" + ex._2
    1247                     }
    1248                     if( flag == false ) {
    1249                         range = "ε"
    1250                         result( getRow(ex._1) )( getColumn("ε") ) = ex._1 + "->" + "ε"
    1251                     }
    1252  
    1253                     // case 3
    1254                     if( range.contains("ε") == true && flag == false ) {
    1255                         for( b <- localFOLLOW(ex._1) ) {
    1256                             result( getRow(ex._1.toString) )( getColumn(b.toString) ) = ex._1 + "->" + ex._2
    1257                         }
    1258                     }
    1259                 }
    1260             }
    1261         }
    1262         result
    1263     }
    1264  
    1265     /*
    1266     * Function name: getRow
    1267     * Function description: 获取指定字符在分析表中的行数
    1268     * Input parameters: -String(指定字符)
    1269     * Return value: -Int(指定字符所在的行数)
    1270     * Exception: 未处理
    1271     * Author: 来自高山
    1272     * Created date: Wed Oct 16 2019 +0800
    1273     * Editor: 来自高山
    1274     * Edited Date: Wed Oct 16 2019 +0800
    1275      */
    1276     def getRow( ch: String ): Int = {
    1277         val matrix = initiateMatrix()
    1278         var result = -1
    1279         if( ch == "α" ) {
    1280             println( "1 --- getRow, ch == " + ch )
    1281         }
    1282         for( i <- 0 to (matrix.length - 1) ) {
    1283             if( matrix(i)(0) == ch ) {
    1284                 result = i
    1285             }
    1286         }
    1287         result
    1288     }
    1289  
    1290     /*
    1291     * Function name: getColumn
    1292     * Function description: 获取指定字符在分析表中的列数
    1293     * Input parameters: -String(指定字符)
    1294     * Return value: -Int(指定字符所在的列数)
    1295     * Exception: 未处理
    1296     * Author: 来自高山
    1297     * Created date: Wed Oct 16 2019 +0800
    1298     * Editor: 来自高山
    1299     * Edited Date: Wed Oct 16 2019 +0800
    1300      */
    1301     def getColumn( ch: String ): Int = {
    1302         val matrix = initiateMatrix()
    1303         var result = -1
    1304         for( i <- 0 to (matrix.length - 1) ) {
    1305             for( j <- 0 to (matrix(i).length - 1) ) {
    1306                 if( matrix(0)(j) == ch ) {
    1307                     result = j
    1308                 }
    1309                 if( matrix(0)(j) == "#" && ch == "ε" ) {
    1310                     result = j
    1311                 }
    1312             }
    1313         }
    1314         result
    1315     }
    1316  
    1317     /*
    1318     * Function name: analyse
    1319     * Function description: 对指定的字符串进行LL(1)分析
    1320     * Input parameters: -String(输入的指定字符串)
    1321     * Return value: -Boolean(分析成功则返回true,否则false)
    1322     * Exception: 未处理(有出错提示)
    1323     * Author: 来自高山
    1324     * Created date: Wed Oct 16 2019 +0800
    1325     * Editor: 来自高山
    1326     * Edited Date: Wed Oct 16 2019 +0800
    1327      */
    1328     def analyse( expression: String ): Boolean = {
    1329         val stack = new mutable.Stack[String]()
    1330         var localExpression = expression
    1331         val table = createMatrix()
    1332         val localVT = VT
    1333         val localVN = VN
    1334         val localRelations = relations
    1335  
    1336         stack.push("#")
    1337         stack.push( localRelations(0)._1 )
    1338  
    1339         var cnt = 0
    1340         staticAnalyseList.append(new Analyse("步骤","分析栈","剩余字符串","所用产生式","动作"));
    1341         staticAnalyseList.append(new Analyse(cnt.toString, displayStack(stack).reverse.toString,localExpression.toString,"","initiate"));
    1342         while( stack.isEmpty == false ) {
    1343             val stackTop = stack.top
    1344             stack.pop()
    1345             // 栈顶符号属于  非终结符
    1346             if( localVN.contains(stackTop) == true ) {
    1347                 // 栈顶符号与表达式左端首字符  存在  关系
    1348                 if( table( getRow(stackTop) )( getColumn( localExpression(0).toString ) ) != null ) {
    1349                     val lastHalf = table( getRow(stackTop) )( getColumn( localExpression(0).toString ) ).split( "->", 2 ).last
    1350                     val length = lastHalf.length
    1351                     for( i <- 0 to (length - 1) ) {
    1352                         if( lastHalf != "ε" ) {
    1353                             stack.push(lastHalf(length - 1 - i).toString)
    1354                         }
    1355                     }
    1356                     cnt += 1
    1357  
    1358                     if( lastHalf != "ε" ) {
    1359                         staticAnalyseList.append(new Analyse(cnt.toString, displayStack(stack).reverse.toString, localExpression.toString, table(getRow(stackTop))(getColumn(localExpression(0).toString)), "POP, PUSH(" + lastHalf.reverse + ")"));
    1360                     }
    1361                     else {
    1362                         staticAnalyseList.append(new Analyse(cnt.toString, displayStack(stack).reverse.toString, localExpression.toString, table(getRow(stackTop))(getColumn(localExpression(0).toString)), "POP"));
    1363                     }
    1364                 }
    1365                 // 栈顶符号与表达式左端首字符  不存在  关系
    1366                 else {
    1367                     // 栈顶符号 等于 表达式左端首字符
    1368                     if( stackTop == "#" && localExpression(0).toString == "#" ) {
    1369                         println("11111")
    1370                         return true
    1371                     }
    1372                     // 栈顶符号 不等于 表达式左端首字符
    1373                     else {
    1374                         println("1 - error")
    1375                         staticAnalyseList.append(new Analyse(cnt.toString, displayStack(stack).reverse.toString,localExpression.toString,"",""));
    1376                         return false
    1377                     }
    1378                 }
    1379             }
    1380             // 栈顶符号属于  终结符
    1381             if( localVT.contains(stackTop) == true ) {
    1382                 // 栈顶符号 等于 表达式左端首字符
    1383                 if( stackTop == localExpression(0).toString ) {
    1384                     if( stackTop == localExpression(0).toString ) {
    1385                         //stack.pop()
    1386                         localExpression = localExpression.drop(1)
    1387                         cnt += 1
    1388                         staticAnalyseList.append(new Analyse(cnt.toString, displayStack(stack).reverse.toString,localExpression.toString,"","GETNEXT(" + stackTop + ")"));
    1389                     }
    1390                     // 栈顶符号 不等于 表达式左端首字符
    1391                     else {
    1392                         println("2 - error")
    1393                         return false
    1394                     }
    1395                 }
    1396             }
    1397         }
    1398  
    1399         true
    1400     }
    1401  
    1402     /*
    1403     * Function name: judgeLeftRecursion
    1404     * Function description: 判断是否存在形式上的左递归
    1405     * Input parameters: -(String, String, String)(产生式的左端与右端的两个(或为1个)元素)
    1406     * Return value: -Int(0表示无,1表示右端第1个元素存在形式上的左递归,2表示右端第2个元素)
    1407     * Exception: 未处理
    1408     * Author: 来自高山
    1409     * Created date: Sat Oct 19 2019 +0800
    1410     * Editor: 来自高山
    1411     * Edited Date: Sat Oct 19 2019 +0800
    1412      */
    1413     def judgeLeftRecursion( expression: (String, String, String) ): Int = {
    1414         var ans = 0             // ans = 0 means the current expression is not involved left-recursion
    1415         if( expression._2.length >= 2 && expression._1 == expression._2(0).toString && expression._2.drop(1) != "ε" ) {
    1416             ans += 1            // ans = 1 means the left recursion involves the expression._2
    1417         }
    1418         if( expression._3.length >= 2 && expression._1 == expression._3(0).toString && expression._3.drop(1) != "ε" ) {
    1419             ans += 2            // ans = 2 means the left recursion involves the expression._3
    1420         }
    1421         ans                     // ans = 3 means the given expression is false since both exp(2) and exp(3) involved
    1422     }
    1423  
    1424     /*
    1425     * Function name: eliminateLeftRecursion
    1426     * Function description: 消除形式上的左递归
    1427     * Input parameters: 无
    1428     * Return value: -ArrayBuffer[ (String, String, String) ](消除左递归后的新文法)
    1429     * Exception: 未处理
    1430     * Author: 来自高山
    1431     * Created date: Sat Oct 19 2019 +0800
    1432     * Editor: 来自高山
    1433     * Edited Date: Sat Oct 19 2019 +0800
    1434      */
    1435     def eliminateLeftRecursion(): ArrayBuffer[ (String, String, String) ] = {
    1436         var localRelations = relations
    1437         var invalidRelations = new ArrayBuffer[ (String, String, String) ]()
    1438         val localCandidateLetters = allCandidateLetters
    1439         val VN1 = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩABCDEFGHIJKLMNOPQRSTUVWXYZ"
    1440         val VT1 = "αβγδεζηθικλμνξοπρστυφχψωabcdefghijklmnopqrstuvwxyz"
    1441         for( ex <- localRelations ) {
    1442             if( ex._3 != "א" ) {
    1443                 if( judgeLeftRecursion( ex._1, ex._2, ex._3 ) == 1 ) {
    1444                     // P = ex._1, α = ex._2 - ex._1, β = ex._3,  P' = newValue
    1445                     invalidRelations += ( ( ex._1, ex._2, ex._3 ) )
    1446                     val newValue = subString( usedCharacters, localCandidateLetters )(0)
    1447                     usedCharacters += newValue
    1448                     if( VN1.contains(newValue) && !VN.contains(newValue) ) {
    1449                         VN += newValue.toString
    1450                         allCharacters += newValue.toString
    1451                     }
    1452                     if( VT1.contains(newValue) && !VT.contains(newValue) ) {
    1453                         VT += newValue.toString
    1454                         allCharacters += newValue.toString
    1455                     }
    1456                     val α = ex._2.drop(1)
    1457                     val exp1 = ( ex._1, ex._3 + newValue.toString, "א" )
    1458                     val exp2 = ( newValue.toString, α.toString + newValue.toString, "ε" )
    1459                     //                    println( "1 -- exp1._1 = " + exp1._1 + ", exp1._2 = " + exp1._2 + ", exp1._3 = " + exp1._3 )
    1460                     //                    println( "1 -- exp2._1 = " + exp2._1 + ", exp2._2 = " + exp2._2 + ", exp2._3 = " + exp2._3 )
    1461                     localRelations += exp1
    1462                     localRelations += exp2
    1463                 }
    1464                 else if( judgeLeftRecursion( ex._1, ex._2, ex._3 ) == 2 ) {
    1465                     // P = ex._1, α = ex._3 - ex._1, β = ex._3,  P' = newValue
    1466                     invalidRelations += ( ( ex._1, ex._2, ex._3 ) )
    1467                     val newValue = subString( usedCharacters, localCandidateLetters )(0)
    1468                     if( VN1.contains(newValue) && !VN.contains(newValue) ) {
    1469                         VN += newValue.toString
    1470                         allCharacters += newValue.toString
    1471                     }
    1472                     if( VT1.contains(newValue) && !VT.contains(newValue) ) {
    1473                         VT += newValue.toString
    1474                         allCharacters += newValue.toString
    1475                     }
    1476                     usedCharacters += newValue
    1477                     val α = ex._3.drop(1)
    1478                     val exp1 = ( ex._1, ex._3 + newValue.toString, "א" )
    1479                     val exp2 = ( newValue.toString, α.toString + newValue.toString, "ε" )
    1480                     //                    println( "2 -- exp1._1 = " + exp1._1 + ", exp1._2 = " + exp1._2 + ", exp1._3 = " + exp1._3 )
    1481                     //                    println( "2 -- exp2._1 = " + exp2._1 + ", exp2._2 = " + exp2._2 + ", exp2._3 = " + exp2._3 )
    1482                     localRelations += exp1
    1483                     localRelations += exp2
    1484                 }
    1485                 else if( judgeLeftRecursion( ex._1, ex._2, ex._3 ) == 3 ){
    1486                     println( "error in the function eliminateLeftRecursion" )
    1487                 }
    1488             }
    1489             else {
    1490                 if( judgeLeftRecursion( ex._1, ex._2, ex._3 ) == 1 ) {
    1491                     // P = ex._1, α = ex._2 - ex._1, β = ex._3,  P' = newValue
    1492                     invalidRelations += ( ( ex._1, ex._2, ex._3 ) )
    1493                     val newValue = subString( usedCharacters, localCandidateLetters )(0)
    1494                     if( VN1.contains(newValue) && !VN.contains(newValue) ) {
    1495                         VN += newValue.toString
    1496                         allCharacters += newValue.toString
    1497                     }
    1498                     if( VT1.contains(newValue) && !VT.contains(newValue) ) {
    1499                         VT += newValue.toString
    1500                         allCharacters += newValue.toString
    1501                     }
    1502                     usedCharacters += newValue
    1503                     val α = ex._2.drop(1)
    1504                     val exp1 = ( ex._1, newValue.toString, "א" )
    1505                     val exp2 = ( newValue.toString, α.toString + newValue.toString, "ε" )
    1506                     //                    println( "3 -- exp1._1 = " + exp1._1 + ", exp1._2 = " + exp1._2 + ", exp1._3 = " + exp1._3 )
    1507                     //                    println( "3 -- exp2._1 = " + exp2._1 + ", exp2._2 = " + exp2._2 + ", exp2._3 = " + exp2._3 )
    1508                     localRelations += exp1
    1509                     localRelations += exp2
    1510                 }
    1511             }
    1512         }
    1513         for( ex <- invalidRelations ) {
    1514             localRelations = localRelations.-(ex)
    1515         }
    1516         relations = localRelations
    1517         localRelations
    1518     }
    1519  
    1520     /*
    1521     * Function name: subString
    1522     * Function description: 获取两输入字符串的差集(要求两者均非空)
    1523     * Input parameters: 无
    1524     * Return value: -String(两输入字符串的差集)
    1525     * Exception: 未处理
    1526     * Author: 来自高山
    1527     * Created date: Sat Oct 19 2019 +0800
    1528     * Editor: 来自高山
    1529     * Edited Date: Sat Oct 19 2019 +0800
    1530      */
    1531     def subString( usedCharacters: String, localCandidateLetters: String ): String = {
    1532         require( usedCharacters.length != 0 && localCandidateLetters.length != 0 )
    1533         var ans = ""
    1534         var A = usedCharacters
    1535         var B = localCandidateLetters
    1536         if( A.length < B.length ) {
    1537             val tmp = A
    1538             A = B
    1539             B = tmp
    1540         }
    1541         for( i <- 0 to (A.length - 1) ) {
    1542             var j = 0
    1543             while( j < B.length && B(j) != A(i) ) {
    1544                 j += 1
    1545             }
    1546             if( j == B.length ) {
    1547                 ans += A(i)
    1548             }
    1549         }
    1550         ans
    1551     }
    1552 }

      

      FileUtil class(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 }

      包pojo中的Analyse class(Java):

     1 package pojo;
     2  
     3 public class Analyse {
     4     private String step;
     5     private String analysisStack;
     6     private String remainingString;
     7     private String productionType;
     8     private String action;
     9  
    10     public Analyse(){
    11  
    12     }
    13  
    14     public Analyse(String step, String analysisStack, String remainingString, String productionType, String action) {
    15         this.step = step;
    16         this.analysisStack = analysisStack;
    17         this.remainingString = remainingString;
    18         this.productionType = productionType;
    19         this.action = action;
    20     }
    21  
    22     public String getStep() {
    23         return step;
    24     }
    25  
    26     public void setStep(String step) {
    27         this.step = step;
    28     }
    29  
    30     public String getAnalysisStack() {
    31         return analysisStack;
    32     }
    33  
    34     public void setAnalysisStack(String analysisStack) {
    35         this.analysisStack = analysisStack;
    36     }
    37  
    38     public String getRemainingString() {
    39         return remainingString;
    40     }
    41  
    42     public void setRemainingString(String remainingString) {
    43         this.remainingString = remainingString;
    44     }
    45  
    46     public String getProductionType() {
    47         return productionType;
    48     }
    49  
    50     public void setProductionType(String productionType) {
    51         this.productionType = productionType;
    52     }
    53  
    54     public String getAction() {
    55         return action;
    56     }
    57  
    58     public void setAction(String action) {
    59         this.action = action;
    60     }
    61 }

      程序截图:

    图 1 开始界面

    图 2 选择文件

    图 3 显示当前文法

    图 4 执行程序(输入表达式为“i+i*i”)

    图 5 执行程序(输入表达式为“i+i*i-i/i”)

  • 相关阅读:
    表的锁机制
    ABAP函数:VIEW_MAINTENANCE_CALL(维护表视图等)
    数据字典中新建表时出现黄色警告的处理
    smartforms长文本处理方式
    打印报表页码
    可以根据柜子内表取出所有的柜子信息的BAPI函数
    方法的重载、类的继承
    构造方法
    函数方法
    方法
  • 原文地址:https://www.cnblogs.com/25th-engineer/p/11707006.html
Copyright © 2020-2023  润新知