PL0语言词法分析程序

合集下载

编译原理实践5—PL0的词法分析程序构造

编译原理实践5—PL0的词法分析程序构造

辅助过程getch
getsym需要一个辅助过程getch,每被 调用一次就读入下一个字符 除此之外的任务:
识别行结束标志,作为空格符处理 拷贝原文输出 在输出文件每行开始添加坐标(书中例子程 序没有体现)
3.词法分析程序的设计
每调用一次getsym,首先用循环结构在 源程序上向前读入一个非空格字符,然 后对此字符进行分析,转相应部分处理 getsym大致可以分为三个部分
字符语法分析安排在同一遍中
,此时词法分析作为语法分析程序的一个子程序。每 当语法分析需要一个新的符号时,就调用词法分析子 程序,词法分析子程序从字符串源程序中识别出一个 具有独立意义的单词,将其符号返给语法分析。这种 方法避免了中间文件,省去了送取符号工作,有利于 提高编译程序的效率。书中采用这种方案。
取符号
字符串源程序
词法分析器
送符号
语法分析器
程序getsym
本课程采用第2种方案,程序名getsym,预先 审视源程序下一个符号,并将读入的符号放在 变量sym中,语法分析的判断分析将以这个读 入的符号为基础 具体任务:
跳过空格字符 识别像begin、end、if、while等这样的保留字 识别非保留字,作为标识符处理 识别数字 识别专用符号组合,如:=、<=、>= 识别特殊的单个字符,如+、-、/、* 跳过注释行(书中例子程序没有体现)
本课程采用第二种方法,Lex方法将在 后续时间补充介绍
2.词法分析程序的任务
词法分析程序的任务:对源程序进行扫描,提 供一个个符号给语法分析程序。 简称为扫描器(scanner)或扫描程序 词法分析程序实现的2种方案: 1.先单独工作一遍,把字符流源程序先变为符号 序列,输出到一个中间文件上,然后将这个文 件作为语法分析程序的输入继续第二遍的编译 过程

编写词法分析程序

编写词法分析程序

实验报告课程名称:编译原理__ 项目名称:编写词法分析程序姓名:专业:计算机科学与技术_ 班级:2011级学号:同组成员:1注:1、实验准备部分包括实验环境准备和实验所需知识点准备。

2、若是单人单组实验,同组成员填无。

二、实验过程记录2:1、实验目的给出PL/0文法规范,要求编写PL/0语言的词法分析程序,深刻理解词法分析的整个过程,提高词法分析方法的实践能力2、实验内容对PL/0语言作如下功能扩充:(1)扩充条件语句的功能使其为:if<条件>then <语句>[else <语句>](2)增加repeat语句,格式为:repeat<语句>{;<语句>}until<条件>3、实验要求要求:(1)给出扩充后的语法图和EBNF的语法描述。

(2)修改PL/0的编译系统,使它能正确编译扩充后的PL/0程序。

4、实验步骤:(1)整型一维数组,数组的定义格式为:VAR<数组标识名>(<下界>:<上界>)其中上界和下界可以是整数或者常量标识名。

访问数组元素的时候,数组下表是整型的表达式,包括整数、常量或者变量和他们的组合。

(2)扩充条件语句,格式为:<条件语句> ::= IF<条件>THEN<语句> [ELSE<语句>]扩充条件语句的语法图为:2注:实验过程记录要包含实验目的、实验原理、实验步骤,页码不够可自行添加。

