编译原理实验LL(1)完整Scala实现代码与测试数据

  完成了形式上的消除左递归,但是还存在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。

   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 }

原文地址:https://www.cnblogs.com/25th-engineer/p/11707006.html

时间: 2024-08-07 05:19:27

编译原理实验LL(1)完整Scala实现代码与测试数据的相关文章

编译原理实验代码(词法分析,语法分析,中间代码生成)

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的.代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码. lexAnalysis.h /* * lexAnalysis.h * * Created on: 2014-12-2 * Author: liuqiushan */ #ifndef LEXANALYSIS_H_ #define LEXANALYSIS_H_ #include <stdio.h> #include

哈工大软件学院编译原理实验1——词法分析

这次实验被"过来人"们定位非常easy,实验内容例如以下: ----------------------------------------------------------------------------------- 对例如以下工作进行展开描写叙述 (1) 给出语言的词法规则描写叙述 · 标识符.keyword.整常数.字符常数.浮点常数 · 单界符:+,-,×,;,- · 双界符:/*,:=,>=,<=,!=,- · 凝视 (2) 针对这样的单词的状态转换图和程

编译原理 实验3 语法分析

语法分析 一. 实验目的 算术表达式的文法可以是(你可以根据需要适当改变): E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 程序输入/输出示例: 如参考C语言的运算符.输入如下表达式(以分号为结束)和输出结果: (1)10; 输出:正确 (2)1+2; 输出:正确 (3)(1+2)/3+4-(5+6/7); 输出:正

吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】

一.实验要求 实验二 基于预測方法的语法分析程序的设计 一.实验目的 了解预測分析器的基本构成及用自顶向下的预測法对表达式进行语法分析的方法,掌握预測语法分析程序的手工构造方法. 二.实验内容 1.了解编译程序的基于预測方法的语法分析过程. 2.依据预測分析原理设计一个基于预測方法的语法分析程序. 三.实验要求 对给定文法G[S]: S->AT       A->BU     T->+AT|$      U->*BU|$    B->(S)|m 当中,$表示空串. 1.推断上

编译原理实验二:LL(1)语法分析器

一.实验要求 不得不想吐槽一下编译原理的实验代码量实在是太大了,是编译原理撑起了我大学四年的代码量... 这次实验比上次要复杂得多,涵盖的功能也更多了,我觉得这次实验主要的难点有两个(其实都是难点...): 1. 提取左公因子或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下面我贴出实验的一些关键代码和算法思想. 二.基于预测分析表法的语法分析 2.1 代码结构 2.1.1  Grammar类    功

编译原理 实验2 DFA的运行

DFA的运行 一. 实验目的 1.理解有穷自动机的作用: 2.利用状态图和状态表表示有穷自动机: 3.以程序实现有穷自动机的运行过程; 4.利用状态表和有穷自动机的运行原理编制程序,使得程序能够识别一个输入串是否为一个有效的符号串.具体可以选择下面之一:无符号定点实数,无符号正偶数,自然数,整数,十六进制数,或其他自己定义的符号串. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 1.简单介绍你所设计的有穷自动机.(要求必须完成无符

编译原理 - 实验三 - 递归下降语法分析器的调试及扩展

一. 语法分析介绍 语法分析是编译过程的核心部分,它的主要任务是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成做准备.执行语法分析任务的程序叫语法分析程序或语法分析器. 二. 所实现的语义分析和代码生成程序能处理什么语句 (1)简单变量的声明语句 (2)表达式语句 (3)if语句. (4)while语句 (5)for语句 (6)write语句 (7)read语句 (8)do语句. (9)处理过程调用和返回 三.实验过程 ①用VC

编译原理 实验1 PL/0语言词法分析

PL/0语言词法分析 一. 实验目的 通过完成词法分析程序,了解词法分析的过程.编制一个读单词程序,对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,即基本保留字.标识符.常数.运算符.界符五大类. 二. 实验环境 操作系统:window xp 编写环境:visual c++ .c-free.turbo c 编写语言:c语言 分析语言:PL/0 三. 实验内容 对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,其词法描述如下: (1) 关键字:

编译原理 - 实验四 - yacc基本使用(bison)

一.介绍 只要在Unix环境中写过程序,必定会邂逅神秘的Lex&YACC,就如GNU/Linux用户所熟知的Flex&Bison,这里的Flex就是由Vern Paxon实现的一个Lex,Bison则是GNU版本的YACC,在此我们将统一称呼这些程序为Lex和YACC,所以我们将用Flex和Bison来尝试下我们的实例. 二.准备工作(win7) ①  下载flex和bison并安装到D:\GnuWin32(尽量是根目录) ②    由于我们使用的flex和bison都是GNU的工具,所以