语法分析(LL1java代码实现)

mac2024-05-31  28

实验三、  语法分析程序的设计

【实验目的与要求】

语法分析是编译过程的核心部分,常用的语法分析方法有:LL(1)分析法、递归子程序分析法、算符优先分析法、LR(0)分析法、SLR(1)分析法等。语法分析的主要任务是根据程序语言的语法规则,对词法分析产生的单词序列进行语法检查。

通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。要求:选择具有代表性的语法分析方法,如:LL(K)分析法、递归子程序法、运算符优先数法、LR(K)分析法等方法之一进行设计;选择对各种常见程序语言都通用的语法结构,如赋值语句(尤指算术表达式)作为分析对象,并与所选语法分析方法要比较贴切。

【实验设备和环境】

本实验使用C、C++或Java等语言编写程序。

【实验内容】

编写算术表达式的语法分析程序,进行调试,调试例子应包括符合语法规则的算术表达式,以及分析程序能够判别的若干错例。

首先先给出〈表达式〉的文法

     〈表达式〉::=〈项〉│〈表达式〉+〈项〉│〈表达式〉-〈项〉

      〈项〉::=〈因子〉│〈项〉*〈因子〉│〈项〉/〈因子〉

     〈因子〉::= 〈初等量〉│〈因子〉↑〈初等量〉

〈初等量〉::= (〈表达式〉)│i

或表示为:G[E]

表达式  E→E+T | E-T | T

项      T→T*F | T/F | F

因子    F→F↑P | P

初等量  P→(E) | i

消除左递归:  

              E→T { ( + | - ) T }

              T→F { ( *  | / ) F }

              F→P {↑P }

              P→(E) | i

下面给出LL(1)分析法、递归子程序分析法、算符优先分析法、LR(0)分析法、SLR(1)分析法中用到的内容。

LL(1)语法分析方法

 LL(1)是一种自顶向下的语法分析方法,又称为预测分析法。

 

           图3-1   LL(1)分析器的逻辑结构

构造LL(1)分析表的算法如下:

1)对于A::=Dβ(D∈VN)且select(A::=Dβ)={b1,b2…bn}

       则M[A,bi]=RE(Dβ)/R

       表示:用Dβ的逆替换A,重读当前字符.

2)对于A::=aβ(a∈VT)

       则M[A,a]= RE(β)/C

       表示:用β的逆替换A,继续读入下一字符.

3)对于A::=ε且select(A::=ε)={b1,b2…bn}

       则M[A,bi]=RE(ε)/R=ε/R

4)对所有没出现在规则右部的首部的终结符a,

       令M[a,a]=RE(ε)/C=ε/C

5)对于#,令M[#,#]=succ,表示分析成功,结束.

6)其他情况属于出错,在分析表中用空白表示.

【实验总结】 对实验结果进行分析,讨论如何解决语法分析过程中遇到的问题及解决办法,总结本次实验的收获及感想。

实验说明:学生应在实验课前仔细阅读实验相关内容,明确实验的目的和要求,然后了解词法分析和语法分析的基本方法,利用一种高级语言(如C语言、C++语言、PASCAL语言等),编写无符号数的词法分析程序、逆波兰式生成程序、语法分析程序(其中实验一必做,实验二和三选做一个)。调试程序后,打印程序代码及实验结果,写出实验报告。

 


这个我写的是LL1 分析法的,表达式。

我先给弄成消除左递归的,消除左递归算法,无敌。

然后这就可以搞出来一个LL1分析表

用这个表,完了就是打代码了。

先看代码效果

如对代码有疑问,下面有详细的解释

