词法分析(编译原理不用慌)
创始人
2024-03-08 00:50:39
0

目录

一.简单版

二.简单版(文本保存)

c++版

运行结果:

 Java版

运行结果:

三.第三版(文本保存)

c++版

运行结果:


一.简单版

#include
#include
using namespace std;
#include//char  prog[80]="begin if x>=24 then s:=0 end #"
char prog[80];
char token[8];    //prog存放输入符号串;token存放识别出的单词
int   syn, p, sum,m;
char ch;            //syn-种别码;p-prog数组的下标;sum-识别出的整数
char *rwtab[6] = {"begin", "if", "then", "while", "do", "end"};     //关键字表置初值//扫描子程序
void scaner( )
{   m=0;for (int n=0; n<8; n++ ) token[n]=NULL;     //将token清空ch=prog[p++] ;         //根据全局变量p读取下一个字符,分析下一个单词    while (ch==' '|| ch == '\n')  ch=prog[p++] ;         //1.首字符为字母的情况,可能为标识符或关键字if(ch<='z'&& ch>='a'){    m=0;  while (ch<='z'&& ch>='a'||ch<='9'&& ch>='0') { token[m++]=ch;//将ch保存至token[m++]中ch=prog[p++] ;//读取下一个字符}token[m++]='\0'; p--;//...... syn=10 ; //标识符,置syn=10         for (int n=0; n<6; n++ )    //判断当前标识符是否为关键字if (strcmp( token, rwtab[n])==0){  syn=n+1;//关键字,置关键字syn  break ;} } //2.首字符为数字的情况,为整数else if (ch<='9'&& ch>='0'){   while (ch<='9'&& ch>='0'){ sum=sum*10+ch-'0';  //将ch数字字符转换成整数送入sum,进位故sum*10,ch=prog[p++] ;//读取下一个字符 }p--;//....... syn=11;      //整数,置syn=11   }//3.其他算符或界符等情况	else             	switch(ch){case '<': token[m++]=ch;	//ch存入token ;ch=prog[p++] ;// 读下一个字符 ;//三种情况,<=或<>或<	if (ch=='>'){  syn=21;//将<>的种别码赋给syn;	    token[p++]=ch;	//ch存入token ;}else if (ch=='='){  syn=22;//将<=的种别码赋给syn;		                token[p++]=ch; // ch存入token ;}else { syn=20;//将<的种别码赋给syn;		            p--;}break;case '>': token[m++]=ch;	ch=prog[p++] ;// 读下一个字符 ;if (ch=='='){  syn=24;//将<=的种别码赋给syn;		                token[m++]=ch; // ch存入token ;}else { syn=23;//将<的种别码赋给syn;		            p--;}break;case ':':token[m++]=ch;	//ch存入token ;ch=prog[p++] ;// 读下一个字符 ;if (ch=='='){  syn=18;//将<=的种别码赋给syn;		                token[m++]=ch; // ch存入token ;}else { syn=17;//将<的种别码赋给syn;		            p--;}break;case '+': token[m++]=ch;syn=13;break;case '-': token[m++]=ch;syn=14;break;case '*': token[m++]=ch;syn=15;break;case '/': token[m++]=ch;syn=16;break;case '=': token[m++]=ch;syn=25;break;case ';': token[m++]=ch;syn=26;break;case '(': token[m++]=ch;syn=27;break;case ')': token[m++]=ch;syn=28;break;case '#': token[m++]=ch;syn=0;break;default: syn= -1; }token[m++]='\0';
}int main( ){ //......printf( "\n please input  string : \n" ) ;do{   ch=getchar( );prog[p++]=ch ;	} while(ch!='#');p=0;//......do{   //循环调用scanner()函数分析prog中的字符串,直到syn为0(即#)分析结束scaner();switch(syn){case 11:  //根据syn的值输出(syn,sum或者token)二元组printf("%-6d     %-5d\n",sum,syn);break;default: printf("%-6s     %-5d\n",token,syn);}}while(syn!=0);
}

二.简单版(文本保存)

c++版

此处是自己先创建一个1.txt文件

如:

const    a=10;
var    b,c;
procedure    p;
      begin
    c:=b+a
      end;
begin#
 