(3)增加repeatT语句,格式为:<复合语句> ::= repeat<语句>UNTL<条件>扩充repeat语句的语法图为:源程序代码:#include<stdio.h>#include<string.h>inti,j,k,sign,number,flag,run,sum,autuor;charch;charwords[10]={""};charprogram[500];intScan(charprogram[]){char*keywords[39]={ "auto","default","do","extern","goto","int","short","static","struct","switch", "typedef","void","break","case","char","const","continue","double","else","enum ","float","for","if","long","register","return","signed","zhaixinyuan","sizeof" ,"union","unsigned","volatile","while","main","printf","scanf","include","defin e","string"};number=0;flag=0;j=0;ch=program[i++];while((ch=='')||(ch=='\r')||(ch=='\n'))ch=program[i++];if((ch>='a')&&(ch<='z')){while((ch>='a')&&(ch<='z')){words[j++]=ch;ch=program[i++];}i--;words[j++]='\0';for(k=0;k<38;k++)if(strcmp(words,keywords[k])==0)keywords[k])==0{sign=k+1;flag=1;if(k==27)autuor=1;break;}if(flag==0){sign=100;运行结果:3注:1、实验小结应包含实验所需知识点和实验方法的总结,实验心得体会等。

pl0语法分析词法分析语义分析

pl0语法分析词法分析语义分析

作者:love冥天出处:PL/O语言是Pascal语言的一个子集,我们这里分析的PL/O的编译程序包括了对PL/O语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。

PL/O语言编译程序釆用以语法分析为核心、一遍扫描的编译方法。

词法分析和代码生成作为独立的子程序供语法分析程序调用。

语法分析的同时,提供了出错报告和出错恢复的功能。

在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。

词法分析子程序分析:词法分析子程序名为getsym,功能是从源程序中读出一个单词符号(token), 把它的信息放入全局变量sym. id和num中,语法分析器需要单词时,直接从这三个变量中获得。

(注意!语法分析器每次用完这三个变量的值就立即调用getsym子程序获取新的单词供下一次使用。

而不是在需要新单词时才调用getsym iS 程。

)getsym过程通过反复调用getch子过程从源程序过获取字符,并把它们拼成单词。

getch过程中使用了行缓冲区技术以提高程序运行效率。

词法分析器的分析过程:调用getsym时,它通过getch过程从源程序中获得一个字符。

如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把sym变量赋成相应的保留字类型值;如果没有查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过程的名字),把sym置为ident,把这个单词存入id变量。

查保留字表时使用了二分法查找以提高效率。

如果getch获得的字符是数字,则继续用getch获取数字,并把它们拼成一个整数,然后把sym置为number,并把拼成的数值放入num变量。

如果识别出其它合法的符号(比如:赋值号、大于号、小于等于号等),则把sym则成相应的类型。

如果遇到不合法的字符,把sym置成nul。

语法分析子程序分析:语法分析子程序采用了自顶向下的递归子程序法,语法分析同时也根据程序的语意生成相应的代码,并提供了出错处理的机制。

《编译原理(实验部分)》实验3_PL0语法分析

《编译原理(实验部分)》实验3_PL0语法分析

《编译原理(实验部分)》实验3_PL0语法分析《编译原理》(实验部分)实验3_PL0语法分析一、实验目的加深和巩固对于语法分析的了解和掌握;给出PL/0文法规范,要求编写PL/0语言的语法分析程序。

二、实验设备1、PC 兼容机一台;操作系统为WindowsWindowsXP。

2、Visual C++ 6.0 或以上版本, Windows 2000 或以上版本,汇编工具(在Software 子目录下)。

三、实验原理PL/O语言的编译程序,是用高级语言PASCAL语言书写的。

整个编译过程是由一些嵌套及并列的过程或函数完成。

语法分析是由过程BLOCK完成。

采用自顶向下的递归子程序法。

所产生的目标程序为假象栈式计算机的汇编语言。

对目标程序的执行是由PASCAL语言书写的解释程序进行的。

