精华内容
下载资源
问答
  • 语法分析

    2018-04-26 23:22:44
    一、主要内容1....语法分析的过程:语法分析就是判断一个输入串是否符合语法规则,判断的方法是自上而下的分析,自下而上的规约。分析的结果是构造一颗语法树。(1)自上而下的分析:即对于一个输...

    一、主要内容

    1.语法分析的过程

    2.文法的改造

    3.递归下降分析器的设计

    4.语法分析器的自动生成

    二、

    1.什么是语法分析:语法分析师编译过程的核心部分,它的任务是再次发分析识别出单词符号串的基础上,分析并判定程序的语法结构是否符合语法规则。


    语法分析的过程:语法分析就是判断一个输入串是否符合语法规则,判断的方法是自上而下的分析,自下而上的规约。分析的结果是构造一颗语法树。

    (1)自上而下的分析:即对于一个输入串,从文法的根节点开始,根据文法自上而下的为输入串建立一个语法树。即为输入串寻找一个最左推导。

    面临的问题:文法的左递归问题,回溯的不确定性,虚假匹配的问题,不能准确地确定出错的地方,效率低。

    (2)LL(1)分析法:

    消除直接左递归:


    消除间接左递归:

    将间接左递归改为直接左递归:


    消除直接左递归:


    消除回溯:

    消除回溯,需要定义FIRST集,令文法G是不含左递归的文法,对G的非终结符的候选α,定义它的开始符号(终结首符)集合。

    提取公共左因子:

    假设A的产生式为:A→δβ1|δβ2||δβn|γ1| γ2||γm,其中每个γ不以δ开头,那么把这些产生式改写为:  A→δA’ |γ1| γ2||γm         A’→β1|β2||βn。

    反复提取左因子(包括对新引进的非终结符,例如A)。


    (3)递归下降程序分析

    递归下降分析器,就是一个由一组递归程序组成,每个程序对应一个非终结符的分析程序。具体做法是对文法的每一个非终结符都编一个分析程序。当根据文法和当时的输入符号预测到要用某个非终结符去匹配输入串时,就调用该非终结符的分析程序。

    (4)预测分析从程序

    预测分析程序就是LL(1)分析器的一种,它使用一张分析表和一个栈进行控制。

    工作过程:

    LL分析程序构造和分析过程,这一部分由三部分能组成:分析表,执行程序和符号栈。

    构建预测分析表:

    FIRST(X):

    FOLLOW(X)


    构建预测分析表:


    (5)LL(1)分析中的错误处理

    跳过输入串中的一些符号,直到遇到同步符号。遇到同步符号时,将符号栈顶的非终结符出栈。将FOLLOW(A)设为同步符号。将FIRST(A)加入到同步符号。如果非终结符产生空串,可以自动匹配,以推迟检测到错误的时间。如果栈顶是终结符,当出错时,直接将栈顶出栈。

    三、习题

      

    总结:

    这一张还挺难的,反正我是没怎么理解。看课件也只能看到一知半解,做的题也是找大神教着我做的。总的来说这一张承接了上一张的内容,可能是因为我上一章的内容就没怎么弄明白,所以这一章就更不会了,还要继续自己看。


    展开全文
  • 语法分析器-LL(1)语法分析

    千次阅读 多人点赞 2019-07-09 09:39:45
    通过设计、编制、调试-个典型的语法分析程序(任选有代表性的语法分析方法,如LL(1)、递归下降分析法、LR、 算符优先分析法)等,作为编制语法分析程序的依据,对词法分析器所提供的单词序列进行语法检测和结构分析,...

    一丶实验名称

    语法分析器

    二丶实验目的及要求

    通过设计、编制、调试-个典型的语法分析程序(任选有代表性的语法分析方法,如LL(1)、递归下降分析法、LR、 算符优先分析法)等,作为编制语法分析程序的依据,对词法分析器所提供的单词序列进行语法检测和结构分析,实现并进- -步掌握常用的语法分析方法。

    三、实验内容

    选择对各种常见高级程序设计语言都较为通用的语法结构作为分析对象(例如表达式、if、 while、for 等等),给出其文法规则描述(注意,文法规则的描述要符合所选分析方法的要求,比如用LL(1)分析法,文法必须是LL(1)文法),设计并实现一一个完整的语法分析程序。

    输入:源程序以文件的形式输入。

    输出:对于输入的源程序,如果输入源程序是给定文法定义的合法程序,则输出“success",如果不是,即输入源程序有错误,则输出“Error”,并且尽可能指出出错位置和原因。

    四、实验算法描述

    文法规则:

     E→TZ

     Z→+TZ|ε

     T→FY

     Y→*FY|ε

     F→(E)|i

    程序描述(LL(1)文法)

    本程序是基于以构建好的某一语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。

    基本实现思想:接收用户输入的字符串(字符串以“#”表示结束)后,对用作分析栈的一维数组和存放分析表的二维数组进行初始化。然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,则出错,则语法分析结束,输入的字符串为文法的一个句子,否则出错,若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。若不为“#”且不与当前输入符号一样,则出错。

    1.First集和Follow集

    FIRST(E)={(,i} FOLLOW(E)={),#}

    FIRST(Z)={+,ε} FOLLOW(Z)={),#}

    FIRST(T)={(,i} FOLLOW(T)={+,),#}

    FIRST(Y)={*,ε} FOLLOW(Y)={+,),#}

    FIRST(F)={(,i} FOLLOW(F)={*,+,),#}

    2.构建好的预测分析表

     

    i

    +

    *

    (

    )

    #

    E

    →TZ

     

     

    →TZ

    synch

    synch

    Z

     

    →+TZ

     

     

    →ε

    →ε

    T

    →FY

    synch

     

    →FY

    synch

    synch

    Y

     

    →ε

    →*FY

     

    →ε

    →ε

    F

    →i

    synch

    synch

    →(E)

    synch

    synch

                                          LL(1)预测分析表

    3.运行结果

    输入正确的源程序截图:

    输出结果截图

     

    输入错误的源程序截图:

    输出结果截图

     

    五、设计技巧和心得体会

    这次实验编写了一个语法分析方法的程序。但是在LL (1)分析器的编写中我只达到了最低要求,就是自己手动输入的文法规则然后通过程序将预测分析表构造出来,然后自已编写总控程序根据分析表进行分析。

    通过本次试验,我能够设计一个简单的语法分析程序,实现对文法规则进行语法检查和结构分析,进一步掌握常用的语法分析方法。

    六、源程序清单(电子版)

    import java.util.Stack;
    
    public class GramerAnasys {
    	
    	//加入同步符号的LL(1)分析表
    	private  String [][] analysisTable = new String[][]{
    			{"TZ","","","TZ","synch","synch"},
    			{"","+TZ","","","ε","ε"},
    			{"FY","synch","","FY","synch","synch"},
    			{"","ε","*FY","","ε","ε"},
    			{"i","synch","synch","(E)","synch","synch"}
    	};
    	
    	//存储终结符
    	private String [] VT = new String[]{"i","+","*","(",")","#"};
    	
    	//存储终结符
    	private String [] VN = new String[]{"E","Z","T","Y","F"};
    	//输入串
    	
    	private StringBuilder strToken = new StringBuilder("i*i)+i");
    	
    	//分析栈
    	private Stack<String> stack = new Stack<String>();
    	
    	//a保存从输入串中读取的一个输入符号,当前符号
    	private String a = null;
    	
    	//X中保存stack栈顶符号
    	private String X = null;
    	
    	//flag标志预测分析是否成功
    	private boolean flag = true;
    	
    	//记录输入串中当前字符的位置
    	private int cur = 0;
    	
    	//记录步数
    	private int count = 0;
    	
    	//输出语法规则
    	protected void print(){
    		System.out.printf("E→TZ \n"+"Z→+TZ|ε \n"+"T→FY \n"+"Y→*FY|ε \n"+"F→(E)|i \n");
    		
    	}
    	//初始化
    	protected void init(){
    		strToken.append("#");
    		stack.push("#");
    		System.out.printf("%-9s %-38s %6s %-20s\n","步骤 ","符号栈 ","        输入串 ","    所用产生式 ");
    		stack.push("E");
    		curCharacter();
    		System.out.printf("%-6d %-20s %6s \n",count,stack.toString(),strToken.substring(cur, strToken.length()));
    	}
    	
    	//读取当前栈顶符号
    	protected String stackPeek(){
    		X = stack.peek();
    		return X;
    	}
    	
    	//返回输入串中当前位置的字母
    	private String curCharacter(){
    			a = String.valueOf(strToken.charAt(cur));
    		return a;
    	}
    	
    	//判断X是否是终结符
    	protected boolean XisVT(){
    		for(int i = 0 ; i < (VT.length - 1); i++){
    			if(VT[i].equals(X)){
    				return true;
    			}
    		}
    		return false;
    	}
    	
    	//查找X在非终结符中分析表中的横坐标
    	protected String VNTI(){
    		int Ni = 0 , Tj = 0;
    		for(int i = 0 ; i < VN.length ; i++){
    			if(VN[i].equals(X)){
    				Ni = i;
    			}
    		}
    		for(int j = 0 ; j < VT.length ; j++){
    			if(VT[j].equals(a)){
    				Tj = j;
    			}
    		}
    		return analysisTable[Ni][Tj];
    	}
    	
    	//判断M[A,a]={X->X1X2...Xk}
    	//把X1X2...Xk推进栈
    	//X1X2...Xk=ε,不推什么进栈
    	protected boolean productionType(){
    		if(VNTI() != ""){
    			return true;
    		}
    		return false;
    	}
    	
    	//推进stack栈
    	protected void pushStack(){
    		stack.pop();
    		String M = VNTI();
    		String ch;
    		for(int i = (M.length() -1) ; i >= 0 ; i--){
    			ch = String.valueOf(M.charAt(i));
    			stack.push(ch);
    		}
    		System.out.printf("%-6d %-20s %6s %-1s->%-12s\n",(++count),stack.toString(),strToken.substring(cur, strToken.length()),X,M);
    	}
    	
    	//总控程序
    	protected void totalControlProgram(){
    		while(flag == true){
    			stackPeek();
    			if(XisVT() == true){
    				if(X.equals(a)){
    					cur++;
    					a = curCharacter();
    					stack.pop();
    					System.out.printf("%-6d %-20s %6s \n",(++count),stack.toString(),strToken.substring(cur, strToken.length()));
    				}else{
    					ERROR();
    				}
    			}else if(X.equals("#")){
    				if(X.equals(a)){
    					flag = false;
    				}else{
    					ERROR();
    				}
    			}else if(productionType() == true){
    				if(VNTI().equals("synch")){
    					ERROR();
    				}else if(VNTI().equals("ε")){
    					stack.pop();
    					System.out.printf("%-6d %-20s %6s %-1s->%-12s\n",(++count),stack.toString(),strToken.substring(cur, strToken.length()),X,VNTI());
    				}else{
    					pushStack();
    				}
    			}else{
    				ERROR();
    			}
    		}
    	}
    	
    	//出现错误
    	protected void ERROR(){
    		System.out.println("Error.输入串出现错误,无法进行分析");
    		System.exit(0);
    	}
    	
    	//打印存储分析表
    	protected void printf(){
    		if(flag == false){
    			System.out.println("********success");
    		}else {
    			System.out.println("********Error");
    		}
    		
    	}
    	
    	public static void main(String[] args) {
    		
    		GramerAnasys gramerAnasys= new GramerAnasys();
    		gramerAnasys.print();
    		gramerAnasys.init();
    		gramerAnasys.totalControlProgram();
    		gramerAnasys.printf();
    	}
    	
    }

     

    展开全文
  • 编译原理:语法分析

    万次阅读 多人点赞 2019-04-29 17:01:40
    通过设计、编制、调试一个典型的语法分析程序(任选有代表性的语法分析方法,如LL(1)、递归下降分析法、LR、算符优先分析法)等,作为编制语法分析程序的依据,对词法分析器所提供的单词序列进行语法检测和结构分析...

    语法分析程序



    一、作业目的和要求

    通过设计、编制、调试一个典型的语法分析程序(任选有代表性的语法分析方法,如LL(1)、递归下降分析法、LR、算符优先分析法)等,作为编制语法分析程序的依据,对词法分析器所提供的单词序列进行语法检测和结构分析,实现并进一步掌握常用的语法分析方法。


    二、作业内容

    选择对各种常见高级程序设计语言都较为通用的语法结构作为分析对象(例如表达式、if、while、for等等),给出其文法规则描述(注意,文法规则的描述要符合所选分析方法的要求,比如用LL(1)分析法,文法必须是LL(1)文法),设计并实现一个完整的语法分析程序。

    • 输入:源程序以文件的形式输入。
    • 输出:对于输入的源程序,如果输入源程序是给定文法定义的合法程序,则输出”success”,如果不是,即输入源程序有错误,则输出“Error”,并且尽可能指出出错位置和原因。

    三、作业要求

    1、说明语法分析的源语言是什么?
    能分析的语法成分有哪些(比如if、while、表达式、switch等等)。
    给出每个语法规则的文法描述。(可以自定义语法成分,设计合理的语法规则。)

    运用的Java语言写成的语法分析程序,
    语法成分包括:if选择结构,while循环结构,for循环结构。

    2、说明选择的语法分析方法是哪种?描述总体设计思路和主要的流程图。

    语法分析的方法是LL(1)文法。

    • 设计思路:

    • 1.构造单个文法符号X的first集:
      如果X为终结符,First(X)=X;
      如果X->ε是产生式,把ε加入First(X);
      如果X是非终结符,如X->YZW。从左往右扫描产生式右部,把First(Y)加入First(X); 如果First(Y)不包含ε,表示Y不可为空,便不再往后处理;如果First(Y)包含ε,表示Y可为空,则处理Z,依次类推。
      构造文法符号串的first集,如:X->YZW;求YZW的first集
      从左往右扫描该式,加入其非空first集:把First(Y)加入First(YZW)
      若包含空串,处理下一个符号:如果First(Y)包含空串,便处理Z;不包含就退出;处理到尾部,即所有符号的first集都包含空串 把空串加入First(YZW)。

    • 2.在计算First(X)集之后的基础上:
      (1)$属于FOLLOW(S),S是开始符;
      (2)查找输入的所有产生式,确定X后紧跟的终结符;
      (3)如果存在A->αBβ,(α、β是任意文法符号串,A、B为非终结符),把first(β)的非空符号加入follow(B);
      (4)如果存在A->αB或A->αBβ 但first(β)包含空,把follow(A)加入follow(B)。

    • 3.构造预测分析表:
      对于每个产生式A->α,first(α)中的终结符a,把A->α加入M[A,a]。
      如果空串在first(α)中,说明可为空,找它的follow集,对于follow(A)中的终结符b,把A->α加入M[A,b];
      如果空串在first(α)中,且 “$”也在follow(A)中,说明A后可以接终结符,故把A->α加入M[A,$]中。

    • 4.执行分析:
      输入一个串,文法G的预测分析表,输出推导过程:
      $ 和 开始符S入栈,栈顶符号X,index指向分析串的待分析符号a。
      栈非空执行以下循环:
      如果X==a,表示匹配,符号栈弹出一个,index++指向下一个符号;
      否则,如果X是终结符,出错;
      否则,如果查表为error,出错;
      否则,查表正确,弹出栈顶符号,把其右部各个符号进栈,令X为栈顶符号。

    • 流程图:
      在这里插入图片描述
      在这里插入图片描述

    3、编程实现,程序中编写的各种函数,需要给出注释,说明函数的作用。
    通过实现接口中的方法来完成语法分析的功能。

    package Try;
    
    interface MyAnalyseFun {
        void Init();//初始化
        void getVnVt();//获取非终结符和终结符的集合
        void getFirst(Character c);//first集
        void getFirst(String s);//任意字符的first集
        void getFollow(char c);//follow集
        void createTable();//构造表
        void analyzeLL();//LL(1)分析过程
        String find(char X, char a);//查找
        void insert(char X, char a,String s);//插入
        void displayLL();//输出分析过程
        void ouput();//其他输出信息
    }
    

        package Try;
        
        import java.io.*;
        import java.util.*;
        
        public class MyAnalyse implements MyAnalyseFun{
            /**
             * 几个比较重要的参数
             * @param MyfirstSet 终结符的first集合
             * @param MyfirstSetX 任意符号的first集合
             * @param start 文法的开始符
             * @param MyfollowSet follow集
             * @param VnSet 终结符的集合
             * @param VtSet 终结符的集合
             * @param inputStrings 文法拓展的输入
             * @param outputSet 输出的集合
             * @param table 分析表
             * @param MyAnaStatck 分析栈
             * @param strInput 需要使用预测分析器的输入串
             * @param MyAction 分析动作
             * @param Index 分析的索引值
             */
            //从文件中读入时后台无法识别空串ε,因此用符号&代替空串ε
    
        //first集是终结符的first集
        protected HashMap<Character, HashSet<Character>> MyfirstSet = new HashMap<>();
        //firstX集是指任意符号串的first集
        protected HashMap<String, HashSet<Character>> MyfirstSetX = new HashMap<>();
        //文法的开始符
        protected Character start = 'S';
        //follow集
        protected HashMap<Character, HashSet<Character>> MyfollowSet = new HashMap<>();
    
        //存储非终结符的结合
        protected HashSet<Character> VnSet = new HashSet<>();
        //存储终结符的结合
        protected HashSet<Character> VtSet = new HashSet<>();
        protected HashMap<Character, ArrayList<String>> outputSet = new HashMap<>();
        //输入文法
        //S->a|^|(T)
        //T->SU
        //U->,SU|&
    //    protected String [] inputStrings = {   "S->a",
    //                                        "S->^",
    //                                        "S->(T)",
    //                                        "T->SU",
    //                                        "U->,SU",
    //                                        //"U->ε",
    //                                        "U->&"   };
        //定义分析表
        protected String [][] table;
        //分析栈
        protected Stack<Character> MyAnaStatck = new Stack<>();
        //定义要分析的输入串
        protected String strInput = "(a,a)$";
        //对动作的初始化
        protected String MyAction = "";
        int Index = 0;
    
        //从文件中读入
        protected String[] inputStrings = getSource();
    
        protected MyAnalyse() {
        }
    
        public static void main(String[] args){
            MyAnalyse test = new MyAnalyse();
    
            test.getVnVt();
            test.Init();
            test.createTable();
            test.analyzeLL();
            test.ouput();
            
        }
    
        //从文件中读入文法的方法
        public  static  String[] getSource(){
            StringBuffer temp = new StringBuffer();
            FileInputStream fis= null;
            try {
                fis = new FileInputStream("E:\\readin.txt");
                byte[] buff=new byte[1024];
                int len=0;
                while((len=fis.read(buff))!=-1){
                    temp.append(new String(buff,0,len));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return temp.toString().split("\n");
        }
    
        //初始化
        @Override
        public void Init() {
            for (String s1 : inputStrings) {
                //"S->a",
                //"S->^",
                //"S->(T)",
                //"T->SU",
                //"U->,SU",
                //"U->&"
                String[] str = s1.split("->");//通过符号“->”分隔每行的文法
                char c = str[0].charAt(0);//取得左边的非终结符
                ArrayList<String> list = outputSet.containsKey(c) ? outputSet.get(c) : new ArrayList<>();
                list.add(str[1]);//添加文法右边的内容到集合中
                outputSet.put(c, list);
            }
            //求非终结符的first集
            for (Character c1 : VnSet)
                getFirst(c1);
    
            for (Character c2 : VnSet) {
                ArrayList<String> l = outputSet.get(c2);
                for (String s2 : l)
                    getFirst(s2);
            }
            //求出follow集
            getFollow(start);
            for (Character c3 : VnSet) {
                getFollow(c3);
            }
        }
    
        @Override
        public void getVnVt() {//取出终结符和非终结符的集合
            for (String s3 : inputStrings) {
                String[] str = s3.split("->");
                VnSet.add(str[0].charAt(0));
            }
            for (String s4 : inputStrings) {
                String[] str = s4.split("->");
                String right = str[1];
                for (int i = 0; i < right.length(); i++)
                    if (!VnSet.contains(right.charAt(i)))
                        VtSet.add(right.charAt(i));
            }
        }
    
        @Override
        public void getFirst(Character c) {
            ArrayList<String> list = outputSet.get(c);
            HashSet<Character> set = MyfirstSet.containsKey(c) ? MyfirstSet.get(c) : new HashSet<Character>();
            // c为终结符 直接添加
            if (VtSet.contains(c)) {
                set.add(c);
                MyfirstSet.put(c, set);
                return;
            }
            // c为非终结符 处理其每条产生式
            for (String s5 : list) {
                // c 推出空串 直接添加
                if (s5 == Character.toString('&')) {
                    set.add('&');
                }
                // X -> Y1Y2Y3… 情况
                else {
                    // 从左往右扫描生成式右部
                    int i = 0;
                    while (i < s5.length()) {
                        char tn = s5.charAt(i);
                        //先处理防止未初始化
                        getFirst(tn);
                        HashSet<Character> tvSet = MyfirstSet.get(tn);
                        // 将其first集加入左部
                        for (Character tmp : tvSet)
                            set.add(tmp);
                        // 若包含空串 处理下一个符号
                        if (tvSet.contains('&'))
                            i++;
                            // 否则退出 处理下一个产生式
                        else
                            break;
                    }
                }
            }
            MyfirstSet.put(c, set);
        }
    
        @Override
        public void getFirst(String s) {
            HashSet<Character> set = (MyfirstSetX.containsKey(s))? MyfirstSetX.get(s) : new HashSet<Character>();
            // 从左往右扫描该式
            int i = 0;
            while (i < s.length()) {
                char tn = s.charAt(i);
                HashSet<Character> tvSet = MyfirstSet.get(tn);
                // 将其非空 first集加入左部
                for (Character tmp : tvSet)
                    if(tmp != '&')
                        set.add(tmp);
                // 若包含空串 处理下一个符号
                if (tvSet.contains('&'))
                    i++;
                    // 否则结束
                else
                    break;
                // 到了尾部 即所有符号的first集都包含空串 把空串加入
                if (i == s.length()) {
                    set.add('&');
                }
            }
            MyfirstSetX.put(s, set);
        }
    
        @Override
        public void getFollow(char ch) {
            ArrayList<String> list = outputSet.get(ch);
            HashSet<Character> setA = MyfollowSet.containsKey(ch) ? MyfollowSet.get(ch) : new HashSet<Character>();
            //如果是开始符 添加 $
            if (ch == start) {
                setA.add('$');
            }
            //查找输入的所有产生式,确定c的后跟 终结符
            for (Character cha : VnSet) {
                ArrayList<String> l = outputSet.get(cha);
                for (String s : l)
                    for (int i = 0; i < s.length(); i++)
                        if (s.charAt(i) == ch && i + 1 < s.length() && VtSet.contains(s.charAt(i + 1)))
                            setA.add(s.charAt(i + 1));
            }
            MyfollowSet.put(ch, setA);
            //处理c的每一条产生式
            for (String s : list) {
                int i = s.length() - 1;
                while (i >= 0 ) {
                    char tn = s.charAt(i);
                    //只处理非终结符
                    if(VnSet.contains(tn)){
                        // 都按 A->αB&  形式处理
                        //若&不存在   followA 加入 followB
                        //若&存在,把&的非空first集  加入followB
                        //若&存在  且 first(&)包含空串   followA 加入 followB
    
                        //若&存在
                        if (s.length() - i - 1 > 0) {
                            String right = s.substring(i + 1);
                            //非空first集 加入 followB
                            HashSet<Character> setF = null;
                            if( right.length() == 1 && MyfirstSet.containsKey(right.charAt(0))) {
                                setF = MyfirstSet.get(right.charAt(0));
                            }
                            else{
                                if(!MyfirstSetX.containsKey(right)){
                                    HashSet<Character> set = new HashSet<Character>();
                                    MyfirstSetX.put(right, set);
                                }
                                setF = MyfirstSetX.get(right);
                            }
                            HashSet<Character> setX = MyfollowSet.containsKey(tn) ? MyfollowSet.get(tn) : new HashSet<Character>();
                            for (Character cha : setF) {
                                if (cha != '&') {
                                    setX.add(cha);
                                }
                            }
                            MyfollowSet.put(tn, setX);
    
                            // 若first(&)包含&   followA 加入 followB
                            if(setF.contains('&')){
                                if(tn != ch){
                                    HashSet<Character> setB = MyfollowSet.containsKey(tn) ? MyfollowSet.get(tn) : new HashSet<Character>();
                                    for (Character cha : setA) {
                                        setB.add(cha);
                                    }
                                    MyfollowSet.put(tn, setB);
                                }
                            }
                        }
                        //若&不存在   followA 加入 followB
                        else{
                            // A和B相同不添加
                            if(tn != ch){
                                HashSet<Character> setB = MyfollowSet.containsKey(tn) ? MyfollowSet.get(tn) : new HashSet<Character>();
                                for (Character cha : setA)
                                    setB.add(cha);
                                MyfollowSet.put(tn, setB);
                            }
                        }
                        i--;
                    }
                    //如果是终结符往前扫描  如 A->aaaBCDaaaa  此时&为 CDaaaa
                    else i--;
                }
            }
        }
    
        @Override
        public void createTable() {//构造预测分析表的格式
            //终结符数组
            Object[] VtArray = VtSet.toArray();
            //非终结符数组
            Object[] VnArray = VnSet.toArray();
            // 预测分析表初始化
            table = new String[VnArray.length + 1][VtArray.length + 1];
            table[0][0] = "Vn/Vt";
            //初始化首行首列
            for (int i = 0; i < VtArray.length; i++)
                table[0][i + 1] = (VtArray[i].toString().charAt(0) == '&') ? "$" : VtArray[i].toString();
            for (int i = 0; i < VnArray.length; i++)
                table[i + 1][0] = VnArray[i] + "";
            //全部置error
            for (int i = 0; i < VnArray.length; i++)
                for (int j = 0; j < VtArray.length; j++)
                    table[i + 1][j + 1] = "error";
    
            //插入生成式
            for (char A : VnSet) {
                ArrayList<String> l = outputSet.get(A);
                for(String s : l){
                    HashSet<Character> set = MyfirstSetX.get(s);
                    for (char a : set)
                        insert(A, a, s);
                    if(set.contains('&'))  {//如果包含&
                        HashSet<Character> setFollow = MyfollowSet.get(A);
                        if(setFollow.contains('$'))//判断follow集中是否包含$
                            insert(A, '$', s);
                        for (char b : setFollow)
                            insert(A, b, s);
                    }
                }
            }
        }
    
        @Override
        public void analyzeLL() {
            System.out.println("-------------------1.LL分析过程-------------------");
            System.out.println("|               分析栈        输入串     动作|  ");
            MyAnaStatck.push('$');
            MyAnaStatck.push('S');
            displayLL();//调用分析过程方法
            char X = MyAnaStatck.peek();
            while (X != '$') {
                char a = strInput.charAt(Index);
                if (X == a) {
                    MyAction = "match " + MyAnaStatck.peek();
                    MyAnaStatck.pop();
                    Index++;
                } else if (VtSet.contains(X))
                    return;
                else if (find(X, a).equals("error"))
                    return;
                else if (find(X, a).equals("&")) {
                    MyAnaStatck.pop();
                    MyAction = X + "->&";
                } else {
                    String str = find(X, a);
                    if (str != "") {
                        MyAction = X + "->" + str;
                        MyAnaStatck.pop();
                        int len = str.length();
                        for (int i = len - 1; i >= 0; i--)
                            MyAnaStatck.push(str.charAt(i));
                    } else {
                        System.out.println("error at '" + strInput.charAt(Index) + " in " + Index);
                        return;
                    }
                }
                X = MyAnaStatck.peek();
                displayLL();
            }
            System.out.println("LL(1)文法分析成功!");
            System.out.println("-------------------LL分析过程-------------------");
        }
    
        @Override
        public String find(char X, char a) {
            for (int i = 0; i < VnSet.size() + 1; i++) {
                if (table[i][0].charAt(0) == X)
                    for (int j = 0; j < VtSet.size() + 1; j++) {
                        if (table[0][j].charAt(0) == a)
                            return table[i][j];
                    }
            }
            return "";
        }
    
        @Override
        public void insert(char X, char a, String s) {//插入
            if(a == '&')
                a = '$';
            for (int i = 0; i < VnSet.size() + 1; i++) {
                if (table[i][0].charAt(0) == X)
                    for (int j = 0; j < VtSet.size() + 1; j++) {
                        if (table[0][j].charAt(0) == a){
                            table[i][j] = s;
                            return;
                        }
                    }
            }
        }
    
        @Override
        public void displayLL() {// 对输入串(a,a)$ 输出 LL(1)分析过程
            Stack<Character> s = MyAnaStatck;
            System.out.printf("%23s", s );//输出第一列:分析栈
            System.out.printf("%13s", strInput.substring(Index));//输出第二列:输入串
            System.out.printf("%10s", MyAction);//输出第三列:动作
            System.out.println();
        }
    
        @Override
        public void ouput() {
            // 输出终结符的first集
            System.out.println("-------------------2.first集-------------------");
            for (Character c : VnSet) {
                HashSet<Character> set = MyfirstSet.get(c);
                System.out.printf("%10s",c + "  ->   ");
                for (Character cha : set)
                    System.out.print(cha+" ");
                System.out.println();
            }
            System.out.println("-------------------first集-------------------");
            // 输出任意符号串的first集
            System.out.println("-------------------firstX集-------------------");
            Set<String> setStr =  MyfirstSetX.keySet();
            for (String s : setStr) {
                HashSet<Character> set = MyfirstSetX.get(s);
                System.out.printf("%10s",s + "  ->   ");
                for (Character cha : set)
                    System.out.print(cha+" ");
                System.out.println();
            }
            System.out.println("-------------------firstX集-------------------");
            // 输出follow集
            System.out.println("-------------------3.follow集-------------------");
    
            for (Character c : VnSet) {
                HashSet<Character> set = MyfollowSet.get(c);
                System.out.print("Follow " + c + " : ");
                for (Character cha : set)
                    System.out.print(cha+" ");
                System.out.println();
            }
            System.out.println("-------------------follow集-------------------");
            //构造LL1文法预测分析表
            System.out.println("-------------------4.LL1预测分析表-------------------");
    
            for (int i = 0; i < VnSet.size() + 1; i++) {
                for (int j = 0; j < VtSet.size() + 1; j++) {
                    System.out.printf("%8s", table[i][j] + " ");
                }
                System.out.println();
            }
            System.out.println("-------------------LL1预测分析表-------------------");
        }
    }
    

    四、结果分析

    1、输入正确的源程序截图:
    将符号ε替换为&
    在这里插入图片描述

    输出结果截图:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    2、输入错误的源程序截图:
    输入错误文法
    在这里插入图片描述
    输出结果截图:
    在这里插入图片描述
    3、总结(自己的心得体会、你编写的语法分析程序的优缺点)
    S->a|^|(T)
    T->SU
    U->,SU|ε

    • 优点:文法分析过程比较详细,任务整个完成过程是充实的,这个实验报告相当于对编译原理理论课的一次实践尝试,能收获很多课堂上面学不到的知识,同时也能巩固老师所教授的知识。

    • 缺点:在写程序的时候,卡在了空串那个点。最开始尝试直接在程序中定义文法时,ε能在程序中分析成功。后来在用读入文件的方式定义文法时,控制台出现乱码,这个点解决起来花了一点时间,最后决定将符号ε替换为&,程序才能运行成功。

    展开全文
  • 1.美图 2.位置 语法分析器的功能 ...语法分析器的功能:按照文法的产生式(语言的语法规则),识别输入符号串是否为一个句子(合式程序)。 语法分析的方法 不行 ,看不懂,我太难了 ,不看了。。。。 ...

    1.美图

    在这里插入图片描述

    2.位置

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    语法分析器的功能

    1. 语法分析的任务是分析一个文法的句子结构。
    2. 语法分析器的功能:按照文法的产生式(语言的语法规则),识别输入符号串是否为一个句子(合式程序)。

    语法分析的方法

    在这里插入图片描述
    在这里插入图片描述

    不行 ,看不懂,我太难了 ,不看了。。。。

    展开全文
  • 语法分析:自上而下分析

    万次阅读 2016-10-18 17:48:43
    概述本节将介绍编译程序构造中的一些典型的语法分析方法。语法分析器的功能,自上而下分析面临的问题,LL(1)分析法语法分析器的功能语法分析是编译过程的核心部分。它的任务是在词法分析识别出单词符号串的基础上...
  • 语法分析 语法分析,词法分析,语义分析直接将我拍在了沙滩上,我已经懵了,这篇不建议看,我只是从书中取出一个大概的框架,深层次的东西还没有挖掘。 简介 作为编译过程的核心部分,语法分析根据一定的语法...
  • 编译原理-语法分析

    千次阅读 2019-03-29 00:56:33
    1.语法分析概述 1.1 定义 语法分析就是根据高级语言的语法规则对程序的语法结构进行分析。如下图所示: 1.2 任务 语法分析的任务就是在词法分析识别出正确的单词符号串是否符合语言的语法规则,分析并识别...
  • 编译原理 - 语法分析(1): 自上而下的语法分析 为什么我们不用词法分析那一套方式(正则文法、有限状态机等)来解决语法分析? 正则文法通常什么样? 对于文法G=(V, T, S, P),如果产生式的形式如下:...
  • 语法分析——自顶向下分析方法

    千次阅读 2019-11-10 14:43:15
    语法分析:在计算机科学和语言学中,语法分析(英语:syntactic analysis,也叫 parsing)是根据某种给定的形式文法对由单词序列(如英语单词序列)构成的输入文本进行分析并确定其语法结构的一种过程。 (摘自维基...
  • 实验报告三:语法分析一、实验目的 通过设计、开发一个S语言的语法分析程序,实现对源程序的语法检查和结构分析,加深对相关课堂教学内容的理解,提高语法分析方法的实践能力。二、实验要求 根据下列S语言的语法...
  • 词法分析、语法分析、语义分析

    万次阅读 2018-05-27 23:35:09
    这里就是拿翻译句子来举例子,从英语翻译到汉语,我们需要分析句子的语义,要划分句子的成分要想进行语义分析就要划分句子成分,比如说划分为人、铁锤、窗户等等我们要想划分句子当中的各类成分,就要用语法分析来...
  • 语法分析:自上而下分析 目录语法分析:自上而下分析知识背景计算海明校验码步骤一:计算校验码位数步骤二:确定校验组步骤三:计算校验码的值得出海明校验码利用海明校验码校验数据其他总结 知识背景 百度百科: ...
  • 语法分析语法分析程序  语法分析是编译过程的一个逻辑阶段。语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确....
  • 编译原理 语法分析

    千次阅读 2019-10-25 21:19:10
    语法分析 语法分析的若干问题 语法分析的作用 根据词法分析提供的记号流,生成语法树 检查输入中的语法错误 语法错误的处理原则 可能出现的错误:语法错误和语义错误 语法错误: 词法错误:出现非法字符或关键字、...
  • 语法分析器实现过程(java)

    万次阅读 多人点赞 2019-01-19 10:01:07
    语法分析器是编译原理的一个实验,本文将会详细给出实现的具体步骤,利用java进行示例讲解,源码(包含java和c++两种实现方式)可在处下载。 一、实验目的 设计、编写一个语法分析程序,加深对语法分析原理的理解。 ...
  • 语法分析程序以单词串形式的源程序作为输入或分析的对象。它的基本任务是:根据语言的语法规则(即根据描述该语言的前后文无关文法),分析源程序的语法结构,即分析如何由这些单词组成各种语法范畴(如下标变量、...
  • 自下而上语法分析

    2018-05-20 20:38:51
    本章学习自下而上的语法分析,其分析过程为边输入单词符号,边归约,直至归约到文法的开始符号。(归约是指根据文法的产生式规则,把产生式的右部替换成左部符号)自下而上的分析方法的关键就是找到可归约串。 对于...
  • 语法分析

    千次阅读 2018-04-22 18:36:39
    编译原理-简单的递归下降语法分析器LL(1)在网上看了很多篇关于递归下降分析器的博文,均没有满意的,一是所写的程序不对、二是解释的不够清楚。所以想自己写一篇,顺便总结一下所学。递归下降分析法递归下降分析法的...
  • 语法分析实现--表达式解析

    千次阅读 2020-11-18 23:33:04
    语法分析实现 1. 目标及代码 目标: 实现表达式的语法树构建(加减乘除的表达式解析) 如: 将 a = 1+2*5等表达式解析为语法树的形式 代码地址: git代码仓库 注意: 本文章主要目的是记录个人学习历程,如...
  • java编译器源码分析之语法分析

    千次阅读 2018-11-12 21:47:06
    token流到抽象语法树的过程是语法分析。 前面认识到token流,这部分将介绍抽象语法树(AST)。 那么什么是抽象语法树(AST)?AST长啥样?我们的token流是如何转变成AST的?下面围绕这三个问题展开讨论。 针对什么是抽象...
  • 编译原理-语法分析详解

    千次阅读 多人点赞 2020-12-20 20:57:58
    一文带你读懂语法分析(编译原理)一、前言二、前置知识三、自顶向下的语法分析1、自顶向下的分析会遇到的问题a. 二义性问题b. 回溯问题c. 左递归引起的无穷推导问题2、解决以上问题a. 二义性问题 一、前言   最近...
  • 语法分析 C2.1 实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析. C2.2 实验要求 利用C语言编制递归下降分析程序,并对简单语言进行语法分析. C2.2.1待分析的简单语言的...
  • 语法分析器根据语法将标记流(来自词法分析器)转换为语法树。 目标 从“词法分析器” 任务中获取输出,并根据以下语法将其转换为抽象语法树(AST)。输出应为展平格式。 程序应从文件和/或stdin读取输入,并将输出...
  • 编译原理c++语法分析

    万次阅读 2017-05-31 22:54:27
    语法分析器  针对编译原理第三版-何炎祥主编的书中一个 LL(1)语法分析表,利用c++编写了语法分析程序,下附加代码: /* Name: LL(1)语法分析器  Copyright:  Author:y cc  Date: 18/04/17 16:26 Description: ...
  • Java实现 LeetCode 385 迷你语法分析

    万次阅读 多人点赞 2020-03-11 22:59:29
    385. 迷你语法分析器 给定一个用字符串表示的整数的嵌套列表,实现一个解析它的语法分析器。 列表中的每个元素只可能是整数或整数嵌套列表 提示:你可以假定这些字符串都是格式良好的: 字符串非空 字符串不包含空格...
  • 编译原理:语法分析实验(LR分析法)

    千次阅读 2020-05-28 23:16:45
    语法分析实验 一、实验目的 根据LR分析法的原理,对指定文法构造识别活前缀的DFA,做出相应的LR分析表,并编程实现相应的语法分析程序。或根据预测分析法的原理,对指定文法构造预测分析表,并编程实现相应的语法分析...
  • yacc语法分析与lex词法分析相结合

    千次阅读 2015-05-17 15:32:40
    语法对于某些应用,我们所完成的简单的词类识别也许足够用了;而另一些应用需要识别特殊的标记序列并执行适当的动作。...词法分析程序和语法分析程序的通信当一起使用lex扫描程序和yacc语法分析程序的时候,语法

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 558,075
精华内容 223,230
关键字:

语法分析