目录
一.简单版
二.简单版(文本保存)
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);
}
此处是自己先创建一个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;}


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();}
}

#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;
}
