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

       

Table of Contents

        测试数据:

        代码:

        无GUI代码(Scala):

        含GUI代码:

        LR_1_try_GUI类(Scala):

        FileUtil类(Java):

         Analyse类(Java):

        运行截图:


        Java的GUI参考了“菊花侠”的手笔,Scala全部都是本人手写。

        github地址:LR(1)

        测试数据:

E->E+T
E->T
T->T*F
T->F
F->(E)
F->i

        代码:

        无GUI代码(Scala):

import scala.collection.immutable.Stack
import scala.collection.mutable
import scala.collection.mutable.{ArrayBuffer, Map}
import scala.util.matching.Regex




object LR_1 {
	private final var allCharacters = new String()
	private final var relations = new ArrayBuffer[ (String, String, String) ]()
	private final var VN = new String()
	private final var VT = new String()
	private final var rowLength = 0
	private final var columnLength = 0
	private final val itemGroup = Map[ ArrayBuffer[ (String, String, String) ], Int ]()
	private final var LL1_G = new ArrayBuffer[ (String, String) ]()
	//private val allCandidateLetters = "αΑβΒγΓδΔεΕζΖηΗθΘιΙκΚλΛμΜνΝξΞοΟπΠρΡσΣτΤυΥφΦχΧψΨωΩ" + "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"
	private val allCandidateLetters = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩABCDEFGHIJKLMNOPQRSTUVWXYZ"
	private final var usedCharacters = ""
	// private val LL1_G = ArrayBuffer( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"),
	//    ("S", "ε"), ("F", "(E)"), ("F", "i") )//, ("Y", "*FS|/FS"), ("Y", "+TG|-TG"), ("Y", "x"), ("Y", "M"), ("M", "i"), ("M", "ε") )
	//  test data 1:
	//  ( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"),
	//       ("S", "ε"), ("F", "(E)"), ("F", "i"), ("Y", "S"), ("Y", "Gx"), ("Y", "x"), ("Y", "M"), ("M", "i"), ("M", "ε") )
	//  test data 2:
	//         ( ("D", "*FD"), ("D", "ε"), ("T", "FD"), ("E", "TC"), ("F", "(E)"), ("F", "i"), ("C", "+TC"), ("C", "ε") )
	//  test data 3:
	//         ( ("E", "E+T|T"), ("T", "T*F|T"), ("F", "(E)|i") )
	//  stand test data:
	//         ( ("E", "TG"), ("G", "+TG|-TG"), ("G", "ε"), ("T", "FS"), ("S", "*FS|/FS"), ("S", "ε"), ("F", "(E)"), ("F", "i") )

	def main(args: Array[String]): Unit = {

		//test parseFile
		val result = parseFile("/home/hadoop001/Documents/code/Scala/LR(1)/testData/test.data")
		println( "the original language rules:" )
		for( rs <- result ) {
			println( rs._1 + "->" + rs._2 )
		}
		initiate("/home/hadoop001/Documents/code/Scala/LR(1)/testData/test.data")
		utility()
		println("**************")
		analyse("i+i*i#")

	}

	/*
	* Function name: utility
	* Function description: 辅助输出函数
	* Input parameters: 无
	* Return value: 无
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Mon Oct 28 2019 +0800
	* Editor: 来自高山
	* Edited Date: Mon Oct 28 2019 +0800
	 */
	def utility(): Unit = {
		println( "after expanding the language rules:" )
		displayRelations()

		println("**************")
		//test FIRST
		println("FIRST:")
		val testFIRST = FIRST()
		for( ex <- testFIRST ) {
			println( "FIRST(" + ex._1 + ") = {" + ex._2.mkString(",") + "}" )
		}
		println("**************")

		var cnt4 = 0
		for( ex <- itemGroup.toList.sortBy(_._2) ) {
			println( cnt4 + ":\nI" + ex._2 + ":" )
			for (tx <- ex._1 ) {
				println( tx._1 + "->" + tx._2 + ", " + tx._3 )
			}
			println("^^^^^^^^^^^^^^^^^^^^^^^^")
			cnt4 += 1
		}

		println("**************")
		val test_createMatrix = createMatrix
		for ( i <- 0 to test_createMatrix.length - 1 ) {
			for ( j <- 0 to test_createMatrix(i).length - 1 ) {
				print( test_createMatrix(i)(j) + " " )
			}
			println()
		}
	}

	/*
	* Function name: analyse
	* Function description: 对指定的字符串进行LR(1)分析
	* Input parameters: -String(输入的指定字符串)
	* Return value: -Boolean(分析成功则返回true,否则false)
	* Exception: 未处理(有出错提示)
	* Author: 来自高山
	* Created date: Mon Oct 28 2019 +0800
	* Editor: 来自高山
	* Edited Date: Mon Oct 28 2019 +0800
	 */
	def analyse( expression: String ): Boolean = {
		val statusStack = new mutable.Stack[String]()
		val characterStack = new mutable.Stack[String]()
		val analyseTable = createMatrix()
//		val analyseTable = ArrayBuffer(ArrayBuffer(null, "+", "*", "(", ")", "i", "#", "E", "T", "F", "A"),
//										ArrayBuffer("0", null, null, "S4", null, "S5", null, "1", "2", "3", null),
//										ArrayBuffer("1", "S6", null, null, null, null, "acc", null, null, null, null),
//										ArrayBuffer("2", "r2", "S7", null, null, null, "r2", null, null, null, null),
//										ArrayBuffer("3", "r4", "r4", null, null, null, "r4", null, null, null, null),
//										ArrayBuffer("4", null, null, "S4", null, "S11", null, "8", "9", "10", null),
//										ArrayBuffer("5", "r6", "r6", null, null, null, "r6", null, null, null, null),
//										ArrayBuffer("6", null, null, "S4", null, "S5", null, null, "12", "13", null),
//										ArrayBuffer("7", null, null, "S4", null, "S5", null, null, null, "14", null),
//										ArrayBuffer("8", "S15", null, null, "S16", null, null, null, null, null, null),
//										ArrayBuffer("9", "r2", "S17", null, "r2", null, null, null, null, null, null),
//										ArrayBuffer("10", "r4", "r4", null, "r4", null, null, null, null, null, null),
//										ArrayBuffer("11", "r6", "r6", null, "r6", null, null, null, null, null, null),
//										ArrayBuffer("12", "r1", "S18", null, null, null, "r1", null, null, null, null),
//										ArrayBuffer("13", "r4", "r4", null, null, null, "r4",null, null, null, null),
//										ArrayBuffer("14", "r3", "r3", null, null, null, "r3", null, null, null, null),
//										ArrayBuffer("15", null, null, "S4", null, "S11", null, null, "19", "20", null),
//										ArrayBuffer("16", "r5", "r5", null, null, null, "r5", null, null, null, null),
//										ArrayBuffer("17", null, null, "S4", null, "S11", null, null, null, "21", null),
//										ArrayBuffer("18", null, null, "S4", null, "S5", null, null, null, "14", null),
//										ArrayBuffer("19", "r1", "S17", null, "r1", null, null, null, null, null, null),
//										ArrayBuffer("20", "r4", "r4", null, "r4", null, null, null, null, null, null),
//										ArrayBuffer("21", "r3", "r3", null, "r3", null, null, null, null, null, null)
//		)
		var expr = expression
		var flag = false
		var repeat = true
		statusStack.push("0")
		characterStack.push("#")
		var tot = 0
		case class characterToColumn(a: String) {
			var ans = -1
			for( j <- 1 to (columnLength - 1) ) {
				if( analyseTable(0)(j) == a ) {
					ans = j
				}
			}
			//ans
		}
		while ( repeat == true ) {
			//  s = statusTop
			val statusTop = statusStack.top
			val a = expr(0)

			val aColumn = characterToColumn(a.toString).ans
			var sRow = statusTop.toInt
			if(sRow == 0 ) sRow += 1 else sRow += 1

			if( analyseTable(sRow)(aColumn)(0) == 'S' ) {
				val newStatus = analyseTable(sRow)(aColumn).drop(1)
				statusStack.push(newStatus)
				characterStack.push(a.toString)
				expr = expr.drop(1)

				println( tot + "状态栈: [" + displayStack(statusStack.reverse).mkString(",") + "],符号栈:[" +
						displayStack(characterStack.reverse) + "],剩余字符串:" + expr + ",动作:ACTION[" +
						statusTop + ", " + a + "]," + "状态 " + aColumn + " 与符号 " + a + " 分别入栈")
				tot += 1
			}
			else if( analyseTable(sRow)(aColumn)(0) == 'r' ) {
				val exprLineNO =  analyseTable(sRow)(aColumn).drop(1).toInt
				val currentRelation = relations(exprLineNO)

				var popLength = 0
				if( currentRelation._3 != "א" ) {
					popLength = currentRelation._2.length + currentRelation._3.length
				}
				else {
					popLength = currentRelation._2.length
				}
				var cnt = popLength
				val  tmpCharacter = characterStack.reverse.toString.replace("Stack(", "").replace(")", "").replace(",", "").replace(" ", "") //.substring() //.substring(characterStack.length - popLength - 1, characterStack.length - 1 )
				val reduceCharacter = tmpCharacter.drop(tmpCharacter.length - popLength)
				while ( cnt >= 1 ) {
					statusStack.pop()
					characterStack.pop()
					cnt -= 1
				}
				// s' = characterTop
				val statusTop2 = statusStack.top.toInt

				var sRow2 = -1
				if( statusTop2 == 0 ) sRow2 = statusTop2 + 1 else sRow2 = statusTop2 + 1

				val A = currentRelation._1
				characterStack.push(A)
				val tmp = analyseTable(sRow2)( characterToColumn(A).ans )
				statusStack.push(tmp)

				println( tot + "状态栈: [" + displayStack(statusStack.reverse).mkString(",") + "],符号栈:[" +
						displayStack(characterStack.reverse) + "],剩余字符串:" + expr + ",动作:GOTO[" +
						statusTop2 + ", " + A + "]" + ",用产生式 " + A + "->" + reduceCharacter + " 进行规约")
				tot += 1
			}
			else if( analyseTable(sRow)(aColumn) == "acc" ) {
				println("succeed")
				flag = true
				repeat = false
			}
			else {
				println("error")
				println( "error in, sRow = " + sRow + ", aColumn = " + aColumn + ", analyseTable(" + sRow + ")(" + aColumn + ") = " + analyseTable(sRow)(aColumn) )
				flag = true
				repeat = false
			}
			//cnt += 1
		}
		if(flag) true else false
	}