四、实验步骤实验代码int lp=0;int rp=0;#define getsymdo if(-1==getsym()) return -1#define expressiondo() if(-1==expression()) return -1#define termdo() if(-1==term()) return -1#define factordo() if(-1==factor()) return -1int expression();//语法分析int factor(){if(sym!=ident &&sym!=number&&sym!=lparen){err++;if(err==1) printf("语法错误: \n");printf("error----Factor Needs Ident or Number or Lparen\n");}if ((sym == ident) || (sym == number) || (sym == lparen)){if (sym == ident){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("变量后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == number){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("数字后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == lparen){WordAnalyse();lp++;if(getsym()==-1){lp--;err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");return -1;}expressiondo();if (sym == rparen){WordAnalyse();lp--;if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus) {err++;if(err==1) printf("语法错误: \n");printf("括号后没有跟上+-*\\ \n");}}else{err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");}}}return 0;}int term(){factordo();if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=ident&&sym!=number&&sym!=lparen&&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == times) || (sym == slash)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("* \\ 后缺项\n");return -1;}factordo();}return 0;}int expression(){if ((sym == plus) || (sym == minus)){//cout<<strlen(id)<<endl;< p="">if (sym==minus&&2==strlen(ID)+1)flg=1;else{flg=0;WordAnalyse();}getsymdo;termdo();}else{//WordAnalyse();termdo();}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=ident&&sym!=number&&sym!=lparen&&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == plus) || (sym == minus)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("+ - 后缺项\n");return -1;}termdo();}return 0;}int main(int argc, char* argv[]){init();err=0;ifstream fin("in.txt");ofstream fout("out.txt");ch=' ';lp=0;getsymdo;expression();if(err==0) cout<<"语法正确"<<endl;< p="">elsecout<<"语法错误,错误个数: "<<err<<=""></err< </endl;<></strlen(id)<<endl;<>。

《编译原理(实验部分)》实验2_PL0词法分析

《编译原理(实验部分)》实验2_PL0词法分析

《编译原理》(实验部分)实验2_PL0 词法分析一、实验目的加深和巩固对于词法分析的了解和掌握;初步认识PL/0 语言的基础和简单的程序编写;通过本实验能够初步的了解和掌握程序词法分析的整个过程;提高自己上机和编程过程中处理具体问题的能力。

二、实验设备1、P C兼容机一台;操作系统为WindowsWindowsX P2、Visual C++ 6.0 或以上版本,Windows 2000 或以上版本,汇编工具 (在Software 子目录下)。

三、实验原理PL/O语言的编译程序,是用高级语言PASCAL语言书写的。

整个编译过程是由一些嵌套及并列的过程或函数完成。

词法分析程序是独立的过程GETSY完成,供语法分析读单词时使用。

四、实验步骤阅读所给出的词法分析程序( pl0_lexical.c ),搞懂程序中每一个变量的含义,以及每一个过程的作用,并在该过程中进行中文注释;阅读完程序后,画出各过程的流程图;给出的程序包含两处输入错误,利用所给的pl/0 源程序(test.pl0) 对程序进行调试,使其能正确对所给文件进行分析并能够解释运行;在阅读懂所给出的词法分析程序后,将你对词法分析的理解写在实验报告上。