#include
#include
//"begin if x>24 then s:=0 end #"
char  prog[80], token[10];    //prog存放输入符号串;token存放识别出的单词
int   syn, p, sum=0,m;
char ch;            //syn-种别码;p-prog数组的下标;sum-识别出的整数
char str; 
char *rwtab[13] = {"begin", "if", "then", "while", "do", "end","const","var","procedure","odd","call","read","write"};//关键字表置初值
FILE* pf = fopen("2.txt", "w+");//扫描子程序
void scaner( )
{m=0;sum=0;for (int n=0; n<8; n++ ) token[n]=NULL;     //将token清空ch=prog[p++] ;         //根据全局变量p读取下一个字符,分析下一个单词    while (ch==' '|| ch == '\n')  ch=prog[p++] ;         //1.首字符为字母的情况,可能为标识符或关键字if(ch<='z'&& ch>='a'){    m=0;  while (ch<='z'&& ch>='a'||ch<='9'&& ch>='0') { token[m++]=ch;//将ch保存至token[m++]中ch=prog[p++] ;//读取下一个字符}token[m++]='\0'; p--;//...... syn=30 ; //标识符,置syn=30         for (int n=0; n<13; n++ )    //判断当前标识符是否为关键字if (strcmp( token, rwtab[n])==0){  syn=n+1;//关键字,置关键字syn  break ;} } //2.首字符为数字的情况,为整数else if (ch<='9'&& ch>='0'){   while (ch<='9'&& ch>='0'){ sum=sum*10+ch-'0';  //将ch数字字符转换成整数送入sumch=prog[p++] ;//读取下一个字符 }p--;//....... syn=31;      //整数,置syn=31   }//3.其他算符或界符等情况	else             	switch(ch){case '<': token[m++]=ch;	//ch存入token ;ch=prog[p++] ;// 读下一个字符 ;//三种情况,<=或<>或<	if (ch=='>'){  syn=21;//将<>的种别码赋给syn;	    token[m++]=ch;	//ch存入token ;}else if (ch=='='){  syn=22;//将<=的种别码赋给syn;		                token[p++]=ch; // ch存入token ;}else { syn=20;//将<的种别码赋给syn;		            p--;}break;case '>': token[m++]=ch;	ch=prog[p++] ;// 读下一个字符 ;if (ch=='='){  syn=24;//将<=的种别码赋给syn;		                token[p++]=ch; // ch存入token ;}else { syn=23;//将<的种别码赋给syn;		            p--;}break;case ':':token[m++]=ch;	//ch存入token ;ch=prog[p++] ;// 读下一个字符 ;if (ch=='='){  syn=18;//将:=的种别码赋给syn;		                token[m++]=ch; // ch存入token ;}else { syn=17;//将:的种别码赋给syn;		            p--;}break;case '+': token[m++]=ch;syn=32;break;case '-': token[m++]=ch;syn=14;break;case '*': token[m++]=ch;syn=15;break;case '/': token[m++]=ch;syn=16;break;case '=': token[m++]=ch;syn=25;break;case ';': token[m++]=ch;syn=26;break;case '(': token[m++]=ch;syn=27;break;case ')': token[m++]=ch;syn=28;break;case '#': token[m++]=ch;syn=0;break;default: syn= -1; }token[m++]='\0';
}
int f(int syn){if(syn==26||syn==27||syn==28){printf("界符");fprintf(pf,"     界符\n");}else if((syn>=20&&syn<=25)||(syn>=14&&syn<=16)||syn==18||syn==32){printf("运算符");fprintf(pf,"     运算符\n");}else if(syn>=1&&syn<=13){printf("关键字");fprintf(pf,"     关键字\n");}else if(syn==30){printf("标识符");fprintf(pf,"     标识符\n");}else if(syn==17){printf("非法");fprintf(pf,"     非法\n");}
} int main( ){ p=0;FILE* pf1 = fopen("1.txt", "r");while((str=fgetc(pf1))!=EOF){    //如果没有读到末尾,则继续读取信息prog[p++]=str;if(str=='#'){break;}}prog[p++]='\0';p=0;do{   //循环调用scanner()函数分析prog中的字符串,直到syn为0(即#)分析结束scaner();switch(syn){case 31:  //根据syn的值输出(syn,sum或者token)二元组fprintf(pf,"%-6d ",sum);fprintf(pf,"     数字\n");printf("%-6d     数字\n",sum); break;default: {fprintf(pf,"%-6s ",token);printf("%-6s     ",token);f(syn);printf("\n");}}}while(syn!=0);fclose(pf);//关闭文件pf=NULL;
//	fclose(pf1);
//	pf1=NULL;}

运行结果:

 

 Java版

 

 1.txt放你要读的文法

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
/*
*   保留字13个syn赋值1-13const ,var,procedure,begin,end,odd,if,then,call, while,do, read,write
*   标识符syn赋值14
*   常数syn赋值
*   运算符+,-,*,/,= syn赋值16-20 #syn赋值为0 <,<=,>,>=,:= syn赋值21-25
*   界符( ) , ; . syn赋值26-30
* */
public class PL0 {static String  prog="";//static String prog="begin if x>=24 then s:=0 end #";static String  token1;   //做保留识别出的值static int   syn;       //种别码static int p=0;         //做索引static int sum;         //做常数static char ch;         //做字符串索引下取值static String str=" ";  //做写入txt中分隔//13个关键字static String[] rwtab = {"const" ,"var","procedure","begin","end","odd","if","then","call", "while","do", "read","write"};static void scaner(){token1="";     //将token1清空sum=0;        //sum清空ch=prog.charAt(p++) ;         //读字符串p索引下while (ch==' '|| ch == '\n')  ch=prog.charAt(p++) ;//1.首字符为字母的情况,可能为标识符或关键字if(ch<='z'&& ch>='a'){while (ch<='z'&& ch>='a'||ch<='9'&& ch>='0'){token1+=ch;ch=prog.charAt(p++) ;//读取下一个字符}p--;syn=14 ; //标识符,置syn=14for (int n=0; n<13; n++ )    //判断当前标识符是否为关键字if (token1.equals(rwtab[n]) ){syn=n+1;break ;}}//2.首字符为数字的情况,为整数else if (ch<='9'&& ch>='0'){while (ch<='9'&& ch>='0'){sum=sum*10+ch-'0';  //将ch数字字符转换成整数送入sum,进位故sum*10,ch=prog.charAt(p++) ;//读取下一个字符}p--;syn=15;      //常数,置syn=15}//3.其他算符或界符等情况elseswitch(ch){case '+':token1+=ch;syn=16;break;case '-':token1+=ch;syn=17;break;case '*':token1+=ch;syn=18;break;case '/':token1+=ch;syn=19;break;case '=':token1+=ch;syn=20;break;case '#':token1+=ch;syn=0;break;//<与<=case '<':token1+=ch;ch=prog.charAt(p++) ;if (ch=='='){syn=22;token1+=ch;}else{syn=21;p--;}break;//>与>=case '>':token1+=ch;	ch=prog.charAt(p++) ;// 读下一个字符 ;if (ch=='='){syn=24;token1+=ch;}else {syn=23;p--;}break;case ':':token1+=ch;ch=prog.charAt(p++) ;if (ch=='='){syn=25;token1+=ch;}break;case '(':token1+=ch;syn=26;break;case ')':token1+=ch;syn=27;break;case ',':token1+=ch;syn=28;break;case ';':token1+=ch;syn=29;break;case '.':token1+=ch;syn=30;break;default: syn= -1;}}public static void main(String[] args) throws IOException {//System.out.print("please input  string :");//Scanner input = new Scanner(System.in);//prog=input.nextLine();FileInputStream fos0;FileOutputStream fos1;FileOutputStream fos2;FileOutputStream fos3;FileOutputStream fos4;FileOutputStream fos5;try {fos0=new FileInputStream("src/1.txt");int ch=0;while ((ch=fos0.read())!=-1){prog+=(char)ch;}System.out.println(prog);fos0.close();fos1=new FileOutputStream("src/关键字.txt",true);fos2=new FileOutputStream("src/标识符.txt",true);fos3=new FileOutputStream("src/运算符.txt",true);fos4=new FileOutputStream("src/常数.txt",true);fos5=new FileOutputStream("src/界符.txt",true);} catch (FileNotFoundException e) {throw new RuntimeException(e);}do{   //循环调用scanner()函数分析prog中的字符串,直到syn为0(即#)分析结束scaner();if(token1!="") {//System.out.println(token1+" "+syn);System.out.printf("%-8s",token1+" ");}//关键字1-13if(syn>=1&&syn<=13){fos1.write((token1+str+"\n").getBytes(StandardCharsets.UTF_8));System.out.println("基本字");}//标识符14else if(syn==14){fos2.write((token1+str+"\n").getBytes(StandardCharsets.UTF_8));System.out.println("标识符");}//运算符16-25和#0else if(syn>=16&&syn<=25||syn==0){fos3.write((token1+str+"\n").getBytes(StandardCharsets.UTF_8));System.out.println("运算符");}//常数15else if(syn==15){fos4.write((String.valueOf(sum)+str+"\n").getBytes(StandardCharsets.UTF_8));//System.out.println(sum+" "+syn);System.out.printf("%-8d",sum);System.out.println("数字");} else {fos5.write((token1+str+"\n").getBytes(StandardCharsets.UTF_8));System.out.println("界符");}}while(syn!=0);fos0.close();fos1.close();fos2.close();fos3.close();fos4.close();fos5.close();}
}

运行结果:

 

三.第三版(文本保存)

c++版

#include 
#include enum symbol {nul, ident, number, plus, minus,times, slash, oddsym, eql, neq,lss, leq, gtr, geq, lparen,rparen, comma, semicolon, period, becomes,beginsym, endsym, ifsym, thensym, whilesym,writesym, readsym, dosym, callsym, constsym,varsym, procsym,
};int cc, ll;
FILE * fa1;
int err; /*错误计数器*/ 
FILE* fin;
int cx; 
char ch;
char line[81];
#define getchdo if(-1==getch())return -1
# define al 10 
char a[al + 1];
char id[al + 1];
# define norw 13 
char word[norw][al];
enum symbol sym;
enum symbol wsym[norw];
# define nmax 14 
int num;
enum symbol ssym[256];
char fname[al];void init();
void error(int n);
int getch();
int getsym();int main()
{printf("Input pl/0 file?");scanf("%s", fname);					/* 输入PL/0源程序文件名 */fin = fopen(fname, "r");if(fin){printf("Output pl/0 file?");scanf("%s", fname);fa1 = fopen(fname, "w");init();//        err = 0;
//        cc = cx = ll = 0;
//        ch = ' ';while(getsym() != -1);}else{printf("找不到文件\n");}printf("\n");return 0;
}void init()
{int i;/* 设置单字符符号 */for(i=0; i<=255; i++){ssym[i] = nul;}ssym['+'] = plus;ssym['-'] = minus;ssym['*'] = times;ssym['/'] = slash;ssym['('] = lparen;ssym[')'] = rparen;ssym['='] = eql;ssym[','] = comma;ssym['.'] = period;ssym['#'] = neq;ssym[';'] = semicolon;/* 设置保留字名字,按照字母顺序,便于折半查找 */strcpy(word[0], "begin");strcpy(word[1], "call");strcpy(word[2], "const");strcpy(word[3], "do");strcpy(word[4], "end");strcpy(word[5], "if");strcpy(word[6], "odd");strcpy(word[7], "procedure");strcpy(word[8], "read");strcpy(word[9], "then");strcpy(word[10], "var");strcpy(word[11], "while");strcpy(word[12], "write");/* 设置保留字符号 */wsym[0] = beginsym;wsym[1] = callsym;wsym[2] = constsym;wsym[3] = dosym;wsym[4] = endsym;wsym[5] = ifsym;wsym[6] = oddsym;wsym[7] = procsym;wsym[8] = readsym;wsym[9] = thensym;wsym[10] = varsym;wsym[11] = whilesym;wsym[12] = writesym;
}/** 出错处理,打印出错位置和错误编码*/
void error(int n)
{char space[81];memset(space,32,81);space[cc-1] = 0;	//出错时当前符号已经读完,所以cc-1printf("****%s!%d\n",space,n);fprintf(fa1,"****%s!%d\n",space,n);err++;
}/** 漏掉空格,读取一个字符。** 每次读一行,存入line缓冲区,line被getsym取空后再读一行** 被函数getsym调用。*/
int getch()
{if(cc==ll){if(feof(fin)){printf("program incomplete");return -1;}ll=0;cc=0;ch = ' ';while(ch != 10){if(EOF == fscanf(fin,"%c",&ch)){line[ll]=0;break;}//fprintf(fa1,"%c", ch);line[ll]=ch;ll++;}}ch = line[cc];cc++;return 0;
}/** 词法分析,获取一个符号*/
int getsym()
{int i,j,k;if(ch=='#'){return -1;}while(ch==' ' || ch==10 || ch==9)		/* 忽略空格、换行和TAB */{getchdo;}if(ch>='a' && ch<='z'){										/* 名字或保留字以a~z开头*/k = 0;do{if(k='a'&&ch<='z' || ch>='0'&&ch<='9');a[k] = 0;strcpy(id,a);i=0;j=norw-1;do{									/* 搜索当前符号是否为保留字 */k=(i+j)/2;if(strcmp(id,word[k]) <= 0){j=k-1;}if(strcmp(id,word[k]) >= 0){i=k+1;}			}while(i<=j);if(i-1>j){printf("%s  保留字\n", id);fprintf(fa1,"%s  保留字\n", id);sym=wsym[k];}else{printf("%s  标识符\n", id);fprintf(fa1,"%s  标识符\n", id);sym=ident;						/* 搜索失败,则是名字或数字 */}}else{if(ch>='0'&&ch<='9'){									/* 检测是否为数字:以0~9开头 */k=0;num=0;sym=number;do{//printf("%c\n",ch);num=10*num+ch-'0';k++;getchdo;}while(ch>='0'&&ch<='9');		/* 获取数字的值 */k--;if(k>nmax){error(30);}printf("%d  整数\n",num);fprintf(fa1,"%d  整数\n", num);}else{if(ch==':')						/* 检测赋值符号 */{getchdo;if(ch=='='){printf(":=  运算符\n");fprintf(fa1,":=  运算符\n", id);sym=becomes;getchdo;}else{printf(":  error\n");sym=nul;				/* 不能识别的符号 */}}else{if(ch=='<')					/* 检测小于或小于等于符号 */{getchdo;if(ch=='='){printf("<=  运算符\n");fprintf(fa1,"<=  运算符\n", id);sym=leq;getchdo;}else{printf("<  运算符\n");fprintf(fa1,"<  运算符\n", id);sym=lss;}}else{if(ch=='>')					/* 检测大于或大于等于符号 */{getchdo;if(ch=='='){printf(">=  运算符\n");fprintf(fa1,">=  运算符\n", id);sym=geq;getchdo;}else{printf(">  运算符\n");fprintf(fa1,">  运算符\n", id);sym=gtr;}}else{if(ch=='='){printf("=  运算符\n");fprintf(fa1,"=  运算符\n", id);//getchdo;}if(ch=='+'){printf("+  运算符\n");fprintf(fa1,"+  运算符\n", id);getchdo;}else if(ch=='-'){printf("-  运算符\n");fprintf(fa1,"-  运算符\n", id);getchdo;}else if(ch=='*'){printf("*  运算符\n");fprintf(fa1,"*  运算符\n", id);getchdo;}else if(ch=='/'){printf("/  运算符\n");fprintf(fa1,"/  运算符\n", id);getchdo;}else if(ch=='('){printf("(  运算符\n");fprintf(fa1,"(  运算符\n", id);getchdo;}else if(ch==')'){printf(")  运算符\n");fprintf(fa1,")  运算符\n", id);getchdo;}else if(ch==','){printf(",  运算符\n");fprintf(fa1,",  运算符\n", id);getchdo;}else if(ch==';'){printf(";  运算符\n");fprintf(fa1,";  运算符\n", id);getchdo;}else if(ch=='.'){printf(".  运算符\n");fprintf(fa1,".  运算符\n", id);getchdo;}else{							sym=ssym[ch];			/* 当符号不满足上述条件时,全部按照单字符符号处理 */							if(sym != period){getchdo;}							}}}}}}return 0;
}

运行结果:

相关内容

热门资讯

蓝光发展:近期新增诉讼/仲裁涉... 观点网讯:12月24日,四川蓝光发展股份有限公司发布公告,披露公司涉及的重大诉讼情况。 公告显示,近...
北京优化楼市限购政策 多孩家庭... 北京市住房城乡建设委等4部门24日联合印发《关于进一步优化调整本市房地产相关政策的通知》,当日起施行...
ST长方(300301)披露控... 截至2025年12月24日收盘,ST长方(300301)报收于2.42元,较前一交易日上涨0.83%...
ST新亚(002388)披露关... 截至2025年12月24日收盘,ST新亚(002388)报收于6.1元,较前一交易日上涨2.18%,...
张可盈《老舅》再饰律师惊喜亮相... 由郭京飞、王佳佳领衔主演的年代轻喜剧《老舅》正在CCTV-8黄金强档、同步登陆视频平台播出中。其中,...
*ST沐邦控股股东陷借款纠纷 ... 12月24日,*ST沐邦(603398)发布公告,控股股东沐邦新能源控股所持部分股份可能被司法拍卖。...
萧山网友收到一条短信:该政策取... 昨天,萧山一网友在萧内网App发帖: 这下好了,以后从萧山去诸暨,走高速没有免费了! 据了解,...
社保年限再降低!一图看懂北京住... 新京报贝壳财经记者 段文平 制图 任婉晴 编辑 杨娟娟 校对 柳宝庆
原创 猪... 广东潮州一打假博主举报展会摊贩卖假牛肉(实为猪肉),竟在市场监管局工作人员眼皮底下,遭六七名暴徒围殴...
供应精矿后被拖欠超2亿元货款 ... 12月24日晚间,普路通(SZ002769)公告称,子公司广州市普路通供应链管理有限公司(以下简称“...