	/*
	* Function name: createMatrix
	* Function description: 构造ACTION与GOTO分析表
	* Input parameters: 无
	* Return value: -Array[ Array[String] ](分析表矩阵元素构成的二维数组)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Mon Oct 28 2019 +0800
	* Editor: 来自高山
	* Edited Date: Mon Oct 28 2019 +0800
	 */
	def createMatrix(): Array[ Array[String] ] = {
		val result = initiateMatrix()
		val localVT = VT
		val localVN = VN

		case class getColumn( ch: String ) {
			val matrix = initiateMatrix()
			var ans = -1
			for( j <- 0 to (columnLength - 1) ) {
				if( matrix(0)(j) == ch ) {
					ans = j
				}
			}
		}


		for( ex <- itemGroup ) {
			for( tx <- ex._1 ) {
				val pointPosition = tx._2.indexOf("·")
				//· 不在最右边
				//若项目[A->α·aβ] ∈ Ik,且GO(Ik, a) = Ij,a为终结符,则置ACTION[k, a]为“sj”
				if (pointPosition < tx._2.length - 1) {
					val a = tx._2( pointPosition + 1 )
					if( localVT.contains(a) == true && findItemOrder(ex._1, a.toString) != -1 ) {
						val j = findItemOrder(ex._1, a.toString)
						var tmpRow = -1
						tmpRow = ex._2 + 1
						result(tmpRow)( getColumn(a.toString).ans ) = "S" + j.toString
					}
				}
				if (pointPosition == tx._2.length - 1 ) {
					val a = tx._3
					var tmpRow = -1
					tmpRow = ex._2 + 1
					result(tmpRow)(getColumn(a).ans) = "r" + ( findRelationOrder( (tx._1,
							tx._2.replace("·", "") ) ) )
				}
				if( tx._1 == relations(0)._1 && tx._2 == relations(0)._2 + "·" && tx._3 == "#" ) {
					var tmpRow = -1
					tmpRow = ex._2 + 1
					result(tmpRow)( getColumn("#").ans ) = "acc"
				}
			}
			for( ch <- localVN ) {
				if( findItemOrder(ex._1, ch.toString) != -1 ) {
					val gotoNumber = findItemOrder(ex._1, ch.toString)
					var tmpRow = -1
					tmpRow = ex._2 + 1
					//A = ch
					result(tmpRow)( getColumn(ch.toString).ans ) = gotoNumber.toString
				}
			}
		}
		result
	}

	/*
	* Function name: findRelationOrder
	* Function description: 获取产生式的位于文法的第几行,从0开始
	* Input parameters: -(String, String)(給定的产生式)
	* Return value: -Int(給定的产生式在給定文法中的行数)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Mon Oct 28 2019 +0800
	* Editor: 来自高山
	* Edited Date: Mon Oct 28 2019 +0800
	 */
	def findRelationOrder( expression: (String, String) ): Int ={
		var ans = -1
		var cnt = 0
		val localRelations = relations
		for( ex <- localRelations ) {
			var expr = ""
			if( ex._3 != "א" ) {
				expr = ex._1 + ex._2 + ex._3
			}
			else {
				expr = ex._1 + ex._2
			}
			if( expr.equals(expression._1 + expression._2) ) {
				ans = cnt
			}
			cnt += 1
		}
		ans
	}

	/*
	* Function name: findItemOrder
	* Function description: 获取特定项目对于指定字符在项目集族中的编号,从0开始
	* Input parameters: -ArrayBuffer[ (String, String, String) ](給定项目), -String(給定字符)
	* Return value: -Int(給定的项目对于指定字符在项目集族中的编号)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Mon Oct 28 2019 +0800
	* Editor: 来自高山
	* Edited Date: Mon Oct 28 2019 +0800
	 */
	def findItemOrder( item: ArrayBuffer[ (String, String, String) ], a: String ): Int = {
		var ans = -1
		val givenItem = go( item, a).sorted
		val localItemGroup = itemGroup
		for( ex <- localItemGroup ) {
			if( ex._1.sorted.equals(givenItem) ) {
				ans = ex._2
			}
		}
		ans
	}

	/*
	* Function name: initiateMatrix
	* Function description: 初始化分析表,即ACTION表与GOTO表
	* Input parameters: 无
	* Return value: -Array[ Array[ String] ](已完成初始的分析表)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sun Oct 27 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sun Oct 27 2019 +0800
	 */
	def initiateMatrix(): Array[ Array[ String] ] = {
		val localVN = VN
		val localVT = VT
		val tableRowLength = rowLength
		val tableColumnLength = columnLength
		val result = Array.ofDim[String](tableRowLength, tableColumnLength)
		for( j <- 1 to localVT.length ) {
			result(0)(j) = localVT(j - 1).toString
		}
		for( j <- localVT.length + 1 to tableColumnLength - 1 ) {
			result(0)(j) = localVN(j - localVT.length - 1).toString
		}
		for( i <- 1 to ( tableRowLength - 1 ) ) {
			result(i)(0) = (i - 1).toString
		}
		for( i <- 0 to (tableRowLength - 1) ) {
			for( j <- 0 to (tableColumnLength - 1) ) {
				if( result.isEmpty != false ) {
					result(i)(j) = null
				}
			}
		}

		result
	}

	/*
	* Function name: getItemGroup
	* Function description: 对于输入的文法,建立初始化的项目集
	* Input parameters: 无
	* Return value: -Unit
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Wed Oct 23 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sun Oct 27 2019 +0800
	 */
	def getItemGroup(): Unit = {
		val ldx = ( relations(0)._1, "·" + relations(0)._2, "#" )
		val I0 = getClosure( ArrayBuffer(ldx) )
		val wholeCharacters = allCharacters
		var tot = 0
//		var cnt = 0
		itemGroup(I0) = tot
		var appendFlag = true
		while (appendFlag == true) {
			var originalAns = Map[ ArrayBuffer[ (String, String, String) ], Int ]()
			originalAns = itemGroup.clone()
			//为什么用I作为遍历变量不行?!
			for(item <- itemGroup.keys) {
				for (ch <- wholeCharacters) {
					val newItem = go(item, ch.toString).sorted
					if (newItem.isEmpty == false && itemGroup.contains(newItem) == false) {
						tot += 1
						itemGroup(newItem) = tot
					}
				}
			}
			if( originalAns.equals(itemGroup) == true ) {
				appendFlag = false
//				println( cnt + ", all same" )
//				cnt += 1
			}
			else {
				originalAns.clear()
				originalAns = itemGroup.clone()
//				println( cnt + ", changed" )
//				cnt += 1
			}
		}
	}

	/*
	* Function name: getItems
	* Function description: 返回文法的初始项目集I0
	* Input parameters: 无
	* Return value: -ArrayBuffer[String](文法的项目集,第一个元素是文法产生式左边符号,第二个是对应的右边字符串所生成的项目)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Wed Oct 23 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sar Oct 26 2019 +0800
	 */
	def getItems(): ArrayBuffer[ (String, String, String) ] = {
		val result = new ArrayBuffer[ (String, String, String) ]()
		val localRelations = relations
		//initiate
		for (ex <- localRelations) {
			if (ex._3 != "א") {
				result += ((ex._1, "·" + ex._2, "#"))
				result += ((ex._1, "·" + ex._3, "#"))
			}
			else {
				result += ((ex._1, "·" + ex._2, "#"))
			}
		}
		result
	}

	/*
	* Function name: go
	* Function description: 求給定项目对于特定字符的下一状态
	* Input parameters: -ArrayBuffer[ (String, String, String) ](給定项目), String(特定字符)
	* Return value: -ArrayBuffer[ (String, String, String) ](給定项目对于特定字符的下一状态)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sat Oct 26 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sat Oct 26 2019 +0800
	 */
	def go( I: ArrayBuffer[ (String, String, String) ], X: String ): ArrayBuffer[ (String, String, String) ] = {
		//GO(I, X) = CLOSURE(J)
		//J = {任何形如[A->αX·β, a]的项目|[A->α·Xβ, a]∈I}
		val ans = new ArrayBuffer[ (String, String, String) ]()
		val items = new ArrayBuffer[ (String, String, String) ]()

		for( ex <- I ) {
			val pointPosition = ex._2.indexOf("·")
			//· 不在最右边
			if (pointPosition < ex._2.length - 1) {
				val A = ex._1
				val possibleX = ex._2( pointPosition + 1)
				//  αXβ
				val noPointExpressionPart2 = ex._2.replace("·", "")
				if( X == possibleX.toString ) {
					//  αX·β
					val newPart2 = noPointExpressionPart2.substring(0, pointPosition + 1) + "·" +
							noPointExpressionPart2.substring(pointPosition + 1, noPointExpressionPart2.length)
					val a = ex._3
					items += ( (A, newPart2, a) )
				}
			}
		}
		ans.appendAll( getClosure(items) )
		ans
	}