实验代码#include<stdio.h>main(){ printf ("my name is 08061118 yuchaofeng ");}主程序:#include <stdio.h>#include <ctype.h>#include <alloc.h>#include <stdlib.h>#include <string.h>#define NULL 0FILE *fp;char cbuffer;char *key[8]={"DO","BEGIN","ELSE","END","IF","THEN","VAR","WHILE"}; char *border[6]={",",";",":=",".","(",")"};char *arithmetic[4]={"+","-","*","/"};char *relation[6]={"<","<=","=",">",">=","<>"};char *consts[20];char *label[20];int constnum=0,labelnum=0;int search(char searchchar[],int wordtype){int i=0;switch (wordtype) {case 1:for (i=0;i<=7;i++){if (strcmp(key[i],searchchar)==0)return(i+1);};case 2:{for (i=0;i<=5;i++){if (strcmp(border[i],searchchar)==0)return(i+1);};return(0);}case 3:{for (i=0;i<=3;i++){ if (strcmp(arithmetic[i],searchchar)==0){};};return(0);};case 4:{for (i=0;i<=5;i++){ if (strcmp(relation[i],searchchar)==0){return(i+1);};};return(0);};case 5:{for (i=0;i<=constnum;i++){ if (strcmp(consts[i],searchchar)==0){return(i+1);};}consts[i-1]=(char *)malloc(sizeof(searchchar));strcpy(consts[i-1],searchchar);constnum++;return(i);};case 6:{for (i=0;i<=labelnum;i++){ if (strcmp(label[i],searchchar)==0){ return(i+1);};}label[i-1]=(char *)malloc(sizeof(searchchar)); strcpy(label[i-1],searchchar);return(i);};}}char alphaprocess(char buffer){int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))){ alphatp[++i]=buffer; buffer=fgetc(fp);}; alphatp[i+1]='\0';if (atype=search(alphatp,1)) printf("%s (1,%d)\n",alphatp,atype-1); else { atype=search(alphatp,6);printf("%s (6,%d)\n",alphatp,atype-1); };return(buffer);char digitprocess(char buffer){int i=-1;char digittp[20];int dtype;while ((isdigit(buffer))){ digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';dtype=search(digittp,5);printf("%s (5,%d)\n",digittp,dtype-1); return(buffer);}char otherprocess(char buffer){int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';if (otype=search(othertp,3)){printf("%s (3,%d)\n",othertp,otype-1);buffer=fgetc(fp);goto out;};if (otype=search(othertp,4)){buffer=fgetc(fp);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,4)){printf("%s (4,%d)\n",othertp,otypetp-1); goto out;}elseothertp[1]='\0';printf("%s (4,%d)\n",othertp,otype-1);goto out;};if (buffer==':'){ buffer=fgetc(fp);if (buffer=='=')printf(":= (2,2)\n");buffer=fgetc(fp);goto out;}else{if (otype=search(othertp,2)){ printf("%s (2,%d)\n",othertp,otype-1); buffer=fgetc(fp); goto out;}};if ((buffer!='\n')&&(buffer!=' '))printf("%c error,not a word\n",buffer); buffer=fgetc(fp);out: return(buffer);} void main(){ int i;for (i=0;i<=20;i++){label[i]=NULL; consts[i]=NULL;};if ((fp=fopen("skh.c","r"))==NULL) printf("error");else{ cbuffer = fgetc(fp);while (cbuffer!=EOF){if (isalpha(cbuffer)) cbuffer=alphaprocess(cbuffer);else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer); else cbuffer=otherprocess(cbuffer); };printf("over\n");};}。

PL0词法分析.ppt

PL0词法分析.ppt
1
❖单词的种类: ➢基本字(保留字):BEGIN、 END、 IF、 THEN等 ➢运算符: 如+、-、*、/、:=、#、>=、<=等 ➢标识符: 用户定义的变量名、常数名、过程名 ➢常数: 如10、25、100等整数 ➢界符: 如‘,’、‘.’ 、‘;’ 、‘(’ 、‘)’等 ❖词法分析程序GETSYM所要完成的任务: ➢滤空格、识别保留字 ➢识别标识符、拼数 ➢拼复合词、输出源程序
§2.3 PL/O编译程序的词法分析
❖PL/O词法分析程序功能:为语法语义分析提供单词,把输 入的字符串形式的源程序分割成一个个单词符号传递给语法 语义分析
❖PL/O编译程序设置的三个全程变量: ➢SYM:存放单词的类别,如beginsym, ident, number ➢ID: 存放用户所定义的标识符的值 ➢NUM:存放用户定义的数
2
❖PL/O的词法分析过程GETSYM,YM
4
❖取字符过程GETCH:
图 2.6 取字符过程GETCH
5

实验一 词法分析程序的设计与实现

实验一  词法分析程序的设计与实现

实验一词法分析程序的设计与实现一、实验内容【实验目的和要求】设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解。

【实验内容】通过对PL/0词法分析程序(GETSYM)的分析,并在此基础上按照附录A中给出的PL/0语言的语法描述,编写一个PL/0语言的词法分析程序。

此程序应具有如下功能:输入为字符串(待进行词法分析的源程序),输出为单词串,即由(单词、类别)所组成的二元组序列。

有一定检查错误的能力,例如发现2A这类不能作为单词的字符串。

【实验环境】Windows PC机,任何语言。

【提交内容】提交实验报告,报告内容如下:目的要求、算法描述、程序结构、主要变量名说明、程序清单、调试情况、设计技巧、心得体会。

