语法分析器_语法分析器实验报告 - CSDN
精华内容
参与话题
  • 编译原理:语法分析器

    万次阅读 多人点赞 2019-05-05 18:03:59
    通过设计、编制、调试一个典型的语法分析程序(任选有代表性的语法分析方法,如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|ε

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

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

    展开全文
  • 利用C语言编制递归下降分析程序,并对简单语言进行语法分析。 2.1 待分析的简单语言的语法 用扩充的BNF表示如下: ⑴<程序>::=begin<语句串>end ⑵<语句串>::=<语句>{;<语句>...

    一、实验目的

    编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

    二、实验内容

    利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

    2.1 待分析的简单语言的语法

    用扩充的BNF表示如下:

    ⑴<程序>::=begin<语句串>end

    ⑵<语句串>::=<语句>{;<语句>}

    ⑶<语句>::=<赋值语句>

    ⑷<赋值语句>::=ID:=<表达式>

    ⑸<表达式>::=<项>{+<项> | -<项>}

    ⑹<项>::=<因子>{*<因子> | /<因子>}

    ⑺<因子>::=ID | NUM | (<表达式>)

    2.2 实验要求说明

    输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。

    例如:

        输入  begin a:=9; x:=2*3; b:=a+x end #

        输出  success!

        输入  x:=a+b*c end #

        输出  error!

     

     

    代码如下:

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    //定义几个全局变量 
    int syn;
    char s[1000];
    int p=0;
    int k=0;// 定义 k 作为一个标记符,记录是否出错,若 k=0 ,则说明没有出错,否则发生错误 
    char key[6][20] = {"begin","if","then","while","do","end"};//定义一个二维数组存放关键字 
    char token[20];	//存放字符(单词) 
    void expression();
    //判断关键字 
    int isKey(char s[])
    {
    	for(int i = 0; i < 6;i++)
    	{
    		if(strcmp(s,key[i]) == 0)
    		{
    			return i+1;	//关键字的种别码依次为 begin=1,if=2,then=3,while=4,do=5,end=6即为 i+1 的值 
    		}
    	}
    	return -1;
    }
    //判断是不是字母 
    bool isChar(char ch)
    {
    	if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))
    	return true;
    	else
    	return false;
    }
    //判断是不是数字 
    bool isNum(char ch)
    {
    	if(ch>='0' && ch<='9')
    	return true;
    	else
    	return false;
    }
    //词法分析器 
    void scanner()
    {
    	int count = 0;
    	if(s[p] == ' ') p++;
    	//开头是字母
    	if(isChar(s[p]))
    	{
    		while(isNum(s[p]) || isChar(s[p]))
    		{
    			token[count++] = s[p];
    			p++;
    		}
    		token[count] = '\0';	//'\0'作为结束符 ,将单词分隔开 
    		syn = isKey(token);
    		if(syn == -1)	
    		{
    			syn = 10;	//标识符letter(letter|digit) *
    		}
    	}
    	
    	//开头是数字
    	else if(isNum(s[p]))
    	{
    		while(isNum(s[p]))
    		{
    			token[count++] = s[p];
    			p++;
    		}
    		token[count] = '\0';//结束标识 
    		syn = 11;	//数字digit(digit) *
    	}
    	
    	//如果是运算符或者界符
    	else
    	{
    		//先处理没有争议的字符 
    		switch(s[p])
    		{
    			case '+': syn = 13;token[0] = s[p];token[1]='\0';break;
    			case '-': syn = 14;token[0] = s[p];token[1]='\0';break;
    			case '*': syn = 15;token[0] = s[p];token[1]='\0';break;
    			case '/': syn = 16;token[0] = s[p];token[1]='\0';break;
    			case '=': syn = 25;token[0] = s[p];token[1]='\0';break;
    			case ';': syn = 26;token[0] = s[p];token[1]='\0';break;
    			case '(': syn = 27;token[0] = s[p];token[1]='\0';break;
    			case ')': syn = 28;token[0] = s[p];token[1]='\0';break;
    			case '#': syn = 0 ;token[0] = s[p];token[1]='\0';break;
    		}
    		
    		
    		//处理有争议的
    		//: :=
    		if(s[p] == ':')
    		{
    			token[count++] = s[p];
    			if(s[p+1] == '=')
    			{
    				p++;
    				token[count++] = s[p];
    				syn = 18;
    			}
    			else
    			{
    				syn = 17;
    			}
    			token[count] = '\0';
    		}
    		
    		//< <> <=
    		if(s[p] == '<')
    		{
    			token[count++] = s[p];
    			if(s[p+1] == '>')
    			{
    				p++;
    				token[count++] = s[p];
    				syn = 21;
    			}
    			else if(s[p+1] == '=')
    			{
    				p++;
    				token[count++] = s[p];
    				syn = 22;
    			}
    			else
    			{
    				syn = 20;
    			}
    			token[count] = '\0';
    		}
    		
    		//> >=
    		if(s[p] == '>')
    		{
    			token[count++] = s[p];
    			if(s[p+1] == '=')
    			{
    				p++;
    				token[count++] = s[p];
    				syn = 24;
    			}
    			else
    			{
    				syn = 23;
    			}
    			token[count] = '\0';
    		}
    		
    		//后移 
    		p++;	//判断运算符和界符的这部分由于指针 p 没有向后指,所以需要将指针 p 向后移一位 
    	}
    	 
    } 
    
    以下各函数均要先调用 scanner()函数,用于首先产生 syn 的值 
    //因子-->项-->表达式-->赋值语句-->语句-->程序
    //由小到大逐层封装函数 
    void factor()	//因子 :<因子> :=ID | NUM | (<表达式>) 
    {
    	if(syn==10||syn==11)	//当扫描的是数字或者字母时,继续扫描
    	{
    		scanner();
    	} 
    	else if(syn==27)	//当扫描到 '('时,后面应该为一个表达式,继续扫描
    	{
    		scanner();
    		expression();
    		if(syn==28)		//当扫描的是 ')'时,继续扫描
    			scanner();
    		else
    		{
    			k=1;	//出错 
    			cout<<"ERROR!缺少')'"<<endl;	//表达式缺 ')',出错 
    		}
    	} 
    	else
    	{
    		k=1;
    		cout<<"ERROR!运算符号后面不是常数或'('或标识符"<<endl;	//扫描表达式 ,表达式不是以 '('开头 
    	}
    } 
    
    void term()//项 : <项> :=<因子>{*<因子> | /<因子> } 
    {
    	factor();
    	while(syn==15||syn==16)	//当开头扫描的是 '*' 或者 '/'时('*'或者'/'后面是因子),继续扫描
    	{
    		scanner();
    		factor();
    	} 
    } 
    
    void expression()//表达式 : <表达式> :=<项>{+<项> | -<项>}
    {
    	term();
    	while(syn==13||syn==14)	//当开头扫描的是 '+' 或者 '-'时('+'或者'-'后面是项),继续扫描
    	{
    		scanner();
    		term();
    	}
    } 
    
    void statement()//赋值语句 : ID = <表达式>
    {
    	if(syn==10)	//当开头扫描的是字母时,继续扫描
    	{
    		scanner();
    		if(syn==18)		//扫描的是 ':='时,继续扫描
    		{
    			scanner();
    			expression();
    		} 
    		else
    		{
    			k=1;
    			cout<<"ERROR!缺少 ':=' "<<endl;
    		 } 
    	 } 
    	else
    	{
    		k=1; 
    		cout<<"ERROR!开头不是标识符!"<<endl;
    	}
     } 
     
    void sens()//语句串 :<语句串>:=<语句>{;<语句>}
    {
    	statement();
    	while(syn==26)	//当开始扫描的是 ';'时,继续扫描
    	{
    		scanner();
    		statement();
    	 } 
    } 
    
    //程序 : <程序> :=begin<语句串>end
    void lrparser() 
    {
    	if(syn==1)	//当开头扫描的是 'begin'时,继续扫描
    	{
    		scanner() ;
    		sens();
    		if(syn==6) //扫描到 'end'时,继续扫描 
    		{
    			scanner();
    			if(syn==0&&k==0)	//当数字串最后扫描的是 '#',而且无出错,分析成功
    				cout<<"success!" <<endl;
    			else if(syn!=0||k==1)
    				cout<<"error!"<<endl;
    		} 
    		else
    		{
    			cout<<"ERROR!没有 'end'"<<endl;
    		}
     	}
     	else
     	{
     		cout<<"ERROR!没有 'begin'"<<endl;
    	}
    }
    int main()
    {
    	char ch;
    	while(true)
    	{
    		cout<<"Please input a string:  "<<endl;
    		cin.getline(s,1000);//getline()函数可以滤去空格 
    		p=0;
    		scanner();
    		lrparser();
    	}
    	return 0; 
    }
    

    展开全文
  • 编译原理c++语法分析器

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

    语法分析器

         针对编译原理第三版-何炎祥主编的书中一个 LL(1)语法分析表利用c++编写了语法分析程序,下附加代码

    /*
    Name: LL(1)语法分析器 
    Copyright: 
    Author:y cc 
    Date: 18/04/17 16:26
    Description: 根据固定的分析表,这里是编译原理第三版-何炎祥主编的书中一个语法分析表 对输入以$结尾的字符串进行判断是否符合语法 
    */
    #include<iostream>
    #include<stdlib.h>
    #include<string.h>
    using namespace std;
    typedef struct
    {
    char data[10];
    int top;
    } message;//栈内元素对象 
    void create(message *&m)
    {
    m=(message *)malloc(sizeof(message));
    m->top=-1;
    }
    void push(message *&m,char i)//进栈操作 
    {
    if(m->top<10)
    {
    m->top++;
    m->data[m->top]=i;
    }
    else
    cout<<"栈满"; 
    }
    char pop(message *&m)//出栈操作 
    {
    char i;
    if(m->top!=-1)
    {
    i=m->data[m->top];
    m->top--;
    return i;
    }
    else
    cout<<"栈空"; 
    }
    void getStr(char str[])//将输入的以$结尾的字符串 保存于字符串数组中 
    {
    int j=0;
    while(true)
    {
    cin>>str[j];
    if(str[j]=='$')
    break;
    else
    j++;
    }
    }
    void output(message *m,char *j)//用于输出符号栈与输入串的代码 
    {
        int counti=0,countj=0;
        while(m->top>-1)
        {
        cout<<m->data[m->top];
        m->top--;
        counti++;
        }
        cout<<"   ";
        while(*j!='$')
        {
        cout<<*j;
        j++;
        countj++;
        }
            cout<<"$";
        while(counti!=0)
        {
        m->top++;
    counti--; 
        }
        while(countj!=0)
        {
        j--;
    countj--; 
        } 
    }
    int main() //main方法 
    {
    string b[6][6]={{""," "," ","a","a"," "},//对应分析表 
    {" "," "," ","bA","bA"," "},
    {"ibA"," ","#"," "," ","#"},
    {" "," "," ","cB","cB"," "},
    {"#","+cB","#"," "," ","#"},
    {" "," "," ","(",")a*"," "}};
    int i=-1;
    message *m;
    create(m);
        cout<<"输入字符串,字符串以$结尾,注意调成英文输入法。例如 (i($"<<endl; 
        char str[20];
        getStr(str);//获取字符串 
        char *j=str;
    push(m,'$');//'$'进栈 
        push(m,'s');//'s'进栈 
        cout<<"        符号串分析过程          "<<endl;
        cout<<"符号栈m 输入串str[j] 产生式b[][]"<<endl;
        while(true)  
      {
      //终结符时的判断 
         if(m->data[m->top]=='i'||m->data[m->top]=='+'||m->data[m->top]=='*'||m->data[m->top]=='('||m->data[m->top]==')'||m->data[m->top]=='#'||m->data[m->top]=='$')
        {
        if(m->data[m->top]==*j)
        {
        if(m->data[m->top]=='$')//设定终结条件 
        {
                  output(m,j);//用于输出符号栈与输入串的代码 
                cout<<"           ";
        cout<<"ok";
        break;
        }
        else
        {
                output(m,j);//用于输出符号栈与输入串的代码 
                cout<<endl; 
        j++;
       pop(m); 
        }
        } 
    else 
    {
        cout<<"不是一个句子";
        break;
        }
        }
        //非终结符的判断开始 
    else if(m->data[m->top]=='s')//非终结符's' 
        {
        output(m,j);//用于输出符号栈与输入串的代码 
        int m1=0;
        int n;
        int k;
        switch(*j) //利用这种方式查找产生式,这是我觉得比较得意的方式 
        {
        case 'i':n=0;break;
        case '+':n=1;break;
        case '*':n=2;break;
        case '(':n=3;break;
        case ')':n=4;break;
        case '$':n=5;break;
        }
        if(b[m1][n]=="#")
        {
        cout<<"     ";
        cout<<"#"<<endl; 
        pop(m);
        }
        else
         {
          cout<<"     ";
          cout<<b[m1][n]<<endl; 
          pop(m);
            k=b[m1][n].size();
        if(b[m1][n]!=" ")
      {
      char c[k];
    strcpy(c,b[m1][n].c_str());//将String转化为 char[] 
        for(int j=0;j<k;j++)
    {
    push(m,c[k-j-1]);
    }
      } 
        else
      {
        cout<<"不是一个句子";
        break;
        }
         } 
        } //非终结符's' 
        else if(m->data[m->top]=='a') //非终结符'a' 
        {
        output(m,j);//用于输出符号栈与输入串的代码 
        int m1=1;
        int n;
        int k;
        switch(*j)
        {
        case 'i':n=0;break;
        case '+':n=1;break;
        case '*':n=2;break;
        case '(':n=3;break;
        case ')':n=4;break;
        case '$':n=5;break;
        }
          if(b[m1][n]=="#")
        {
        cout<<"     ";
        cout<<"#"<<endl; 
        pop(m);
        }
        else
         {
          cout<<"     ";
          cout<<b[m1][n]<<endl; 
          pop(m);
            k=b[m1][n].size();
        if(b[m1][n]!=" ")
      {
      char c[k];
    strcpy(c,b[m1][n].c_str());//将String转化为 char[] 
        for(int j=0;j<k;j++)
    {
    push(m,c[k-j-1]);
    }
      } 
        else
      {
        cout<<"不是一个句子";
        break;
        }
         } 
        }//非终结符'a' 
        else if(m->data[m->top]=='A')//非终结符'A' 
        {
        output(m,j);//用于输出符号栈与输入串的代码  
        int m1=2;
        int n;
        int k;
        switch(*j)
        {
        case 'i':n=0;break;
        case '+':n=1;break;
        case '*':n=2;break;
        case '(':n=3;break;
        case ')':n=4;break;
        case '$':n=5;break;
        }
          if(b[m1][n]=="#")
        {
        cout<<"     ";
        cout<<"#"<<endl; 
        pop(m);
        }
        else
         {
          cout<<"     ";
          cout<<b[m1][n]<<endl; 
          pop(m);
            k=b[m1][n].size();
        if(b[m1][n]!=" ")
      {
      char c[k];
    strcpy(c,b[m1][n].c_str());//将String转化为 char[] 
        for(int j=0;j<k;j++)
    {
    push(m,c[k-j-1]);
    }
      } 
        else
      {
        cout<<"不是一个句子";
        break;
        }
         } 
        }//非终结符'A' 
       else if(m->data[m->top]=='b')//非终结符'b' 
        {
        output(m,j);//用于输出符号栈与输入串的代码 
        int m1=3;
        int n;
        int k;
        switch(*j)
        {
        case 'i':n=0;break;
        case '+':n=1;break;
        case '*':n=2;break;
        case '(':n=3;break;
        case ')':n=4;break;
        case '$':n=5;break;
        }
          if(b[m1][n]=="#")
        {
        cout<<"     ";
        cout<<"#"<<endl; 
        pop(m);
        }
        else
         {
          cout<<"     ";
          cout<<b[m1][n]<<endl; 
          pop(m);
            k=b[m1][n].size();
        if(b[m1][n]!=" ")
      {
      char c[k];
    strcpy(c,b[m1][n].c_str());//将String转化为 char[] 
        for(int j=0;j<k;j++)
    {
    push(m,c[k-j-1]);
    }
      } 
        else
      {
        cout<<"不是一个句子";
        break;
        }
         } 
        }//非终结符'b' 
        else if(m->data[m->top]=='B')//非终结符'B' 
        {
        output(m,j);//用于输出符号栈与输入串的代码 
        int m1=4;
        int n;
        int k;
        switch(*j)
        {
        case 'i':n=0;break;
        case '+':n=1;break;
        case '*':n=2;break;
        case '(':n=3;break;
        case ')':n=4;break;
        case '$':n=5;break;
        } 
        if(b[m1][n]=="#")
        {
        cout<<"     ";
        cout<<"#"<<endl; 
        pop(m);
        }
        else
        {
          cout<<"     ";
          cout<<b[m1][n]<<endl; 
        pop(m);
            k=b[m1][n].size();
        if(b[m1][n]!=" ")
      {
      char c[k];
    strcpy(c,b[m1][n].c_str());//将String转化为 char[] 
        for(int j=0;j<k;j++)
    {
    push(m,c[k-j-1]);
    }
      } 
        else
      {
        cout<<"不是一个句子";
        break;
        }
        }  
        }//非终结符'B' 
        else//非终结符'C' 
        { 
        output(m,j);//用于输出符号栈与输入串的代码 
        int m1=5;
        int n;
        int k;
        switch(*j)
        {
        case 'i':n=0;break;
        case '+':n=1;break;
        case '*':n=2;break;
        case '(':n=3;break;
        case ')':n=4;break;
        case '$':n=5;break;
        }
        if(b[m1][n]=="#")
        {
        cout<<"     ";
        cout<<"#"<<endl; 
        pop(m);
        }
        else
        {
        cout<<"     ";
          cout<<b[m1][n]<<endl; 
        pop(m);
            k=b[m1][n].size();
        if(b[m1][n]!=" ")
      {
      char c[k];
    strcpy(c,b[m1][n].c_str());//将String转化为 char[] 
        for(int j=0;j<k;j++)
    {
    push(m,c[k-j-1]);
    }
      } 
        else
     {
        cout<<"不是一个句子";
        break;
    }
        }  
        }//非终结符'C' 
    }
    return 0;
    }


       运行结果截图:



    展开全文
  • 编译原理实验 —— 语法分析器

    千次阅读 2018-11-03 13:59:11
    分析的简单语言的语法 用扩充的BNF表示如下: ⑴&lt;程序&gt;::=begin&lt;语句串&gt;end ⑵&lt;语句串&gt;::=&lt;语句&gt;{;&lt;语句&gt;} ⑶&lt;语句&gt;...
    /*
    待分析的简单语言的语法
    用扩充的BNF表示如下:
    ⑴<程序>::=begin<语句串>end
    ⑵<语句串>::=<语句>{;<语句>}
    ⑶<语句>::=<赋值语句>
    ⑷<赋值语句>::=ID:=<表达式>
    ⑸<表达式>::=<项>{+<项> | -<项>}
    ⑹<项>::=<因子>{*<因子> | /<因子>
    ⑺<因子>::=ID | NUM | (<表达式>)
    */
    
    #include "stdio.h"
    #include "string.h"
    char prog[100],token[8],ch;//prog[100],用来存储要处理的对象,token用来与关键字比较,ch用来存储一个字符
    char *rwtab[6]={"begin","if","then","while","do","end"};//关键字表
    int syn,p,m,n,sum;
    /*syn是种别码,p为prog数组的指针,m为token数组的指针,n为rwtab数组的指针,sum为词法分析器里的数字数值大小*/
    int flag;//flag与判断是否end有关
    
    void factor(void);//因式 factor
    void expression(void);//表达式 expression
    void yucu(void);
    void term(void);//项 term
    void statement(void);// 语句 statement
    void parser(void);
    void scaner(void);//扫描器
    
    
    int main(void)
    {
    	p=flag=0;
    	printf("\nplease input a string (end with '#'): \n");
    
        /*从命令行读取要处理的对象,并存储在prog[]数组中*/
    	do
    	{
    		scanf("%c",&ch);
    		//printf("\n input %c now\n",ch);
    		prog[p++]=ch;
    	}while(ch!='#');
    
    	p=0;
    	scaner();//主要完成赋值种别码等词法分析功能
    	parser();//调用各种递归子程序,完成语法分析的过程
    	//getch();
    }
    
    /*调用各种递归子程序,完成语法分析的过程*/
    void parser(void)
    {
    	if(syn==1)//begin
    	{
    		scaner();       /*读下一个单词符号*/
    		yucu();         /*调用yucu()函数;*/
    
    		if(syn==6)//end
    		{
    			scaner();
    			if((syn==0)&&(flag==0))//出现#且flag=0
    			printf("success!\n");
    		}
    		else
    		{
    			if(flag!=1) printf("the string haven't got a 'end'!\n");//flag来判断是否end
    			flag=1;
    		}
    	}
    	else
    	{
    		printf("haven't got a 'begin'!\n");
    		flag=1;
    	}
    
    	return;
    }
    
    void yucu(void)
    {
    	statement();         /*调用函数statement();*/
    
    	while(syn==26)//分号
    	{
    		scaner();          /*读下一个单词符号*/
    		if(syn!=6)
    			statement();         /*调用函数statement();*/
    	}
    
    	return;
    }
    
    void statement(void)
    {
    	if(syn==10)
    	{
    		scaner();        /*读下一个单词符号*/
    		if(syn==18)
    		{
    			scaner();      /*读下一个单词符号*/
    			expression();      /*调用函数expression();*/
    		}
    		else
    		{
    			printf("the sing ':=' is wrong!\n");
    			flag=1;
    		}
    	}
    	else
    	{
    		printf("wrong sentence!\n");
    		flag=1;
    	}
    
    	return;
    }
    
    void expression(void)
    {
    	term();
    
      	while((syn==13)||(syn==14))
        {
        	scaner();             /*读下一个单词符号*/
          	term();               /*调用函数term();*/
        }
    
     	return;
    }
    
    void term(void)
    {
    	factor();
    
      	while((syn==15)||(syn==16))
        {
        	scaner();             /*读下一个单词符号*/
          	factor();              /*调用函数factor(); */
        }
    
    	return;
    }
    
    void factor(void)//因式处理函数
    {
    	if((syn==10)||(syn==11))//标识符,数字
    	{
    		scaner();
    	}
      	else if(syn==27)//开头是左括号(
        {
        	scaner();           /*读下一个单词符号*/
         	expression();        /*调用函数statement();*/
    
    		if(syn==28)//出现右括号)
    		{
    			scaner();          /*读下一个单词符号*/
    		}
          	else
    	  	{
    	  		printf("the error on '('\n");
          		flag=1;
         	}
        }
      	else
    	{
    		printf("the expression error!\n");
      		flag=1;
        }
    
      	return;
    }
    
    /*主要完成赋值种别码等词法分析功能*/
    void scaner(void)//扫描器,词法分析器内容
    {
    	sum=0;//数字初始化为0
    
    	for(m=0;m<8;m++)//初始化token
    		token[m++]=NULL;
    
    	m=0;//m为token的指针
    	ch=prog[p++];//数组指针+1
    
    	while(ch==' ')//遇到空格+1
    		ch=prog[p++];
    
    	if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))//遇到字母
    	{
    		while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
    		{
    			token[m++]=ch;
    			ch=prog[p++];//p+1,下次循环使用
    		}
    		p--;//循环跳出,要-1
    		syn=10;//10,字母开头
    		token[m++]='\0';//\0为字符串结束符
    
    		/*判别是否为关键字*/
    		for(n=0;n<6;n++)//n为rwtab的指针
    		if(strcmp(token,rwtab[n])==0)//strcmp返回值为0,则两个参数大小相同
    		{
    			syn=n+1;
    			break;
    		}
    	}
    
    
    	else if((ch>='0')&&(ch<='9'))//遇到数字
    	{
    		while((ch>='0')&&(ch<='9'))
    		{
    			sum=sum*10+ch-'0';
    			ch=prog[p++];
    		}
    		p--;//回溯
    		syn=11;//11为数字
    	}
    
    	/*除数字和字母开头以外的其他符号*/
    	else
    	switch(ch)
    	{
    		case '<':
    			m=0;
    			ch=prog[p++];
    			if(ch=='>')
    			{
    				syn=21;
    			}
    			else if(ch=='=')
    			{
    				syn=22;
    			}
    			else
    			{
    				syn=20;
    				p--;//回溯
    			}
    		break;
    
    		case '>':
    			m=0;
    			ch=prog[p++];
    			if(ch=='=')
    			{
    				syn=24;
    			}
    			else
    			{
    				syn=23;
    				p--;
    			}
    		break;
    
    		case ':':
    			m=0;
    			ch=prog[p++];
    			if(ch=='=')
    			{
    				syn=18;
    			}
    			else
    			{
    				syn=17;
    				p--;
    			}
    			break;
    
    		case '+':
    			syn=13;
    		break;
    
    		case '-':
    			syn=14;
    		break;
    
    		case '*':
    			syn=15;
    		break;
    
    		case '/':
    			syn=16;
    		break;
    
    		case '(':
    			syn=27;
    		break;
    
    		case ')':
    			syn=28;
    		break;
    
    		case '=':
    			syn=25;
    		break;
    
    		case ';':
    			syn=26;
    		break;
    
    		case '#':
    			syn=0;
    		break;
    
    		default:
    			syn=-1;
    		break;
    	}
    }
    
    

     

    展开全文
  • C++写的一个简单的语法分析器(分析C语言)

    万次阅读 多人点赞 2012-11-23 15:36:26
    本程序实现一个分析C语言的词法分析+语法分析。 注意: 1.文法简略,没有实现的部分,可以在此文法的基础上进行扩充,本程序的采用自顶向下的LL(1)文法。 2.可以自动实现求First 集和 Follow 集。 3.处终结符外...
  • 语法分析器(java)

    千次阅读 2019-03-05 10:27:49
    本文用的是LL(1)分析方法 LL(1)分析是通过文法构造first集合follow集形成预测分析表,然后根据预测分析表来判断句子是不是正确符合文法的。 该的程序中用了数组储存分析表。 1.输入文法并标号,划分终结符和...
  • 语法分析器 Java版

    千次阅读 2019-04-21 10:52:55
    编译原理实验二,语法分析器 本文章中用到的代码中缺失的部分需要参考我的上一篇文章,词法分析器 Java版, 因为语法分析器是建立在词法分析器的基础之上的 原文链接...
  • 【编译原理】LL(1)语法分析器

    万次阅读 多人点赞 2018-05-10 20:44:43
    1.项目要求文法要求:(1)从文件读入,每条产生式占用一行(2)文法为LL(1)文法从文件中读入文法,从键盘上输入待分析的符号串,采用 LL(1)分析算法判断该符号串是否为该文法的句子。2.实验思路:首先实现集合FIRST...
  • 语法分析器实现过程(java)

    千次阅读 多人点赞 2019-10-16 11:23:35
    语法分析器是编译原理的一个实验,本文将会详细给出实现的具体步骤,利用java进行示例讲解,源码(包含java和c++两种实现方式)可在处下载。 一、实验目的 设计、编写一个语法分析程序,加深对语法分析原理的理解。 ...
  • 语法分析器java实现

    2020-07-23 23:30:33
    语法分析器java实现,包含词法分析器。程序代码作为词法分析器的输入,词法分析器的输出作为语法分析器的输入,由语法分析器输出语法分析的结果。
  • 用java实现的语法分析器

    千次下载 热门讨论 2020-07-30 23:32:56
    语法分析器调用的是词法分析器的类。。。 自己写的。。LL(1)。。。 预测分析。。。
  • 由于这学期学了编译原理这门课,实验要求写词法分析器以及语法分析器,这才写的,不同网络其他的代码,我采用的是java实现的,也算费了好多脑细胞,希望能大伙看看咋样,不喜勿喷哦,各自学习就是了!
  • SLR语法分析器

    2020-07-15 23:34:55
    1. 对输入的文法进行判断,是否为相应SLR文法,若不是提示重新输入文法。 2. 输出相应的项目集规范簇 3. 输出相应的LR分析表。 4. 输入一个句子,输出其分析过程(移进,归约,接受)
  • 这是一个单文档的tiny语言语法分析器,良好的MFC单文档界面。
  • YACC是语法分析器生成工具中最著名的,也是最早开发出来的一个。该工具和LEX都是源于贝尔实验室的UNIX计划,如今YACC也成为了UNIX系统的标准实用程序。它大大地简化了在语法分析器设计时的手工劳动,将程序设计语言...
  • c#语法分析器(自上而下)

    热门讨论 2020-07-30 23:30:55
    实现的功能: (1)选定一文法,选定...(2)允许用户输入语句并对该语句进行相应的语法分析 (3)要求显示语法树的建立过程以及跟踪分析表和分析栈的状态 (4)要提供单步运行,让用户跟踪分析器工作的每一个步骤 。
  • 语法分析器——java实现

    万次阅读 2018-06-05 21:04:25
    部分代码见——词法分析器expr221.txt{ i1=14; i2=i1+2*3; i3=i1-5*(i2%2)+5; if(i1==i4&amp;&amp;i2&gt;=20){ i3=i3+1;} else{ i3=i3+2;} }expr222.txt{ m=12;n=21; if(m&lt;n){ t=m;m...
  • 编译课里的辅助代码,是你的必备之选,教你如何做一个属于你自己的编译器
  • 语法分析器和词法分析器的java实现代码,以证明可以,望各位下载。
  • 编译原理 lr语法分析器 课程实验报告 编译原理 lr语法分析器 课程实验报告
1 2 3 4 5 ... 20
收藏数 278,150
精华内容 111,260
关键字:

语法分析器