编译原理 语法分析器 (java完美运行版)(精选.)
编译原理语法分析器(java完美运行版)
编译原理语法分析器(java完美运行版)第一篇:编译原理语法分析器 (java完美运行版)实验二语法分析器一、实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。
使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。
有利于提高学生的专业素质,为培养适应社会多方面需要的能力。
二、实验内容υ根据某一文法编制调试 LL(1)分析程序,以便对任意输入的符号串进行分析。
υ构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。
υ分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。
三、LL(1)分析法实验设计思想及算法υ模块结构:(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
四、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
2、如果遇到错误的表达式,应输出错误提示信息。
3、对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i 输出的格式如下:五、实验源程序LL1.java import java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.table.DefaultTableModel;import java.sql.*;import java.util.Vector;public class LL1 extends JFrame implements ActionListener { /****/private static final long serialVersionUID = 1L;JTextField tf1;JTextField tf2;JLabel l;JButton b0;JPanel p1,p2,p3;JTextArea t1,t2,t3;JButton b1,b2,b3;JLabel l0,l1,l2,l3,l4;JTable table;Statement sta;Connection conn;ResultSet rs;DefaultTableModel dtm;String Vn[]=null;Vector P=null;int firstComplete[]=null;//存储已判断过first的数据char first[][]=null;//存储最后first结果int followComplete[]=null;//存储已判断过follow的数据char follow[][]=null;//存储最后follow结果char select[][]=null;//存储最后select结果int LL=0;//标记是否为LL(1)String vt_tou[]=null;//储存VtObject shuju[][]=null;//存储表达式数据char yn_null[]=null;//存储能否推出空LL1(){ setLocation(100,0);setSize(700,780);tf1=new JTextField(13);tf2=new JTextField(13);l=new JLabel(“>>”);l0=new JLabel(“输入字符串:”);l1=new JLabel(“输入的文法”);l2=new JLabel(“ ”);l3=new JLabel(“分析的结”);l4=new JLabel(“预测分析”);//p1=new JPanel();p2=new JPanel();p3=new JPanel();t1=new JTextArea(24,20);t2=new JTextArea(1,30);t3=new JTextArea(24,40);b0=new JButton(“确定(S为开始)”);b1=new JButton(“ 判断文法”);为:果:表:b2=new JButton(“输入”);b3=new JButton(“清空”);table=new JTable();JScrollPane jp1=new JScrollPane(t1);JScrollPane jp2=new JScrollPane(t2);JScrollPane jp3=new JScrollPane(t3);p2.add(tf1);p2.add(l);p2.add(tf2);p2.add(b0);p2.add(b1);p2.add(l0);p2.add(l2);p2.add(jp2);p2. add(b2);p2.add(b3);p2.add(l1);p2.add(l3);p2.add(jp1);p2.add(jp3);p3.add(l4);p3.add(newJScrollPane(table));add(p2,“Center”);add(p3,“South”);b0.addActionListener(this);b1.addActionListener(this);b2.ad dActionListener(this);b3.addActionListener(this);setDefaultClose Operation(JFrame.EXIT_ON_CLOSE);table.setPreferredScrollable ViewportSize(new Dimension(660,200));setVisible(true);} public void actionPerformed(ActionEvent e){ if(e.getSource()==b0){ String a=tf1.getText();String b=tf2.getText();t1.append(a+'→'+b+'n');}if(e.getSource()==b1){ t3.setText(“");int Vnnum=0,k;Vn=new String[100];P=new Vector();String s[]=t1.getText().split(”n“);for(int i=0;ireturn;}if(s[i].charAt(0)<='Z'&&s[i].charAt(0)>='A'&&s[i].charAt(1)=='→'){ for(k=0;k=Vnnum){ Vn[Vnnum]=s[i].substring(0, 1);//存入Vn数据 Vnnum++;} P.add(s[i]);} else { t3.setText(”文法输入有误,请重新输入“);return;} } yn_null=new char[100];first=new char[Vnnum][100];int flag=0;String firstVn[]=null;firstComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++)//依次求FIRST** { flag=0;firstVn=new String[20];if((flag=add_First(first[i],Vn[i],firstVn,flag))==-1)return;firstComplete[i]=1;} t3.append(”first集:“+”n“);//显示FIRST**for(inti=0;Vn[i]!=null;i++){ t3.append(”first(“+Vn[i]+”)={ “);for(int j=0;first[i][j]!='';j++){ t3.append(first[i][j]+” , “);} t3.append(”}“+”n“);}follow=new char[Vnnum][100];String followVn[]=null;followComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++)//求FOLLOW** { flag=0;followVn=new String[20];if((flag=tianjiaFollow(follow[i],Vn[i],followVn,flag))==-1)return;followComplete[i]=1;} t3.append(”fol low集:“+”n“);//显示FOLLOW**for(inti=0;Vn[i]!=null;i++){ t3.append(”follow(“+Vn[i]+”)={ “);for(i nt j=0;follow[i][j]!='';j++){ t3.append(follow[i][j]+” , “);} t3.append(”}“+”n“);} select=new char[P.size()][100];for(int i=0;itianjiaSelect(select[i],(String)P.elementAt(i),flag);}t3.append(”select集:“+”n“);//显示SELECT**for(int i=0;ifor(int i=0;Vn[i]!=null;i++)//判断select交集是否为空{ intbiaozhi=0;char save[]=new char[100];for(int j=0;jif(t.substring(0,1).equals(Vn[i])){ for(k=0;select[j][k]!='';k++){ if(puanduanChar(save,select[j][k])){ save[biaozhi]=select[j][k];bia ozhi++;} else//当有交集时,不为LL(1)文法{ t3.append(”不是LL(1)文法!“+”n“);return;} } } } } char Vt[]=new char[100];int biaozhi=0;for(int i=0;i{ if(t.charAt(j)>'Z'||t.charAt(j)<'A'){ if(puanduanChar(Vt,t.cha rAt(j))){ Vt[biaozhi]=t.charAt(j);biaozhi++;} } } } if(puanduanChar(Vt,'#'))//若可推出空集,则将#加入Vt。
编译原理实验:java实现语法分析器
编译原理实验:java实现语法分析器实验⽅法:递归下降分析法基本思想是,对⽂法中的每个⾮终结符编写⼀个函数,每个函数的功能是识别由该⾮终结符所表⽰的语法成分。
因此需要分别构造 E,E’,T,T’,F 函数来执⾏⾃⼰的识别功能,根据⽂法的内容顺序决定函数的识别功能。
java程序实现:import java.util.Scanner;public class GrammarAnalysis {static char[] s = new char[100];static int sing;static int i; //⽤来记录数组s中的下标;static int n;//装语句中的⾃变量;static void P() {if(sing==0) {if(s[i]=='b') {++i;S();if(s[i]=='e') {++i;}else{sing=1;System.out.println("error!--------不是结尾符号e");System.exit(-1);}}else {sing=1;System.out.println("error!--------缺少开头符号b");System.exit(-1);}}}static void S() {if(sing==0) {A();if(s[i]==';') {++i;// if(s[i]!='e') {S1();// }}else {sing=1;System.out.println("error!-----------缺少结尾符号;"); System.exit(-1);}}}static void S1() {if(sing==0) {if(s[i]!='e') {// ++i;S();}}}static void A() {if(sing==0){if(s[i+1]=='=') {n=s[i];++i;++i;E();if(s[i]==')'||s[i]==';') {if(s[i]==')') {++i;}}else {sing=1;System.out.println("error!--------不是结尾符号;或者)"); System.exit(-1);}}else {sing=1;System.out.println("error!---------不是赋值语句");}}}static void E() {if(sing==0){T();if(s[i]=='+'||s[i]=='-'||s[i]==';'||s[i]==')') {E1();}else {sing=1;System.out.println("error!-----------不是结尾符号+或者-或者;或者)"); System.exit(-1);}}}static void T() {if(sing==0){F();if(s[i]=='+'||s[i]=='-'||s[i]==';'||s[i]==')'||s[i]=='*'||s[i]=='/') {T1();}}}static void F() {if(sing==0){if(s[i]=='(') {++i;E();}else {n=s[i];++i;}}}static void T1() {if(sing==0){if(s[i]=='*') {++i;F();T1();}else if(s[i]=='/'){++i;F();T1();}}}static void E1() {if(sing==0){if(s[i]=='+') {++i;T();E1();}else if(s[i]=='-'){++i;T();E1();}}}public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输⼊语句段:"); String str=sc.next();s=str.toCharArray();i=0;sing=0;if(s[0]=='#') System.exit(-1);P();if(s[i]=='#') {System.out.println("success!");}else {System.out.println("error!-------不是结尾符号#"); System.exit(-1);}}}//测试:bi=i+i*(i/i-i);i=i+i;e#//测试:i=i+i*ie #运⾏结果测试:不太规范的语法树:(主要⽤来⾃⼰分析逻辑⾛向~)。
编译原理-语法分析器-(java完美运行版)-副本详解
实验二语法分析器一、实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。
使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。
有利于提高学生的专业素质,为培养适应社会多方面需要的能力。
二、实验内容◆根据某一文法编制调试LL (1 )分析程序,以便对任意输入的符号串进行分析。
◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。
◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。
三、LL(1)分析法实验设计思想及算法◆模块结构:(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
四、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
2、如果遇到错误的表达式,应输出错误提示信息。
3、对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i输出的格式如下:五、实验源程序LL1.javaimport java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.table.DefaultTableModel;import java.sql.*;import java.util.Vector;public class LL1 extends JFrame implements ActionListener {/****/private static final long serialVersionUID = 1L;JTextField tf1;JTextField tf2;JLabel l;JButton b0;JPanel p1,p2,p3;JTextArea t1,t2,t3;JButton b1,b2,b3;JLabel l0,l1,l2,l3,l4;JTable table;Statement sta;Connection conn;ResultSet rs;DefaultTableModel dtm;String Vn[]=null;Vector<String> P=null;int firstComplete[]=null;//存储已判断过first的数据char first[][]=null;//存储最后first结果int followComplete[]=null;//存储已判断过follow的数据char follow[][]=null;//存储最后follow结果char select[][]=null;//存储最后select结果int LL=0;//标记是否为LL(1)String vt_tou[]=null;//储存VtObject shuju[][]=null;//存储表达式数据char yn_null[]=null;//存储能否推出空LL1(){setLocation(100,0);setSize(700,780);tf1=new JTextField(13);tf2=new JTextField(13);l=new JLabel(">>");l0=new JLabel("输入字符串:");l1=new JLabel("输入的文法为:");l2=new JLabel(" ");l3=new JLabel("分析的结果:");l4=new JLabel("预测分析表:");//p1=new JPanel();p2=new JPanel();p3=new JPanel();t1=new JTextArea(24,20);t2=new JTextArea(1,30);t3=new JTextArea(24,40);b0=new JButton("确定(S为开始)");b1=new JButton(" 判断文法 ");b2=new JButton("输入");b3=new JButton("清空");table=new JTable();JScrollPane jp1=new JScrollPane(t1);JScrollPane jp2=new JScrollPane(t2);JScrollPane jp3=new JScrollPane(t3);p2.add(tf1);p2.add(l);p2.add(tf2);p2.add(b0);p2.add(b1);p2.add(l0);p2.add(l2);p2.add(jp2);p2.add(b2);p2.add(b3);p2.add(l1);p2.add(l3);p2.add(jp1);p2.add(jp3);p3.add(l4);p3.add(new JScrollPane(table));add(p2,"Center");add(p3,"South");b0.addActionListener(this);b1.addActionListener(this);b2.addActionListener(this);b3.addActionListener(this);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);table.setPreferredScrollableViewportSize(new Dimension(660,200));setVisible(true);}public void actionPerformed(ActionEvent e){if(e.getSource()==b0){String a=tf1.getText();String b=tf2.getText();t1.append(a+'→'+b+'\n');}if(e.getSource()==b1){t3.setText("");int Vnnum=0,k;Vn=new String[100];P=new Vector<String>();String s[]=t1.getText().split("\n");for(int i=0;i<s.length;i++){if(s.length<2){t3.setText("文法输入有误,请重新输入");//判断长度是否符合return;}if(s[i].charAt(0)<='Z'&&s[i].charAt(0)>='A'&&s[i].charAt(1)=='→') {for(k=0;k<Vnnum;k++){if(Vn[k].equals(s[i].substring(0, 1))){break;}}if(Vnnum==0||k>=Vnnum){Vn[Vnnum]=s[i].substring(0, 1);//存入Vn数据Vnnum++;}P.add(s[i]);}else{t3.setText("文法输入有误,请重新输入");return;}}yn_null=new char[100];first=new char[Vnnum][100];int flag=0;String firstVn[]=null;firstComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++) //依次求 FIRST**{flag=0;firstVn=new String[20];if((flag=add_First(first[i],Vn[i],firstVn,flag))==-1)return;firstComplete[i]=1;}t3.append("first集:"+"\n"); //显示FIRST**for(int i=0;Vn[i]!=null;i++){t3.append("first("+Vn[i]+")={ ");for(int j=0;first[i][j]!='\0';j++){t3.append(first[i][j]+" , ");}t3.append("}"+"\n");}//follow=new char[Vnnum][100];String followVn[]=null;followComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++) //求FOLLOW**{flag=0;followVn=new String[20];if((flag=tianjiaFollow(follow[i],Vn[i],followVn,flag))==-1)return ;followComplete[i]=1;}t3.append("follow集:"+"\n"); //显示FOLLOW**for(int i=0;Vn[i]!=null;i++){t3.append("follow("+Vn[i]+")={ ");for(int j=0;follow[i][j]!='\0';j++){// t3.append(follow[i][j]+" , ");}t3.append("}"+"\n");}select=new char[P.size()][100];for(int i=0;i<P.size();i++) //求SELECT**{flag=0;tianjiaSelect(select[i],(String)P.elementAt(i),flag);}t3.append("select集:"+"\n"); //显示SELECT**for(int i=0;i<P.size();i++){//t3.append("select("+(String)P.elementAt(i)+")={ ");for(int j=0;select[i][j]!='\0';j++){t3.append(select[i][j]+" , ");}t3.append("}"+"\n");}for(int i=0;Vn[i]!=null;i++)//判断select交集是否为空{int biaozhi=0;char save[]=new char[100];for(int j=0;j<P.size();j++){//String t=(String)P.elementAt(j);if(t.substring(0,1).equals(Vn[i])){for(k=0;select[j][k]!='\0';k++){if(puanduanChar(save,select[j][k])){save[biaozhi]=select[j][k];biaozhi++;}else//当有交集时,不为LL(1)文法{t3.append("不是LL(1)文法!!"+"\n");return;}}}}}char Vt[]=new char[100];int biaozhi=0;for(int i=0;i<P.size();i++){String t=(String)P.elementAt(i);for(int j=2;j<t.length();j++)//提取表达式右侧的终结符存入Vt{if(t.charAt(j)>'Z'||t.charAt(j)<'A'){if(puanduanChar(Vt,t.charAt(j))){Vt[biaozhi]=t.charAt(j);biaozhi++;}}}}if(puanduanChar(Vt,'#'))//若可推出空集,则将#加入Vt。
编译原理实验报告(词法分析器语法分析器)
编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。
三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
2、程序流程图(1(2)扫描子程序3五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k (int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。
字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。
2 实验词法分析器源程序:#include <stdio.h>#include <math.h>#include <string.h>int i,j,k;char c,s,a[20],token[20]={'0'};int letter(char s){if((s>=97)&&(s<=122)) return(1);else return(0);}int digit(char s){if((s>=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else")==0) return(3);else if(strcmp(token,"switch")==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf("please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=1;j=0;get();while(s!='#'){ memset(token,0,20);switch(s){case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)",6,token);else printf("(%d,-)",k);break;case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':while(digit(s)){token[j]=s;j=j+1;get();}retract();printf("%d,%s",7,token);break;case '+':printf("('+',NULL)");break;case '-':printf("('-',null)");break; case '*':printf("('*',null)");break;case '<':get();if(s=='=') printf("(relop,LE)");else{retract();printf("(relop,LT)");}break;case '=':get();if(s=='=')printf("(relop,EQ)");else{retract();printf("('=',null)");}break;case ';':printf("(;,null)");break;case ' ':break;default:printf("!\n");}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术。
编译原理 Java 词法分析器
import java.io.*;public class Analysis{public static void main(String args[]){if(args.length!=1){System.out.println("参数个数不合法!五秒钟后自动退出!");try{Thread.sleep(5000);}catch(InterruptedException e){e.printStackTrace();}System.exit(1);}else{File fpath=new File(args[0]);if(!fpath.exists()){System.out.println("参数个数不合法!五秒钟后自动退出!");try{Thread.sleep(5000);}catch(InterruptedException e){e.printStackTrace();}System.exit(1);}else{String str=null; //读入的程序字符串int start=0; //开始节点int i=0;try{FileInputStream fr=new FileInputStream(fpath);byte[] b=new byte[(int)fpath.length()];fr.read(b);str=new String(b);}catch(FileNotFoundException e){e.printStackTrace();}catch(IOException e){e.printStackTrace();}char[] c=str.toCharArray();for(i=0;i<c.length;i++){String s1=""+c[i]; //当前字符String s2=s1;if(i!=c.length-1){s2=s1+c[i+1]; //当前和下一个字符,防止越界}if(start==i){//忽略掉回车或者换行符,制表符if(s1.equals("\r")||s1.equals("\n")||s1.equals("\t")){start++;continue;}if(s2.equals("/*")){System.out.println("/* 是注释开始符。
编译原理的分析器
编译原理的分析器编译原理是计算机科学中的重要学科,研究如何将高级程序语言转化为机器语言,实现程序的编译和执行。
而分析器则是编译过程中的重要组成部分,用于将源程序分析成各种语法成分,为后续的语义分析和代码生成做准备。
本文将对编译原理的分析器进行简要介绍和分析。
一、词法分析器词法分析器是编译原理中的第一步,其主要作用是将源程序分解成一个个记号(Token),为语法分析器提供输入。
词法分析器通过有限自动机(DFA)或正则表达式来实现记号的识别。
在编译原理中,一般会使用词法分析器生成器(如Lex、Flex等工具)来自动生成词法分析器的代码。
二、语法分析器语法分析器是编译原理中的第二步,其主要作用是通过文法规则来分析记号流,判断其是否符合语法规则。
常用的语法分析算法有递归下降法、LL(1)分析法、LR(k)分析法等。
在语法分析过程中,可以根据文法规则构建语法树,用于表示程序的语法结构。
三、语义分析器语义分析器是编译原理中的第三步,其主要作用是对语法分析得到的语法树进行语义分析,包括类型检查、符号表管理和中间代码生成等。
语义分析器会对源程序进行语义上的错误检测,并生成中间表示形式(如三地址码、抽象语法树等),为后续的代码优化和代码生成做准备。
四、符号表管理符号表是编译过程中用于存储程序中的标识符和其属性信息的数据结构。
符号表管理器是编译器中的重要模块,用于管理符号表的创建、插入、查询和删除等操作。
符号表管理器还负责处理作用域和命名冲突等问题,确保符号的正确引用和解析。
五、中间代码生成中间代码是一种介于源代码和目标代码之间的表示形式,用于描述程序的抽象语义。
在编译过程中,中间代码生成器将语法树或其他中间表示形式转换成中间代码,以便于后续的代码优化和代码生成。
常见的中间代码形式包括三地址码、四元式、LLVM IR等。
六、错误处理在编译过程中,错误处理是一个重要的环节。
编译器需要能够检测和报告源程序中的错误,并给出准确的错误信息。
编译原理LL(1)语法分析器java版完整源代码
编译原理LL(1)语法分析器java版完整源代码public class Accept2 {public static StringBuffer stack=new StringBuffer("#E");public static StringBuffer stack2=new StringBuffer("i+i*#");public static void main(String arts[]){//stack2.deleteCharAt(0);System.out.print(accept(stack,stack2));}public static boolean accept(StringBuffer stack,StringBuffer stack2){//判断识别与否boolean result=true;outer:while (true) {System.out.format("%-9s",stack+"");System.out.format("%9s",stack2+"\n");char c1 = stack.charAt(stack.length() - 1);char c2 = stack2.charAt(0);if(c1=='#'&&c2=='#')return true;switch (c1) {case'E':if(!E(c2)) {result=false;break outer;}break;case'P': //P代表E’if(!P(c2)) {result=false;break outer;}break;case'T':if(!T(c2)) {result=false;break outer;}break;case'Q': //Q代表T’if(!Q(c2)) {result=false;break outer;}break;case'F':if(!F(c2)) {result=false;break outer;}break;default: {//终结符的时候if(c2==c1){//System.out.println();}else{return false;}}}if(result=false)break outer;}return result;}public static boolean E(char c) {//语法分析⼦程序 E boolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("PT");}else if(c=='('){stack.deleteCharAt(stack.length()-1);stack.append("PT");else{System.err.println("E 推导时错误!不能匹配!"); result=false;}return result;}public static boolean P(char c){//语法分析⼦程序 P boolean result=true;if(c=='+') {stack.deleteCharAt(stack.length()-1);stack.append("PT+");}else if(c==')') {//stack.append("");System.out.println("P->/");}else if(c=='#') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("P->/");else{System.err.println("P 推导时错误!不能匹配!");result=false;}return result;}public static boolean T(char c) {//语法分析⼦程序 Tboolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("QF");}else if(c=='(') {stack.deleteCharAt(stack.length()-1);stack.append("QF");}else{result=false;System.err.println("T 推导时错误!不能匹配!");}return result;public static boolean Q(char c){//语法分析⼦程序 Q boolean result=true; if(c=='+') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}stack.deleteCharAt(stack.length()-1);stack.append("QF*");}else if(c==')') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}else if(c=='#') {stack.deleteCharAt(stack.length()-1);//stack.append("");System.out.println("Q->/");}else{result=false;System.err.println("Q 推导时错误!不能匹配!"); }return result;}public static boolean F(char c) {//语法分析⼦程序 F boolean result=true;if(c=='i') {stack.deleteCharAt(stack.length()-1);stack.append("i");}else if(c=='(') {stack.deleteCharAt(stack.length()-1);stack.append(")E(");}else{result=false;System.err.println("F 推导时错误!不能匹配!"); }return result;/* public static StringBuffer changeOrder(String s){//左右交换顺序StringBuffer sb=new StringBuffer();for(int i=0;isb.append(s.charAt(s.length()-1-i));}return sb;}*/}#E i+i*i+i##PT i+i*i+i##PQF i+i*i+i##PQi i+i*i+i##PQ +i*i+i#Q->/#P +i*i+i##PT+ +i*i+i##PT i*i+i##PQF i*i+i##PQi i*i+i##PQ *i+i##PQF* *i+i##PQF i+i##PQi i+i##PQ +i#Q->/#P +i##PT+ +i##PT i##PQF i##PQi i##PQ #Q->/#P #P->/True#E i+i*##PT i+i*##PQF i+i*##PQi i+i*##PQ +i*#Q->/#P +i*##PT+ +i*##PT i*##PQF i*##PQi i*##PQ *##PQF* *##PQF #falseF 推导时错误!不能匹配!。
Java实现《编译原理》简单-语法分析功能-LL(1)文法-程序解析
Java实现《编译原理》简单-语法分析功能-LL(1)⽂法-程序解析Java 实现《编译原理》简单-语法分析功能-LL(1)⽂法 - 程序解析编译原理学习,语法分析程序设计(⼀)要求及功能已知 LL(1) ⽂法为:G'[E]: E→TE'E'→+TE'|εT→FT'T'→*FT'|εF→(E)|i为了⽅便处理,⽤:M 代替 E',N 代表 T';并展开相同同⼀⾮终结符的产⽣式;不影响含义,可⾃⾏再优化即有:G[E]: E→TMM→+TMM→εT→FNN→*FNN→εF→(E)F→i根据⽂法建⽴ LL(1) 分析表,并对输⼊串 i+i*i 进⾏语法分析,判断其是否是合法的句⼦(⼆)整体与执⾏结果所需类:执⾏结果:(三)程序源代码(1)Grammar.java ⽂件:package com.java997.analyzer.grammar; import java.io.File;import java.io.FileWriter;import java.io.Serializable;import java.io.Writer;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;/*** LL(1)⽂法* 1.获取 First 集* 2.获取 Follow 集* 3.获取 SELECT 集** @author XiaoPengwei* @since 2019-06-18*/public class Grammar implements Serializable {private static final long serialVersionUID = 1L;public Grammar() {super();gsArray = new ArrayList<String>();nvSet = new TreeSet<Character>();ntSet = new TreeSet<Character>();firstMap = new HashMap<Character, TreeSet<Character>>();followMap = new HashMap<Character, TreeSet<Character>>();selectMap = new TreeMap<Character, HashMap<String, TreeSet<Character>>>(); }private String[][] analyzeTable;/*** Select集合*/private TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap;/*** LL(1)⽂法产⽣集合*/private ArrayList<String> gsArray;/*** 表达式集合*/private HashMap<Character, ArrayList<String>> expressionMap;/*** 开始符*/private Character s;/*** Vn⾮终结符集合*/private TreeSet<Character> nvSet;/*** Vt终结符集合*/private TreeSet<Character> ntSet;/*** First集合*/private HashMap<Character, TreeSet<Character>> firstMap;/*** Follow集合*/private HashMap<Character, TreeSet<Character>> followMap;public String[][] getAnalyzeTable() {return analyzeTable;}public void setAnalyzeTable(String[][] analyzeTable) {this.analyzeTable = analyzeTable;public TreeMap<Character, HashMap<String, TreeSet<Character>>> getSelectMap() {return selectMap;}public void setSelectMap(TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap) { this.selectMap = selectMap;}public HashMap<Character, TreeSet<Character>> getFirstMap() {return firstMap;}public void setFirstMap(HashMap<Character, TreeSet<Character>> firstMap) {this.firstMap = firstMap;}public HashMap<Character, TreeSet<Character>> getFollowMap() {return followMap;}public void setFollowMap(HashMap<Character, TreeSet<Character>> followMap) {this.followMap = followMap;}public HashMap<Character, ArrayList<String>> getExpressionMap() {return expressionMap;}public void setExpressionMap(HashMap<Character, ArrayList<String>> expressionMap) {this.expressionMap = expressionMap;}public ArrayList<String> getGsArray() {return gsArray;}public void setGsArray(ArrayList<String> gsArray) {this.gsArray = gsArray;}public Character getS() {return s;}public void setS(Character s) {this.s = s;}public TreeSet<Character> getNvSet() {return nvSet;}public void setNvSet(TreeSet<Character> nvSet) {this.nvSet = nvSet;}public TreeSet<Character> getNtSet() {return ntSet;}public void setNtSet(TreeSet<Character> ntSet) {this.ntSet = ntSet;}/*** 获取⾮终结符集与终结符集*/public void getNvNt() {for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");String charItemStr = nvNtItem[0];char charItem = charItemStr.charAt(0);// nv在左边nvSet.add(charItem);}for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");// nt在右边String nvItemStr = nvNtItem[1];// 遍历每⼀个字for (int i = 0; i < nvItemStr.length(); i++) {char charItem = nvItemStr.charAt(i);if (!nvSet.contains(charItem)) {ntSet.add(charItem);}}}}/*** 初始化表达式集合*/public void initExpressionMaps() {expressionMap = new HashMap<Character, ArrayList<String>>(); for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");String charItemStr = nvNtItem[0];String charItemRightStr = nvNtItem[1];char charItem = charItemStr.charAt(0);if (!expressionMap.containsKey(charItem)) {ArrayList<String> expArr = new ArrayList<String>();expArr.add(charItemRightStr);expressionMap.put(charItem, expArr);} else {ArrayList<String> expArr = expressionMap.get(charItem);expArr.add(charItemRightStr);expressionMap.put(charItem, expArr);}}}/*** 获取 First 集*/public void getFirst() {// 遍历所有Nv,求出它们的First集合Iterator<Character> iterator = nvSet.iterator();while (iterator.hasNext()) {Character charItem = iterator.next();ArrayList<String> arrayList = expressionMap.get(charItem);for (String itemStr : arrayList) {boolean shouldBreak = false;// Y1Y2Y3...Ykfor (int i = 0; i < itemStr.length(); i++) {char itemitemChar = itemStr.charAt(i);TreeSet<Character> itemSet = firstMap.get(charItem);if (null == itemSet) {itemSet = new TreeSet<Character>();}shouldBreak = calcFirst(itemSet, charItem, itemitemChar); if (shouldBreak) {break;}}}}}/*** 计算 First 函数** @param itemSet* @param charItem* @param itemitemChar* @return boolean*/private boolean calcFirst(TreeSet<Character> itemSet, Character charItem, char itemitemChar) {// 将它的每⼀位和Nt判断下// 是终结符或空串,就停⽌,并将它加到FirstMap中if (itemitemChar == 'ε' || ntSet.contains(itemitemChar)) {itemSet.add(itemitemChar);firstMap.put(charItem, itemSet);// break;return true;} else if (nvSet.contains(itemitemChar)) {// 这⼀位是⼀个⾮终结符ArrayList<String> arrayList = expressionMap.get(itemitemChar);for (int i = 0; i < arrayList.size(); i++) {String string = arrayList.get(i);char tempChar = string.charAt(0);calcFirst(itemSet, charItem, tempChar);}}return true;}/*** 获取 Follow 集合*/public void getFollow() {for (Character tempKey : nvSet) {TreeSet<Character> tempSet = new TreeSet<Character>();followMap.put(tempKey, tempSet);}// 遍历所有Nv,求出它们的First集合Iterator<Character> iterator = nvSet.descendingIterator();while (iterator.hasNext()) {Character charItem = iterator.next();System.out.println("charItem:" + charItem);Set<Character> keySet = expressionMap.keySet();for (Character keyCharItem : keySet) {ArrayList<String> charItemArray = expressionMap.get(keyCharItem);for (String itemCharStr : charItemArray) {System.out.println(keyCharItem + "->" + itemCharStr);TreeSet<Character> itemSet = followMap.get(charItem);calcFollow(charItem, charItem, keyCharItem, itemCharStr, itemSet);}}}}/*** 计算 Follow 集** @param putCharItem 正在查询item* @param charItem 待找item* @param keyCharItem 节点名* @param itemCharStr 符号集* @param itemSet 结果集合*/private void calcFollow(Character putCharItem, Character charItem, Character keyCharItem, String itemCharStr, TreeSet<Character> itemSet) {// (1)A是S(开始符),加⼊#if (charItem.equals(s)) {itemSet.add('#');System.out.println("---------------find S:" + charItem + " ={#}+Follow(E)");followMap.put(putCharItem, itemSet);}// (2)Ab,=First(b)-ε,直接添加终结符if (TextUtil.containsAb(ntSet, itemCharStr, charItem)) {Character alastChar = TextUtil.getAlastChar(itemCharStr, charItem);System.out.println("---------------find Ab:" + itemCharStr + " " + charItem + " =" + alastChar);itemSet.add(alastChar);followMap.put(putCharItem, itemSet);// return;}// (2).2AB,=First(B)-ε,=First(B)-ε,添加first集合if (TextUtil.containsAB(nvSet, itemCharStr, charItem)) {Character alastChar = TextUtil.getAlastChar(itemCharStr, charItem);System.out.println("---------------find AB:" + itemCharStr + " " + charItem + " =First(" + alastChar + ")");TreeSet<Character> treeSet = firstMap.get(alastChar);itemSet.addAll(treeSet);if (treeSet.contains('ε')) {itemSet.add('#');}itemSet.remove('ε');followMap.put(putCharItem, itemSet);if (TextUtil.containsbAbIsNull(nvSet, itemCharStr, charItem, expressionMap)) {char tempChar = TextUtil.getAlastChar(itemCharStr, charItem);System.out.println("tempChar:" + tempChar + " key" + keyCharItem);if (!keyCharItem.equals(charItem)) {System.out.println("---------------find tempChar bA: " + "tempChar:" + tempChar + keyCharItem+ " " + itemCharStr + " " + charItem + " =Follow(" + keyCharItem + ")");Set<Character> keySet = expressionMap.keySet();for (Character keyCharItems : keySet) {ArrayList<String> charItemArray = expressionMap.get(keyCharItems);for (String itemCharStrs : charItemArray) {calcFollow(putCharItem, keyCharItem, keyCharItems, itemCharStrs, itemSet);}}}}}// (3)B->aA,=Follow(B),添加followBif (TextUtil.containsbA(nvSet, itemCharStr, charItem, expressionMap)) {if (!keyCharItem.equals(charItem)) {System.out.println("---------------find bA: " + keyCharItem + " " + itemCharStr + " " + charItem+ " =Follow(" + keyCharItem + ")");Set<Character> keySet = expressionMap.keySet();for (Character keyCharItems : keySet) {ArrayList<String> charItemArray = expressionMap.get(keyCharItems);for (String itemCharStrs : charItemArray) {calcFollow(putCharItem, keyCharItem, keyCharItems, itemCharStrs, itemSet);}}}}}/*** 获取 Select 集合*/public void getSelect() {// 遍历每⼀个表达式// HashMap<Character, HashMap<String, TreeSet<Character>>>Set<Character> keySet = expressionMap.keySet();for (Character selectKey : keySet) {ArrayList<String> arrayList = expressionMap.get(selectKey);// 每⼀个表达式HashMap<String, TreeSet<Character>> selectItemMap = new HashMap<String, TreeSet<Character>>(); for (String selectExp : arrayList) {/*** 存放select结果的集合*/TreeSet<Character> selectSet = new TreeSet<Character>();// set⾥存放的数据分3种情况,由selectExp决定// 1.A->ε,=follow(A)if (TextUtil.isEmptyStart(selectExp)) {selectSet = followMap.get(selectKey);selectSet.remove('ε');selectItemMap.put(selectExp, selectSet);}// 2.Nt开始,=Nt// <br>终结符开始if (TextUtil.isNtStart(ntSet, selectExp)) {selectSet.add(selectExp.charAt(0));selectSet.remove('ε');selectItemMap.put(selectExp, selectSet);}// 3.Nv开始,=first(Nv)if (TextUtil.isNvStart(nvSet, selectExp)) {selectSet = firstMap.get(selectKey);selectSet.remove('ε');selectItemMap.put(selectExp, selectSet);}selectMap.put(selectKey, selectItemMap);}}}/*** ⽣成预测分析表*/public void genAnalyzeTable() throws Exception {Object[] ntArray = ntSet.toArray();Object[] nvArray = nvSet.toArray();// 预测分析表初始化analyzeTable = new String[nvArray.length + 1][ntArray.length + 1];System.out.println("====================\n预测分析表\n====================");File outputFile = new File("D:\\template\\analyzer\\src\\main\\java\\com\\java997\\analyzer\\grammar\\analyzeTable.txt"); try (Writer writer = new FileWriter(outputFile)) {writer.write("====================\n预测分析表\n====================\n");// 输出⼀个占位符System.out.print("表" + "\t");writer.write("表" + "\t");analyzeTable[0][0] = "Nv/Nt";// 初始化⾸⾏for (int i = 0; i < ntArray.length; i++) {if (ntArray[i].equals('ε')) {ntArray[i] = '#';}writer.write(ntArray[i] + "\t\t");System.out.print(ntArray[i] + "\t\t");analyzeTable[0][i + 1] = ntArray[i] + "";}System.out.println("");writer.write("\n");for (int i = 0; i < nvArray.length; i++) {// ⾸列初始化writer.write(nvArray[i] + "\t");System.out.print(nvArray[i] + "\t");analyzeTable[i + 1][0] = nvArray[i] + "";for (int j = 0; j < ntArray.length; j++) {String findUseExp = TextUtil.findUseExp(selectMap, Character.valueOf((Character) nvArray[i]),Character.valueOf((Character) ntArray[j]));if (null == findUseExp) {writer.write("空\t\t");System.out.print("空\t\t");analyzeTable[i + 1][j + 1] = "";} else {writer.write(nvArray[i] + "->" + findUseExp + "\t");System.out.print(nvArray[i] + "->" + findUseExp + "\t");analyzeTable[i + 1][j + 1] = nvArray[i] + "->" + findUseExp; }}writer.write("\n");System.out.println();}} catch (Exception e) {e.printStackTrace();}}}(2)Analyzer.javapackage com.java997.analyzer.grammar;import java.util.ArrayList;import java.util.Stack;/*** <p>* 主程序句⼦分析器** @author XiaoPengwei* @since 2019-06-18*/public class Analyzer {public Analyzer() {super();analyzeStatck = new Stack<Character>();// 结束符进栈analyzeStatck.push('#');}private ArrayList<AnalyzeProduce> analyzeProduces;/*** LL(1)⽂法*/private Grammar ll1Grammar;public Grammar getLl1Grammar() {return ll1Grammar;}public void setLl1Grammar(Grammar ll1Grammar) {this.ll1Grammar = ll1Grammar;}/*** 开始符*/private Character startChar;/*** 分析栈*/private Stack<Character> analyzeStatck;/*** 剩余输⼊串*/private String str;/*** 推导所⽤产⽣或匹配*/private String useExp;public ArrayList<AnalyzeProduce> getAnalyzeProduces() {return analyzeProduces;}public void setAnalyzeProduces(ArrayList<AnalyzeProduce> analyzeProduces) {this.analyzeProduces = analyzeProduces;}public Character getStartChar() {return startChar;}public void setStartChar(Character startChar) {this.startChar = startChar;}public Stack<Character> getAnalyzeStatck() {return analyzeStatck;}public void setAnalyzeStatck(Stack<Character> analyzeStatck) {this.analyzeStatck = analyzeStatck;}public String getStr() {return str;}public void setStr(String str) {this.str = str;}public String getUseExp() {return useExp;}public void setUseExp(String useExp) {eExp = useExp;}/*** 分析*/public void analyze() {analyzeProduces = new ArrayList<AnalyzeProduce>();// 开始符进栈analyzeStatck.push(startChar);System.out.println("====================\nLL(1)⽂法分析过程\n====================");System.out.println("开始符:" + startChar);System.out.println("序号\t\t符号栈\t\t\t输⼊串\t\t\t所⽤产⽣式");int index = 0;// 开始分析// while (analyzeStatck.peek() != '#' && str.charAt(0) != '#') {while (!analyzeStatck.empty()) {index++;if (analyzeStatck.peek() != str.charAt(0)) {// 到分析表中找到这个产⽣式String nowUseExpStr = TextUtil.findUseExp(ll1Grammar.getSelectMap(), analyzeStatck.peek(), str.charAt(0)); //打印表格注意, 制表符的个数if (analyzeStatck.size()==1){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t\t\t" + str + "\t\t\t"+ analyzeStatck.peek() + "->" + nowUseExpStr);}else if (analyzeStatck.size()==2){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t\t" + str + "\t\t\t"+ analyzeStatck.peek() + "->" + nowUseExpStr);}else if (analyzeStatck.size()==3){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t" + str + "\t\t\t"+ analyzeStatck.peek() + "->" + nowUseExpStr);}else {System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t" + str + "\t\t\t"+ analyzeStatck.peek() + "->" + nowUseExpStr);}AnalyzeProduce produce = new AnalyzeProduce();produce.setIndex(index);produce.setAnalyzeStackStr(analyzeStatck.toString());produce.setStr(str);if (null == nowUseExpStr) {produce.setUseExpStr("⽆法匹配!");} else {produce.setUseExpStr(analyzeStatck.peek() + "->" + nowUseExpStr);}analyzeProduces.add(produce);// 将之前的分析栈中的栈顶出栈analyzeStatck.pop();// 将要⽤到的表达式⼊栈,反序⼊栈if (null != nowUseExpStr && nowUseExpStr.charAt(0) != 'ε') {for (int j = nowUseExpStr.length() - 1; j >= 0; j--) {char currentChar = nowUseExpStr.charAt(j);analyzeStatck.push(currentChar);}}continue;}// 如果可以匹配,分析栈出栈,串去掉⼀位if (analyzeStatck.peek() == str.charAt(0)) {if (analyzeStatck.size()==1){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t\t\t" + str + "\t\t\t" + "“" + str.charAt(0) + "”匹配");}else if (analyzeStatck.size()==2){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t\t" + str + "\t\t\t" + "“" + str.charAt(0) + "”匹配");}else if (analyzeStatck.size()==3){System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t\t" + str + "\t\t\t" + "“" + str.charAt(0) + "”匹配");}else {System.out.println(index + "\t\t" + analyzeStatck.toString() + "\t" + str + "\t\t\t" + "“"+ str.charAt(0) + "”匹配");}AnalyzeProduce produce = new AnalyzeProduce();produce.setIndex(index);produce.setAnalyzeStackStr(analyzeStatck.toString());produce.setStr(str);produce.setUseExpStr("“" + str.charAt(0) + "”匹配");analyzeProduces.add(produce);analyzeStatck.pop();str = str.substring(1);continue;}}}}(3)AnalyzeProduce.javapackage com.java997.analyzer.grammar;import java.io.Serializable;/*** <p>* 分析过程 Bean** @author XiaoPengwei* @since 2019-06-18*/public class AnalyzeProduce implements Serializable {private static final long serialVersionUID = 10L;private Integer index;private String analyzeStackStr;private String str;private String useExpStr;public Integer getIndex() {return index;}public void setIndex(Integer index) {this.index = index;}public String getAnalyzeStackStr() {return analyzeStackStr;}public void setAnalyzeStackStr(String analyzeStackStr) { this.analyzeStackStr = analyzeStackStr;}public String getStr() {return str;}public void setStr(String str) {this.str = str;}public String getUseExpStr() {return useExpStr;}public void setUseExpStr(String useExpStr) {eExpStr = useExpStr;}}(4)Main.javapackage com.java997.analyzer.grammar;import java.util.ArrayList;import java.util.TreeSet;/*** <p>* 主程序** @author XiaoPengwei* @since 2019-06-18*/public class Main {public static void main(String[] args) throws Exception { // 第⼀步:获取 LL(1)⽂法ArrayList<String> gsArray = new ArrayList<String>(); Grammar grammar = new Grammar();//初始化 LL(1), 设定该⽂法的产⽣式initGs(gsArray);grammar.setGsArray(gsArray);grammar.getNvNt();grammar.initExpressionMaps();grammar.getFirst();// 设置开始符grammar.setS('E');grammar.getFollow();grammar.getSelect();//打印预测分析表, 并保存⽂件grammar.genAnalyzeTable();// 创建⼀个分析器Analyzer analyzer = new Analyzer();// 设定开始符号analyzer.setStartChar('E');analyzer.setLl1Grammar(grammar);// 待分析的字符串analyzer.setStr("i+i*i#");// 执⾏分析, 打印分析步骤, 保存⽂件analyzer.analyze();}/*** 获取⾮终结符集与终结符集** @param gsArray* @param nvSet* @param ntSet*/private static void getNvNt(ArrayList<String> gsArray, TreeSet<Character> nvSet, TreeSet<Character> ntSet) { for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");String charItemStr = nvNtItem[0];char charItem = charItemStr.charAt(0);// nv在左边nvSet.add(charItem);}for (String gsItem : gsArray) {String[] nvNtItem = gsItem.split("->");// nt在右边String nvItemStr = nvNtItem[1];// 遍历每⼀个字for (int i = 0; i < nvItemStr.length(); i++) {char charItem = nvItemStr.charAt(i);if (!nvSet.contains(charItem)) {ntSet.add(charItem);}}}}/*** 初始化 LL(1)⽂法, 设定产⽣式** @param gsArray*/private static void initGs(ArrayList<String> gsArray) {//E' = M//T' = NgsArray.add("E->TM");gsArray.add("M->+TF");gsArray.add("M->ε");gsArray.add("T->FN");gsArray.add("N->*FN");gsArray.add("N->ε");gsArray.add("F->(E)");gsArray.add("F->i");}}(5)TextUtil.javapackage com.java997.analyzer.grammar;import java.util.ArrayList;import java.util.HashMap;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;/*** <p>* 字符⼯具类** @author XiaoPengwei* @since 2019-06-18*/public class TextUtil {/*** (3)B->aA,=Follow(B)** @param nvSet* @param itemCharStr* @param a* @param expressionMap*/public static boolean containsbA(TreeSet<Character> nvSet, String itemCharStr, Character a,HashMap<Character, ArrayList<String>> expressionMap) {String aStr = a.toString();String lastStr = itemCharStr.substring(itemCharStr.length() - 1);return lastStr.equals(aStr);}/*** 形如 aBb,b=空** @param nvSet* @param itemCharStr* @param a* @param expressionMap*/public static boolean containsbAbIsNull(TreeSet<Character> nvSet, String itemCharStr, Character a, HashMap<Character, ArrayList<String>> expressionMap) {String aStr = a.toString();if (containsAB(nvSet, itemCharStr, a)) {Character alastChar = getAlastChar(itemCharStr, a);System.out.println("----------------+++++++++++++++++++--" + expressionMap.toString());ArrayList<String> arrayList = expressionMap.get(alastChar);if (arrayList.contains("ε")) {System.out.println(alastChar + " contains('ε')" + aStr);return true;}}return false;}/***是否包含这种的字符串<Br>* (2)Ab,=First(b)-ε,直接添加终结符** @param ntSet* @param itemCharStr* @param a* @return boolean*/public static boolean containsAb(TreeSet<Character> ntSet, String itemCharStr, Character a) {String aStr = a.toString();if (itemCharStr.contains(aStr)){int aIndex = itemCharStr.indexOf(aStr);String findStr;try {findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);} catch (Exception e) {return false;}return ntSet.contains(findStr.charAt(0));} else {return false;}}/*** 是否包含这种的字符串<Br>* (2).2Ab,=First(b)-ε* @param nvSet* @param itemCharStr* @param a* @return boolean*/public static boolean containsAB(TreeSet<Character> nvSet, String itemCharStr, Character a) { String aStr = a.toString();if (itemCharStr.contains(aStr)) {int aIndex = itemCharStr.indexOf(aStr);String findStr;try {findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);} catch (Exception e) {return false;}return nvSet.contains(findStr.charAt(0));} else {return false;}}/*** 获取 A 后的字符** @param itemCharStr* @param a*/public static Character getAlastChar(String itemCharStr, Character a) {String aStr = a.toString();if (itemCharStr.contains(aStr)) {int aIndex = itemCharStr.indexOf(aStr);String findStr = "";try {findStr = itemCharStr.substring(aIndex + 1, aIndex + 2);} catch (Exception e) {return null;}return findStr.charAt(0);}return null;}/*** 是否为ε开始的** @param selectExp*/public static boolean isEmptyStart(String selectExp) {char charAt = selectExp.charAt(0);return charAt == 'ε';}/*** 是否是终结符开始的** @param ntSet* @param selectExp*/public static boolean isNtStart(TreeSet<Character> ntSet, String selectExp) {char charAt = selectExp.charAt(0);return ntSet.contains(charAt);}/*** 是否是⾮终结符开始的** @param nvSet* @param selectExp* @return*/public static boolean isNvStart(TreeSet<Character> nvSet, String selectExp) {char charAt = selectExp.charAt(0);return nvSet.contains(charAt);}/*** 查找产⽣式** @param selectMap* @param peek 当前 Nv* @param charAt 当前字符* @return*/public static String findUseExp(TreeMap<Character, HashMap<String, TreeSet<Character>>> selectMap, Character peek, char charAt) {try {HashMap<String, TreeSet<Character>> hashMap = selectMap.get(peek);Set<String> keySet = hashMap.keySet();for (String useExp : keySet) {TreeSet<Character> treeSet = hashMap.get(useExp);if (treeSet.contains(charAt)) {return useExp;}}} catch (Exception e) {return null;}return null;}}执⾏ Main.java。
编译原理语法分析器(完美运行版)
学院(系)名称:计算机工程系实验环境:Windows XP实验分析:(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分实验程序:#include<iostream>#include<stack>using namespace std;stack<char> symbol;stack<int> state;char sen[50];char sym[12][6]={//符号表{'s','e','e','s','e','e'},{'e','s','e','e','e','a'},{'r','r','s','r','r','r'},{'r','r','r','r','r','r'},{'s','e','e','s','e','e'},{'r','r','r','r','r','r'},{'s','e','e','s','e','e'},{'s','e','e','s','e','e'},{'e','s','e','e','s','e'},{'r','r','s','r','r','r'},{'r','r','r','r','r','r'},{'r','r','r','r','r','r'}};char snum[12][6]={//数字表{5,1,1,4,2,1},{3,6,5,3,2,0},{2,2,7,2,2,2},{4,4,4,4,4,4},{5,1,1,4,2,1},{6,6,6,6,6,6},{5,1,1,4,2,1},{5,1,1,4,2,1},{3,6,5,3,11,4},{1,1,7,1,1,1},{3,3,3,3,3,3},{5,5,5,5,5,5}};int go2[12][3]={//goto表{1,2,3},{0,0,0},{0,0,0},{0,0,0},{8,2,3},{0,0,0},{0,9,3},{0,0,10},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};void action(int i,char *&a,char &how,int &num,char &A,int &b)//action函数[i,a] {int j;switch(*a){case 'i':j=0;break;case '+':j=1;break;case '*':j=2;break;case '(':j=3;break;case ')':j=4;break;case '#':j=5;break;default:j=-1;break;}if(j!=-1){how=sym[i][j];num=snum[i][j];if(how=='r'){switch(num){case 1:A='E',b=3;cout<<"按E->E+T规约"<<endl; break;case 2:A='E',b=1;cout<<"按E->T规约"<<endl; break;case 3:A='T',b=3;cout<<"按T->T*F规约"<<endl; break;case 4:A='T',b=1;cout<<"按T->F规约"<<endl; break;case 5:A='F',b=3;cout<<"按F->(E)规约"<<endl; break;case 6:A='F',b=1;cout<<"按F->id规约"<<endl; break;default:break;}}}}int go(int t,char A)//goto[t,A] {switch(A){case 'E':return go2[t][0];break;case 'T':return go2[t][1];break;case 'F':return go2[t][2];break;}}void error(int i,int j,char *&a)//error处理函数{cout<<"error"<<endl;switch(j){case 1://期望输入id或左括号,但是碰到+,*,或$,就假设已经输入id了,转到状态5 state.push(5);symbol.push('i');//必须有这个,如果假设输入id的话,符号栈里必须有....cout<<"缺少运算对象id"<<endl;break;case 2://从输入中删除右括号a++;cout<<"不配对的右括号"<<endl;break;case 3://期望碰到+,但是输入id或左括号,假设已经输入算符+,转到状态6state.push(6);symbol.push('+');cout<<"缺少运算符"<<endl;break;case 4://缺少右括号,假设已经输入右括号,转到状态11state.push(11);symbol.push(')');cout<<"缺少右括号"<<endl;break;case 5:a++;cout<<"*号无效,应该输入+号!"<<endl;case 6:a++;}}int main(){int s;char *a;char how;int num;int b;char A;while(1){cin>>sen;a=sen;state.push(0);//先输入0状态while(*a!='\0'){b=0;num=0;how='\0';A='\0';s=state.top();action(s,a,how,num,A,b);if(how=='s')//移进{cout<<"移进"<<endl;symbol.push(*a);state.push(num);// if(*a=='i')// a++;//在这里忽略i后面的da++;}else if(how=='r')//规约{for(int i=0;i<b;i++){if(!state.empty())state.pop();if(!symbol.empty())symbol.pop();}int t=state.top();symbol.push(A);state.push(go(t,A));}else if(how=='a')//接受break;else{error(s,num,a);//错误处理}}cout<<"成功接受"<<endl;}return 0;}测试用例:i*(i+i)+i#测试结果:心得体会:通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,实验过程中对于程序的逻辑理解欠缺了考虑,在多次的调试和改进中最终完善了程序,而在调试过程中学习的知识得到了完善和补充,对语法分析器的理解更进一步。
编译原理词法分析器
编译原理词法分析器
编译原理词法分析器是编译器中的一个重要组成部分。
它负责将源代码分解成一个个词素(token)。
在进行词法分析过程中,我们需要定义各种词法规则,例如标识符的命名规则、关键字的集合、运算符的定义以及常量的表示方式等。
词法分析器通常使用有限自动机来实现。
有限自动机是一种能接受或拒绝某个输入序列的计算模型。
在词法分析器中,有限自动机可以方便地根据输入字符的不同状态进行相应的转移,直至得到一个完整的词法单元。
在编写词法分析器时,我们通常会先定义各个词法规则,然后将其转化为正则表达式或有限自动机的形式。
接下来,我们会根据这些规则生成一个词法分析器的状态转换图,并使用该图构建词法分析器的代码。
词法分析器的工作过程如下:输入源代码文本,逐个读取字符并根据当前状态进行状态转移。
如果当前字符能够完成一个词法单元的匹配,那么就将当前词法单元输出,并进入下一个状态。
如果当前字符不能完成一个词法单元的匹配,则继续读取下一个字符,直至完成一个词法单元的匹配或遇到非法字符。
通过词法分析器,我们可以将源代码文本转化为一系列的词法单元,例如关键字、标识符、运算符、常量等。
这些词法单元将作为编译器后续阶段的输入,用于进行语法分析和语义分析。
词法分析器是编译器的重要基础工具之一,它能够帮助我们更好地理解和处理源代码。
编译原理课程设计(JAVA)-语法分析器
福建农林大学计算机与信息学院计算机类课程设计报告课程名称:编译原理课程设计题目:语法分析器姓名:系:计算机专业:计算机科学与技术年级:2009级学号:指导教师:职称:2010~2011学年第一学期福建农林大学计算机与信息学院计算机类课程设计结果评定评语:成绩:指导教师签字:任务下达日期:评定日期:目录1 正则表达式 (1)1.1 正则表达式 (1)1.2 确定化(化简)后的状态转换图 (1)1.3 分析程序代码 (1)1.4 程序运行截图 (1)1.5 小结 (8)2 LL(1)分析 ········································································错误!未定义书签。
2.1 LL(1)文法 ·······························································错误!未定义书签。
编译原理语法分析器
编译原理语法分析器编译原理语法分析器是编译器中的重要组成部分,它负责将源代码解析成抽象语法树,为后续的语义分析和代码生成做准备。
本文将介绍语法分析器的原理、分类和常用算法。
一、语法分析器的原理语法分析器的主要任务是根据给定的文法定义,将源代码解析成一个个语法单元,并构建出一棵抽象语法树。
它通过递归下降、预测分析和LR分析等算法来实现。
1. 递归下降法递归下降法是一种基于产生式的自顶向下分析方法。
它从文法的开始符号出发,通过不断地推导和回溯,逐步地构建抽象语法树。
递归下降法易于理解和实现,但对左递归和回溯有一定的局限性。
2. 预测分析法预测分析法也是自顶向下的分析方法,它通过预测下一个输入符号来选择适当的产生式进行推导。
为了提高效率,预测分析法使用预测分析表来存储各个非终结符和终结符的关系。
3. LR分析法LR分析法是一种自底向上的分析方法,它使用LR自动机和LR分析表来进行分析。
LR自动机是一个有限状态控制器,通过状态转移和规约动作来解析源代码。
LR分析表存储了状态转移和规约的规则。
二、语法分析器的分类根据语法分析器的特性和实现方式,可以将其分为LL分析器和LR 分析器。
1. LL分析器LL分析器是基于递归下降法和预测分析法的一类分析器。
它从左到右、从左到右地扫描源代码,并根据预测分析表进行推导。
常见的LL分析器有LL(1)分析器和LL(k)分析器。
2. LR分析器LR分析器是基于LR分析法的一类分析器。
它先通过移进-归约的方式建立一棵语法树,然后再进行规约操作。
LR分析器具有强大的语法处理能力,常见的LR分析器有LR(0)、SLR(1)、LR(1)和LALR(1)分析器。
三、常用的语法分析算法除了递归下降法、预测分析法和LR分析法,还有一些其他的语法分析算法。
1. LL算法LL算法是一种递归下降法的改进算法,它通过构造LL表和预测分析表实现分析过程。
LL算法具有很好的可读性和易于理解的特点。
2. LR算法LR算法是一种自底向上的分析方法,它通过建立LR自动机和构造LR分析表来进行分析。
编译原理实验二:LL(1)语法分析器
编译原理实验⼆:LL(1)语法分析器⼀、实验要求 1. 提取左公因⼦或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下⾯我贴出实验的⼀些关键代码和算法思想。
⼆、基于预测分析表法的语法分析 2.1 代码结构 2.1.1 Grammar类 功能:主要⽤来处理输⼊的⽂法,包括将⽂法中的终结符和⾮终结符分别存储,检测直接左递归和左公因⼦,消除直接左递归,获得所有⾮终结符的First集,Follow集以及产⽣式的Select集。
#ifndef GRAMMAR_H#define GRAMMAR_H#include <string>#include <cstring>#include <iostream>#include <vector>#include <set>#include <iomanip>#include <algorithm>using namespace std;const int maxn = 110;//产⽣式结构体struct EXP{char left; //左部string right; //右部};class Grammar{public:Grammar(); //构造函数bool isNotTer(char x); //判断是否是终结符int getTer(char x); //获取终结符下标int getNonTer(char x); //获取⾮终结符下标void getFirst(char x); //获取某个⾮终结符的First集void getFollow(char x); //获取某个⾮终结符的Follow集void getSelect(char x); //获取产⽣式的Select集void input(); //输⼊⽂法void scanExp(); //扫描输⼊的产⽣式,检测是否有左递归和左公因⼦void remove(); //消除左递归void solve(); //处理⽂法,获得所有First集,Follow集以及Select集void display(); //打印First集,Follow集,Select集void debug(); //⽤于debug的函数~Grammar(); //析构函数protected:int cnt; //产⽣式数⽬EXP exp[maxn]; //产⽣式集合set<char> First[maxn]; //First集set<char> Follow[maxn]; //Follow集set<char> Select[maxn]; //select集vector<char> ter_copy; //去掉$的终结符vector<char> ter; //终结符vector<char> not_ter; //⾮终结符};#endif 2.1.2 AnalyzTable类 功能:得到预测分析表,判断输⼊的⽂法是否是LL(1)⽂法,⽤预测分析表法判断输⼊的符号串是否符合刚才输⼊的⽂法,并打印出分析过程。
编译原理词法分析器java
实验一词法分析器的设计一、实验目的1.理解词法分析器的任务和输出形式2.理解扫描器的工作原理3.掌握状态转换图的绘制以及单词的识别技术4.掌握词法分析器的设计过程,能够使用某种高级语言实现一个词法分析器二、实验环境Myeclipse三、实验要求给出一个简单的词法语言规则描述,其中:1开头的种别码为关键词,2开头的为算符,3开头的为界符,4开头的为标识符,5开头的为常数,标识符为字母开头,以字母和数字组成的任意符号串,常数为整数,即以数字组成的符号串。
四、实验难点1.对整数的二进制转换,以及对指针的操作2.标识符的设置五、实验代码1.ciFa.Javapackage com.yaoer.test1;import javax.swing.*;import javax.swing.border.TitledBorder;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;@SuppressWarnings("serial")public class ciFa extends JFrame{private JButton jbtShow = new JButton("进行词法分析");//按钮private JTextArea jta = new JTextArea();//输入文本框private JTextArea jtaOut = new JTextArea();//输出文本框private JPanel jpl=new JPanel();private String intput ="";private String output ="";private compiler comp = new compiler();* @param args*/public static void main(String[] args){ciFa frame = new ciFa();frame.setTitle("词法分析器");//frame.setLocationRelativeTo(frame);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(500, 400);frame.setVisible(true);}public ciFa(){jta.setWrapStyleWord(true);jta.setLineWrap(true);jtaOut.setWrapStyleWord(true);jtaOut.setLineWrap(true);jtaOut.setEditable(false);JScrollPane scrollPane = new JScrollPane(jta);JScrollPane scrollPane2 = new JScrollPane(jtaOut);scrollPane.setPreferredSize(new Dimension(300,300));scrollPane2.setPreferredSize(new Dimension(300,300));jtaOut.setBorder(new TitledBorder("词法分析结果"));jta.setBorder(new TitledBorder("请在这输入"));jpl.setLayout(new GridLayout(2,2));jpl.add(jta);jpl.add(jtaOut);add(jbtShow,BorderLayout.SOUTH);add(jpl);jbtShow.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){intput = jta.getText();output=puterComp(intput);jtaOut.append(output);}});}piler.Javapackage com.yaoer.test1;public class compiler {public String computerComp(String str){String output="";int index=0;int k = 0;while(index<str.length()){if(isJieFu(str.charAt(index))!=-1){ //判断界符output+=("( 30"+isJieFu(str.charAt(index))+" "+str.charAt(index)+" 界符)");index++;}else if(isMath(str.charAt(index))){ //判断常数int index1=index;output+=("( ");String sub;String result;while(isMath(str.charAt(index))){output+=(str.charAt(index));index++;if(index>=str.length()){if(str.charAt(index1)=='0'){if(index1+1>=str.length()){sub =str.substring(index1, index);result = Zhuan(sub);output+=(" "+result+" 数字)");}else{if(isMath(str.charAt(index1+1))){output+=(" 非法字符)"); }else{sub =str.substring(index1, index);result = Zhuan(sub);output+=(" "+result+" 数字)");}}}else{sub =str.substring(index1, index);result = Zhuan(sub);output+=(" "+result+" 数字)");}return output;}}if(isLetter(str.charAt(index))){if(str.charAt(index)==' '||str.charAt(index)=='\n'){//空格或者回车处理index++;}while((!isMath(str.charAt(index)))||(isLetter(str.charAt(index)))){output+=(str.charAt(index));index++;if(index>=str.length()) {output+=(" 非标识符)");return output;}}output+=(" 非法字符)");}else{if(str.charAt(index1)=='0'){if(isMath(str.charAt(index1+1))){output+=(" 非法字符)"); }else{sub =str.substring(index1, index);result = Zhuan(sub);output+=(" "+result+" 数字)");}}else{sub =str.substring(index1, index);result = Zhuan(sub);output+=(" "+result+" 数字)");}}}else if(isLetter(str.charAt(index))){ //标识符判断int i=index;String sub;while(isLetter(str.charAt(index))||isMath(str.charAt(index))){index++;if(index>=str.length()){//System.out.println(index);sub =str.substring(i, index);if(isKeyword(sub)!=0){if(isKeyword(sub)>=10){output+=("( "+" 1"+isKeyword(sub)+" "+sub+" 关键字)");}else{output+=("( "+" 10"+isKeyword(sub)+" "+sub+" 关键字)");}}else{output+=("( "+sub+" 标识符)");}return output;}}sub = str.substring(i, index);//判断是不是关键字if(isKeyword(sub)!=0){if(isKeyword(sub)>=10){output+=("( "+" 1"+isKeyword(sub)+" "+sub+" 关键字)");}else{output+=("( "+" 10"+isKeyword(sub)+" "+sub+" 关键字)");}}else{output+=("("+sub+" 标识符)");}}else if(isCompu(str.charAt(index))!=0){if(index+1>=str.length()){if(str.charAt(index)=='&'||str.charAt(index)=='|'){output+=("("+str.charAt(index)+" 非法字符)");index++;}else{if(isCompu(str.charAt(index))<=8){output+=("("+" 20"+isCompu(str.charAt(index))+" "+str.charAt(index)+" 运算符)");}else if(str.charAt(index)=='!'){output+=("( 218 "+str.charAt(index)+" 运算符)");}index++;}}else{if(isCompu(str.charAt(index+1))==0){if(str.charAt(index)=='&'||str.charAt(index)=='|'){output+=("("+str.charAt(index)+" 非法字符)");index++;}else{if(isCompu(str.charAt(index))<=8){output+=("("+"20"+isCompu(str.charAt(index))+" "+str.charAt(index)+" 运算符)");}else if(str.charAt(index)=='!'){output+=("("+" 218"+str.charAt(index)+" 运算符)");}index++;}}else{if(index+2>=str.length()){if( isCompu(str.charAt(index+1))!=0){if(str.charAt(index)=='='){if(str.charAt(index+1)=='='){output+=("("+" 210 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='<' ){switch (str.charAt(index+1)) {case '=':output+=("("+" 209 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;break;case '<':output+=("( 215 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;break;case '>':output+=("( 211 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;break;default:output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;break;}}else if(str.charAt(index)=='>' ){if(str.charAt(index+1)=='='){output+=("( 207 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else if(str.charAt(index+1)=='>'){output+=("( 214 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='&'){if(str.charAt(index+1)=='&'){output+=("( 216 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='|'){if(str.charAt(index+1)=='|'){output+=("( 217 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='+'){if(str.charAt(index+1)=='+'){output+=("( 212 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='-'){if(str.charAt(index+1)=='-'){output+=("( 213 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}return output;}else{if( isCompu(str.charAt(index+1))!=0){if(str.charAt(index)=='='){if(str.charAt(index+1)=='='){output+=("("+" 210 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='<' ){switch (str.charAt(index+1)) {case '=':output+=("("+" 209 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;break;case '<':output+=("("+" 215 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;break;case '>':output+=("( 211 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;break;default:output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;break;}}else if(str.charAt(index)=='>' ){if(str.charAt(index+1)=='='){output+=("( 207 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else if(str.charAt(index+1)=='>'){output+=("( 214 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='&'){if(str.charAt(index+1)=='&'){output+=("( 216 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='|'){if(str.charAt(index+1)=='|'){output+=("( 217 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='+'){if(str.charAt(index+1)=='+'){output+=("( 212"+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else if(str.charAt(index)=='-'){if(str.charAt(index+1)=='-'){output+=("( 213 "+str.charAt(index)+str.charAt(index+1)+" 运算符)");index++;index++;}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}else{output+=("("+str.charAt(index)+str.charAt(index+1)+" 非法字符)");index++;index++;}}}}}}else if(str.charAt(index)==' '||str.charAt(index)=='\n'){//空格或者回车处理index++;}else {//其他字符output+=("("+str.charAt(index)+" 非法字符)");index++;}k++;if(k%10==0){output+=("\n");}}return output;}/*** 1.判断是不是关键字* @param str* @return*/public int isKeyword(String str){int result = 0;String[]arr={"void","main","int","char","if","else","for","while","return","cout","ci n"} ;for(int i=0;i<arr.length;i++){if(str.equals(arr[i])){result = i+1;break;}else {result = 0;}}return result;}/*** 2.判断是不是运算符* @param charr* @return*/public int isCompu(char charr) {char arr[]={'+','-','*','/','=','>','&','<','!','|'};for(int i=0;i<arr.length;i++) {if (charr==arr[i]){return i+1;}}return 0;}/*** 3.判断是不是界符* @param charr* @return*/public int isJieFu(char charr){char arr[]={'(',')','[',']','{','}',',',';'};for(int i=0;i<arr.length;i++){if (charr==arr[i]){return i+1;}}return -1;}/*** 4.判断是不是标识符* @param charr* @return*/public boolean isLetter(char charr){if(((charr>='a'&&charr<='z')||(charr>='A'&&charr<='Z')) ||charr=='_'){ return true;}else{return false;}}/*** 5.判断是不是数字* @param charr* @return*/public boolean isMath(char charr){if((charr>='0')&&(charr<='9')){return true;}else{return false;}}/*** 将十进制转换为二进制* @param num* @return*/public String Zhuan(String num){int number = Integer.parseInt(num);int sum;String result = "";for (int i = number; i >= 1; i /= 2) {if (i % 2 == 0) {sum = 0;} else {sum = 1;}result = sum + result;}return result;}}六、实验中遇到的问题及感想在编写词法分析器的程序中,几个子函数的功能还是比较容易实现的,但是要把它们的功能连在一起,实现对程序源代码的词法分析就困难了,例如在分析运算符的时候,有的运算符是由2个符号组成的,有的是1个,在读入一个字符的时候还要进行超前搜索,看看第二个字符是否可以和第一个字符组成一个运算符。
编译原理名词解释
编译原理名词解释1. 词法分析器(Lexer):也称为扫描器(Scanner),用于将源代码分割成一个个单词(Token)。
2. 语法分析器(Parser):将词法分析器生成的单词序列转换成语法树(Parse Tree)或抽象语法树(Abstract Syntax Tree)。
3. 语法树(Parse Tree):表示源代码的语法结构的树状结构,它由语法分析器根据语法规则生成。
4. 抽象语法树(Abstract Syntax Tree):比语法树更加简化和抽象的树状结构,用于表示源代码的语义结构。
5. 语义分析器(Semantic Analyzer):对抽象语法树进行语义检查,并生成中间代码或目标代码。
6. 中间代码(Intermediate code):一种介于源代码和目标代码之间的中间表示形式,可以被不同的优化器和代码生成器使用。
7. 目标代码生成器(Code Generator):将中间代码转换成特定目标平台的机器代码。
8. 优化器(Optimizer):用于对中间代码进行优化,以提高代码的执行效率和资源利用率。
9. 符号表(Symbol Table):用于存储程序中的标识符(变量、函数等)的信息,包括名称、类型等。
10. 语言文法(Grammar):定义了一种语言的语法规则,常用的形式包括上下文无关文法和正则文法。
11. 上下文无关文法(Context-free Grammar):一种形式化的语法表示方法,由产生式和非终结符组成,描述一种语言的句子结构。
12. 语言解释器(Interpreter):将源代码逐行解释执行的程序,不需要生成目标代码。
13. 回溯法(Backtracking):一种递归式的算法,用于在语法分析过程中根据产生式进行选择。
14. 正则表达式(Regular Expression):用于描述一类字符串的表达式,可以用于词法分析中的模式匹配。
15. 自顶向下分析(Top-down Parsing):从文法的起始符号开始,按照语法规则逐步构建语法树的过程。
编译原理词法分析器
编译原理词法分析器
编译原理词法分析器是编译器的一个重要组成部分,负责将输入的源代码转换成一系列的词法单元,供后续的语法分析器进行进一步处理。
词法分析器的主要任务是按照预先定义的词法规则,识别出源代码中的各个合法的词法单元,并将其转化为内部表示形式。
在这个过程中,词法分析器需要读取输入字符流,并根据定义的词法规则进行模式匹配和转换。
一个基本的词法分析器通常由以下几个部分组成:
1. 字符扫描器(Scanner):负责从输入流中读取字符,并进行必要的预处理。
例如,过滤掉注释、空白字符等。
2. 词法规则(Lexical Rules):是定义词法单元的正则表达式或者有限自动机。
每个词法单元都有一个对应的识别规则。
3. 标记生成器(Token Generator):根据词法规则和字符扫描器的输出,生成符合内部表示形式的词法单元。
4. 符号表(Symbol Table):维护着程序中出现的所有标识符的符号表,包括标识符的名称和属性信息。
词法分析器的工作流程如下:
1. 初始化字符扫描器,读取第一个字符。
2. 逐个字符进行扫描和匹配,直到获取了一个完整的词法单元。
3. 根据匹配到的词法规则,生成对应的词法单元。
4. 如果需要记录标识符信息,将其添加到符号表中。
5. 返回步骤2,直到扫描完整个输入代码。
通过词法分析器的工作,我们能够将输入的源代码按照词法规则进行分割,将其转换为一系列的词法单元,为后续的语法分析器提供了处理的基础。
编译原理—语法分析器
import java.util.Stack;public class LL1Compuliter{public static void main(String [] args){String [] topString = {"i", "+","*","(",")","#"};String [] leftString = {"E","G","T","S","F","@"};String [][]bottomString = {{"TG","","","TG","",""},{"","+TG","","","@","@"},{"FS","","","FS","",""},{"","@","*FS","","@","@"},{"i","","","(E)","",""}};LL1Compuliter ll1 = new LL1Compuliter();String temp = "i*i+i+(i)#";Stack st = new Stack();st.push("#"); //入栈String sstr = "E"; //开始符进栈st.push(sstr);while(temp.indexOf("#")>=0){String ss = temp.substring(0,1); //获取第一个字符System.out.print(ss);int indexCell = ll1.isString(topString, ss);//存在终结符的获取列下标if(indexCell>=0){String SSRow = (String) stElement();//获取栈顶元素//判断栈顶元素是非终结符如果是非终结符进循环判断操作while(ll1.isString(leftString, SSRow)>=0){SSRow = (String) stElement(); //获取栈顶元素if(SSRow.equals("@")||SSRow=="@")//判断栈顶元素是不是空如果是出栈{st.pop();continue;}else{int indexRow = ll1.isString(leftString,SSRow);//找到行下标if(indexRow>=0){System.out.print(" "+"出栈元素:"+stElement());st.pop();String strr = bottomString[indexRow][indexCell];//找到表格元素if(strr==""||strr.equals("")){System.out.print(" "+"元素所在位置为空出错"+stElement()+"现在元素:"+temp);break;}else{eStack(st, strr);//进栈}}else{if(ll1.isString(topString,(String)stElement())>=0){st.pop();break;}else{System.out.print(""+(String)stElement());break;}}}}if(SSRow.equals(ss)||SSRow==ss)//匹配成功{System.out.print(" "+"匹配成功"+SSRow);}else{System.out.print(" "+"匹配失败"+ss);break;}}else{System.out.print(" "+"没有此字符串");break;}temp = temp.substring(1,temp.length());//截取字符串System.out.println();}if(st.isEmpty()){System.out.print(" "+"执行成功");}else{String top = (String)stElement();if((top.equals("@#")&&temp.equals("#"))||(top.equals("#")&&tem p.equals("#"))){System.out.println(" "+"执行成功");}else{System.out .println(" "+"匹配结果:栈顶元素为:"+top+"缓冲区元素为:"+temp);System.out .println(" "+"执行失败!!!!!");}}}// 判断是不是和标头和左列对应相等public int isString(String[] str,String ss){int index = -1;for(int i = 0;i<str.length;i++){if(ss==str[i]||ss.equals(str[i])){index = i;break;}}return index;}public void comeStack(Stack st,String ss){char []cc = ss.toCharArray();for(int i=cc.length-1;i>=0;i--){String str = cc[i]+"";System.out.print(" "+"进栈元素:"+str);st.push(str);}}}。
编译原理实验报告(语法分析器)
.编译原理实验专业:13级网络工程语法分析器1一、实现方法描述所给文法为G【E】;E->TE’E’->+TE’|空T->FT’T’->*FT’|空F->i|(E)递归子程序法:首先计算出五个非终结符的first集合follow集,然后根据五个产生式定义了五个函数。
定义字符数组vocabulary来存储输入的句子,字符指针ch指向vocabulary。
从非终结符E函数出发,如果首字符属于E的first集,则依次进入T函数和E’函数,开始递归调用。
在每个函数中,都要判断指针所指字符是否属于该非终结符的first集,属于则根据产生式进入下一个函数进行调用,若first集中有空字符,还要判断是否属于该非终结符的follow集。
以分号作为结束符。
二、实现代码头文件shiyan3.h#include<iostream>#include<cstdio>#include<string>using namespace std;#define num 100char vocabulary[num];char *ch;void judge_E();void judge_EE();void judge_T();void judge_TT();void judge_F();源文件#include"shiyan3.h"void judge_E(){if(*ch==';'){cout<<"该句子符合此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}elseif(*ch=='('||*ch=='i'){judge_T();judge_EE();}else{cout<<"该句子不匹配此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}}void judge_EE(){if(*ch==';'){cout<<"该句子符合此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}if(*ch=='+'){ch++;judge_T();judge_EE();}elseif(*ch=='#'||*ch==')')return;else{cout<<"该句子不匹配此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}}void judge_T(){if(*ch==';'){cout<<"该句子符合此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}if(*ch=='('||*ch=='i'){judge_F();judge_TT();}else{cout<<"该句子不匹配此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}}void judge_TT(){if(*ch==';'){cout<<"该句子符合此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}if(*ch=='*'){ch++;judge_F();judge_TT();}elseif(*ch==')'||*ch=='+'||*ch=='#')return;else{cout<<"该句子不匹配此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}}void judge_F(){if(*ch==';'){cout<<"该句子符合此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}if(*ch=='('){ch++;judge_E();if(*ch==')'){ch++;}else{cout<<"该句子不匹配此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}}elseif(*ch=='i'){ch++;//cout<<*ch;}else{cout<<"该句子不匹配此文法!"<<endl;int a=0;cout<<"按1结束程序"<<endl;cin>>a;if(a==1)exit(0);}}void main(){//char *ch;cout<<"**********************欢迎使用语法分析器************************"<<endl;cout<<"请输入一个句子:"<<endl;cin.getline(vocabulary,15);ch=vocabulary;judge_E();cout<<endl;cout<<"************************结束使用,再见!**************************"<<endl;}三、运行结果四、心得体会此次实验使用的是递归子程序法,用这个方法最大的问题就是函数里的递归调用,一不小心就把人绕糊涂了。
编译原理(第三版)语法分析器
编译原理(第三版)语法分析器语法分析器在词法分析器的基础上增加了递归下降分析程序,咱也不知道啥是递归下降程序,咱也不想问。
但是有程序框图和伪代码把程序跑通咱还是⽐较在⾏滴。
为了便于理解,debug过程中的输出也保留了。
下⾯是完整代码。
1/*2 begin a:= 9; x:=2*3;b:=a+x end#3 x:= a+b*c end #4*/5 #include <stdio.h>6 #include <stdlib.h>7 #include <string.h>8#define _KEY_WORD_END "waiting for your expanding"9 typedef struct10 {11int typenum;12char *word;13 }WORD;14char input[255];15char token[255]="";16int p_input;17int p_token;18char ch;19char* rwtab[] = {"begin","if","then","while","do","end",_KEY_WORD_END};20 WORD * scaner();21 WORD* oneword = new WORD;22int syn,kk;23void expression();24void factor()25 {26if(syn == 10 || syn == 11)27 {28 oneword = scaner();29 syn = oneword->typenum;30 printf("%s %d\n",oneword->word,syn);31 }32else if(syn == 27)33 {34 oneword = scaner();35 syn = oneword->typenum;36 printf("%s %d\n",oneword->word,syn);37 expression();38if(syn == 28)39 {40 oneword = scaner();41 syn = oneword->typenum;42 printf("%s %d\n",oneword->word,syn);43 }44else{45 printf("右括号错误\n");46 kk = 1;47 }48 }49else50 {51 printf("表达式错误\n");52 kk = 1;53 }54return;55 }56void term()57 {58 factor();59while(syn == 15 || syn == 16)60 {61 oneword = scaner();62 syn = oneword->typenum;63 printf("%s %d\n",oneword->word,syn);64 factor();65 }66return;67 }68void expression()69 {70 term();71while(syn == 13 || syn == 14)72 {73 oneword = scaner();74 syn = oneword->typenum;75 printf("%s %d\n",oneword->word,syn);76 term();77 }78return;79 }80void statement()81 {82if(syn == 10)83 {84 oneword = scaner();85 syn = oneword->typenum;86 printf("%s %d\n",oneword->word,syn); 87if(syn == 18)88 {89 oneword = scaner();90 syn = oneword->typenum;91 printf("%s %d\n",oneword->word,syn);92 expression();93 }94else{95 printf("赋值号错误\n");96 kk = 1;97 }98 }99else{100 printf("语句错误\n");101 kk = 1;102 }103return;104 }105void yucu()106 {107 statement();108while(syn == 26)109 {110 oneword = scaner();111 syn = oneword->typenum;112 printf("%s %d\n",oneword->word,syn); 113 statement();114 }115return;116 }117void Irparser()118 {119if(syn == 1)120 {121 oneword = scaner();122 syn = oneword->typenum;123 printf("%s %d\n",oneword->word,syn);124 yucu();125126if(syn==6)127 {128 oneword = scaner();129 syn = oneword->typenum;130if(syn == 0 && (kk == 0))131 printf("success\n");132 }133else{134if(kk != 1)135 {136 printf("缺少end错误\n");137 kk = 1;138 }139 }140 }141else{142 printf("begin错误\n");143 kk = 1;144 }145return;146 }147int main()148 {149int over = 1;150151 printf("Enter Your words(end with #):");152 scanf("%[^#]s",input);153 p_input = 0;154 printf("Your words:\n%s\n",input);155156//获取下⼀个单词符号157 oneword = scaner();158 syn = oneword->typenum;159 Irparser();160161 printf("\npress # to exit:");162 scanf("%[^#]s",input);163return0;164 }165char m_getch()166 {167 ch = input[p_input];168 p_input = p_input+1;169return(ch);170 }171void getbc()172 {173while(ch == ''||ch == 10)174 {175 ch = input[p_input];176 p_input++;177 }178 }179void concat()180 {181 token[p_token] = ch;182 p_token++;183 token[p_token] = '\0';184 }185int letter()186 {187if((ch >= 'a'&& ch <= 'z')|| (ch >='A'&&ch <= 'Z')) 188return1;189else190return0;191 }192int digit()193 {194if(ch >= '0'&&ch <='9')return1;195else return0;196 }197int reserve()198 {199int i = 0;200while(strcmp(rwtab[i],_KEY_WORD_END))201 {202if(!strcmp(rwtab[i],token))203return i+1;204 i++;205 }206return10;207 }208void retract()209 {210 p_input--;211 }212213char* dtb()214 {215return NULL;216 }217218 WORD* scaner()219 {220221 WORD* myword = new WORD; 222 myword->typenum = 10;223 myword->word = "";224 p_token = 0;225 m_getch();226 getbc();227if(letter())228 {229while(letter()||digit())230 {231 concat();232 m_getch();233 }234 retract();235 myword->typenum = reserve(); 236 myword->word = token;237return(myword);238 }239else if(digit())240 {241while(digit())242 {243 concat();244 m_getch();245 }246 retract();247 myword->typenum = 11;248 myword->word = token;249return(myword);250 }251else switch(ch)252 {253case'=':m_getch();254if(ch == '=')255 {256 myword->typenum = 25; 257 myword->word = "=="; 258return(myword);259 }260 retract();261 myword->typenum = 21; 262 myword->word = "=";263return(myword);264break;265case'+':266 myword->typenum = 13; 267 myword->word = "+";268return(myword);269break;270case'-':271 myword->typenum = 14; 272 myword->word = "-";273return(myword);274break;275case'*':276 myword->typenum = 15; 277 myword->word = "*";278return(myword);279break;280case'/':281 myword->typenum = 16; 282 myword->word = "/";283return(myword);284break;289break;290case')':291 myword->typenum = 28; 292 myword->word = ")";293return(myword);294break;295case'[':296 myword->typenum = 28; 297 myword->word = "[";298return(myword);299break;300case']':301 myword->typenum = 29; 302 myword->word = "]";303return(myword);304break;305case'{':306 myword->typenum = 30; 307 myword->word = "{";308return(myword);309break;310case'}':311 myword->typenum = 31; 312 myword->word = "}";313return(myword);314break;315case',':316 myword->typenum = 32; 317 myword->word = ",";318return(myword);319break;320case':':m_getch();321if(ch == '=')322 {323 myword->typenum = 18; 324 myword->word = ":="; 325return(myword);326 }327 retract();328 myword->typenum = 17; 329 myword->word = ":";330return(myword);331break;332case';':333 myword->typenum = 26; 334 myword->word = ";";335return(myword);336break;337case'>':m_getch();338if(ch == '=')339 {340 myword->typenum = 24; 341 myword->word = ">="; 342return(myword);343 }344 retract();345 myword->typenum = 23; 346 myword->word = ">";347return(myword);348break;349case'<':m_getch();350if(ch == '=')351 {352 myword->typenum = 22; 353 myword->word = "<="; 354return(myword);355 }356else if(ch == '>')357 {358 myword->typenum = 21; 359 myword->word = "<>"; 360return(myword);361 }362 retract();363 myword->typenum = 20; 364 myword->word = "<";365return(myword);366break;367case'!':m_getch();368if(ch == '=')373 }374 retract();375 myword->typenum = -1; 376 myword->word = "ERROR"; 377return(myword);378break;379case'#':380 myword->typenum = 0;381 myword->word = "#";382return(myword);383break;384case'\0':385 myword->typenum = 0;386 myword->word = "OVER"; 387return(myword);388break;389default: myword->typenum = -1; 390 myword->word = "ERROR"; 391return(myword);392 }393 }。
编译原理-语法分析器-仅供参考,不可滥用!
青岛理工大学课程实验报告
(2).递归下降分析程序示意图(左)语法串分析程序示意图(右)
(4)statement 语法分析程序流程图(左)expression表达式分析函数示意图(右)
(3)term分析函数示意图(左)factor分析过程示意图(右)
调试过程及实验1.测试一
输入begin x:=9; x:=2*3; b:=a+x;end ;# 后经语法分析输出如图所示:
结
果
2.测试二
输入x:=a+b*c end # 后经语法分析输出如图所示:
3.测试三
输入 begin q:=6; d:=4; end #,经语法分析输出如图所示:
4.测试四
输入 begin a:=4;b:=5;c:=a*b+a #,经语法分析输出如图所示:
总结
通过本次试验,我们设计出了一个比较符合要求的语法分析器,同时了解了语法分析的过程,其主程序大致流程为:“置初值”→调用wordScanAnalyse函数读下一个单词符号→调用IrParse→结束。
分析程序的各个判断条件可以知道,需要调用函数factor();expression();yucu();term();statement();lrparser();其中嵌套了条件语句
使得拥有较为全面的处理机制,当程序不以“begin”开头,或不以“end #”。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验二语法分析器一、实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。
使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。
有利于提高学生的专业素质,为培养适应社会多方面需要的能力。
二、实验内容◆根据某一文法编制调试LL (1 )分析程序,以便对任意输入的符号串进行分析。
◆构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。
◆分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。
三、LL(1)分析法实验设计思想及算法◆模块结构:(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
四、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
2、如果遇到错误的表达式,应输出错误提示信息。
3、对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i输出的格式如下:五、实验源程序LL1.javaimport java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.table.DefaultTableModel;import java.sql.*;import java.util.Vector;public class LL1 extends JFrame implements ActionListener {/****/private static final long serialVersionUID = 1L;JTextField tf1;JTextField tf2;JLabel l;JButton b0;JPanel p1,p2,p3;JTextArea t1,t2,t3;JButton b1,b2,b3;JLabel l0,l1,l2,l3,l4;JTable table;Statement sta;Connection conn;ResultSet rs;DefaultTableModel dtm;String Vn[]=null;Vector<String> P=null;int firstComplete[]=null;//存储已判断过first的数据char first[][]=null;//存储最后first结果int followComplete[]=null;//存储已判断过follow的数据char follow[][]=null;//存储最后follow结果char select[][]=null;//存储最后select结果int LL=0;//标记是否为LL(1)String vt_tou[]=null;//储存VtObject shuju[][]=null;//存储表达式数据char yn_null[]=null;//存储能否推出空LL1(){setLocation(100,0);setSize(700,780);tf1=new JTextField(13);tf2=new JTextField(13);l=new JLabel(">>");l0=new JLabel("输入字符串:");l1=new JLabel("输入的文法为:");l2=new JLabel(" ");l3=new JLabel("分析的结果:");l4=new JLabel("预测分析表:");//p1=new JPanel();p2=new JPanel();p3=new JPanel();t1=new JTextArea(24,20);t2=new JTextArea(1,30);t3=new JTextArea(24,40);b0=new JButton("确定(S为开始)");b1=new JButton(" 判断文法 ");b2=new JButton("输入");b3=new JButton("清空");table=new JTable();JScrollPane jp1=new JScrollPane(t1);JScrollPane jp2=new JScrollPane(t2);JScrollPane jp3=new JScrollPane(t3);p2.add(tf1);p2.add(l);p2.add(tf2);p2.add(b0);p2.add(b1);p2.add(l0);p2.add(l2);p2.add(jp2);p2.add(b2);p2.add(b3);p2.add(l1);p2.add(l3);p2.add(jp1);p2.add(jp3);p3.add(l4);p3.add(new JScrollPane(table));add(p2,"Center");add(p3,"South");b0.addActionListener(this);b1.addActionListener(this);b2.addActionListener(this);b3.addActionListener(this);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);table.setPreferredScrollableViewportSize(new Dimension(660,200));setVisible(true);}public void actionPerformed(ActionEvent e){if(e.getSource()==b0){String a=tf1.getText();String b=tf2.getText();t1.append(a+'→'+b+'\n');}if(e.getSource()==b1){t3.setText("");int Vnnum=0,k;Vn=new String[100];P=new Vector<String>();String s[]=t1.getText().split("\n");for(int i=0;i<s.length;i++){if(s.length<2){t3.setText("文法输入有误,请重新输入");//判断长度是否符合return;}if(s[i].charAt(0)<='Z'&&s[i].charAt(0)>='A'&&s[i].charAt(1)=='→') {for(k=0;k<Vnnum;k++){if(Vn[k].equals(s[i].substring(0, 1))){break;}}if(Vnnum==0||k>=Vnnum){Vn[Vnnum]=s[i].substring(0, 1);//存入Vn数据Vnnum++;}P.add(s[i]);}else{t3.setText("文法输入有误,请重新输入");return;}}yn_null=new char[100];first=new char[Vnnum][100];int flag=0;String firstVn[]=null;firstComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++) //依次求 FIRST**{flag=0;firstVn=new String[20];if((flag=add_First(first[i],Vn[i],firstVn,flag))==-1)return;firstComplete[i]=1;}t3.append("first集:"+"\n"); //显示FIRST**for(int i=0;Vn[i]!=null;i++){t3.append("first("+Vn[i]+")={ ");for(int j=0;first[i][j]!='\0';j++){t3.append(first[i][j]+" , ");}t3.append("}"+"\n");}follow=new char[Vnnum][100];String followVn[]=null;followComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++) //求FOLLOW**{flag=0;followVn=new String[20];if((flag=tianjiaFollow(follow[i],Vn[i],followVn,flag))==-1)return ;followComplete[i]=1;}t3.append("follow集:"+"\n"); //显示FOLLOW**for(int i=0;Vn[i]!=null;i++){t3.append("follow("+Vn[i]+")={ ");for(int j=0;follow[i][j]!='\0';j++){t3.append(follow[i][j]+" , ");}t3.append("}"+"\n");}select=new char[P.size()][100];for(int i=0;i<P.size();i++) //求SELECT**{flag=0;tianjiaSelect(select[i],(String)P.elementAt(i),flag);}t3.append("select集:"+"\n"); //显示SELECT**for(int i=0;i<P.size();i++){t3.append("select("+(String)P.elementAt(i)+")={ ");for(int j=0;select[i][j]!='\0';j++){t3.append(select[i][j]+" , ");}t3.append("}"+"\n");}for(int i=0;Vn[i]!=null;i++)//判断select交集是否为空{int biaozhi=0;char save[]=new char[100];for(int j=0;j<P.size();j++){String t=(String)P.elementAt(j);if(t.substring(0,1).equals(Vn[i])){for(k=0;select[j][k]!='\0';k++){if(puanduanChar(save,select[j][k])){save[biaozhi]=select[j][k];biaozhi++;}else//当有交集时,不为LL(1)文法{t3.append("不是LL(1)文法!!"+"\n");return;}}}}}char Vt[]=new char[100];int biaozhi=0;for(int i=0;i<P.size();i++){String t=(String)P.elementAt(i);for(int j=2;j<t.length();j++)//提取表达式右侧的终结符存入Vt{if(t.charAt(j)>'Z'||t.charAt(j)<'A'){if(puanduanChar(Vt,t.charAt(j))){Vt[biaozhi]=t.charAt(j);biaozhi++;}}}}if(puanduanChar(Vt,'#'))//若可推出空集,则将#加入Vt。