合肥工业大学编译原理实验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 +"\r\n");
  76         staticStringBuilder.append("VN = " + VN +"\r\n");
  77         staticStringBuilder.append( "allCharacters = " + allCharacters +"\r\n");
  78         val tx = FIRST(LL1_G)
  79         staticStringBuilder.append(  "FIRST集: " +"\r\n");
  80         for( t <- tx ) {
  81             if( allCharacters.contains( t._1 ) ) {
  82                 staticStringBuilder.append( "FIRST("+ t._1 + ") = {" + t._2.mkString(",") + "}\r\n");
  83             }
  84         }
  85         val ex = FOLLOW(LL1_G)
  86         staticStringBuilder.append("FOLLOW集: "+"\r\n");
  87         for( t <- ex ) {
  88             if( VN.contains( t._1 ) ) {
  89                 staticStringBuilder.append( "FOLLOW("+ t._1 + ") = {" + t._2.mkString(",") + "}\r\n");
  90             }
  91         }
  92         val testMatrix1 = createMatrix()
  93         staticTestMatrix = testMatrix1;
  94         for( ex <- LL1_G ) {
  95             staticStringBuilder2.append( ex._1 + "->" + ex._2 + "\r\n")
  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+"\r\n");
26             }
27         } catch (Exception e) {
28             e.printStackTrace();
29         } finally {
30             try {
31                 br.close();
32                 is.close();
33             } catch (IOException e) {
34                 e.printStackTrace();
35             }
36         }
37         return sb.toString();
38     }
39 }

 

  包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”)

 

posted on 2019-10-20 11:17  25th_engineer  阅读(1064)  评论(0编辑  收藏  举报