提交源程序和可执行文件。

【学时】4课时。

二、实验说明词法分析程序的任务就是扫描源程序,依据词法规则识别单词并报告构词错误信息。

通常将单词分为5种类型。

1)基本字:也叫关键字、保留字,是程序设计语言用来表示特定语法含义的一种标识符,如if、begin等。

2)运算符:如+、-、*、/、:=、>、<等。

3)标识符:用户定义的变量名、常数名、函数名等。

不同的高级程序设计语言对关键字是否可以作为普通标识符有不同的要求,有的语言允许程序员使用关键字作为普通标识符,有的程序设计语言则不允许程序员将关键字用着普通标识符(如C/C++、Pascal等都不允许)。

在允许程序员将关键字用作普通标识符的程序设计语言的编译器中,编译器必须具备能够区分一个标识符到底是关键字还是普通标识符的功能。

4)常数:如23、6等。

5)界符:如“,”、“;”、“(”、“)”、“.”等。

注意事项●空格的作用仅仅是将一个个单词分割开来,源程序中的空格不具备别的语法意义,在语法分析及其后续阶段都没有任何作用,因此,词法分析的另一个工作是过滤空格。

●注释对整个源程序的编译也没有任何语法意义,只是为了便于阅读和交流,因此,有的编译程序的词法分析程序也负责过滤注释。

编译原理实验--词法分析器

编译原理实验--词法分析器

实验一词法分析器设计【实验目的】1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。

2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。

3.通过完成词法分析程序,了解词法分析的过程。

【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。

【实验流程图】【实验步骤】1.提取pl/0文件中基本字的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE];int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {printf("%s\t",wsym[m]);m=14;n=k+1;} }2.提取pl/0文件中标识符的源代码while((ch=fgetc(stream))!='.'){int k=-1;char a[SIZE]=" ";int s=0;while(ch>='a' && ch<='z'||ch>='A' && ch<='Z'){if(ch>='A' && ch<='Z') ch+=32;a[++k]=(char)ch;ch=fgetc(stream);}for(int m=0;m<=12&&k!=-1;m++)for(int n=0;n<=k;n++){if(a[n]==wsym[m][n]) ++s;else s=0;if(s==(strlen(wsym[m]))) {m=14;n=k+1;}}if(m==13) for(m=0;a[m]!=NULL;m++) printf("%c ",a[m]);3.提取pl/0文件中常数的源代码while((ch=fgetc(stream))!='.'){while(ch>='0' && ch<='9'){num=10*num+ch-'0';ch=fgetc(stream);}if(num!=0) printf("%d ",num);num=0;}4.提取pl/0文件中运算符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case'+': printf("+ ");break;case'-': printf("- ");break;case'*': printf("* ");break;case'/': printf("/ ");break;case'>': if(fgetc(stream)=='=')printf(">= "); else printf("> ");break;case'<': if(fgetc(stream)=='=')printf("<= "); else printf("< ");break;case':': printf(":= ");break;case'#': printf("# ");break;case'=': printf("= ");break;default: break;}ch=fgetc(stream);5.提取pl/0文件中界符的源代码int ch=fgetc(stream);while(ch!='.'){switch(ch){case',': printf(", ");break;case';': printf("; ");break;case'(': printf("( ");break;case')': printf(") ");break;default: break;}ch=fgetc(stream);}【实验结果】1.pl/0文件(222.txt)内容const a=10;var b,c;procedure p;beginc:=b+a;end;beginread(b);while b#0 dobegincall p;write(2*c);read(b)endend .2.实验运行结果【实验小结】1.了解程序在运行过程中对词法分析,识别一个个字符并组合成相应的单词,是机器能过明白程序,定义各种关键字,界符。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

PL/0语言词法分析程序//这是我编译原理的一次作业,中间有许多不足之处希望大家指正/*编写PL/0语言的词法分析程序要求:1、读入用PL/0语言编写的源程序,正确的进行词法分析,并输出二元式序列。

2、若源程序有词法错误,能够给出出错的准确位置。