	/*
	* Function name: getClosure
	* Function description: 求給定项目集的闭包
	* Input parameters: -ArrayBuffer[ (String, String, String) ](給定的项目集)
	* Return value: -ArrayBuffer[ (String, String, String) ](給定项目集的闭包)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sat Oct 26 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sun Oct 27 2019 +0800
	 */
	def getClosure( items: ArrayBuffer[ (String, String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
		val result = new ArrayBuffer[ (String, String, String) ]()
		result.appendAll(items)
		val localFIRST = FIRST()
		var addFlag = true
		var cnt = 1
		while (addFlag == true ) {
			val originalResult = new ArrayBuffer[(String, String, String)]()
			originalResult.appendAll(result)
			for (ex <- result) {

				val pointPosition = ex._2.indexOf("·")
				//· 不在最右边
				if (pointPosition < ex._2.length - 1) {
					//B在 · 的右边
					val B = ex._2(pointPosition + 1)
					val a = ex._3

					// case 1: β != Φ and a != # or
					// case 2: β != Φ and a = #
					if (pointPosition < ex._2.length - 2) {
						val β = ex._2(pointPosition + 2)
						//  ξ
						val rightExpressionsOfB = getRightExpressions(B.toString)
						val FIRST_Of_βa = localFIRST(β.toString)
						for (b <- FIRST_Of_βa) {
							for (ksi <- rightExpressionsOfB) {
								val tmp = ((B.toString, "·" + ksi, b.toString))

								if (result.contains(tmp) == false) {
									result += tmp
								}
							}
						}
					}
					// case 3: β = Φ and a equals any character
					if (pointPosition == ex._2.length - 2) {
						val rightExpressionsOfB = getRightExpressions(B.toString)
						val FIRST_Of_βa = localFIRST(a.toString)
						for (b <- FIRST_Of_βa) {
							for (ksi <- rightExpressionsOfB) {
								val tmp = ((B.toString, "·" + ksi, b.toString))
								if (result.contains(tmp) == false) {
									result += tmp
								}
							}
						}
					}
				}
			}
			if (result != originalResult) {
				originalResult.remove(0, originalResult.length)
				originalResult.appendAll(result)
				cnt += 1
			}
			else {
				addFlag = false
				cnt += 1
			}
		}
		result
	}

	/*
	* Function name: getRightExpressions
	* Function description: 获取給定非终结符所在产生式的右部,可能不止一个,因此返回值是String类型的ArrayBuffer数组
	* Input parameters: -String(給定的非终结符)
	* Return value: -ArrayBuffer[String](給定非终结符所在产生式的右部)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Fri Oct 25 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 25 2019 +0800
	 */
	def getRightExpressions(ch: String): ArrayBuffer[String] = {
		val result = new ArrayBuffer[String]()
		val localRelations = relations
		for( ex <- localRelations ) {
			if( ex._1 == ch ) {
				if( ex._3 != "א" ) {
					result += ex._2
					result += ex._3
				}
				else {
					result += ex._2
				}
			}
		}
		result
	}

	def getSingleRelation( ch: String ): ArrayBuffer[ (String, String, String) ] = {
		val result = new ArrayBuffer[ (String, String, String) ]()
		val localRelations = relations
		for( ex<- localRelations ) {
			if(ex._1 == ch ) {
				result += ex
			}
		}
		result
	}

	/*
	* Function name: splitString
	* Function description: 从字符串的首字符的左边到尾字符的右边,依次插入点“·”;每插入一个点即将其作为元素加入待返回String类型的ArrayBuffer数组
	* Input parameters: -String(待处理的String类型的字符串)
	* Return value: -ArrayBuffer[String](输入字符串依次添加点“·”为元素的字符串数组)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Wed Oct 23 2019 +0800
	* Editor: 来自高山
	* Edited Date: Wed Oct 23 2019 +0800
	 */
	def splitString( string: String ): ArrayBuffer[String] = {
		val result = new ArrayBuffer[String]()
		val stringLength = string.length
		for( i <- 0 to stringLength ) {
			result += string.substring(0, i) + "·" + string.substring(i, stringLength)
		}
		result
	}

	/*
	* Function name: displayStack
	* Function description: 输出栈的所有元素
	* Input parameters: -mutable.Stack[String](待处理的String类型的栈)
	* Return value: -String(栈所有元素组成的字符串)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Mon Oct 21 2019 +0800
	* Editor: 来自高山
	* Edited Date: Mon Oct 21 2019 +0800
	 */
	def displayStack( stack: mutable.Stack[String] ): String = {
		var result = ""
		for( ex <- stack ) {
			result += ex
		}
		result
	}

	/*
	* Function name: initiate
	* Function description: 初始化全局变量
	* Input parameters: the absolute path of the language-rule source file
	* Return value: 无
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sat Oct 19 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sun Oct 27 2019 +0800
	 */
	def initiate( filePath: String ): Unit = {
		LL1_G = parseFile(filePath)
		allCharacters = getWholeCharacters(LL1_G)
		usedCharacters = allCharacters
		relations = getRelation(LL1_G)
		VN = getVN(allCharacters)
		VT = getVT(allCharacters)
		val leftCharacters = subString(allCandidateLetters, VN)
		//relations += ( ( leftCharacters(0).toString, (relations(0)._1), "א" ) )
		relations.insert(0, ( leftCharacters(0).toString, (relations(0)._1), "א" ) )
		VN += leftCharacters(0).toString
		usedCharacters += leftCharacters(0).toString
		allCharacters += leftCharacters(0).toString

		allCharacters += "#"
		usedCharacters += "#"
		VT += "#"
		getItemGroup
		columnLength = VN.length + VT.length + 1
		rowLength = itemGroup.size + 1
	}

	/*
	* Function name: subString
	* Function description: 获取两输入字符串的差集(要求两者均非空)
	* Input parameters: 无
	* Return value: -String(两输入字符串的差集)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sat Oct 19 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sat Oct 19 2019 +0800
	 */
	def subString( usedCharacters: String, localCandidateLetters: String ): String = {
		require( usedCharacters.length != 0 && localCandidateLetters.length != 0 )
		var ans = ""
		var A = usedCharacters
		var B = localCandidateLetters
		if( A.length < B.length ) {
			val tmp = A
			A = B
			B = tmp
		}
		for( i <- 0 to (A.length - 1) ) {
			var j = 0
			while( j < B.length && B(j) != A(i) ) {
				j += 1
			}
			if( j == B.length ) {
				ans += A(i)
			}
		}
		ans
	}

	/*
	* Function name: displayRelations
	* Function description: display all he language rules
	* Input parameters: 无
	* Return value: 无
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sat Oct 19 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sat Oct 19 2019 +0800
	 */
	def displayRelations(): Unit = {
		for( ex <- relations ) {
			if( ex._3 != "א" ) {
				println( ex._1 + "->" + ex._2 + "|" + ex._3 )
			}
			else {
				println( ex._1 + "->" + ex._2 )
			}
		}
	}

	/*
	* Function name: parseFile
	* Function description: 解析文本文件,保存在数组中
	* Input parameters: 文本绝对路径
	* Return value: -ArrayBuffer[ ( String, String ) ](String类型的元组ArrayBuffer数组)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Fri Oct 18 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 18 2019 +0800
	 */
	def parseFile( filePath: String ): ArrayBuffer[ ( String, String ) ] = {
		val result = new ArrayBuffer[ ( String, String ) ]( countLines( readFromTxtByLine(filePath) ) )
		val sourceFile = readFromTxtByLine(filePath) //filePath
		for( line <- sourceFile ) {
			val tmp = line.split( "->", 2 )
			result += ( ( tmp.head, tmp.last ) )
		}
		result
	}

	/*
	* Function name: countLines
	* Function description: 计算文本行数,用于创建接收数组时开辟相应空间
	* Input parameters: -Array[String](文本文件数据构成的数组)
	* Return value: -Int(文本行数)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Fri Oct 18 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sat Oct 19 2019 +0800
	 */
	def countLines( sourceFile: Array[String] ): Int = {
		var cnt = 0
		for( line <- sourceFile ) {
			cnt += 1
		}
		cnt
	}

	/*
	* Function name: readFromTxtByLine
	* Function description: 读取文本文件
	* Input parameters: -String(文本文件绝对路径)
	* Return value: -Array[String](文本文件构成的数组,每行数据占一个数组元素)
	* Exception: -未处理
	* Author: 来自高山
	* Created date: Fri Oct 18 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 18 2019 +0800
	 */
	def readFromTxtByLine(filePath: String): Array[String] = {
		import scala.io.Source
		val source = Source.fromFile(filePath, "UTF-8")
		//val lineIterator = source.getLines()
		//lineIterator.foreach()
		val lines = source.getLines().toArray
		source.close()
		//println(lines.size)
		lines
	}

	/*
	* Function name: getWholeCharacters
	* Function description: 获取文法的除“|”之外的所有字符
	* Input parameters: -ArrayBuffer[ (String, String) ](由文法左右两部分字符构成一个元组的数组,筛掉“|”)
	* Return value: -String(文法的除“|”之外的所有字符)
	* Exception: 未处理(有出错提示)
	* Author: 来自高山
	* Created date: Fri Oct 11 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 11 2019 +0800
	 */
	def getWholeCharacters( string: ArrayBuffer[ (String, String) ] ): String = {
		var wholeCharacters = ""
		for( expression <- string ) {
			wholeCharacters += expression._1 + expression._2
		}
		val pattern = new Regex("\\|")
		val result = pattern replaceAllIn( wholeCharacters, "" )
		if( result.isEmpty )
			"function getWholeCharacters failed"
		else
			result.distinct
	}
	/*
	* Function name: getVN
	* Function description: 获取文法的所有非终结符(non-terminal character),默认大写字母为非终结符,使用正则表达式匹配
	* Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
	* Return value: -String(文法的所有非终结符)
	* Exception: 未处理(有出错提示)
	* Author: 来自高山
	* Created date: Fri Oct 11 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 11 2019 +0800
	 */
	def getVN( string: String ): String = {
		//match big letter:
		//^[A-Z]+$
		val pattern = new Regex("[A-Z]")//("^[A-Z]+$")
		if( (pattern findAllIn string) != null )
			(pattern findAllIn string).mkString("")
		else
			"function getVN failed"
	}

	/*
	* Function name: getVT
	* Function description: 获取文法的所有非终结符(terminal character),默认大写字母外的字符为终结符,使用正则表达式匹配
	* Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
	* Return value: -String(文法的所有终结符)
	* Exception: 未处理(有出错提示)
	* Author: 来自高山
	* Created date: Fri Oct 11 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 11 2019 +0800
	 */
	def getVT( string: String ): String = {
		val pattern1 = new Regex("[A-Z]")
		val pattern2 = new Regex("\\|")
		val firstFilter = pattern1 replaceAllIn( string, "" )
		val result = pattern2 replaceAllIn( firstFilter, "" )
		if( result.isEmpty == false )
			result
		else
			return "function getVT failed"
	}
	/*
	* Function name: getRelation
	* Function description: 获取文法每一行对应的推导关系,若文法只推出了1项(即没有符号“|”),则返回元组的第三个用希伯来字母“א”示空
	* Input parameters: -ArrayBuffer[ (String, String)(已经分割好的文法左右部分构成的数组)
	* Return value: -ArrayBuffer[ (String, String, String) ](元组第一个元素为推导式左边符号,第二为右边第二个符号串,第三为右边(若有)第三个符号串)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Fri Oct 11 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 11 2019 +0800
	 */
	def getRelation( string: ArrayBuffer[ (String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
		val relation = new ArrayBuffer[ (String, String, String) ]()
		for( expression <- string ) {
			if( expression._2.contains("|") == false ) {
				relation += ( ( expression._1, expression._2, "א" ) )
			}
			else {
				val tmp = expression._2.split("\\|", 2 )
				relation += ( ( expression._1, tmp.head, tmp.last ) )
			}
		}
		relation
	}

	/*
	* Function name: findFirst
	* Function description: 获取指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串
	* Input parameters: -String(指定字符)
	* Return value: -String(指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Fri Oct 11 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 11 2019 +0800
	 */
	def findFirst( ch: String ): String = {

		val localRelations = relations
		var result = ""
		for( ex <- localRelations ) {
			if( ch == ex._1 ) {
				if( ex._3 != "א" ) {
					if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
						result += ex._2(0).toString
					}
					if( VT.contains( ex._3(0) ) && ex._3(0) != 'ε' ) {
						result += ex._3(0).toString
					}
				}
				else {
					if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
						result += ex._2(0).toString
					}
				}
			}
		}
		result
	}

	/*
	* Function name: judgeOnlyOneVoidSuccession
	* Function description: 判断指定字符是否可推出唯一的字符ε
	* Input parameters: -String(指定字符串)
	* Return value: -Boolean(存在则true,否则false)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Fri Oct 11 2019 +0800
	* Editor: 来自高山
	* Edited Date: Fri Oct 11 2019 +0800
	 */
	def judgeOnlyOneVoidSuccession( ch: String ): Boolean = {
		val localRelations = relations
		var result = 1
		for( ex <- localRelations ) {
			if( ch == ex._1 ) {
				if( ex._3 != "א" ) {
					if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) || (ex._3.length == 1 && ex._3(0) == 'ε') ) {
						result = 1
					}
					else {
						result = 0
					}
				}
				else {
					if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) ) {
						result = 1
					}
					else {
						result = 0
					}
				}
			}
		}
		if( result == 1 ) true else false
	}

	/*
	* Function name: judgeCaseXY
	* Function description: 判断构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)
	* Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
	* Return value: -Boolean(满足则true,否则false)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sat Oct 12 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sat Oct 12 2019 +0800
	 */
	def judgeCaseXY( ch: Char ): Boolean = {
		val localVN = VN
		val localRelations = relations
		var result = 0
		if( localVN.contains(ch) == true ) {
			for( ex <- localRelations ) {
				if( ex._1(0) == ch ) {
					if( localVN.contains( ex._2(0) ) || localVN.contains( ex._3(0) ) ) {
						result += 1
					}
				}
			}
		}
		if( result > 0 )
			true
		else
			false
	}

	/*
	* Function name: findCase_Y_In_XY
	* Function description: 获取构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)时的Y
	* Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
	* Return value: -String(Y构成的String字符串,无则为空)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sat Oct 12 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sat Oct 12 2019 +0800
	 */
	def findCase_Y_In_XY( ch: Char ): String = {
		val localVN = VN
		val localRelations = relations
		var result = ""
		if( localVN.contains(ch) == true ) {
			for( ex <- localRelations ) {
				if( ex._1(0) == ch ) {
					if( ex._3 != "א" ) {
						if( localVN.contains( ex._2(0) ) == true ) {
							result += ex._2(0).toString
						}
						if( localVN.contains( ex._3(0) ) == true ) {
							result += ex._3(0).toString
						}
					}
					else {
						if( localVN.contains( ex._2(0) ) == true ) {
							result += ex._2(0).toString
						}
					}
				}
			}
		}
		result
	}

	/*
	* Function name: findCase_Y_In_nY
	* Function description: 获取构造FIRST集时可能的第3种情况的(2)时的FIRST(Yi)中所有的非ε-元素(省略描述若干字)
	* Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
	* Return value: -String(FIRST(Yi)中所有的非ε-元素构成的String字符串,无则为空)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Sat Oct 12 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sat Oct 12 2019 +0800
	 */
	def findCase_Y_In_nY( ch: Char ): String = {
		val localVN = VN
		val localRelations = relations
		var result = ""
		for( ex <- localRelations ) {
			if (ex._1 == ch.toString) {
				var tmp = ""

				if (ex._3 != 'א') {
					var cnt = 0
					for (tx <- ex._2) {
						// add the element belongs to tmp
						if (localVN.contains(tx)) {
							tmp += tx.toString
							cnt += 1
						}
						// otherwise, reset tmp as empty string
						else {
							tmp = ""
						}
					}
					if (cnt == ex._2.length) {
						result += tmp
					}

					// reset
					cnt = 0
					tmp = ""
					for (tx <- ex._3) {
						// add the element belongs to tmp
						if (localVN.contains(tx)) {
							tmp += tx.toString
							cnt += 1
						}
						// otherwise, reset result as empty string
						else {
							tmp = ""
						}
					}
					if (cnt == ex._3.length) {
						result += tmp
					}
				}
				else {
					tmp = ""
					var cnt = 0
					for (tx <- ex._2) {
						// add the element belongs to tmp
						if (localVN.contains(tx)) {
							tmp += tx.toString
							cnt += 1
						}
						// otherwise, reset tmp as empty string
						else {
							tmp = ""
						}
					}
					if (cnt == ex._2.length) {
						result += tmp
					}
				}
			}
		}
		result = result.distinct
		result
	}

	/*
	* Function name: FIRST
	* Function description: 按照教材P78左下角的算法描述实现求解指定文法FIRST集;因用的是循环迭代求解,因此代码较长
	* Input parameters: -ArrayBuffer[ (String, String) ](产生式左右两部分分别构成元组的第1个和第2个元素)
	* Return value: -Map[ String, String ](Map的key是非终结符,value是其FIRST元素)
	* Exception: 未处理
	* Author: 来自高山
	* Created date: Mon Oct 14 2019 +0800
	* Editor: 来自高山
	* Edited Date: Sat Oct 19 2019 +0800
	 */
	def FIRST(): Map[ String, String ] = {
		val FIRST_Group = Map[ String, String ]()
		val wholeCharacters = allCharacters
		val localVT = VT
		val localVN = VN

		for( character <- wholeCharacters ) {
			// case 1
			if( localVT.contains(character) ) {
				//if there exist the original key that equals the current one
				if( FIRST_Group.contains(character.toString) == true ) {
					val tmp = character.toString + FIRST_Group(character.toString)
					FIRST_Group(character.toString) = tmp.distinct
				}
				//otherwise
				else {
					FIRST_Group(character.toString) = character.toString
				}
			}

			// case 2
			if( localVN.contains(character.toString) == true ) {
				// case 2.1
				val value = findFirst(character.toString)
				if ( value.length != 0 ) {
					if ( FIRST_Group.contains(character.toString) == true ) {
						for( ch <- value ) {
							val tmp = ch + FIRST_Group(character.toString)
							FIRST_Group(character.toString) = tmp.distinct
						}
					}
					else {
						FIRST_Group(character.toString) = value.toString
					}
				}

				// case 2.2
				if( judgeOnlyOneVoidSuccession(character.toString) == true ) {
					if ( FIRST_Group.contains(character.toString) == true ) {
						val tmp = "ε" + FIRST_Group(character.toString)
						FIRST_Group(character.toString) = tmp.distinct
					}
					else {
						FIRST_Group(character.toString) = "ε"
					}
				}
			}

			for( character <- wholeCharacters ) {
				// case 3
				// case 3.1
				if( judgeCaseXY(character) == true ) {
					val tmpReply = findCase_Y_In_XY(character)
					for( eachTmpReply <- tmpReply ) {
						if( FIRST_Group.contains(eachTmpReply.toString) == true ) {
							for (ex <- FIRST_Group(eachTmpReply.toString)) {
								if (ex != 'ε') {
									if (FIRST_Group.contains(character.toString) == true) {
										val tmp = ex.toString + FIRST_Group(character.toString)
										FIRST_Group(character.toString) = tmp.distinct
									}
									else {
										FIRST_Group(character.toString) = ex.toString
									}
								}
							}
						}
					}
				}

				// case 3.2
				if( findCase_Y_In_nY(character).length > 0 ) {
					var flag = true
					val tmpReply = findCase_Y_In_nY(character)

					for( ex <- tmpReply ) {
						if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true )  {
							if( FIRST_Group(ex.toString).contains("ε") == false ) {
								flag = false
							}
						}
						else {
							flag = false
						}
						if( flag == true ) {
							if (FIRST_Group.contains(character.toString) == true) {
								val tmp = FIRST_Group(ex.toString).replace( "ε", "" ) + FIRST_Group(character.toString)
								FIRST_Group(character.toString) = tmp.distinct
							}
							else {
								FIRST_Group(character.toString) = FIRST_Group(ex.toString).replace( "ε", "" )
							}

						}
					}
				}
				// case 3.3
				if( findCase_Y_In_nY(character).length > 0 ) {
					var flag = true
					val tmpReply = findCase_Y_In_nY(character)
					for( ex <- tmpReply ) {
						if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true )  {
							if( FIRST_Group(ex.toString).contains("ε") == false ) {
								flag = false
							}
						}
						else {
							flag = false
						}
						if( flag == true ) {

							if (FIRST_Group.contains(character.toString) == true) {
								val tmp = "ε" + FIRST_Group(character.toString)
								FIRST_Group(character.toString) = tmp.distinct
							}
							else {
								FIRST_Group(character.toString) = "ε"
							}
						}
					}
				}
			}
		}
		FIRST_Group
	}

}

        含GUI代码:

        LR_1_try_GUI类(Scala):

