Table of Contents
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