3、词法代号如下(+,+);(-,-);(*,*);(/,/);((,();(),));(,,,);(;,;);(.,.);(#,#);(=,=);(>,>);(<,<);(:=,a);(>=,b);(<=,c);(数字,d);(标识符,e);关键字代号:(begin,f);(call,g);(const,h);(do,i);(end,j);(if,k);(odd,l); (procedure,m); (read,n);(then,o);(var,p);(while,q);(write,r);4、等于运算符号为一个 = 测试程序:A.C====================== CONST A=10;VAR B,C; PROCEDURE P;VAR D;PROCEDURE Q;VAR X;BEGINREAD(X);D:=X;WHILE XDO CALL P;END;BEGINWRITE(D);CALL Q;END;BEGINCALL P;END.*//*program name:chifufenxi*//*作者:小万 QQ:421404493*//*date:2004.10.11*/#include#include#include#include#include#define N 256//每一行的字符数不能超过256个char buffer[N]; //用作存放一行字符char word[20]; //用作存放经过分析单词char *kword[13]={"begin","call","const","do","end","if","odd","procedure","read","the n","var","while","write"};char ktype[13]={'f','g','h','i','j','k','l','m','n','o','p','q','r'};int len;//记录每一行的长度int count=0;//用来记录行数void write(char *wstr,char wc,FILE *wout)//将分析结果按照规则写入到文件{fputc('(',wout);fputs(wstr,wout);fputc(',',wout);fputc(wc,wout);fputc(')',wout);}int readbuffer(FILE *fp){char ch;len=0;ch=fgetc(fp);while(!feof(fp) && ch!='\n')//读取字符到缓冲区{buffer[len]=ch;ch=fgetc(fp);len++;}len--;//用来控制词法分析时行分析中字母的个数if(feof(fp))//标志文件是否结束return 0;elsereturn 1;}void error(int type){if(type==1)printf("为无效字符,第%d行词法出错,标志符不能以数字开头\n",count); else if(type==2)printf("第%d行词法出错,赋值符应为\:\= \n ",count);else printf("为无效字符,第%d行词法出错\n",count);void check(char *str,FILE *out);//声明函数,此函数用来分类单词void fenxi(char *row,FILE *op)//此函数用来对每一行的单词进行语法分析{//printf("%d\n",count);int k=0;//用作控制临时存放单词的变量str0int i=0;//定义两个变量用作控制每一行是否结束,int ferror=0;//用作出错标志char str0[20];//临时存放单词的变量while(i<=len){k=0;//将k置0strcpy(word,"\0");//将存放单词的变量清空/*去除空格*/if(isspace(row[i]))//去出空格,跳格符,换行符{i++;continue;}/*去出无效字符*/while(!isalpha(row[i])&&!isdigit(row[i])&&i<=len&&!isspace(row[i])&&!(row[i]=='\ 0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]=='+' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='=')){putchar(row[i]);i++;ferror=1;//设置错误标志符if(ferror==1){error(3);//调用出错处理函数ferror=0;}/*对注释进行处理,假设此语言的注释只能单行注释以双斜杠"//"为注释开始标志*/if(row[i]=='/'){i++;if(row[i]=='/'){i=len+1;//忽略注释符后面的单词continue;}elsei--;}/*判断是否为数字*/if(isdigit(row[i])){while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i] =='<'||row[i]=='+' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='='))//当不到行尾,是数字或字母当然有可能是无效字符{if(isdigit(row[i]))//是数字则将字符逐个存入临时数组{str0[k]=row[i];i++;k++;// putchar('e');}else //数字中加有字母或无效字符则报错{// putchar('x');ferror=1;break;//已经出错设置标志并退出循环}}if(ferror==1)//检测是否出错{ /*将刚刚的那个单词后面的数字和字母清空,如123abc123或则123$$23等,当出现错误后,需要消除abc123和$$23 以免误作为下一个标志符*/for(int j=0;j putchar(str0[j]);while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i] =='<'||row[i]=='+' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='=')){putchar(row[i]);i++;}error(1);//putchar('e');//调用出错处理函数ferror=0;//重新设置错误标志位//i--;//strcpy(word,"");}else//未出错照常处理{str0[k]='\0';strcpy(word,str0);i--;//减一是为了使最后取出的那个字符不在被下面的程序判断// str0[0]='\0';}}/*判断是否为标志符和关键字即由字母开头并且不含标点符号用ispunct(int ch)判断标点符号*/if(isalpha(row[i]))//标志符或关键字由字母开头{k=0;while(i<=len&&row[i]!=32&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'| |row[i]=='+' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='='))//关键字和标志符由数字和字母组成{if(isalpha(row[i])||isdigit(row[i]))//由数字和字母组成{str0[k]=row[i];i++;k++;}else//出错,原因可能是出现了不可识别的字符{ferror=1;break;}}if(ferror){for(int j=0;j putchar(str0[j]);while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i] =='<'||row[i]=='+' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='=')){putchar(row[i]);//消除整个非法单词i++;}ferror=0;error(3);//i--;}else{str0[k]='\0';strcpy(word,str0);str0[0]='\0';i--;}}/*判断运算符*/if(row[i]=='+' ||row[i]=='-' ||row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'||row[i]=='.'||row[i]=='#' || row[i]=='=') {str0[0]=row[i];str0[1]='\0';strcpy(word,str0);str0[0]='\0';}//要先判断单个字符的运算符,以避免诸如>=的运算符后面的=再次被判断if(row[i]==':'){i++;if(row[i]=='='){//word[0]=':';//word[1]='=';//word[2]='\0';strcpy(word,">=");}else{error(2);//出错后调用处理函数i--;}}if(row[i]=='>'){i++;if(row[i]=='='){strcpy(word,">=");}else{strcpy(word,">");i--;}}if(row[i]=='<'){i++;if(row[i]=='='){strcpy(word,"<=");}else{strcpy(word,"<");i--;}}//puts(word);check(word,op);/*调用分类函数,辨别每一个单词的类别要求输入的每一个单词必须符合词法规则*///word[0]='\0';i++;//使指针后移,取出下一个字母}}void check(char *str,FILE *out){if(isdigit(str[0]))/*如果第一个字符是数字那么整个单词都是数字组成的,即为常数*/{write(str,'d',out);//调用写函数将分好类的单词写入文件}if(isalpha(str[0]))/*如果第一个字符是字母,那么这个单词是标志符或关键字*/ {int fyiyong=0;//用作标记这个单词是否已被分类/*以下判别是否是关键字*/for(int ct=0;ct<13;ct++){if(!strcmp(str,kword[ct])){write(str,ktype[ct],out);fyiyong=1;}}/*经过以上判别,可以判别是否是关键字,不是即为标志符*/if(fyiyong!=1){write(str,'e',out);}/*以下对运算符分类*/ if(str[0]=='>'){if(str[1]=='='){write(str,'b',out); }else{write(str,'>',out); }}if(str[0]=='<'){if(str[1]=='='){write(str,'c',out); }else{write(str,'<',out); }}if(!strcmp(str,":=")) {write(str,'a',out); }if(str[0]=='+' || str[0]=='-' || str[0]=='*' || str[0]=='/' || str[0]=='(' || str[0]==')' || str[0]==',' || str[0]==';'|| str[0]=='.'|| str[0]=='#' || str[0]=='=' ){write(str,str[0],out);}}void main(){count=1;char scfilename[20],rsfilename[20];//定义用来存放输入源文件和输出目标文件的名字printf("Please input your source file name:");gets(scfilename);printf("Please input your result file name:");gets(rsfilename);FILE *fp,*op;fp=fopen(scfilename,"r");op=fopen(rsfilename,"w");if(fp)//打开文件成功后调用函数对源文件进行词法分析{while(readbuffer(fp)){fenxi(buffer,op);count++;//行加一}else//while the file not exist{printf("Your souce file not exist!!!\n"); exit(0);}fclose(fp);//close the filesfclose(op);printf("ok!");//output the mark of end getchar();}。

相关文档
最新文档