import java.awt.{Color}
import java.awt.event.{ActionEvent, ActionListener}

import javax.swing.table.{AbstractTableModel}
import javax.swing.{JButton, JFileChooser, JFrame, JPanel, JScrollPane, JTable, JTextField, JTextPane}
import pojo.Analyse

import scala.collection.mutable
import scala.collection.mutable.{ArrayBuffer, Map}
import scala.util.matching.Regex


object LR_1_try_GUI {
    private final var allCharacters = new String()
    private final var relations = new ArrayBuffer[ (String, String, String) ]()
    private final var VN = new String()
    private final var VT = new String()
    private final var rowLength = 0
    private final var columnLength = 0
    private final val itemGroup = Map[ ArrayBuffer[ (String, String, String) ], Int ]()
    private final var LL1_G = new ArrayBuffer[ (String, String) ]()
    private val allCandidateLetters = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩABCDEFGHIJKLMNOPQRSTUVWXYZ"
    private final var usedCharacters = ""

    val staticAnalyseList : ArrayBuffer[Analyse] = new ArrayBuffer[Analyse]();
    var staticTestMatrix : Array[ Array[String] ] = new Array[Array[String]](0)
    var staticStringBuilder : StringBuilder = new StringBuilder();
    var staticStringBuilder2 : StringBuilder = new StringBuilder();

    def main(args: Array[String]): Unit = {
        GUI1
    }

    /*
    * Function name: GUI1
    * Function description: 实现图形化界面展示,开始界面
    * Input parameters: 无
    * Return value: 无
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sun Oct 20 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 28 2019 +0800
     */
    def GUI1(): Unit = {
        val jFrame = new JFrame("LR(1)词法分析");
        val jPanel = new JPanel();
        jFrame.setBounds( 0, 10,1000,90);

        val appendFileJButton2 = new JButton("开始分析");
        appendFileJButton2.setBounds( 100, 400,200,30);
        appendFileJButton2.addActionListener(new ActionListener {
            override def actionPerformed(e: ActionEvent): Unit = {
                GUI2
                jFrame.dispose()
            }
        })

        //添加文件按钮
        val appendFileJButton = new JButton("添加文件");
        appendFileJButton.setBounds( 300, 400,200,30);
        appendFileJButton.addActionListener(new ActionListener {
            override def actionPerformed(e: ActionEvent): Unit = {
                val fileChooser = new JFileChooser();
                fileChooser.showOpenDialog(jFrame);
                val filePath = fileChooser.getSelectedFile.getAbsolutePath
                initiate(filePath)
                utility
            }
        })

        val appendFileJButton3 = new JButton("退出程序")
        appendFileJButton3.setBounds(500, 400, 200, 30)
        appendFileJButton3.addActionListener(new ActionListener {
            override def actionPerformed(e: ActionEvent): Unit = {
                jFrame.dispose()
            }
        })

        jPanel.add(appendFileJButton)
        jPanel.add(appendFileJButton2)
        jPanel.add(appendFileJButton3)
        jPanel.setBackground(Color.gray)
        jFrame.add(jPanel)
        import java.awt.FlowLayout
        jPanel.setLayout(new FlowLayout(FlowLayout.LEADING, 200, 20))
        jFrame.setResizable(false);
        jFrame.setVisible(true);
    }