package com.cbt.compiler; import java.util.Scanner; import java.util.Stack; class AnalysisTable { public String[][] table = { // 0 1 2 3 4 5 6 7 8 // i * / + - ( ) @ # /* 0 */ { "eT", "", "", "", "", "eT", "", "", "" }, // E /* 1 */ { "", "", "", "eT", "eT", "", ".", "", "." }, // e /* 2 */ { "tF", "", "", "eT", "eT", "tF", "", "", "" }, // T /* 3 */ { "", "tF", "tF", ".", ".", "", ".", "", "." }, // t /* 4 */ { "fP", "", "", "", "", "fP", "", "", "" }, // F /* 5 */ { "", ".", ".", ".", ".", "", ".", "fP", "." }, // f /* 6 */ { ".", "", "", "eT", "eT", ")E", "", "", "" }, // P /* 7 */ { "", "", "", "", "", "", ".", "", "" }, // ) /* 8 */ { "", "", "", "", "", "", "", "", "succ" } }; public int[][] flag = new int[9][9]; AnalysisTable() { flag[1][3] = 1; flag[1][4] = 1; flag[3][1] = 1; flag[3][2] = 1; flag[5][7] = 1; flag[6][0] = 1; flag[6][5] = 1; flag[7][6] = 1; } } public class Comprehensive { public static void main(String[] args) { boolean hasPrinted = false; Stack<Character> stack = new Stack<Character>(); // String[] strArr = {"i*i+i*i+i/(i)","i*i", "i+*i", "i+i*i", "i*i*i", "i*i+(i+i)", "iii", "i+(", "i+(i*i)", "iiiii", "s","i/i/i" }; // for (String s : strArr) { Scanner sc = new Scanner(System.in); String s = sc.nextLine(); hasPrinted = false; s = s + "#"; String[] str = new String[20]; for (int i = 0, k = 0; i < s.length(); i++) { if (s.charAt(i) != ' ') { str[k++] = "" + s.charAt(i); } } stack.clear(); stack.add('#'); stack.add('E'); AnalysisTable table = new AnalysisTable(); // 挨个去读它 System.out.print("分析栈\t\t\t\t"+"余留输入串\t\t\t\t"+"动作\n"); for (int i = 0; i <= getLen(str); i++) { String temp = str[i]; int row = analyNoneCharacter(stack.peek()); int column = AnalysisTCharacter(temp); if (row == -1 || column == -1) { System.out.println(s + "No"); hasPrinted = true; break; } // 不是空,表示可以继续读取 String value = table.table[row][column]; //输出分析栈 for(Character s1:stack) { System.out.print(s1); } System.out.print("\t\t\t\t"); //输出余留输入串 for(int j = i;j<=getLen(str);j++) { System.out.print(str[j]); } System.out.print("\t\t\t\t"); if (value.equals("succ")) { hasPrinted = true; System.out.println(s + "Yes"); break; } // value 表示表里的是空的出错 if (!value.equals("")) { int flag = table.flag[row][column]; // 如果是C if (flag == 1) { System.out.print(value+"/C\n"); stack.pop(); // 如果不是空串替换 if (!value.equals(".")) { for (int j = 0; j < value.length(); j++) { stack.add(value.charAt(j)); } } if (getLen(str) == i) { i--; } } else { // 如果是R System.out.print(value+"/R\n"); stack.pop(); // 如果不是空串替换 if (!value.equals(".")) { for (int j = 0; j < value.length(); j++) { stack.add(value.charAt(j)); } } i--; } } else { if (!hasPrinted) { System.out.println(s + "No"); hasPrinted = true; break; } } } // for if (!hasPrinted) { System.out.println("No"); } // } // String s :strArr } public static int analyNoneCharacter(char ch) { char c = ch; int flag = -1; switch (c) { case 'E': flag = 0; break; case 'e': flag = 1; break; case 'T': flag = 2; break; case 't': flag = 3; break; case 'F': flag = 4; break; case 'f': flag = 5; break; case 'P': flag = 6; break; case ')': flag = 7; break; case '#': flag = 8; } return flag; } public static int AnalysisTCharacter(String s) { char ch = s.charAt(0); switch (ch) { case 'i': return 0; case '*': return 1; case '/': return 2; case '+': return 3; case '-': return 4; case '(': return 5; case ')': return 6; case '@': return 7; case '#': return 8; } return -1; } public static int getLen(String[] str) { if (str == null) return 0; for (int i = 0; i < str.length; i++) { if (str[i] == null) { return i - 1; } } return 0; } }

思路是:

table用来存放LL1分析表。

用.表示空串

flag数组 表示C或者R

输入字符串s,先在s后面添加一个#号

用栈stack来存放分析栈,先在栈底放一个#,然后添加E.

从开始一直往后对这个s进行遍历,如果碰到r就重读当前的,直到#碰到#value = succ;

emmmmm,描述的好像不是很准确.

欢迎讨论交流,后来看这段代码有点冗余,但是懒得改了,其实不用这么麻烦.对字符串的操作不熟练导致.

QQ:1410497065

欢迎交流

最新回复(0)