精华内容
下载资源
问答
  • 参考C语言版本,用Java写的递归下降分析程序,能对词法分析程序所提供的单词序列进行语法检查和结构分析。被分析的语言应该是PL/0,语法表示如下: (1)<程序>::=begin<语句串>end (2)<语句串>::=<语句>{;...
  • 递归下降分析程序

    2015-06-16 20:57:32
    编译原理递归下降程序,编译原理实验 void E(); //功能识别函数 void E1(); // E' void T(); void T1(); // T' void F(); void input(); // 输入函数 void advance(); //字符串进一
  • 自己写的,很容易读懂,Java程序
  • 编译原理课程设计---递归下降分析程序的实现
  • 递归下降分析程序的设计和实现

    千次阅读 2019-10-29 16:11:32
    递归下降分析程序的设计和实现 一、实验的目的和要求 1、了解语法分析的主要任务。 2、实现基本的递归下降分析器,能够分析任意的符号串是否为该文法所定义的合法算术表达式。 二、实验环境 Windows7 + Dev-C++ 三...

    递归下降分析程序的设计和实现

    一、实验的目的和要求
    1、了解语法分析的主要任务。
    2、实现基本的递归下降分析器,能够分析任意的符号串是否为该文法所定义的合法算术表达式。
    
    二、实验环境
    Windows7 + Dev-C++
    
    三、实验准备
    先将递归下降分析程序的生成认真的学习一遍,理解递归下降分析程序的构成过程。
    
    已知文法G[S]:
    		S → aB | bD
    		B → bC
    		C → aS | bD | ε
    		D → aB | bD | ε
    
    1. 经观察此文法不含左公因式,也不含左递归,求出此文法的FIRST、FOLLOW以及SELECT集。
    产生式FIRSTFOLLOWSELECT
    S → aB{a}{#}{a}
    S → bD{b}{b}
    B → bC{b}{#}{b}
    C → aS{a}{#}{a}
    C → bD{b}{#}{b}
    C → ε{ε}{#}
    D → aB{a}{#}{a}
    D → bD{b}{b}
    D → ε{ε}{#}
    1. 因为S、B、C、D的SELECT集有交集且为空,所以此文法为LL(1)文法。

    2. 测试用例如下(文法推导所得,推导过程略):

      ab
      abb
      abaab
      ababbbbbbbbb
      bbbbbbbbbbbbbbbbbbbbbbbbbbb
      baaaaabbbb(错误用例)
      a##b#(错误用例)
      abcdefg(错误用例)
      ABCDEFG(错误用例)
      
    四、实验内容及步骤

    1. 用递归下降分析程序测试自己写的文法

    #include<stdio.h>
    
    // 函数声明
    void S(void);
    void B(void);
    void C(void);
    void D(void);
    // 定义一个长度为100的字符数组
    char s[100];
    // 用来作数组索引,当每次匹配成功存入数据时index自增1
    int i;
    //  用来标记语句是否正确
    int SIGN;
    
    int main()
    {
        printf("please input a yuju ends with #\n");
        // 一个死循环
        while( 1 )
        {
            SIGN = 0;//语句是否正确用SIGN
            i=0;
            
            // 类似Java中的Scanner,读取输入的字符串
            scanf("%s",&s[0]);
            
            // 当输入的第一个字符为#时,程序直接结束
            if( s[0] == '#')
                return 0;
                 
            S();
            // 如果最后的字符以#结束则输出下面
            if(s[i] == '#' && SIGN == 0){
                printf("This is a right yuju!\n");
            }else{
                printf("This a wrong yuju\n");
            }
            printf("please input a yuju ends with #\n");
        }
        return 1;
    }
    
    void S()
    {
        if(SIGN==0)
        {
            // 当输入的字符串中首字母为a时
            if(s[i]=='a'){
                ++i;    // 自增操作
                B();
            }else if(s[i]=='b'){
                ++i;
                D();
            }else{
                SIGN=1;
            }
        }
    }
    
    void B()
    {
        if(SIGN==0){
           if(s[i]=='b'){
                ++i;
                C();
            }else if(s[i] == '#'){
                SIGN=1;
            }
        }
    }
    
    void C()
    {
        if(SIGN==0){
            if(s[i]=='a'){
                ++i;
                S();
            }else if(s[i]=='b'){
                ++i;
                D();
            }else if(s[i]!='#'){
                SIGN=1;
            }
        }
    }
    
    void D()
    {
        if(SIGN==0){
            if(s[i]=='a'){
                ++i;
                B();
            }else if(s[i]=='b'){
                ++i;
                D();
            }else if(s[i]!='#'){
                SIGN=1;
            }
        }
    }
    

    注: 此代码正好100行,不过可以看出代码质量很差(冗余代码很多),每个函数中的功能都是一样的,应该抽取一下,代码应该可以简洁很多。

    2. 测试用例测试如下
    在这里插入图片描述

    五、实验小结

    1. 遇到的主要问题
    答:
    刚开始测试测试用例时,根据文法推导的句子在程序中一直报错,首先我确定自己推导没有问题,又看了程序代码好像也没有问题,找了好久没有找到,最后使用Xcode(Mac平台下由apple公司维护用来开发iPhone程序和Mac程序的一款集成开发环境)打断点通过单步调试把问题找了出来,因为我把s[i] = ‘p’ 写成了s[i] = ‘P’ 将小写字母写成了大写。这就表现出调试程序的重要性,通过调试可以看计算机如何一步步来执行程序的,对程序有更好的理解。(附上一张调试图)
    在这里插入图片描述
    这是S函数,当我从控制台录入pba时,第一个字符p和s[i]相同,但是当程序执行直接从39行调到了45行,没有执行if(s[i] == ‘P’)语句,我才找到上面所说的错误!

    3. 得到的经验
    答:
    ①:C语言函数声明,这和Java以及其他编程语言不相同,当在main()函数中调用其他函数时,编译器会在main()函数上面找这些函数,如果函数没有声明就会编译报错(找不到),若将函数写在main()函数上,就不会报错。
    ②:首先更加清晰的理解了语法分析的主要任务,它是在词法分析的基础上将单词组合起来,组成一些语句,比如说在Java中,public static void main(String[]args);方法中,如果void写在public前面编译器就会报错,那是因为编译器已经做好了语法分析的工作,说白了对源代码在结构是否正确这就是语法分析的任务。
    ③:理解了递归下降分析法,它是一种自顶向下的分析,根据文法来构造C函数,遇到终结符时通过和自己在屏幕中录入的数据作比较,若相同修改数组索引,这个终结符后面若是一个非终结符则调用这个非终结符的函数。一层一层的向下分析,有时会在函数体中调用自己,这就形成了递归。

    展开全文
  • 递归下降分析程序Java

    2020-06-01 11:08:50
    递归下降分析程序 直接上代码啦0.0 package com.hyh.recursive; import java.util.Scanner; /* 测试正确语句( a ) + b或者^ + ( b ) 测试不同语句需修改字符串数组的长度 懒得改自定义长度了 */ public ...

    在这里插入图片描述
    求递归下降分析程序
    直接上代码啦0.0
    package com.hyh.recursive;

    import java.util.Scanner;
    /*

    • 测试正确语句( a ) + b或者^ + ( b )

    • 测试不同语句需修改字符串数组的长度

    • 懒得改自定义长度了
      */
      public class test2 {

      private static int index = 0;
      private static String[] string = new String[6];

      static void E() {
      // E ->TE’
      if (string[index].equals("(")||string[index].equals(“a”)||string[index].equals(“b”)||string[index].equals("^")) {
      T();
      E1();
      System.out.println(“E-> TE’”);
      }
      }

      static void E1() {
      // E’-> +E|ε
      if (string[index].equals("+")) {
      index++;
      E();
      System.out.println(“E’-> +E”);
      }
      }

      static void T() {
      // T ->FT’
      if (string[index].equals("(")||string[index].equals(“a”)||string[index].equals(“b”)||string[index].equals("^")) {
      F();
      T1();
      System.out.println(“T-> FT’”);
      }
      }

      static void T1() {
      // T’ ->T|ε
      if (string[index].equals("(")||string[index].equals(“a”)||string[index].equals(“b”)||string[index].equals("^")) {
      T();
      System.out.println(“T’-> T”);
      }
      }

      static void F() {
      // F ->PF’
      if (string[index].equals("(")||string[index].equals(“a”)||string[index].equals(“b”)||string[index].equals("^")) {
      P();
      F1();
      System.out.println(“F-> PF’”);
      }
      }

      static void F1() {
      //F’ ->F’|ε
      if (string[index].equals("
      ")) {
      index++;
      F1();
      System.out.println(“F’-> *F’”);
      }
      }

      static void P() {
      //P ->(E)|a|b|^
      if (string[index].equals(“a”)) {
      index++;
      System.out.println(“P-> a”);
      } else if(string[index].equals(“b”)) {
      index++;
      System.out.println(“P-> b”);
      }else if(string[index].equals("^")) {
      index++;
      System.out.println(“P-> ^”);
      }else if (string[index].equals("(")) {
      index++;
      E();
      if (string[index].equals(")")) {
      index++;
      System.out.println(“P->(E)”);
      } else {
      System.out.println(“分析失败”);
      }
      } else {
      System.out.println(“分析失败”);
      }
      }

      public static void main(String[] args) {

       Scanner sc = new Scanner(System.in);
       //System.out.println("请输入算数表达式");
       while (!sc.equals("----")) {
       	System.out.println("请输入算数表达式");
       	string[5] = "#";
       	for (int i = 0; i < 5; i++) {
       		string[i] = sc.next();
       		try {
       			if (string[i].matches("^(-?\\d+)(\\.\\d+)?$")) {
       				string[i] = "i";
       			} else if (string[i].matches("^-?\\d+$")) {
       				string[i] = "i";
       			}
       		} catch (Exception e) {
       		}
       	}
       	E();
       	System.out.println("正确语句");
       	//string.notifyAll();
       }
      

      }
      }

    展开全文
  • 实现一个递归下降语法分析程序,识别用户输入的算术表达式。 二、实验主要内容 1、文法如下: E®TE` E’®+TE’|-TE’|e T®FT` T’®*FT’|/FT’|e F®(E)|i 2、求取各非终结符的First及Follow集合 3、编程...
  • 定义每个非终结符的递归下降分析程序 从开始符号递归下降分析 如递归下降能到输入串的最后一个符号,则输入串合法;反之输入串不合法 代码实现 定义全局变量i用来表示当前输入串指针所在位置 i=0 E的递归下降分析...

    例子文法
    在这里插入图片描述
    实现步骤

    1. 定义每个非终结符的递归下降分析程序
    2. 从开始符号递归下降分析
    3. 如递归下降能到输入串的最后一个符号,则输入串合法;反之输入串不合法

    代码实现

    1. 定义全局变量i用来表示当前输入串指针所在位置
    i=0
    
    1. E的递归下降分析程序:根据文法有E=T∩G
    def E(): # E->TG
        if  T() and G():
            return True
        else:
            return False
    
    1. T的递归下降分析程序:根据文法有T=F∩S
    def T(): # T->FS
        if F() and S():
            return True
        else:
            return False
    
    1. G的递归下降分析程序:根据文法有两种情况,当前输入串指针所指的字符是‘+’或‘-’,将指针前进一位后,返回T∩G
    def G(): # G->+TG|-TG
        global i
        if line[i]=='+' or line[i]=='-':
            i=i+1
            if T() and G():
                return True
            else:
                return False
        else:
            return True
    
    1. S的递归下降分析程序:实现代码原理与G类似
    def S(): # S->*FS|/FS
        global i
        if line[i]=='*' or line[i]=='/':
            i=i+1
            if F() and S():
                return True
            else:
                return False
        else:
            return True
    
    1. F的递归下降分析程序:
    def F(): # F->(E)|i
        global i
        if line[i]=='i':
            i=i+1
            return True
        if line[i]=='(':
            i=i+1
            if E() and line[i]==')':
                i=i+1
                return True
        return False
    
    1. 主函数:如果输入串为q退出程序;若不为q,则在输入串末尾添加#用于确认是否分析完成;若从E开始递归下降分析能到输入串的最后一个字符即当前字符为#,则输入串合法,反之判定为非法字符串并输出错误字符所在的位置
    if __name__ == "__main__":
        print("递归下降分析程序")
        while True:
            i=0
            line=input("输入符号串(包括+-*/()i): ")
            if line=='q':
                break
            line=line+'#'
            if E() and line[i]=='#':
                print("输出结果:"+line[0:len(line)-1]+"为合法符号串")
            else:
                print("输出结果:"+line[0:len(line)-1]+"为非法的符号串")
                print("参考错误:出错字符位于第"+str(i+1)+"处, 该字符为 "+line[i])
    
    1. 输出结果
      在这里插入图片描述

    完整代码

    i=0
    
    def E(): # E->TG
        if  T() and G():
            return True
        else:
            return False
    
    def T(): # T->FS
        if F() and S():
            return True
        else:
            return False
    
    def G(): # G->+TG|-TG
        global i
        if line[i]=='+' or line[i]=='-':
            i=i+1
            if T() and G():
                return True
            else:
                return False
        else:
            return True
    
    def S(): # S->*FS|/FS
        global i
        if line[i]=='*' or line[i]=='/':
            i=i+1
            if F() and S():
                return True
            else:
                return False
        else:
            return True
    
    def F(): # F->(E)|i
        global i
        if line[i]=='i':
            i=i+1
            return True
        if line[i]=='(':
            i=i+1
            if E() and line[i]==')':
                i=i+1
                return True
        return False
    
    if __name__ == "__main__":
        print("递归下降分析程序")
        while True:
            i=0
            line=input("输入符号串(包括+-*/()i): ")
            if line=='q':
                break
            line=line+'#'
            if E() and line[i]=='#':
                print("输出结果:"+line[0:len(line)-1]+"为合法符号串")
            else:
                print("输出结果:"+line[0:len(line)-1]+"为非法的符号串")
                print("参考错误:出错字符位于第"+str(i+1)+"处, 该字符为 "+line[i])
    

    总结
    在代码实现上,递归下降分析法几乎可以称得上是最简单的一种语法分析方法了,但也造成了它的局限性,它只能用于分析LL(1)文法。

    展开全文
  • 对下列文法,用递归下降分析法对任意输入的符号串进行分析: ...(1)递归下降分析程序,编制人:姓名,学号,班级 (2)输入一以#结束的符号串:在此位置输入符号串例如:eadeaa# (3)输出结果:eadeaa#为合法符号串
  • 1. 根据某一文法编制递归下降分析程序,以便对任意输入的符号串进行分析。 2. 本次实验的目的是加深对递归下降分析法的理解。
  • 这是一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
  • 对于文法: E->TG G->+TG|-TG|ε T->FS S->*FS|/FS|ε F->(E)|i 用递归下降分析法对任意输入的符号串进行分析,输入输出参考main函数。
  • 对文法 G: E→E+T|T 构造出G的递归下降分析程序。程序显示输出 T→T*F|F 匹配过程(即自上而下生成语法分析树的步骤, F→(E)|i 输出各匹配产生式序号即可)。
  • 实验二 语法分析—(1)递归下降分析法 程序输入/输出示例: ...(1)递归下降分析程序,编制人:姓名,学号,班级 (2)输入一以#结束的符号串:在此位置输入符号串例如:eadeaa# (3)输出结果:eadeaa#为合法符号串
  • 完成以下描述赋值语句的LL(1)文法的递归下降分析程序 G[S]: S→V=E E→TE′ E′→ATE′|ε T→FT′ T′→MFT′|ε F→ (E)|i A→+|- M→*|/ V→i 2、[设计说明] 终结符号i为用户定义的简单变量,即...

    实验要求:

    1、[实验项目]

    完成以下描述赋值语句的LL(1)文法的递归下降分析程序

    G[S]:
    S→V=E
    E→TE′
    E′→ATE′|ε
    T→FT′
    T′→MFT′|ε
    F→ (E)|i
    A→+|-
    M→*|/
    V→i

    2、[设计说明]

    终结符号i为用户定义的简单变量,即标识符的定义。

    3、[设计要求]

    (1)输入串应是词法分析的输出二元式序列,即某算术表达式“专题1”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;

    (2)递归下降分析程序应能发现简单的语法错误;

    (3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果;

    (4)选做:如有可能,考虑如何用文法描述C语言的if语句,使整个文法仍然为LL1文法,并使得你的递归下降程序可以分析赋值语句和if语句。

    实验过程:

    1、文法扩充修改

    1.1、修改文法:

    (4)选做:如有可能,考虑如何用文法描述C语言的if语句,使整个文法仍然为LL(1)文法,并使得你的递归下降程序可以分析赋值语句和if语句。

    针对(4)选做我对文法进行了扩充和修改

    扩充修改后的文法:

    基本可以识别c语言if语句、判断语句和赋值语句:

    G[P]:
    P→S|Q|;
    S→V=E;
    V→i
    E→TR
    R→ATR|$
    T→FY
    Y→MFY|$
    F→CZ
    Z→OCZ|$
    C→BI
    I→XBI|$
    B→(E)|i
    A→+|-
    M→*|/
    X→a|o //a表示逻辑符号&&,o表示逻辑符号||
    O→t|d|g|l|u|e //t表示>=,d表示<=,g表示>,l表示<,e表示==,u表示!=
    Q→8JKH //8表示if在符号表中序号
    H→fJKH|9K|$ //f 表示 else if符号的组合、9表示else在符号表中的序号
    J→(E) //逻辑语句
    K→S|{U}|; //if语句程序体
    U→PU|{U}U|$

    1.2、扩充后E表示的表达式可以识别逻辑表达式

    规则:

    F→CF′
    F′→OCF′|ε
    C→BC′
    C′→XBC′|ε
    X→a|o//a表示逻辑符号&&,o表示逻辑符号||
    O→t|d|g|l//t表示>=,d表示<=,g表示>,l表示<

    将逻辑与(&&)和逻辑或(||)加入到表达式中,将关系运算符(<=、>=、==、!=、<、>)加入到表达式中。

    1.3、if语句文法设计说明

    Q→8JKH//8表示if在符号表中的序号
    H→89JKH|9K|ε//9表示else在符号表中的序号
    J→(E) //逻辑语句
    K→S|{U}|; //if语句程序体
    U→PU|{U}U|$

    这部分规则,表示的是if语句的识别规则:

    Q→if<判断语句><IF语句程序体><ELSE IF 或者 ELSE语句程序体>
    <ELSE IF 或者 ELSE语句程序体>→else if<判断语句><IF语句程序体><ELSE IF
    或者 ELSE语句程序体>|else<IF语句程序体>|$
    <判断语句>→(E) //逻辑语句
    <IF语句程序体>→S|{U}|; //if语句程序体
    U→PU|{U}U|$
    //U这个部分保证了if语句程序体中能够出现赋值语句和if语句的闭包,并且能识别普通的程序体

    3、

    其中 S→V=E; 规则我在最后加入了 ;
    终结符号,使所有的赋值表达式都比较符合c语言规则。

    2、递归下降分析程序设计说明

    2.1设计要求:

    (1)输入串应是词法分析的输出二元式序列,即某算术表达式“专题1”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;
    (2)递归下降分析程序应能发现简单的语法错误;
    (3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果;
    (4)选做:如有可能,考虑如何用文法描述C语言的if语句,使整个文法仍然为LL1文法,并使得你的递归下降程序可以分析赋值语句和if语句。

    2.2设计说明:

    (1)该语言大小写不敏感;

    (2)字母为a-zA-Z,数字为0-9;

    (3)对上述文法进行扩充和改造;

    (4)“/*……*/”为程序的注释部分;

    (5)“/*”作为左注释,“*/”作为右注释,分别作为一种类别,所以左注释和右注释必须成对出现,否则错误;左右注释中字符忽略不进行识别;

    (6)“//”作为单行注释,“//”后的字符忽略不进行识别。

    (7)扩充后E表示的表达式可以识别逻辑表达式

    规则:
    F→CF′
    F′→OCF′|ε
    C→BC′
    C′→XBC′|ε
    X→a|o//a表示逻辑符号&&,o表示逻辑符号||
    O→t|d|g|l//t表示>=,d表示<=,g表示>,l表示<

    将逻辑与(&&)和逻辑或(||)加入到表达式中,将关系运算符(<=、>=、==、!=、<、>)加入到表达式中。

    Q→8JKH//8表示if在符号表中的序号
    H→89JKH|9K|ε//9表示else在符号表中的序号
    J→(E) //逻辑语句
    K→S|{U}|; //if语句程序体
    U→PU|{U}U|$

    这部分规则,表示的是if语句的识别规则(将字母替换成文字意义的非终结符号):

    Q→if<判断语句><IF语句程序体><ELSE IF 或者 ELSE语句程序体>
    <ELSE IF 或者 ELSE语句程序体>→else if<判断语句><IF语句程序体><ELSE IF
    或者 ELSE语句程序体>|else<IF语句程序体>|$
    <判断语句>→(E) //逻辑语句
    <IF语句程序体>→S|{U}|; //if语句程序体
    U→PU|{U}U|$
    //U这个部分保证了if语句程序体中能够出现赋值语句和if语句的闭包,并且能识别普通的程序体

    3、程序功能描述

    (1)、能够录入一个.tys文件中的二元式内容;

    (2)、根据.tys文件内容进行语法分析,可识别

    ①赋值表达式
    ②逻辑表达式
    ③c语言if语句;

    (3)、根据输入的二元式内容进行分析语法分析,并打印结果;

    (4)、打印分析过程和错误提示。

    4、主要的数据结构描述

    4.1主要使用的java数据结构类型
    4.1.1 List
    list中添加,获取,删除元素
    List\<String\> person=new ArrayList\<\>();
    
    person.add("jackie"); //索引为0 //.add(e)
    
    person.add("peter"); //索引为1
    
    person.add("annie"); //索引为2
    
    person.add("martin"); //索引为3
    
    person.add("marry"); //索引为4
    
    person.remove(3); //.remove(index)
    
    person.remove("marry"); //.remove(Object o)
    
    String per="";
    
    per=person.get(1);
    
    System.out.println(per); .get(index)
    
    for (int i = 0; i \< person.size(); i++) {
    
    System.out.println(person.get(i)); //.get(index)
    
    }
    
    list中是否包含某个元素
    方法:.contains(Object o); 返回true或者false
    
    List\<String\> fruits=new ArrayList\<\>();
    
    fruits.add("苹果");
    
    fruits.add("香蕉");
    
    fruits.add("桃子");
    
    //for循环遍历list
    
    for (int i = 0; i \< fruits.size(); i++) {
    
    System.out.println(fruits.get(i));
    
    }
    
    String appleString="苹果";
    
    //true or false
    
    System.out.println("fruits中是否包含苹果:"+fruits.contains(appleString));
    
    if (fruits.contains(appleString)) {
    
    System.out.println("我喜欢吃苹果");
    
    }else {
    
    System.out.println("我不开心");
    
    }
    
    list中根据索引将元素数值改变(替换)
    .set(index, element); 和 .add(index, element); 的不同
    
    String a="白龙马", b="沙和尚", c="八戒", d="唐僧", e="悟空";
    
    List\<String\> people=new ArrayList\<\>();
    
    people.add(a);
    
    people.add(b);
    
    people.add(c);
    
    people.set(0, d); //.set(index, element);
    //将d唐僧放到list中索引为0的位置,替换a白龙马
    
    people.add(1, e); //.add(index, element);
    //将e悟空放到list中索引为1的位置,原来位置的b沙和尚后移一位
    
    //增强for循环遍历list
    
    for(String str:people){
    
    System.out.println(str);
    
    }
    
    list中查看(判断)元素的索引
      注意:.indexOf(); 和 lastIndexOf()的不同;
    
    List\<String\> names=new ArrayList\<\>();
    
    names.add("刘备"); //索引为0
    
    names.add("关羽"); //索引为1
    
    names.add("张飞"); //索引为2
    
    names.add("刘备"); //索引为3
    
    names.add("张飞"); //索引为4
    
    System.out.println(names.indexOf("刘备"));
    
    System.out.println(names.lastIndexOf("刘备"));
    
    System.out.println(names.indexOf("张飞"));
    
    System.out.println(names.lastIndexOf("张飞"));
    
    根据元素索引位置进行的判断
    if (names.indexOf("刘备")==0) {
    
    System.out.println("刘备在这里");
    
    }else if (names.lastIndexOf("刘备")==3) {
    
    System.out.println("刘备在那里");
    
    }else {
    
    System.out.println("刘备到底在哪里?");
    
    }
    
    利用list中索引位置重新生成一个新的list(截取集合)
    方法: .subList(fromIndex, toIndex);  .size() ; 该方法得到list中的元素数的和
    
    List\<String\> phone=new ArrayList\<\>();
    
    phone.add("三星"); //索引为0
    
    phone.add("苹果"); //索引为1
    
    phone.add("锤子"); //索引为2
    
    phone.add("华为"); //索引为3
    
    phone.add("小米"); //索引为4
    
    //原list进行遍历
    
    for(String pho:phone){
    
    System.out.println(pho);
    
    }
    
    //生成新list
    
    phone=phone.subList(1, 4); //.subList(fromIndex, toIndex)
    //利用索引1-4的对象重新生成一个list,但是不包含索引为4的元素,4-1=3
    
    for (int i = 0; i \< phone.size(); i++) { // phone.size()
    该方法得到list中的元素数的和
    
    System.out.println("新的list包含的元素是"+phone.get(i));
    
    }
    
    对比两个list中的所有元素
      //两个相等对象的equals方法一定为true,
    但两个hashcode相等的对象不一定是相等的对象
    
    //1.\<br\>if (person.equals(fruits)) {
    
    System.out.println("两个list中的所有元素相同");
    
    }else {
    
    System.out.println("两个list中的所有元素不一样");
    
    }
    
    //2.
    
    if (person.hashCode()==fruits.hashCode()) {
    
    System.out.println("我们相同");
    
    }else {
    
    System.out.println("我们不一样");
    
    }
    
    判断list是否为空
      //空则返回true,非空则返回false
    
    if (person.isEmpty()) {
    
    System.out.println("空的");
    
    }else {
    
    System.out.println("不是空的");
    
    }
    
    4.2 二元式文件结构

    二元式文件通过专题1的词法分析程序得到:

    其中一个测试用例为:

    (8,if)
    (3,()
    (3,()
    (3,()
    (1,num1)
    (24,>=)
    (1,num2)
    (3,))
    (41,&&)
    (3,()
    (1,num1)
    (14,+)
    (1,num2)
    (28,!=)
    (2,23)
    (3,))
    (3,))
    (42,||)
    (1,a)
    (24,>=)
    (1,num1)
    (3,))
    (3,{)
    (1,a)
    (23,=)
    (1,num1)
    (14,+)
    (1,num2)
    (3,?
    (8,if)
    (3,()
    (1,a)
    (24,>=)
    (1,num1)
    (3,))
    (3,{)
    (3,?
    (3,})
    (9,else)
    (3,{)
    (1,a)
    (23,=)
    (1,num1)
    (14,+)
    (1,num2)
    (3,?
    (3,})
    (1,a)
    (23,=)
    (1,num1)
    (14,+)
    (1,num2)
    (3,?
    (3,})
    (9,else)
    (8,if)
    (3,()
    (1,num1)
    (24,>=)
    (1,num2)
    (3,))
    (3,{)
    (8,if)
    (3,()
    (1,a)
    (24,>=)
    (1,num1)
    (3,))
    (3,{)
    (1,a)
    (23,=)
    (1,num1)
    (14,+)
    (1,num2)
    (3,?
    (3,})
    (9,else)
    (3,{)
    (1,a)
    (23,=)
    (1,num1)
    (14,+)
    (1,num2)
    (3,?
    (3,})
    (3,})
    (9,else)
    (8,if)
    (3,()
    (1,num1)
    (24,>=)
    (1,num2)
    (3,))
    (3,?
    (9,else)
    (3,{)
    (3,{)
    (8,if)
    (3,()
    (1,a)
    (24,>=)
    (1,num1)
    (3,))
    (1,a)
    (23,=)
    (1,num1)
    (14,+)
    (1,num2)
    (3,?
    (9,else)
    (3,{)
    (1,a)
    (23,=)
    (1,num1)
    (14,+)
    (1,num2)
    (3,?
    (3,})
    (3,})
    (3,})

    其源程序为:

    if(((num1>=num2)&&(num1+num2!=23))||a>=num1)
    { //该部分对if语句程序进行赋值语句和if语句的循环套嵌进行测试
    a = num1+num2;
    if(a>=num1)
    { ; } //该部分对边缘性{;}语句进行测试
    else
    {
    a = num1+num2;
    }
    a = num1+num2;
    }
    else if (num1>=num2)//该部分对else if 语句进行。
    {
    if(a>=num1)
    {
    a = num1+num2;
    }
    else
    {
    a = num1+num2;
    }
    }
    else if (num1>=num2)
    ; //该部分进行了边缘性测试只有 ‘ ;’ 的语句
    else
    {
    { //该部分进行了普通程序体测试,即{ }包括的程序语句。
    if(a>=num1)
    a = num1+num2;//该语句测试单赋值语句与if语句的嵌
    else
    {
    a = num1+num2;
    }
    }
    }
    可见该if语句包含了许多特殊、复杂和边缘的情况,非常具有代表性

    二元式文件内容被录入到
    private static List<String> InputStream = new ArrayList<String>(); //从二元式文件中拆解的符号穿输入流

    InputStream是一个Java
    List列表的一个对象,list列表是一系列的String类型的字符串,具体的操作:

    br = new BufferedReader(new InputStreamReader(new FileInputStream(fp.getName())));
    			String erYuanShi = "";
    			while((erYuanShi=br.readLine())!=null) {
    				//截取符号串
    				InputStream.add(erYuanShi.substring(erYuanShi.indexOf(",") + 1, erYuanShi.lastIndexOf(")")));
    			}
    			InputStream.add("#");  //末尾添加#号
    
    

    br
    为一个文件的读入流,通过使用br.readLine()方法读入二元式文件当前行内容并返回给String类型的变量erYuanShi,然后每一行的内容类似为(1,num1)的形式,但是我们需要就是num1,所以通过

    erYuanShi.substring(erYuanShi.indexOf(",")+ 1,erYuanShi.lastIndexOf(")"))

    方法将num1截取下来,放入List列表对象InputStream中,继续读文件,直到读取结束。这样就将二元式文件的内容读取到了List列表对象InputStream中。

    然后每次分析当前符号的时候,都需要到列表对象InputStream中读取一个字符串进行分析,但是读取列表内容的时候,不能直接使用,因为,源程序和我们的文法有转换的地方,也就if被8替换,a表示&&等等,所以读取list内容之后,要通过一个函数进行转换:

    public String get_indexP(int index)

    该函数要传入当前扫描指针位置,也就是indexP,根据indexP的位置,得到当前字符,然后该函数根据当前字符进行转换,返回转换后的字符。具体细节可以查看源程序或者该函数的批注。

    4.3 FIRST 集

    产生式 FIRST集

    产生式			FIRST集						
     *  P->S			[i]
     *  P->Q			[8]
     *  P->;			[;]
    	S->V=E;			[i]
    	V->i			[i]
    	E->TR			[(, i]
    	R->ATR			[+, -]
    	R->$			[$]
    	T->FY			[(, i]
    	Y->MFY			[*, /]
    	Y->$			[$]
    	F->CZ			[(, i]
    	Z->OCZ			[t, d, u, e, g, l]
    	Z->$			[$]
    	C->BI			[(, i]
    	I->XBI			[a, o]
    	I->$			[$]
    	B->(E)			[(]
    	B->i			[i]
    	A->-			[-]
    	A->+			[+]
    	M->*			[*]
    	M->/			[/]
    	X->a			[a]
    	X->o			[o]
    	O->l			[l]
    	O->e			[e]
    	O->g			[g]
    	O->t			[t]
    	O->u			[u]
    	O->d			[d]
    	
    	Q->8JKH			[8]
    	H->fJKH			[f]
    	H->9K			[9]
    	H->$			[$]
    	J->(E)			[(]
    	K->{U}			[{]
    	K->;			[;]
    	K->S			[i]
    	U->PU			[8, i, ;]
    	U->$			[$]
    	U->{U}U			[{]
    
    
    4.4 FOLLOW 集

    非终结符号 FOLLOW集

    非终结符号		FOLLOW集
    	P 			# 8 i ; { } 
    	Q 			# 8 i ; { } 
    	J 			i { ; 
    	K 			# f 8 9 i ; { } 
    	H 			# 8 i ; { } 
    	S 			# f 8 9 i ; { } 
    	V 			= 
    	E 			) ; 
    	R 			) ; 
    	T 			) + ; - 
    	Y 			) + ; - 
    	F 			) * + ; - / 
    	A 			( i 
    	M 			( i 
    	Z 			) * + ; - / 
    	C 			t d u e g ) * + ; l - / 
    	I 			t d u e g ) * + ; l - / 
    	B 			a d e g ) * + l - o / t u ; 
    	X 			( i 
    	O 			( i 
    	U 			} 
    
    
    	
    
    

    5、程序结构描述

    5.1 java类 及其方法分析
    5.1.1 Java 主类:递归下降语法分析的入口类
    public class RecursiveAnalysisMain {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		//1:构造递归下降语法分析类
    		RecursiveDescentParsing rdp = new RecursiveDescentParsing("zhuanti3_2.tys");
    		//2:执行算法
    		boolean k = rdp.grammaticalAnalysis();
    		if(k==true)
    			System.out.println("\n满足该文法");
    		else 
    			System.out.println("\n不满足该文法");
    	}
    
    }	
    
    

    该类只有一个main函数,该函数创建递归下降语法分析类的一个对象rdp,通过rdp对象调用语法分析入口函数grammaticalAnalysis()

    boolean k = rdp.grammaticalAnalysis();
    		if(k==true)
    			System.out.println("\n满足该文法");
    		else 
    			System.out.println("\n不满足该文法");
    
    

    grammaticalAnalysis()返回布尔类型,如果为真则表示分析成功,否则分析失败。

    5.1.2 Java 副类:递归下降分析类在这里插入图片描述

    1)私有变量:

    private BufferedReader br = null; //输入的二元式文件流,

    private BufferedReader br = null; //输入的二元式文件流,
    	private static List<String> InputStream = new ArrayList<String>(); //从二元式文件中读入内容,保存源代码。
    	private int indexP = 0; //扫描指针,初始为0
    	private int tab = 1; //制符表的数量,初始为1,作为源程序输出时的保持格式的制表符数量
    类方法分析:
    	//语法分析入口函数
    	public boolean grammaticalAnalysis() {
    		System.out.println("-------------分析过程-------------------");
    		System.out.print("    ");
    		return P();
    	}
    
    

    2)语法分析入口,打印提示信息后,直接进入非终结符号的P的分析函数:

    private boolean P() { 
    		String s =get_indexP( indexP);
    		//System.out.println(s);
    		
    		//System.out.println(sequals);
    		if(s.equals("i")) {
    			
    			if(!S())
    				return false;
    		}else if (s.equals("8"))
    		{
    			if(!Q())
    				return false;
    		}
    		else if (s.equals(";"))
    		{
    				print_indexp(indexP);indexP++;
    				return true;
    		}
    		else 
    			return false;
    		return true;
    	}
    
    

    String s =get_indexP( indexP); 通过
    get_indexP()函数得到扫描指针所在的二元式内容,并返回一个可以供各个非终结符号分析识别的符号。get_indexP()函数会将if转换为8返回,将elseif转换为f返回,也就根据文法的内容,get_indexP()函数进行转换,返回各类二元式代表的终结符号。

    如果当前的符号为i,也就是用户定义的变量(get_indexP()函数将所用的变量,标识符和数字全部转换为i,方便分析函数分析)就调用非终结符号S(赋值表达式的入口)的分析函数。

    如果当前的符号为8,也即if,会调用非终结符号的Q(if语句的入口)的分析函数。

    如果是终结符号 ‘;’ ,则扫描指针加1,返回真。

    3)非终结符号S(赋值表达式的入口)的分析函数

    private boolean S() { //S→V=E:    i    
    		String s =get_indexP( indexP);
    		print_indexp(indexP);
    		String sequals = get_indexP( ++indexP);;
    		//System.out.println(sequals);
    		if(s.equals("i")) {
    			if(sequals.equals("="))
    			{
    				print_indexp(indexP);indexP++;
    				if(!E())
    					return false;
    			}
    			else {
    				System.out.println("\n缺少 = ");
    				return false;
    			}
    			
    		}else
    		{
    			System.out.println("\n非法格式");
    			return false;
    		}
    			
    		return true;
    	}
    
    

    函数首先根据产生式/S→V=E:
    的FIRST集[i],判断当前符号是否为i,赋值表达式的第一个字符一定是变量i,如果是i,则扫描指针加1,得到下一个符号,并且这个符号必须为=,如果不是则打印错误信息,返回false,结束分析。如果是=,则进入非终结符号E的分析函数:

    /**
    	 * E->TR			[(, i]
    	 * @return
    	 */
    	private boolean E() { //E→TR: (,i    ),#
    	
    		String s =get_indexP( indexP);
    		
    		if(s.equals("(")||s.equals("i")) {
    			if(!T())
    				return false;
    			if(!R())
    				return false;
    		}else
    		{
    			System.out.println("算术表达式格式错误");
    			return false;
    		}
    		return true;
    	}
    
    

    同理分析根据产生式E->TR的FIRST集[(, i],
    判断当前符号是否为i或则(,如果是则进入产生式右部的非终结符号的分析函数,也就是T、R的分析函数,如果不是则输出错误提示信息,返回false:

    R的分析函数:

    /**
    	 *  R->ATR			[+, -]
    		R->$			[$]
    		
    		R 			) ; 
    	 * @return
    	 */
    	private boolean R() { //R→ATR|ε:+,-	        ),;
    		String s =get_indexP( indexP);
    		if(s.equals("+")||s.equals("-")) {
    			if(!A())
    				return false;
    			if(!T())
    				return false;
    			if(!R())
    				return false;
    		}else if(s.equals(")")) {
    			return true;
    		}else if(s.equals(";")) {
    			
    			return true;
    		}
    		else
    		{
    			System.out.println("算术表达式格式错误");
    			return false;
    		}
    		
    		return true;
    	}
    
    

    同理分析根据产生式R->ATR的FIRST集[+, -],
    判断当前符号是否为+或-,如果是则进入产生式右部的非终结符号的分析函数,也就是A、T、R的分析函数,与前面不同的是,R的产生式具有空,所以如果当前符号不是+或则-,则要判断是否为R的FOLLOW集的终结符号,R的FOLLOW集为
    ) 、; 两个符号, 判断当前符号是否为)或;
    ,如果是则返回true,不是FIRST集和FOLLOW集的终结符号的,则打印错误信息,返回false。

    同上面几个函数的构造情况,可以构造出所有非终结符号的分析函数,具体的情况的可以查看源程序,下面也有函数的用流程图。

    5.2流程图:

    下面列出了所有非终结符号的分析函数流程图:

    P:

    在这里插入图片描述

    S:

    在这里插入图片描述

    E:

    在这里插入图片描述

    T:

    在这里插入图片描述

    R:

    在这里插入图片描述

    F:

    在这里插入图片描述

    Y:

    在这里插入图片描述

    C:

    在这里插入图片描述

    Z:

    在这里插入图片描述

    B:

    在这里插入图片描述

    I:

    在这里插入图片描述

    X:

    在这里插入图片描述

    O:

    在这里插入图片描述

    A:

    在这里插入图片描述

    M:

    在这里插入图片描述

    Q:

    在这里插入图片描述

    J:

    在这里插入图片描述

    K:

    在这里插入图片描述

    H:

    在这里插入图片描述

    U:

    在这里插入图片描述
    每个流程图,参照各个分析函数进行绘制,其中token可以看做取当前的扫描指针位置的符号,indexP++操作表示扫描指针加1,则下面的token代表加1后的扫描指针位置的符号。其中if,在程序为:8
    ,else为:9,else if为f,逻辑运算符&&为:a,||为o,等等细节在文法中已经说明。

    流程图对应每个非终结符号的分析函数,但是在程序中有具体的实现细节,还要根据设计的数据结构进行分析。

    6、程序测试

    6.1 测试用例1分析成功:

    测试用例为二元式文件结构部分的用例

    结果为:

    在这里插入图片描述

    在这里插入图片描述

    6.2 修改测试用例1使其不符合if语句语法:
    6.2.1缺少 ‘;’符号

    在这里插入图片描述

    输出错误提示:

    在这里插入图片描述

    6.2.1缺少 ‘)’符号

    在这里插入图片描述

    6.2.3缺少if语句程序体:

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

    实验总结与反思

    实验过程总结

    递归下降分析法的原理是利用函数之间的递归调用模拟语法树自上而下的构造过程,具体实现方法概述如下:

    1.1 非终结符号分析函数实现步骤

    1)每个非终结符对应一个分析函数;
    2)产生式右部为该产生式左部非终结符所对应分析函数的“函数体”;
    特别的对于产生式能推出空ε的时候,函数体应判断,对应左部非终结符号的FOLLOW集。
    3)产生式右部终结符对应从输入串中“消耗”该终结符的操作;
    在右部
    遇到终结符号的时候,应该将扫描符号向下扫描,也就是往下分析二元式文件内容的操作。
    4)产生式中右部的‘|’对应函数体中的“if-else”语句。
    产生式右部不总是一个,有的多个,这就需要判断当前符号,选择进入的函数体,也就是,LL1文法,所代表的意思,向前分析1步,得到当前前进方向。

    在构造每个非终结符号分析函数的时候,大致就是如上的步骤。具体的细节有很多实现的方法,这也和自己构造的数据结构有关。

    1.2 分析函数错误提示

    在实验结果中设计程序,使函数输出分析过程,如下:

    -------------分析过程-------------------
        P→Q→if J→( E→T→F→C→B→( E→T→F→C→B→( E→T→F→C→B→num1 I→Z→O→>= C→B→num2 I→Z→Y→) I→X→&& B→( E→T→F→C→B→num1 I→Z→Y→A→+ T→F→C→B→num2 I→Z→O→!= C→B→23 I→Z→Y→) I→Z→Y→) I→X→|| B→a I→Z→O→>= C→B→num1 I→Z→Y→) K→
        {U→P→S→
            a = E→T→F→C→B→num1 I→Z→Y→A→+ T→F→C→B→num2 I→Z→Y→;
    U→P→Q→
            if J→( E→T→F→C→B→a I→Z→O→>= C→B→num1 I→Z→Y→) K→
            {U→P→
                ;
    U→        }H→
            else K→
            {U→P→S→
                a = E→T→F→C→B→num1 I→Z→Y→A→+ T→F→C→B→num2 I→Z→Y→;
    U→        }U→P→S→
            a = E→T→F→C→B→num1 I→Z→Y→A→+ T→F→C→B→num2 I→Z→Y→;
    U→    }H→
        else if J→( E→T→F→C→B→num1 I→Z→O→>= C→B→num2 I→Z→Y→) K→
        {U→P→Q→
            if J→( E→T→F→C→B→a I→Z→O→>= C→B→num1 I→Z→Y→) K→
            {U→P→S→
                a = E→T→F→C→B→num1 I→Z→Y→A→+ T→F→C→B→num2 I→Z→Y→;
    U→        }H→
            else K→
            {U→P→S→
                a = E→T→F→C→B→num1 I→Z→Y→A→+ T→F→C→B→num2 I→Z→Y→;
    U→        }U→
        }H→
        else if J→( E→T→F→C→B→num1 I→Z→O→>= C→B→num2 I→Z→Y→) K→;
    H→
        else K→
        {U→
            {U→P→Q→
                if J→( E→T→F→C→B→a I→Z→O→>= C→B→num1 I→Z→Y→) K→S→a = E→T→F→C→B→num1 I→Z→Y→A→+ T→F→C→B→num2 I→Z→Y→;
    H→
                else K→
                {U→P→S→
                    a = E→T→F→C→B→num1 I→Z→Y→A→+ T→F→C→B→num2 I→Z→Y→;
    U→            }U→
            }
        }
    满足该文法
    
    

    具体的实现细节就是在每个分析函数体开始的时候,让其打印当前分析函数的非终结符号,这样就可以得到递归下降的调用各个分析函数的情况。可以看出,分析的时候是有规律的,但是对于LL1递归下降分析函数过程来说,如果分析二元式文件是个正确的程序话,会正常分析下去,但是遇到错误,程序就不能继续往下分析,因为对于LL1文法,向前看1步,但是向前看1步的时候出现错误,有时候可以判断出简单的错误,但是对于复杂的式子,是无法判断当前的被分析程序的出现的具体错误,例如:

    if ( ( ( num1 >= num2 ) ( num1 + num2 != 23 ) ) || a >= num1 ) 
       		 {
            a = num1 + num2 ;
    
            if ( a >= num1 ) 
            {
                ;
            }
            else 
            {
                a = num1 + num2 ;
            }
            a = num1 + num2 ;
        }
    
    

    这个程序if的判断语句有错误的,我们很容易判断出缺少的一个逻辑操作符,但是对于递归下降分析函数来说,它不可能分析整个判断语句,然后再做出判断,它只能往前看1步,这就限制了递归下降分析函数不能进行太多的分析,如下递归下降分析程序的报错结果:

    在这里插入图片描述

    ( ( ( num1 >= num2 ) 这个是if
    语句的判断语句,对于对于递归下降分析过程来说,进入非终结符号J的分析函数,J→(E),然后读取(
    ,然后进入E等等,num2后的)符号之后,递归下降分析函数发现后面操作是*( num1 + num2
    != 23 )要进入下一个E,但是要先结束当前E,但是发现如果结束E的话,也就是要( (
    num1 >= num2 ))*
    ,缺少了一个(,递归下降分析过程,只能分析到这,报错然后退出程序,实现不了太智能的错误提示。

    1.3实验输出分析过程的完善,print_indexp(int i)

    该函数进行了对输出分析过程的格式完善,也就是怎么将二元式文件输出为源程序,输出的时候不仅仅只对源程序考虑为一个字符串进行输出,还要注意到了缩进,也就是程序的对齐,保证其可读性。大致结果就是如下:

     if ( ( ( num1 >= num2 ) && ( num1 + num2 != 23 ) ) || a >= num1 ) 
        {
            a = num1 + num2 ;
    
            if ( a >= num1 ) 
            {
                ;
            }
            else 
            {
                a = num1 + num2 ;
            }
            a = num1 + num2 ;
        }
        else if ( num1 >= num2 ) 
        {
            if ( a >= num1 ) 
            {
                a = num1 + num2 ;
            }
            else 
            {
                a = num1 + num2 ;
            }
        }
        else if ( num1 >= num2 ) ;
    
        else 
        {
            {
                if ( a >= num1 ) a = num1 + num2 ;
    
                else 
                {
                    a = num1 + num2 ;
                }
            }
    }
    
    

    而不是输出一个字符串,可读性非常差,例如下面这样:

    if(((num1>=num2)&&(num1+num2!=23))||a>=num1) { a = num1+num2;
    if(a>=num1) { ; } else { a = num1+num2; } a = num1+num2; } else if
    (num1>=num2) { if(a>=num1) { a = num1+num2; } else { a = num1+num2; } }
    else if (num1>=num2) ; else { { if(a>=num1) a = num1+num2; else { a =
    num1+num2; } } }

    public void print_indexp(int i)
    根据当前字符的情况,进行分析,是否进行格式的输出,主要控制格式的就是tab和换行符,函数根据当前字符的情况,分析出应当先输出几个tab或是否应该输出\n换行符。private
    int
    tab = 1; //制符表的数量,初始为1的作用就是管理tab数量的一个私有变量。

    举个简单的例子,遇到’{‘符号,我们要先考虑当前的tab数量应该输出多少,并且要输出一个\n换行符,然后要改变一下tab的数量,因为按照习惯,遇到一个’{’符号后,在输入语句的时候,我们会进行一个相对tab的输入,所以tab要++。同理
    ‘}’要考虑当前的tab数量应该输出多少,并且要输出一个\n换行符,然后要改变一下tab的数量,但是tab要–。还有很多具体的情况要具体对待,具体的细节可以查看批注或者源程序。

    最后源码地址
    https://github.com/Topdu/Compilation-principle/blob/master/RecursiveAnalysisMain.java

    展开全文
  • 编制递归下降分析程序,并对简单语言进行语法分析。
  • 实验三 递归下降分析法 一实验目的 根据某一文法编制调试递归下降分析程序以便对任意输入的符号串进行分析本次实验的目的主要是加深对递归下降分析法的理解 程序比较复杂需要利用到程序设计语言的知识和大量编程技巧...
  • 【20200416】编译原理课程课业打卡十六之构造预测分析表&递归下降分析程序 一、课业打卡十六之构造预测分析表&递归下降分析程序 二、知识巩固 1、预测分析表构造步骤 2、预测分析表【LL(1)分析表】的构造实例详解 3...
  • 编程实现给定算术表达式的递归下降分析器。算术表达式文法如下: EE+T | T TT*F | F F(E) | i
  • (使用Python实现,注释详尽)在词法分析器的基础上,采用递归下降的方法实现算术表达式的语法分析器,以加深对自上而下语法分析过程的理解。 1、对算术表达式文法: E→TE' ...构造其递归下降分析程序
  • 编译原理实验(课程设计)递归下降分析,包含错误恢复(恐慌模式),c语言实现附源码,文法如下 G: S -> SaA | bB A -> aB | c B -> Bb | d
  • 递归下降分析程序构造方法

    千次阅读 2016-05-25 22:25:49
    递归下降分析程序构造方法 作业要求   对于文法 E -> E + T | E – T | T T ->T * F | T / F | F F -> (E) | i 取消左递归后,改为: E ->TE’ E’ -> +TE’ | -TE’ |ε T ->FT’ T’ -> *FT’ | /FT’|...
  • 文法:E->TE' E'->+TE'|ε T->FT' T'->*FT'|ε F->(E)|i 构造上述LL(1)文法的递归下降分析程序
  • 计算机科学与工程学院 专业班级 学生学号 学生姓名 实验项目 实验类别 实 验 目 的 及 要 求 类 别 上机表现 实验报告 说明 编译原理实验报告 实验地点 指导教师 实验时间 实验二算术表达式递归下降分析程序设计 ...
  • 词法分析程序scaner( ),sym;error( ) 每个函数名是相应的非终结符,函数体是根据右部符号串的结构编写。 当遇到终结符时,则编写语句if(当前读入的符号==a)则读入下一个单词当遇到非终结符A时,则编写语句调用A...
  • 编译原理|递归下降分析程序

    千次阅读 2019-12-10 00:13:35
    递归下降分析程序 一、实验目的 掌握最基本的自顶向下分析方法,即递归下降子程序方法,理解其特点和适用范围(回溯,左递归等现象),锻炼递归调用程序的构造方法。 二、实验内容 给定CP语言中简单算术表达式...
  • 编程实现给定算术表达式的递归下降分析器。 算术表达式文法如下: E-->E+T|T T-->T*F|F F-->(E)|i

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,148
精华内容 7,659
关键字:

递归下降分析程序