    /*
    * Function name: GUI2
    * Function description: 实现图形化界面展示,分析界面
    * Input parameters: 无
    * Return value: 无
    * Exception: 未处理
    * Author: 菊花侠
    * Created date: Sat Oct 19 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 28 2019 +0800
     */
    def GUI2(): Unit = {
        val jFrame = new JFrame("LR(1)词法分析");
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        jFrame.setResizable(false)
        jFrame.setBounds(0,0,1000,1000);
        jFrame.setLayout(null)

        //输入行
        val inputJPanel = new JPanel();
        inputJPanel.setBounds(0,0,1000,30);
        inputJPanel.setLayout(null);

        val inputJTextField = new JTextField();
        inputJTextField.setBounds(0,0,300,30);
        val inputJButton = new JButton("确认");
        inputJButton.setBounds(320,0,60,30);
        inputJPanel.add(inputJTextField)
        inputJPanel.add(inputJButton)
        jFrame.add(inputJPanel);


        val displayFileJTextPane = new JTextPane();
        displayFileJTextPane.setEditable(false);

        val displayFileJScrollPane = new JScrollPane();
        displayFileJScrollPane.setBounds(0,64,1000,300);
        displayFileJScrollPane.setViewportView(displayFileJTextPane);
        jFrame.add(displayFileJScrollPane)

        val appendFileJButton = new JButton("显示初始文法")
        appendFileJButton.setBounds(0, 32,120,30)
        appendFileJButton.addActionListener(new ActionListener {
            override def actionPerformed(e: ActionEvent): Unit = {
                displayFileJTextPane.setText(staticStringBuilder2.toString());
            }
        })

        val appendFileJButton2 = new JButton("返回")
        appendFileJButton2.setBounds(220, 32, 120, 30)
        appendFileJButton2.addActionListener(new ActionListener {
            override def actionPerformed(e: ActionEvent): Unit = {
                GUI1
                jFrame.dispose()
            }
        })

        val appendFileJButton3 = new JButton("退出")
        appendFileJButton3.setBounds(440, 32, 120, 30)
        appendFileJButton3.addActionListener(new ActionListener {
            override def actionPerformed(e: ActionEvent): Unit = {
                jFrame.dispose()
            }
        })

        jFrame.add(appendFileJButton)
        jFrame.add(appendFileJButton2)
        jFrame.add(appendFileJButton3)

        val dataMode1 = new AbstractTableModel() {

            override def getColumnCount = 5

            override

            def getRowCount = staticAnalyseList.length

            override

            def getValueAt(row: Int, col: Int): String = {
                val a = staticAnalyseList(row);
                if(col == 0){
                    return a.getStep();
                }
                if(col == 1){
                    return a.getAnalysisStack;
                }
                if(col == 2){
                    return a.getRemainingString;
                }
                if(col == 3){
                    return a.getProductionType;
                }
                if(col == 4){
                    return a.getAction;
                }
                return new String();
            }
        }

        val table1JScrollPane = new JScrollPane();
        val table1JTable = new JTable(dataMode1);



        table1JScrollPane.setBounds(0,370,690,300)
        table1JScrollPane.setViewportView(table1JTable);

        val table1JTextPaneScrollPan = new JScrollPane();
        table1JTextPaneScrollPan.setBounds(692,370,300,300);


        val table1JTextPane = new JTextPane();
        table1JTextPane.setEditable(false);
        table1JTextPaneScrollPan.setViewportView(table1JTextPane);
        jFrame.add(table1JTextPaneScrollPan);
        jFrame.add(table1JScrollPane);

        val table2JTable = new JTable();
        table2JTable.setBounds(0,682,1000,300);

        val table2JScrollPane = new JScrollPane();

        table2JScrollPane.setBounds(0,682,1000,300)
        table2JScrollPane.setViewportView(table2JTable);//ryr

        table2JScrollPane.add(table2JTable)
        jFrame.add(table2JTable);

        jFrame.setVisible(true);

        inputJButton.addActionListener(new ActionListener {
            override def actionPerformed(e: ActionEvent): Unit = {
                staticAnalyseList.clear();
                staticTestMatrix = createMatrix();
                analyse( inputJTextField.getText() + "#" );
                val dataMode1 = new AbstractTableModel() {

                    override def getColumnCount = 5

                    override

                    def getRowCount = staticAnalyseList.length

                    override

                    def getValueAt(row: Int, col: Int): String = {
                        val a = staticAnalyseList(row);
                        if(col == 0){
                            return a.getStep();
                        }
                        if(col == 1){
                            return a.getAnalysisStack;
                        }
                        if(col == 2){
                            return a.getRemainingString;
                        }
                        if(col == 3){
                            return a.getProductionType;
                        }
                        if(col == 4){
                            return a.getAction;
                        }
                        return new String();
                    }

                }
                table1JTable.setModel(dataMode1);

                val dataMode2 = new AbstractTableModel() {

                    override def getColumnCount = columnLength

                    override

                    def getRowCount = rowLength

                    override

                    def getValueAt(row: Int, col: Int) = staticTestMatrix(row)(col)
                }
                table2JTable.setModel(dataMode2);
                table1JTextPane.setText(staticStringBuilder.toString())
            }
        })
    }

    /*
    * Function name: utility
    * Function description: 辅助输出函数
    * Input parameters: 无
    * Return value: 无
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Mon Oct 28 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 28 2019 +0800
     */
    def utility(): Unit = {
        
        staticStringBuilder.append( "after expanding the language rules:" + "\r\n" )
        displayRelations()
        staticStringBuilder.append( "**************" + "\r\n" )
        staticStringBuilder.append( "FIRST:" + "\r\n" )
        val testFIRST = FIRST()
        for( ex <- testFIRST ) {
            staticStringBuilder.append( "FIRST(" + ex._1 + ") = {" + ex._2.mkString(",") + "}" + "\r\n" )
        }
        staticStringBuilder.append( "**************" + "\r\n" )
        //test getItemGroup
        var cnt4 = 0
        for( ex <- itemGroup.toList.sortBy(_._2) ) {
            staticStringBuilder.append( "I" + ex._2 + ":" + "\r\n" )
                for (tx <- ex._1 ) {
                    
                    staticStringBuilder.append( tx._1 + "->" + tx._2 + ", " + tx._3 + "\r\n" )
                }
            staticStringBuilder.append( "^^^^^^^^^^^^^^^^^^^^^^^^" + "\r\n" )
            cnt4 += 1
        }
        staticStringBuilder.append( "**************" + "\r\n" )
        val test_createMatrix = createMatrix
        staticTestMatrix = test_createMatrix
        for ( i <- 0 to test_createMatrix.length - 1 ) {
            for ( j <- 0 to test_createMatrix(i).length - 1 ) {
                print( test_createMatrix(i)(j) + " " )
            }
            
        }
    }

    /*
    * Function name: analyse
    * Function description: 对指定的字符串进行LR(1)分析
    * Input parameters: -String(输入的指定字符串)
    * Return value: -Boolean(分析成功则返回true,否则false)
    * Exception: 未处理(有出错提示)
    * Author: 来自高山
    * Created date: Mon Oct 28 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 28 2019 +0800
     */
    def analyse( expression: String ): Boolean = {
        val statusStack = new mutable.Stack[String]()
        val characterStack = new mutable.Stack[String]()
        val analyseTable = createMatrix()
        var expr = expression
        var flag = false
        var repeat = true
        statusStack.push("0")
        characterStack.push("#")
        var tot = 0
        staticAnalyseList.append(new Analyse("步骤","状态栈","符号栈","剩余字符串","动作"));
        staticAnalyseList.append( new Analyse( tot.toString, statusStack.reverse.mkString(","),
            characterStack.reverse.mkString(""), expr, "initiate") )
        tot += 1
        case class characterToColumn(a: String) {
            var ans = -1
            for( j <- 1 to (columnLength - 1) ) {
                if( analyseTable(0)(j) == a ) {
                    ans = j
                }
            }
            //ans
        }
        while ( repeat == true ) {
            //  s = statusTop
            val statusTop = statusStack.top
            val a = expr(0)

            val aColumn = characterToColumn(a.toString).ans
            var sRow = statusTop.toInt
            if(sRow == 0 ) sRow += 1 else sRow += 1

            if( analyseTable(sRow)(aColumn)(0) == 'S' ) {
                val newStatus = analyseTable(sRow)(aColumn).drop(1)
                statusStack.push(newStatus)
                characterStack.push(a.toString)
                expr = expr.drop(1)
                staticAnalyseList.append( new Analyse( tot.toString,statusStack.reverse.mkString(","),
                    characterStack.reverse.mkString(""), expr, "ACTION[" + statusTop + ", " + a + "]," + "状态 " + aColumn +
                            " 与符号 " + a + " 分别入栈") )
                tot += 1
            }
            else if( analyseTable(sRow)(aColumn)(0) == 'r' ) {
                val exprLineNO =  analyseTable(sRow)(aColumn).drop(1).toInt
                val currentRelation = relations(exprLineNO)

                var popLength = 0
                if( currentRelation._3 != "א" ) {
                    popLength = currentRelation._2.length + currentRelation._3.length
                }
                else {
                    popLength = currentRelation._2.length
                }
                var cnt = popLength
                val  tmpCharacter = characterStack.reverse.toString.replace("Stack(", "").replace(")",
                    "").replace(",", "").replace(" ", "")
                val reduceCharacter = tmpCharacter.drop(tmpCharacter.length - popLength)
                while ( cnt >= 1 ) {
                    statusStack.pop()
                    characterStack.pop()
                    cnt -= 1
                }
                // s' = characterTop
                val statusTop2 = statusStack.top.toInt

                var sRow2 = -1
                if( statusTop2 == 0 ) sRow2 = statusTop2 + 1 else sRow2 = statusTop2 + 1

                val A = currentRelation._1
                characterStack.push(A)
                val tmp = analyseTable(sRow2)( characterToColumn(A).ans )
                statusStack.push(tmp)

                staticAnalyseList.append( new Analyse( tot.toString, statusStack.reverse.mkString(","),
                    characterStack.reverse.mkString(""), expr, "GOTO[" + statusTop2 + ", " + A + "]" +
                            ",用产生式 " + A + "->" + reduceCharacter + " 进行规约") )
                tot += 1
            }
            else if( analyseTable(sRow)(aColumn) == "acc" ) {
                
                staticAnalyseList.append( new Analyse( tot.toString,statusStack.reverse.mkString(","),
                    characterStack.reverse.mkString(""), expr, "ACTION[" + statusTop + ", " + a + "] = " + "acc, succeeded") )
                flag = true
                repeat = false
            }
            else {
                staticAnalyseList.append( new Analyse( tot.toString,statusStack.reverse.mkString(","),
                    characterStack.reverse.toString(), expr, "ACTION[" + statusTop + ", " + a + "] = " +
                            "error in " + "analyseTable[" + sRow + ", " + aColumn + "]") )
                flag = true
                repeat = false
            }
        }
        if(flag) true else false
    }

