编译原理综合应用——Java文件打点

实验目的

编译原理在JAVA可测试性中的应用。通过对源程序进行分析,在特定位置增加特定的打印语句,方便对程序执行过程的跟踪定位。比如:函数出入口增加打印语句。

实验要求

1、 读取一个JAVA文件,进行语法解析,在函数出入口增加打印语句,并将改写后的程序更新到JAVA文件中去。

输入: 从控制台读入一个JAVA程序文件

输出:更新后的JAVA程序文件, 增加了打印语句

2. 输入输出文件示例:(仅为示意)

输入文件:

public class helloworld {

   public static int Add(int a, int b){

      int ret;

      ret =a+b;

      return ret

   }

   public static void main(String[] args) {

      System.out.println("result="+Add(1,2)); 

   }

}

 

输出文件:

public class helloworld {

   public static int Add(int a, int b){

      System.out.println("EnterFunction helloworld::Add(a="+a+",b="+b+")!");

      int ret;

      ret =a+b;

      System.out.println("Exit Function helloworld::Add(a="+a+",b="+b+")!");

      return ret;

   }

   public static void main(String[] args) {

      System.out.println("Enter Functionhelloworld::main(args="+args.toString()+")!");

      System.out.println("result="+Add(1,2)); 

      System.out.println("Exit  Functionhelloworld::main(args="+args.toString()+")!");

   }

}

程序分析设计说明

1)函数入口打印语句可以在变量定义之前

2)对于非void型函数、有返回值的需要在return之前输出函数打印语句。

3)输入输出参数暂只考虑简单类型和String类型,不考虑自定义对象等其它类型。

4)如果有输入参数,捕获输入参数值,并打印出来。

5) 如果Object参数,打印时采用toString()转换。

6) 更新后的文件能正常编译运行成功,且新增加的打印语句不影响原有程序逻辑。


代码:

#include <bits/stdc++.h>
using namespace std;

enum symbol
{
	classsym=0,
	publicsym=1,
	protectedsym=2,
	privatesym=3,
	staticsym=4,
	returnsym=5,
	voidsym=6,
	intsym=7,
	charsym=8,
	booleansym=9,
	Stringsym=10,
	Integersym=11,
	lbrace=12,//{
	rbrace=13,//}
	lparen=14,//(
	rparen=15,//)
	semicolon=16,
	lzhushi=17,/* /* */
	rzhushi=18,//*/
	zhushi=19,//
	comma=20,//,
	lsquare=21,//[
	rsquare=22,//]
	Plus=23,//+
    Minus=24,//-
    times=25,//*
    slash=26,//
    eql=27,//=
    neq=28,/* != */
    lss=29,// <
    leq=30,//<=
    gtr=31,//>
    geq=32,//>=
    quote=33,/*\*/
    period=34,
    number=35,
    ident=36,
    nil=37,
    note=38,
};

struct aFunction{
	string returnType;
	string funcname;
	vector<string> paraList;
	string printfFuncInfo;
};


string programsrc;
string filename;
string strfilename;
string programdest;
string strclassname;
aFunction aFunc;

/*
变量说明:
 line	从终端读入的字符串;		当前所指位置在计数器 p
 token	为存放的单词自身字符串;当前所指位置在计数器 m
 number	整型常数
 sym	每个单词符号种类

*/
char buffer[500];
char line[500],token[12],ch;
enum symbol sym;
int p,m, num;
char *word[12]= {"Integer","String", "boolean","char","class","int","private","protected","public","return","static","void"};
int Err;

void getsym();
void block();
void save();
int error(int x);
void FuncName();
void ParaName();
void FuncBody();


int main()
{
    ifstream in("in.txt");
	p=0;
	if (! in.is_open())
	{ cout << "Error opening file"; exit (1); }
	while (!in.eof() )
	{
		in.getline (buffer,100);

		/*cout<<"i:::";
		cout<<buffer<<endl;*/

		for(int i=0;i<100;i++){
			if(buffer[i]!='\0')line[p++]=buffer[i];
			else break;
		}
		line[p++]='\n';
	}
	cout<<line<<endl;
    line[p++]='\0';
    //逐个单词扫描;

    Err = 0;
    p=0;

    block();
    if ((Err==0)){
        printf("syntax parses success!\n");
        save();
        cout<<programdest;
	}
	else
		printf("syntax parses failed!\n");
    return 0;
}

