实验2《词法分析程序设计与实现》(C语言版)
正文任务描述相关知识词法分析的基本知识实验步骤编程要求测试说明实验答案结语正文
任务描述
本关任务:加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。
相关知识
为了完成本关任务,你需要掌握:词法分析程序设计与实现。
词法分析的基本知识
词法分析程序( Lexical analyzer,简称 Lexer ),负责从左到右逐个字符地对源程序进行扫描和分解,根据语言的词法规则识别出一个个的单词符号。
因此一个词法分析程序应具备如下功能:
从左至右扫描构成源程序的字符流识别出有词法意义的单词返回单词记录,或词法错误信息
由上可知词法分析中的一个重要环节为识别单词符号类型,为了便于语法分析,通常将单词符号分为五类。
标识符
用来命名程序中出现的变量、数组、函数、过程、标号等,通常是一个字母开头的字母数字串,如 length,nextch 等。
基本字
也可以成为关键字或保留字。如 if,while,for,do,goto 等。他们具有标识符的形式,但他们不是由用户而是由语言定义的,其意义是约定的。多数语言中规定,他们不能作为标识符或者标识符的前缀,即用户不能使用它们来定义用户使用的名字,故我们称它为保留字,这些语言如 Pascal 和 C 等。但也有的语言允许将基本字作为标识符或者标识符的前缀,这类语言如 Fortran 等。
常数
包括各种类型的常数,如整型、实型、字符型、布尔型等。如:5、3.1415926、a、TRUE等都是常数。
运算符
算术运算符+、-、×、÷;关系运算符<,<=,>,>=,==,!=以及逻辑运算符&&,(),||或者!等。
界符
如,、;等单字界符和/,/,//等双字界符,空白符等。
在进行词法分析后,识别出来的单词应该采用某种中间表示形式,以便为编译后续阶段方便地引用。通常一个单词用一个二元式来表示:
(单词类别,单词的属性)
其中,第一元用于区分单词所属的类别,以整数编码表示。第二元用于区分该类别中的哪一个单词符号,即单词符号的值。
实验步骤
由一个词法分析程序应具备的功能来看,我们的程序具有如下要求:
对单词的构词规则有明确的定义;编写的分析程序能够正确识别源程序中的单词符号;识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;
编程要求
根据提示,在右侧编辑器补充代码标示符、数字符及其他字符符号的识别程序后,点击评测运行程序,系统会自动进行结果对比。
测试说明
平台会对你编写的代码进行测试:
测试输入:
using namespace std;int main(){int year;cout << "hello" << endl;return 0;}#
开始你的任务吧,祝你成功!
实验答案
#include<stdio.h>#include<string.h>#include<iostream>using namespace std;char prog[80], token[20];char ch;int syn, p, m = 0, n, row, sum = 0;const char* rwtab[8] = { "if","int","for","while","do","return","break","continue" };const char* rwtab1[8] = { "main","a","b","c","d","e","f","g" };void scaner(){/*共分为三大块,分别是标示符、数字、符号,对应下面的 if else if 和 else*/for (n = 0; n < 8; n++) token[n] = NULL;ch = prog[p++];while (ch == ' '){ch = prog[p];p++;}if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {m=0;while(1){if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {token[m++]=ch;ch=prog[p++];}else{p--;break;}}token[m]='\0';syn=0;for(n=0;n<8;n++){if (strcmp(token, rwtab1[n]) == 0){syn = 2;break;}else if (strcmp(token, rwtab[n]) == 0) {syn = 1;break;}}if(!syn)syn=2;}else if ((ch >= '0' && ch <= '9')) {syn=3;sum=ch-'0';}else switch (ch) //其他字符 {case'<':m = 0; token[m++] = ch;ch = prog[p++];if (ch == '>'){syn = 4;token[m++] = ch;}else if (ch == '='){syn = 4;token[m++] = ch;}else{syn = 4;p--;}break;case'>':m = 0; token[m++] = ch;ch = prog[p++];if (ch == '='){syn = 4;token[m++] = ch;}else{syn = 4;p--;}break;case':':m = 0; token[m++] = ch;ch = prog[p++];if (ch == '='){syn = 4;token[m++] = ch;}else{syn = 4;p--;}break;case'*':syn = 4; token[0] = ch; break;case'/':syn = 4; token[0] = ch; break;case'+':syn = 4; token[0] = ch; break;case'-':syn = 4; token[0] = ch; break;case'=':syn = 4; token[0] = ch; break;case';':syn = 5; token[0] = ch; break;case',':syn = 5; token[0] = ch; break;case'(':syn = 5; token[0] = ch; break;case')':syn = 5; token[0] = ch; break;case'{':syn = 5; token[0] = ch; break;case'}':syn = 5; token[0] = ch; break;case'#':syn = 0; token[0] = ch; break;case'\n':syn = -2; break;default: syn = -1; break;}}int main(){p = 0;row = 1;cout << "Please input string:" << endl;do{cin.get(ch);prog[p++] = ch;} while (ch != '#');p=0;do{scaner();//cout<<syn<<endl;//cout<<syn<<endl;switch (syn){case 0: break;case 3: cout << "(" << syn << "," << sum << ")" << endl; break;case -1: cout << "Error in row " << row << "!" << endl; break;case -2: row = row++; break;default: cout << "(" << syn << "," << token << ")" << endl; break;}//cout<<row<<endl;if(syn==-2)row++;} while (syn != 0); }