    /*
    * Function name: createMatrix
    * Function description: 构造ACTION与GOTO分析表
    * Input parameters: 无
    * Return value: -Array[ Array[String] ](分析表矩阵元素构成的二维数组)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Mon Oct 28 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 28 2019 +0800
     */
    def createMatrix(): Array[ Array[String] ] = {
        val result = initiateMatrix()
        val localVT = VT
        val localVN = VN

        case class getColumn( ch: String ) {
            val matrix = initiateMatrix()
            var ans = -1
            for( j <- 0 to (columnLength - 1) ) {
                if( matrix(0)(j) == ch ) {
                    ans = j
                }
            }
        }

        for( ex <- itemGroup ) {
            for( tx <- ex._1 ) {
                val pointPosition = tx._2.indexOf("·")
                //· 不在最右边
                //若项目[A->α·aβ] ∈ Ik,且GO(Ik, a) = Ij,a为终结符,则置ACTION[k, a]为“sj”
                if (pointPosition < tx._2.length - 1) {
                    val a = tx._2( pointPosition + 1 )
                    if( localVT.contains(a) == true && findItemOrder(ex._1, a.toString) != -1 ) {
                        val j = findItemOrder(ex._1, a.toString)
                        var tmpRow = -1
                        tmpRow = ex._2 + 1
                        result(tmpRow)( getColumn(a.toString).ans ) = "S" + j.toString
                    }
                }
                if (pointPosition == tx._2.length - 1 ) {
                    val a = tx._3
                    var tmpRow = -1
                    tmpRow = ex._2 + 1
                    result(tmpRow)(getColumn(a).ans) = "r" + ( findRelationOrder( (tx._1,
                            tx._2.replace("·", "") ) ) )
                }
                if( tx._1 == relations(0)._1 && tx._2 == relations(0)._2 + "·" && tx._3 == "#" ) {
                    var tmpRow = -1
                    tmpRow = ex._2 + 1
                    result(tmpRow)( getColumn("#").ans ) = "acc"
                }
            }
            for( ch <- localVN ) {
                if( findItemOrder(ex._1, ch.toString) != -1 ) {
                    val gotoNumber = findItemOrder(ex._1, ch.toString)
                    var tmpRow = -1
                    tmpRow = ex._2 + 1
                    //A = ch
                    result(tmpRow)( getColumn(ch.toString).ans ) = gotoNumber.toString
                }
            }
        }
        result
    }

    /*
    * Function name: findRelationOrder
    * Function description: 获取产生式的位于文法的第几行,从0开始
    * Input parameters: -(String, String)(給定的产生式)
    * Return value: -Int(給定的产生式在給定文法中的行数)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Mon Oct 28 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 28 2019 +0800
     */
    def findRelationOrder( expression: (String, String) ): Int ={
        var ans = -1
        var cnt = 0
        val localRelations = relations
        for( ex <- localRelations ) {
            var expr = ""
            if( ex._3 != "א" ) {
                expr = ex._1 + ex._2 + ex._3
            }
            else {
                expr = ex._1 + ex._2
            }
            if( expr.equals(expression._1 + expression._2) ) {
                ans = cnt
            }
            cnt += 1
        }
        ans
    }

    /*
    * Function name: findItemOrder
    * Function description: 获取特定项目对于指定字符在项目集族中的编号,从0开始
    * Input parameters: -ArrayBuffer[ (String, String, String) ](給定项目), -String(給定字符)
    * Return value: -Int(給定的项目对于指定字符在项目集族中的编号)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Mon Oct 28 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 28 2019 +0800
     */
    def findItemOrder( item: ArrayBuffer[ (String, String, String) ], a: String ): Int = {
        var ans = -1
        val givenItem = go( item, a).sorted
        val localItemGroup = itemGroup
        for( ex <- localItemGroup ) {
            if( ex._1.sorted.equals(givenItem) ) {
                ans = ex._2
            }
        }
        ans
    }

    /*
    * Function name: initiateMatrix
    * Function description: 初始化分析表,即ACTION表与GOTO表
    * Input parameters: 无
    * Return value: -Array[ Array[ String] ](已完成初始的分析表)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sun Oct 27 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sun Oct 27 2019 +0800
     */
    def initiateMatrix(): Array[ Array[ String] ] = {
        val localVN = VN
        val localVT = VT
        val tableRowLength = rowLength
        val tableColumnLength = columnLength
        val result = Array.ofDim[String](tableRowLength, tableColumnLength)
        for( j <- 1 to localVT.length ) {
            result(0)(j) = localVT(j - 1).toString
        }
        for( j <- localVT.length + 1 to tableColumnLength - 1 ) {
            result(0)(j) = localVN(j - localVT.length - 1).toString
        }
        for( i <- 1 to ( tableRowLength - 1 ) ) {
            result(i)(0) = (i - 1).toString
        }
        for( i <- 0 to (tableRowLength - 1) ) {
            for( j <- 0 to (tableColumnLength - 1) ) {
                if( result.isEmpty != false ) {
                    result(i)(j) = null
                }
            }
        }

        result
    }

    /*
    * Function name: getItemGroup
    * Function description: 对于输入的文法,建立初始化的项目集
    * Input parameters: 无
    * Return value: -Unit
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Wed Oct 23 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sun Oct 27 2019 +0800
     */
    def getItemGroup(): Unit = {
        val ldx = ( relations(0)._1, "·" + relations(0)._2, "#" )
        val I0 = getClosure( ArrayBuffer(ldx) )
        val wholeCharacters = allCharacters
        var tot = 0
        itemGroup(I0) = tot
        var appendFlag = true
        while (appendFlag == true) {
            var originalAns = Map[ ArrayBuffer[ (String, String, String) ], Int ]()
            originalAns = itemGroup.clone()
            //为什么用I作为遍历变量不行?!
            for(item <- itemGroup.keys) {
                for (ch <- wholeCharacters) {
                    val newItem = go(item, ch.toString).sorted
                    if (newItem.isEmpty == false && itemGroup.contains(newItem) == false) {
                        tot += 1
                        itemGroup(newItem) = tot
                    }
                }
            }
            if( originalAns.equals(itemGroup) == true ) {
                appendFlag = false
            }
            else {
                originalAns.clear()
                originalAns = itemGroup.clone()
            }
        }
    }

    /*
    * Function name: go
    * Function description: 求給定项目对于特定字符的下一状态
    * Input parameters: -ArrayBuffer[ (String, String, String) ](給定项目), String(特定字符)
    * Return value: -ArrayBuffer[ (String, String, String) ](給定项目对于特定字符的下一状态)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sat Oct 26 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sat Oct 26 2019 +0800
     */
    def go( I: ArrayBuffer[ (String, String, String) ], X: String ): ArrayBuffer[ (String, String, String) ] = {
        //GO(I, X) = CLOSURE(J)
        //J = {任何形如[A->αX·β, a]的项目|[A->α·Xβ, a]∈I}
        val ans = new ArrayBuffer[ (String, String, String) ]()
        val items = new ArrayBuffer[ (String, String, String) ]()

        for( ex <- I ) {
            val pointPosition = ex._2.indexOf("·")
            //· 不在最右边
            if (pointPosition < ex._2.length - 1) {
                val A = ex._1
                val possibleX = ex._2( pointPosition + 1)
                //  αXβ
                val noPointExpressionPart2 = ex._2.replace("·", "")
                if( X == possibleX.toString ) {
                    //  αX·β
                    val newPart2 = noPointExpressionPart2.substring(0, pointPosition + 1) + "·" +
                            noPointExpressionPart2.substring(pointPosition + 1, noPointExpressionPart2.length)
                    val a = ex._3
                    items += ( (A, newPart2, a) )
                }
            }
        }
        ans.appendAll( getClosure(items) )
        ans
    }

