编译原理练习一(处理c源码)

题目描述:编写一个程序,将C源码中的所有注释字母大写,注释之外的所有保留字大写,所有标识符小写

我使用的是js编程,先画出有限状态机的转换,再用双重switch,case处理自动转换机的状态,(双重循环嵌套的switch,case是

解决此类问题的一个模式,虽不是代码最简,但保证了简单清晰的结构)

首先是状态转换图:


按照状态图,写出代码如下:

const fs = require("fs");
var data="";
const redline = require("readline");
data = fs.readFileSync("test2.txt");
var tem = data.toString();
 var keys = ["auto","break","case","switch","char","const","continue","default","do","while",
"double","else","if","enum","extern","float","for","goto","int","long","register","return","short",
"signed","sizeof","static","struct","typedef","unino","unsigned","void","volatile"]; //关键字的定义
var charArray = "qwertyuiopasdfghjklzxcvbnm"
    +"QWERTYUIOPASDFGHJKLZXCVBNM";
var digitArray = [0,1,2,3,4,5,6,7,8,9];
    //对每一行的数据进行判断
    //用循环case处理
    var t1 = judge(tem);
    //console.log(t1);
fs.writeFileSync("test3.txt",t1.join(""));
console.log("写入完成");

function judge(str) {
        var m=0;
        var n=0;
        var tokens=[];
        for (m=0;m<str.length;) {
            var  state=1;
        while((state===1||state===2||state===3||state===4||state===6||state===9)
        && (m<str.length)){
            switch (state){
                case 1:
                    if(str.charAt(m) === '/'){
                        n=m;
                        m=m+1;
                        state=2;
                        break;
                    }else if ((charArray.indexOf(str.charAt(m))!==-1)||(str.charAt(m) === '_')){
                        n=m;
                        m=m+1;
                        state=9;
                        break;
                    } else{
                        n=m;
                        m=m+1;
                        state=11;
                        break;
                    }
                case 2:
                    if(str.charAt(m) === '/'){
                        m=m+1;
                        state=6;
                        break;
                    }else if (str.charAt(m) === '*'){
                        m=m+1;
                        state=3;
                        break;
                    } else{
                        m=m+1;
                        state=8;
                        break;
                    }
                case 3:
                    if(str.charAt(m) === '*'){
                        m=m+1;
                        state=4;
                        break;
                    }else{
                        m=m+1;
                        state=3;
                        break;
                    }
                case 4:
                    if(str.charAt(m) === '*'){
                        m=m+1;
                        state=4;
                        break;
                    }else if (str.charAt(m) === '/'){
                        m=m+3;
                        state=5;
                        break;
                    } else{
                        m=m+1;
                        state = 3;
                        break;
                    }

                case 6:
                    if(str.charAt(m) === '\r'){
                        m=m+2;
                        state=7;
                        break;
                    }else{
                        m=m+1;
                        state = 6;
                        break;
                    }
                case 9:
                    if((str.charAt(m) === '_')||(charArray.indexOf(str.charAt(m))!==-1)||(digitArray.indexOf(str.charAt(m))!==-1)){
                        m=m+1;
                        state=9;
                        break;
                    } else{
                        m=m+1;
                        state = 10;
                        break;
                    }
            }
        }
                switch (state){
                    case 5:
                        state=1; //块注释
                        var tem1=[];
                        tem1 =str.slice(n,m).split("");
                        for(var mm=0;mm<tem1.length;mm++){
                            if(charArray.indexOf(tem1[mm])!==-1){
                               tem1[mm] = tem1[mm].toUpperCase();
                            }
                        }
                        tokens.push(tem1.join(""));
                        break;
                    case 8:   //其他字符
                        state = 1;
                        break;
                    case 11:  //其他字符
                        state =1;
                        tokens.push(str.slice(n,m));
                        break;
                    case 7:  //行注释
                        state = 1;
                        var tem2=[];
                        tem2 =str.slice(n,m).split("");
                        for(var mm2=0;mm2<tem2.length;mm2++){
                            if(charArray.indexOf(tem2[mm2])!==-1){
                                tem2[mm2]= tem2[mm2].toUpperCase();
                            }
                        }
                        tokens.push(tem2.join(""));
                        break;
                    case 10:  //标识符或关键字
                        m=m-1;
                        state = 1;
                        var tem3=str.slice(n,m);
                        if(keys.indexOf(tem3.toLowerCase())!==-1){
                            tem3=tem3.toUpperCase();
                        }else {
                            tem3= tem3.toLowerCase();
                        }
                        tokens.push(tem3);
                        break;
                }
            }
        // n保存的是m的初值,也就是token的第一个指针指向的字符,m保存的是token的末尾的索引值
        return tokens;
}

经过简单的测试,没有问题,但是肯定不是包含了所有测试样例的。

先就这样啦。


这个编译器的源代码是我原先为了完成编译原理实验课作业而写的,所以只具有教学价值,现在发出来和大家共享 ;-)<br/><br/>和网上流传的版本不同,它从文法开始,一直到了符号表的实现. 想实现自己的编译器的话,只需在把Initializtion.h中的文法修改为自己的即可.<br/><br/>工程结构:<br/>Initializtion.h 初始化文法,便于进一步进行分析,它为构造GRAMMAR类提供了信息.其中默认非终极符用<>括上,修改时需要注意.<br/>Grammar.cpp Grammar.h 定义了文法GRAMMAR类,它通过initializtion.h的信息建立文法的内部表示。<br/>LL1_Analyser.cpp LL1_Analyser.h 定义了LL1分析器,即LL1_Analyser类.<br/>LL1_Recognizer.cpp LL1_Recognizer.h 为LL1语法分析驱动器,可以通过文法,TOKEN序列和LL1分析表,判定语法是否正确,同时驱动动作.<br/>Rec_Parse.cpp Rec_Pares.h 实现了递归下降分析器Rec_Parse类, 递归下降的思想和LL1驱动器一样,不过是把压栈改成调用自己,而把弹栈改成返回.<br/>Scanner.cpp Scanner.h 实现了词法分析器,可以将程序变为TOKEN序列. 扫描的源程序文件路径也在这里被定义(默认为.//demo.txt)<br/>Action.cpp Action.h 实现了语义栈的操作,_Action类定义了动作符号所对应的动作.<br/>SymTable.cpp SymTable.h 实现了符号表的建立和输出.<br/><br/>希望大家能通过该程序对STL和编译原理有更深刻的理解,Have Fun and Good Luck!<br/><br/> -- David.Morre
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值