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