    /*
    * Function name: getClosure
    * Function description: 求給定项目集的闭包
    * Input parameters: -ArrayBuffer[ (String, String, String) ](給定的项目集)
    * Return value: -ArrayBuffer[ (String, String, String) ](給定项目集的闭包)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sat Oct 26 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sun Oct 27 2019 +0800
     */
    def getClosure( items: ArrayBuffer[ (String, String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
        val result = new ArrayBuffer[ (String, String, String) ]()
        result.appendAll(items)
        val localFIRST = FIRST()
        var addFlag = true
        var cnt = 1
        while (addFlag == true ) {
            val originalResult = new ArrayBuffer[(String, String, String)]()
            originalResult.appendAll(result)
            for (ex <- result) {

                val pointPosition = ex._2.indexOf("·")
                //· 不在最右边
                if (pointPosition < ex._2.length - 1) {
                    //B在 · 的右边
                    val B = ex._2(pointPosition + 1)
                    val a = ex._3

                    // case 1: β != Φ and a != # or
                    // case 2: β != Φ and a = #
                    if (pointPosition < ex._2.length - 2) {
                        val β = ex._2(pointPosition + 2)
                        //  ξ
                        val rightExpressionsOfB = getRightExpressions(B.toString)
                        val FIRST_Of_βa = localFIRST(β.toString)
                        for (b <- FIRST_Of_βa) {
                            for (ksi <- rightExpressionsOfB) {
                                val tmp = ((B.toString, "·" + ksi, b.toString))

                                if (result.contains(tmp) == false) {
                                    result += tmp
                                }
                            }
                        }
                    }
                    // case 3: β = Φ and a equals any character
                    if (pointPosition == ex._2.length - 2) {
                        val rightExpressionsOfB = getRightExpressions(B.toString)
                        val FIRST_Of_βa = localFIRST(a.toString)
                        for (b <- FIRST_Of_βa) {
                            for (ksi <- rightExpressionsOfB) {
                                val tmp = ((B.toString, "·" + ksi, b.toString))
                                if (result.contains(tmp) == false) {
                                    result += tmp
                                }
                            }
                        }
                    }
                }
            }
            if (result != originalResult) {
                originalResult.remove(0, originalResult.length)
                originalResult.appendAll(result)
                cnt += 1
            }
            else {
                addFlag = false
                cnt += 1
            }
        }
        result
    }

    /*
    * Function name: getRightExpressions
    * Function description: 获取給定非终结符所在产生式的右部,可能不止一个,因此返回值是String类型的ArrayBuffer数组
    * Input parameters: -String(給定的非终结符)
    * Return value: -ArrayBuffer[String](給定非终结符所在产生式的右部)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Fri Oct 25 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 25 2019 +0800
     */
    def getRightExpressions(ch: String): ArrayBuffer[String] = {
        val result = new ArrayBuffer[String]()
        val localRelations = relations
        for( ex <- localRelations ) {
            if( ex._1 == ch ) {
                if( ex._3 != "א" ) {
                    result += ex._2
                    result += ex._3
                }
                else {
                    result += ex._2
                }
            }
        }
        result
    }

    /*
    * Function name: displayStack
    * Function description: 输出栈的所有元素
    * Input parameters: -mutable.Stack[String](待处理的String类型的栈)
    * Return value: -String(栈所有元素组成的字符串)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Mon Oct 21 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 21 2019 +0800
     */
    def displayStack( stack: mutable.Stack[String] ): String = {
        var result = ""
        for( ex <- stack ) {
            result += ex
        }
        result
    }

    /*
    * Function name: initiate
    * Function description: 初始化全局变量
    * Input parameters: the absolute path of the language-rule source file
    * Return value: 无
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sat Oct 19 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sun Oct 27 2019 +0800
     */
    def initiate( filePath: String ): Unit = {
        LL1_G = parseFile(filePath)
        allCharacters = getWholeCharacters(LL1_G)
        usedCharacters = allCharacters
        relations = getRelation(LL1_G)
        VN = getVN(allCharacters)
        VT = getVT(allCharacters)
        val leftCharacters = subString(allCandidateLetters, VN)
        relations.insert(0, ( leftCharacters(0).toString, (relations(0)._1), "א" ) )
        VN += leftCharacters(0).toString
        usedCharacters += leftCharacters(0).toString
        allCharacters += leftCharacters(0).toString

        allCharacters += "#"
        usedCharacters += "#"
        VT += "#"
        getItemGroup
        columnLength = VN.length + VT.length + 1
        rowLength = itemGroup.size + 1
    }

    /*
    * Function name: subString
    * Function description: 获取两输入字符串的差集(要求两者均非空)
    * Input parameters: 无
    * Return value: -String(两输入字符串的差集)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sat Oct 19 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sat Oct 19 2019 +0800
     */
    def subString( usedCharacters: String, localCandidateLetters: String ): String = {
        require( usedCharacters.length != 0 && localCandidateLetters.length != 0 )
        var ans = ""
        var A = usedCharacters
        var B = localCandidateLetters
        if( A.length < B.length ) {
            val tmp = A
            A = B
            B = tmp
        }
        for( i <- 0 to (A.length - 1) ) {
            var j = 0
            while( j < B.length && B(j) != A(i) ) {
                j += 1
            }
            if( j == B.length ) {
                ans += A(i)
            }
        }
        ans
    }

    /*
    * Function name: displayRelations
    * Function description: display all he language rules
    * Input parameters: 无
    * Return value: 无
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sat Oct 19 2019 +0800
    * Editor: 来自高山
    * Edited Date: Mon Oct 28 2019 +0800
     */
    def displayRelations(): Unit = {
        for( ex <- relations ) {
            if( ex._3 != "א" ) {
                
                staticStringBuilder.append( ex._1 + "->" + ex._2 + "|" + ex._3 + "\r\n")
                if( ex != relations(0) ) {
                    staticStringBuilder2.append(ex._1 + "->" + ex._2 + "|" + ex._3 + "\r\n")
                }
            }
            else {
                
                staticStringBuilder.append( ex._1 + "->" + ex._2 + "\r\n")
                if( ex != relations(0) ) {
                    staticStringBuilder2.append(ex._1 + "->" + ex._2 + "\r\n")
                }
            }
        }
    }

    /*
    * Function name: parseFile
    * Function description: 解析文本文件,保存在数组中
    * Input parameters: 文本绝对路径
    * Return value: -ArrayBuffer[ ( String, String ) ](String类型的元组ArrayBuffer数组)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Fri Oct 18 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 18 2019 +0800
     */
    def parseFile( filePath: String ): ArrayBuffer[ ( String, String ) ] = {
        val result = new ArrayBuffer[ ( String, String ) ]( countLines( readFromTxtByLine(filePath) ) )
        val sourceFile = readFromTxtByLine(filePath) //filePath
        for( line <- sourceFile ) {
            val tmp = line.split( "->", 2 )
            result += ( ( tmp.head, tmp.last ) )
        }
        result
    }

    /*
    * Function name: countLines
    * Function description: 计算文本行数,用于创建接收数组时开辟相应空间
    * Input parameters: -Array[String](文本文件数据构成的数组)
    * Return value: -Int(文本行数)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Fri Oct 18 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sat Oct 19 2019 +0800
     */
    def countLines( sourceFile: Array[String] ): Int = {
        var cnt = 0
        for( line <- sourceFile ) {
            cnt += 1
        }
        cnt
    }

    /*
    * Function name: readFromTxtByLine
    * Function description: 读取文本文件
    * Input parameters: -String(文本文件绝对路径)
    * Return value: -Array[String](文本文件构成的数组,每行数据占一个数组元素)
    * Exception: -未处理
    * Author: 来自高山
    * Created date: Fri Oct 18 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 18 2019 +0800
     */
    def readFromTxtByLine(filePath: String): Array[String] = {
        import scala.io.Source
        val source = Source.fromFile(filePath, "UTF-8")
        //val lineIterator = source.getLines()
        //lineIterator.foreach()
        val lines = source.getLines().toArray
        source.close()
        //
        lines
    }

    /*
    * Function name: getWholeCharacters
    * Function description: 获取文法的除“|”之外的所有字符
    * Input parameters: -ArrayBuffer[ (String, String) ](由文法左右两部分字符构成一个元组的数组,筛掉“|”)
    * Return value: -String(文法的除“|”之外的所有字符)
    * Exception: 未处理(有出错提示)
    * Author: 来自高山
    * Created date: Fri Oct 11 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 11 2019 +0800
     */
    def getWholeCharacters( string: ArrayBuffer[ (String, String) ] ): String = {
        var wholeCharacters = ""
        for( expression <- string ) {
            wholeCharacters += expression._1 + expression._2
        }
        val pattern = new Regex("\\|")
        val result = pattern replaceAllIn( wholeCharacters, "" )
        if( result.isEmpty )
            "function getWholeCharacters failed"
        else
            result.distinct
    }
    /*
    * Function name: getVN
    * Function description: 获取文法的所有非终结符(non-terminal character),默认大写字母为非终结符,使用正则表达式匹配
    * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
    * Return value: -String(文法的所有非终结符)
    * Exception: 未处理(有出错提示)
    * Author: 来自高山
    * Created date: Fri Oct 11 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 11 2019 +0800
     */
    def getVN( string: String ): String = {
        //match big letter:
        //^[A-Z]+$
        val pattern = new Regex("[A-Z]")//("^[A-Z]+$")
        if( (pattern findAllIn string) != null )
            (pattern findAllIn string).mkString("")
        else
            "function getVN failed"
    }

    /*
    * Function name: getVT
    * Function description: 获取文法的所有非终结符(terminal character),默认大写字母外的字符为终结符,使用正则表达式匹配
    * Input parameters: -String(函数getWholeCharacters传来的文法的所有字符)
    * Return value: -String(文法的所有终结符)
    * Exception: 未处理(有出错提示)
    * Author: 来自高山
    * Created date: Fri Oct 11 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 11 2019 +0800
     */
    def getVT( string: String ): String = {
        val pattern1 = new Regex("[A-Z]")
        val pattern2 = new Regex("\\|")
        val firstFilter = pattern1 replaceAllIn( string, "" )
        val result = pattern2 replaceAllIn( firstFilter, "" )
        if( result.isEmpty == false )
            result
        else
            return "function getVT failed"
    }
    /*
    * Function name: getRelation
    * Function description: 获取文法每一行对应的推导关系,若文法只推出了1项(即没有符号“|”),则返回元组的第三个用希伯来字母“א”示空
    * Input parameters: -ArrayBuffer[ (String, String)(已经分割好的文法左右部分构成的数组)
    * Return value: -ArrayBuffer[ (String, String, String) ](元组第一个元素为推导式左边符号,第二为右边第二个符号串,第三为右边(若有)第三个符号串)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Fri Oct 11 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 11 2019 +0800
     */
    def getRelation( string: ArrayBuffer[ (String, String) ] ): ArrayBuffer[ (String, String, String) ] = {
        val relation = new ArrayBuffer[ (String, String, String) ]()
        for( expression <- string ) {
            if( expression._2.contains("|") == false ) {
                relation += ( ( expression._1, expression._2, "א" ) )
            }
            else {
                val tmp = expression._2.split("\\|", 2 )
                relation += ( ( expression._1, tmp.head, tmp.last ) )
            }
        }
        relation
    }

    /*
    * Function name: findFirst
    * Function description: 获取指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串
    * Input parameters: -String(指定字符)
    * Return value: -String(指定字符的右边两个(可能是一个)导出字符串的首个非 ε 组成的字符串)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Fri Oct 11 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 11 2019 +0800
     */
    def findFirst( ch: String ): String = {

        val localRelations = relations
        var result = ""
        for( ex <- localRelations ) {
            if( ch == ex._1 ) {
                if( ex._3 != "א" ) {
                    if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
                        result += ex._2(0).toString
                    }
                    if( VT.contains( ex._3(0) ) && ex._3(0) != 'ε' ) {
                        result += ex._3(0).toString
                    }
                }
                else {
                    if( VT.contains( ex._2(0) ) && ex._2(0) != 'ε' ) {
                        result += ex._2(0).toString
                    }
                }
            }
        }
        result
    }

    /*
    * Function name: judgeOnlyOneVoidSuccession
    * Function description: 判断指定字符是否可推出唯一的字符ε
    * Input parameters: -String(指定字符串)
    * Return value: -Boolean(存在则true,否则false)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Fri Oct 11 2019 +0800
    * Editor: 来自高山
    * Edited Date: Fri Oct 11 2019 +0800
     */
    def judgeOnlyOneVoidSuccession( ch: String ): Boolean = {
        val localRelations = relations
        var result = 1
        for( ex <- localRelations ) {
            if( ch == ex._1 ) {
                if( ex._3 != "א" ) {
                    if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) || (ex._3.length == 1 && ex._3(0) == 'ε') ) {
                        result = 1
                    }
                    else {
                        result = 0
                    }
                }
                else {
                    if( ( ex._2.length == 1 && ex._2(0) == 'ε' ) ) {
                        result = 1
                    }
                    else {
                        result = 0
                    }
                }
            }
        }
        if( result == 1 ) true else false
    }

    /*
    * Function name: judgeCaseXY
    * Function description: 判断构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)
    * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
    * Return value: -Boolean(满足则true,否则false)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sat Oct 12 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sat Oct 12 2019 +0800
     */
    def judgeCaseXY( ch: Char ): Boolean = {
        val localVN = VN
        val localRelations = relations
        var result = 0
        if( localVN.contains(ch) == true ) {
            for( ex <- localRelations ) {
                if( ex._1(0) == ch ) {
                    if( localVN.contains( ex._2(0) ) || localVN.contains( ex._3(0) ) ) {
                        result += 1
                    }
                }
            }
        }
        if( result > 0 )
            true
        else
            false
    }

    /*
    * Function name: findCase_Y_In_XY
    * Function description: 获取构造FIRST集时可能的第3种情况的(1),即若X->Y...是一个产生式且Y∈VN(省略若干描述)时的Y
    * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
    * Return value: -String(Y构成的String字符串,无则为空)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sat Oct 12 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sat Oct 12 2019 +0800
     */
    def findCase_Y_In_XY( ch: Char ): String = {
        val localVN = VN
        val localRelations = relations
        var result = ""
        if( localVN.contains(ch) == true ) {
            for( ex <- localRelations ) {
                if( ex._1(0) == ch ) {
                    if( ex._3 != "א" ) {
                        if( localVN.contains( ex._2(0) ) == true ) {
                            result += ex._2(0).toString
                        }
                        if( localVN.contains( ex._3(0) ) == true ) {
                            result += ex._3(0).toString
                        }
                    }
                    else {
                        if( localVN.contains( ex._2(0) ) == true ) {
                            result += ex._2(0).toString
                        }
                    }
                }
            }
        }
        result
    }

    /*
    * Function name: findCase_Y_In_nY
    * Function description: 获取构造FIRST集时可能的第3种情况的(2)时的FIRST(Yi)中所有的非ε-元素(省略描述若干字)
    * Input parameters: -Char(指定字符,即可能满足条件的产生式的左边字符)
    * Return value: -String(FIRST(Yi)中所有的非ε-元素构成的String字符串,无则为空)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Sat Oct 12 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sat Oct 12 2019 +0800
     */
    def findCase_Y_In_nY( ch: Char ): String = {
        val localVN = VN
        val localRelations = relations
        var result = ""
        for( ex <- localRelations ) {
            if (ex._1 == ch.toString) {
                var tmp = ""

                if (ex._3 != 'א') {
                    var cnt = 0
                    for (tx <- ex._2) {
                        // add the element belongs to tmp
                        if (localVN.contains(tx)) {
                            tmp += tx.toString
                            cnt += 1
                        }
                        // otherwise, reset tmp as empty string
                        else {
                            tmp = ""
                        }
                    }
                    if (cnt == ex._2.length) {
                        result += tmp
                    }

                    // reset
                    cnt = 0
                    tmp = ""
                    for (tx <- ex._3) {
                        // add the element belongs to tmp
                        if (localVN.contains(tx)) {
                            tmp += tx.toString
                            cnt += 1
                        }
                        // otherwise, reset result as empty string
                        else {
                            tmp = ""
                        }
                    }
                    if (cnt == ex._3.length) {
                        result += tmp
                    }
                }
                else {
                    tmp = ""
                    var cnt = 0
                    for (tx <- ex._2) {
                        // add the element belongs to tmp
                        if (localVN.contains(tx)) {
                            tmp += tx.toString
                            cnt += 1
                        }
                        // otherwise, reset tmp as empty string
                        else {
                            tmp = ""
                        }
                    }
                    if (cnt == ex._2.length) {
                        result += tmp
                    }
                }
            }
        }
        result = result.distinct
        result
    }

    /*
    * Function name: FIRST
    * Function description: 按照教材P78左下角的算法描述实现求解指定文法FIRST集;因用的是循环迭代求解,因此代码较长
    * Input parameters: -ArrayBuffer[ (String, String) ](产生式左右两部分分别构成元组的第1个和第2个元素)
    * Return value: -Map[ String, String ](Map的key是非终结符,value是其FIRST元素)
    * Exception: 未处理
    * Author: 来自高山
    * Created date: Mon Oct 14 2019 +0800
    * Editor: 来自高山
    * Edited Date: Sat Oct 19 2019 +0800
     */
    def FIRST(): Map[ String, String ] = {
        val FIRST_Group = Map[ String, String ]()
        val wholeCharacters = allCharacters
        val localVT = VT
        val localVN = VN

        for( character <- wholeCharacters ) {
            // case 1
            if( localVT.contains(character) ) {
                //if there exist the original key that equals the current one
                if( FIRST_Group.contains(character.toString) == true ) {
                    val tmp = character.toString + FIRST_Group(character.toString)
                    FIRST_Group(character.toString) = tmp.distinct
                }
                //otherwise
                else {
                    FIRST_Group(character.toString) = character.toString
                }
            }

            // case 2
            if( localVN.contains(character.toString) == true ) {
                // case 2.1
                val value = findFirst(character.toString)
                if ( value.length != 0 ) {
                    if ( FIRST_Group.contains(character.toString) == true ) {
                        for( ch <- value ) {
                            val tmp = ch + FIRST_Group(character.toString)
                            FIRST_Group(character.toString) = tmp.distinct
                        }
                    }
                    else {
                        FIRST_Group(character.toString) = value.toString
                    }
                }

                // case 2.2
                if( judgeOnlyOneVoidSuccession(character.toString) == true ) {
                    if ( FIRST_Group.contains(character.toString) == true ) {
                        val tmp = "ε" + FIRST_Group(character.toString)
                        FIRST_Group(character.toString) = tmp.distinct
                    }
                    else {
                        FIRST_Group(character.toString) = "ε"
                    }
                }
            }

            for( character <- wholeCharacters ) {
                // case 3
                // case 3.1
                if( judgeCaseXY(character) == true ) {
                    val tmpReply = findCase_Y_In_XY(character)
                    for( eachTmpReply <- tmpReply ) {
                        if( FIRST_Group.contains(eachTmpReply.toString) == true ) {
                            for (ex <- FIRST_Group(eachTmpReply.toString)) {
                                if (ex != 'ε') {
                                    if (FIRST_Group.contains(character.toString) == true) {
                                        val tmp = ex.toString + FIRST_Group(character.toString)
                                        FIRST_Group(character.toString) = tmp.distinct
                                    }
                                    else {
                                        FIRST_Group(character.toString) = ex.toString
                                    }
                                }
                            }
                        }
                    }
                }

                // case 3.2
                if( findCase_Y_In_nY(character).length > 0 ) {
                    var flag = true
                    val tmpReply = findCase_Y_In_nY(character)

                    for( ex <- tmpReply ) {
                        if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true )  {
                            if( FIRST_Group(ex.toString).contains("ε") == false ) {
                                flag = false
                            }
                        }
                        else {
                            flag = false
                        }
                        if( flag == true ) {
                            if (FIRST_Group.contains(character.toString) == true) {
                                val tmp = FIRST_Group(ex.toString).replace( "ε", "" ) + FIRST_Group(character.toString)
                                FIRST_Group(character.toString) = tmp.distinct
                            }
                            else {
                                FIRST_Group(character.toString) = FIRST_Group(ex.toString).replace( "ε", "" )
                            }

                        }
                    }
                }
                // case 3.3
                if( findCase_Y_In_nY(character).length > 0 ) {
                    var flag = true
                    val tmpReply = findCase_Y_In_nY(character)
                    for( ex <- tmpReply ) {
                        if( localVN.contains(ex.toString) && FIRST_Group.contains(ex.toString) == true )  {
                            if( FIRST_Group(ex.toString).contains("ε") == false ) {
                                flag = false
                            }
                        }
                        else {
                            flag = false
                        }
                        if( flag == true ) {

                            if (FIRST_Group.contains(character.toString) == true) {
                                val tmp = "ε" + FIRST_Group(character.toString)
                                FIRST_Group(character.toString) = tmp.distinct
                            }
                            else {
                                FIRST_Group(character.toString) = "ε"
                            }
                        }
                    }
                }
            }
        }
        FIRST_Group
    }

}

        FileUtil类(Java):