void save()
{
	time_t t = time(0);
    char tmp[64];
    strftime( tmp, sizeof(tmp), "%S",localtime(&t) );
    strfilename=tmp;
    strfilename+=".txt";
    char buf[30];

	strcpy(buf, strfilename.c_str());
    strncpy(buf,strfilename.c_str(),strfilename.length());

	freopen(buf,"w",stdout);
}

void getsym()
{
	for(m=0; m<12;m++) token[m++]=NULL;
	ch=line[p++];
	m=0;
	/*TODO 单词识别*/
	while((ch==' '||ch=='\n'||ch=='	')) {
		if(ch==' ') programdest+=" ";
		else if(ch=='\n') programdest+="\n";
		else if(ch=='	') programdest+="	";
		ch=line[p++];
	}

	//字母打头的字符串;标识符
	if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A'))
	{
		do
		{
			token[m++]=ch;
			ch=line[p++];
		}while((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')||(ch<='9'&&ch>='0'));
		sym=ident;
		token[m++]='\0';
		ch=line[p--];
		for(int n=0;n<12;n++)
		{
			if(strcmp(token,word[n])==0)
			{
				if(n==0) sym=Integersym;
				else if(n==1) sym=Stringsym;
				else if(n==2) sym=booleansym;
				else if(n==3) sym=charsym;
				else if(n==4) sym=classsym;
				else if(n==5) sym=intsym;
				else if(n==6) sym=privatesym;
				else if(n==7) sym=protectedsym;
				else if(n==8) sym=publicsym;
				else if(n==9) sym=returnsym;
				else if(n==10) sym=staticsym;
				else if(n==11) sym=voidsym;
				break;
			}
		}
		/*TODO识别标识符IDENT和保留字*/
	}
	else if((ch<='9'&&ch>='0'))
	{
		num=0;
		do{
			num=num*10+ch-'0';
			ch=line[p++];
		}while((ch<='9'&&ch>='0'));
		ch=line[p--];
		sym=number;
		/*TODO识别数字NUMBER*/
	}
	else {
		switch(ch)
		{
		case '=':		//赋值符号
			sym=eql;
			token[m++]=ch;
			break;
		case '<':		//<=和<符号
			token[m++]=ch;
			ch=line[p++];
			if(ch=='=')
			{
				token[m++]=ch;
				sym=leq;
			}
			else{
				sym=lss;
				p--;
			}
			break;
		case '>':		//>=和>符号
			token[m++]=ch;
			ch=line[p++];
			if(ch=='=')
			{
				sym=geq;
				token[m++]=ch;
			}
			else{
				sym=gtr;
				p--;
			}
			break;
		case '+':
			sym=Plus;
			token[m++]=ch;
			break;
		case '-':
			sym=Minus;
			token[m++]=ch;
			break;
		case '*':
			sym=times;
			token[m++]=ch;
			break;
		case '/':
			ch=line[p++];
			if(ch=='*'){
				//cout<<"in\n";
				char fr;//前面的一个符号
				fr='*';
				ch=line[p++];
				while(1){
					fr=ch;
					ch=line[p++];
					if(fr=='*'&&ch=='/') break;
				}
				sym=note;
				token[m++]=ch;
			}
			else
			{
				sym=slash;
				token[m++]=ch;
				p--;
			}
			break;
		case '(':
			sym=lparen;
			token[m++]=ch;
			break;
		case ')':
			sym=rparen;
			token[m++]=ch;
			break;
		case ';':
			sym=semicolon;
			token[m++]=ch;
			break;
		case ',':
			sym=comma;
			token[m++]=ch;
			break;
		case '{':
			sym=lbrace;
			token[m++]=ch;
			break;
		case '}':
			sym=rbrace;
			token[m++]=ch;
			break;
		case '[':
			sym=lsquare;
			token[m++]=ch;
			break;
		case ']':
			sym=rsquare;
			token[m++]=ch;
			break;
		case '.':
			sym=period;
			token[m++]=ch;
			break;
		case ' ':
			token[m++]=ch;
			break;
		case '"':
			sym=quote;
			token[m++]=ch;
			break;
		default:
			sym=nil;
			break;
		}



	}
	token[m++]='\0';
	if(sym!=nil){
		programdest+=&token[0],&token[strlen(token)];
	}
	//如果想看分析的每一个sym,请打开这个注释
    //printSym(sym);

    //处理语句分析中的注释
    if(sym==note) getsym();
}


/*TODO 程序块处理*/
void block()
{
	getsym();
	while(sym!=publicsym&&sym!=protectedsym&&sym!=privatesym&&sym!=classsym) getsym();
	if(sym==publicsym || sym==protectedsym || sym==privatesym) getsym();
	if(sym==classsym){
		getsym();
		strclassname=&token[0],&token[strlen(token)];
		//cout<<"class::::::   "<<strclassname <<endl;
		//class主体
		getsym();
		if(sym!=lbrace){
			error(1);
		}
		getsym();
		while(sym!=rbrace){
			FuncName();
		}
		//class结束
	}

}


/*TODO函数名处理*/
void FuncName()
{
	while(sym!=publicsym&&sym!=protectedsym&&sym!=privatesym&&sym!=staticsym&&sym!=voidsym&&sym!=Stringsym&&sym!=intsym&&sym!=booleansym&&sym!=charsym) getsym();
	if(sym == publicsym || sym == protectedsym || sym == privatesym) getsym();
	if(sym == staticsym) getsym();

	//函数返回类型
	if(sym == voidsym || sym == Stringsym || sym == intsym || sym == booleansym || sym == charsym){
		aFunc.returnType=&token[0],&token[strlen(token)];
		//函数名
		getsym();
		aFunc.funcname=&token[0],&token[strlen(token)];
		//函数参数
		getsym();
		if(sym != lparen){
			error(3);
		}
		getsym();
		ParaName();
		aFunc.printfFuncInfo = "Function "+strclassname + "::" + aFunc.funcname+"(";
		int i;
		for(i=0;i<aFunc.paraList.size()-1;i++){
            aFunc.printfFuncInfo += aFunc.paraList[i]+"=\"+"+aFunc.paraList[i]+"+\",";
		}
		if(aFunc.paraList.size()>0){
			aFunc.printfFuncInfo += aFunc.paraList[i]+"=\"+";
		}
		aFunc.printfFuncInfo+=")!\");";
		programdest+="\n		System.out.println(\"Enter ";
		programdest+=aFunc.printfFuncInfo;

		//函数体
		if(sym!=lbrace){
			error(5);
		}
		FuncBody();
		if(sym!=rbrace){
			error(6);
		}
		getsym();

	}

}

/*TODO函数参数处理*/
void ParaName(){
    aFunc.paraList.clear();
    while(sym != rparen){
		getsym();
		if(sym == lsquare){
			getsym();
			while(sym != rsquare) getsym();
			getsym();
		}
		//&token[0],&token[strlen(token)]
		aFunc.paraList.push_back(token);
		getsym();
		if(sym==comma){
			getsym();
		}
    }
    getsym();
}

/*TODO函数体处理*/
void FuncBody(){
	if(aFunc.returnType.compare("void")!=0){
		while(sym != returnsym) getsym();
		programdest = programdest.substr(0,programdest.length()-6);
		programdest += "\n";
		programdest += "		System.out.println(\"Exit  "+aFunc.printfFuncInfo;
		programdest += "\n		return  ";
	}
	while(sym != rbrace) getsym();
	if(aFunc.returnType.compare("void")==0){
		programdest = programdest.substr(0,programdest.length()-1);
		programdest += "\n";
		programdest += "		System.out.println(\"Exit  "+aFunc.printfFuncInfo+"\r\n";

	}
}

/*TODO出错处理*/
int error(int x){
	switch(x){
	case 1:
		cout<<"Error "<<x<<" : class 定义缺少左括号{";
		break;
	case 2:
		cout<<"Error "<<x<<" : class 定义缺少右括号}";
		break;
	case 3:
		cout<<"Error "<<x<<" : function 定义缺少左括号(";
		break;
	case 4:
		cout<<"Error "<<x<<" : function 定义缺少右括号)";
		break;
	case 5:
		cout<<"Error "<<x<<" : function 定义缺少左括号[";
		break;
	case 6:
		cout<<"Error "<<x<<" : function 定义缺少右括号]";
		break;

	default:
		break;
	}
	cout<<" [pos= "<<p<<";Token = "<<token<<";\n";
	//printSym(sym);
	Err++;
	return Err;
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值