import java.io.*;
import java.util.Vector;

/**
 * 文件工具类
 */
public class FileUtil {
    public static void main(String[] args) throws FileNotFoundException {
        String s = readFile( new FileInputStream("/home/hadoop001/Desktop/test.data") );
        System.out.println(s);
    }
    /**
     * 读取文件内容
     *
     * @param is
     * @return
     */
    public static String readFile(InputStream is) {
        BufferedReader br = null;
        StringBuffer sb = new StringBuffer();
        try {
            br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String readLine = null;
            while ((readLine = br.readLine()) != null) {
                sb.append(readLine+"\r\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}

         Analyse类(Java):

package pojo;

public class Analyse {
    private String step;
    private String analysisStack;
    private String remainingString;
    private String productionType;
    private String action;

    public Analyse(){

    }

    public Analyse(String step, String analysisStack, String remainingString, String productionType, String action) {
        this.step = step;
        this.analysisStack = analysisStack;
        this.remainingString = remainingString;
        this.productionType = productionType;
        this.action = action;
    }

    public String getStep() {
        return step;
    }

    public void setStep(String step) {
        this.step = step;
    }

    public String getAnalysisStack() {
        return analysisStack;
    }

    public void setAnalysisStack(String analysisStack) {
        this.analysisStack = analysisStack;
    }

    public String getRemainingString() {
        return remainingString;
    }

    public void setRemainingString(String remainingString) {
        this.remainingString = remainingString;
    }

    public String getProductionType() {
        return productionType;
    }

    public void setProductionType(String productionType) {
        this.productionType = productionType;
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }
}

        运行截图:

图 1 开始界面
图 2 选择文件
图 3 分析界面
图 4 显示初始文法
图 5 分析完成(输入表达死为“i+i*i”)
图 6 分析完成(输入表达死为“i+i*i”,手动把单元格拉长些)

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

发布了143 篇原创文章 · 获赞 31 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/u25th_engineer/article/details/102789976
今日推荐