编译原理 实验 词法分析 程序源码
编译原理词法分析程序代码#INC...
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#define LEN sizeof(struct Node)#define NULL 0struct Node{char data;struct Node *next;};void output(struct Node*);/*输出函数*/void scaner(); /*词法分析*/void getbc();void getch();void link();int letter(char ch);int degit(char ch);int retu();void tuihui();void back(int a,char *b);struct Node *head,*p;char ch;char *key[]={"main","int","char","if","else","for","while"}; /*关键字表*/ char token[20];int main(void){head=(struct Node *)malloc(LEN); /*分配头节点存储空间*/if(!head) {printf("error");exit(1);}head->next=NULL;head->data=' ';p=head;printf("************************输入@标明源代码输入结束.************************\n");printf("******************************输出源代码.*******************************\n");printf("输入待分析源程序:\n");while(1){ int i=0;char temp[256];gets(temp);if(temp[0]=='@') break;p->next=(struct Node *)malloc(LEN);if(!(head->next)) {printf("");exit(1);}p=p->next;while(temp[i]!='\0' && i<256){p->data=temp[i];p->next=(struct Node *)malloc(LEN);if(!(p->next)) {printf("");exit(1);}p=p->next;i++;}p->data='\n';p->next=NULL;}output(head); /*输出结果*/p=head->next;while(p->next!=NULL)scaner();system("pause");return 0;}void output(struct Node *head) { if(!head) {printf("");exit(1);}p=head->next;while(p->next!=NULL){printf("%c",p->data);p=p->next;}printf("\n");}void getbc() /*读入的不是空白字符*/{while (ch==' ')getch();}void getch() /*读入一字符*/{ch=p->data;}void link() /*将ch中的字符连接到token的后面*/{unsigned int i;i=strlen(token);token[i]=ch;token[i+1]='\0';}int letter(char ch) /*判断ch中的是否是字母*/{return isalpha((int)ch);}int digit(char ch) /*判断ch中的是否是数字*/{return isdigit((int)ch);}int retu() /*判断token中的字符串是否是关键字或是标识符*/ {int k;for(k=0;k<=6;k++){if(strcmp(key[k],token)==0) return (k+1);}return 10;}void tuihui() /*指针回退一个字符*/{struct Node *Q;Q=head->next;while(Q->next!=p)Q=Q->next;p=Q;}void back(int a,char *b) /*返回函数,输出序列*/ {printf("(%d,%s)",a,b);}void scaner() /*词法分析函数*/{token[0]=NULL; /*将token清空*/getch();getbc(); /*读入一个单词*/if(letter(ch)) /*处理字符的情况*/{while(letter(ch)||digit(ch)){link();getch();}tuihui();c=retu();if(c!=10) back(c,token);else back(10,token);}else if(digit(ch)) /*处理数字的情况*/ {while(digit(ch)){link();getch();}tuihui();printf("(20,%d)",atoi(token));}elseswitch(ch) /*处理特殊符号的情况*/{case'+': back(22,"+");break;case'-': back(23,"-");break;case'*': back(24,"*");break;case'/': back(25,"/");break;case'<': getch();if(ch=='=') back(38,"<=");tuihui();back(36,"<");break;case'>': getch();if(ch=='=') back(37,">=");tuihui();back(35,">");break;case';': back(34,";");break; case'{': back(30,"{");break; case'}': back(31,"}");break; case'(': back(26,"(");break; case')': back(27,")");break; case'=': back(21,"=");break; case'\n': break;default: printf("");break; }}试验结果截图:。
编译原理的词法分析代码
Pl0.h 和S1.c编译原理词法分析程序(C语言)/*头文件pl0.h*/#define al 10/*符号的最大长度*/#define nmax 14/*number的最大位数*/#define norw 8/*关键字个数*/char ch;/*获取字符的缓冲区,getch使用*/int cc,ll;/*cc表示当前字符(ch)的位置*/char line[81];/*读取行缓冲区*/char a[al+1];/*临时符号,多处的字节用于存放0*/ char anum[nmax+1];/*临时符号,存放number*/ char inum[nmax+1];/*存放常数*/char word[norw][al];/*保留字*/char fname[al];/*文件名*/char id[al+1];/*存放标识符或保留字*/int num;/*常数*/int err;//错误计数器FILE * fin;FILE * fout;FILE * fas;/*词法分析结果文件*//*函数执行出错,退出程序*/#define getchdo if(-1==getch()) return -1#define getsymdo if(-1==getsym()) return -1 int getch();/*读取一行字符*/int getsym();/*读取一个分词*//*主程序*//**运行环境:Microsoft visual c++ 6.0*//**程序功能要求:*编制一个读单词过程,源程序为一个文件,读取该文件,识别出各个具有独立意义的单词,*即基本保留字、标识符、常数、运算符、界符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
*单词的内部编码如下:*1.保留字:if、int、for、while、do、return、break、continue;单词种别码为1;*2.标识符:除保留字外的以字母开头,后跟字母、数字的字符序列;单词种别码为2;*3.常数为无符号整形数;单词种别码为3;*4.运算符包括:+、-、*、/、=;单词种别码为4;*5.分隔符包括:,、;、{、}、(、);单词种别码为5。
编译原理词法分析和语法分析报告+代码(C语言版)[1]
词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
编译原理 C语言 词法分析 实验 源码
编译原理实验报告 词法分析
南京信息工程大学 计算机与软件学院 软件工程 2009 级 1 班 54andy1@ 一.实验目的
#region 负数 算数减 算数减并赋值 case ANSIC.Character.MinusSign:
break; #endregion
#region 算数乘 算数乘并赋值 case ANSIC.Character.Asterisk:
if (index + 1 < SourceLines[row].Length && SourceLines[row][index + 1] == '+') { Result.Add(new Token(TokenTypes.MultiplyAsign, row, index, 2, "*=")); index++;
word.Append(SourceLines[row][index]); index++; while (index<SourceLines[row].Length) { if (SourceLines[row][index] >= '0' && SourceLines[row][index] <= '9')
编译原理实验报告 词法分析 1 / 19
一开始做词法分析的时候,单纯做词法分析,没有考虑到语法分析,所以没有架构好,在要做语法分析的 时候找不到合适的接口,这是第一个教训。
编译原理词法分析和语法分析报告 代码(C语言版)
admit=0;
for(in=0;in<cal-1;in++){str[in]=str[in+1];}
str[in]='\0';
cal--;
r_find=r_find->next;
}//:入栈~
if(r_find->line_States==s_find->num&&r_find->rank_Letter==str[0]&&r_find->name=='r'){//:规约
词法分析
三、词法分析程序的算法思想:
算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1主程序示意图:
否
是
扫描子程序主要部分流程图
是是
否
字母
数字其他
运算符、符号
界符等符号
否
是
词法分析程序的C语言程序源代码:
//词法分析函数: void scan()
//数据传递:形参fp接收指向文本文件头的文件指针;
//全局变量buffer与line对应保存源文件字符及其行号,char_num保存字符总数。
void scan()
{
char ch;
int flag,j=0,i=-1;
while(!feof(fp1))
{
ch=fgetc(fp1);
flag=judge(ch);
struct Sign *next;
编译原理词法分析器代码
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include <conio.h>#define KEYWORD_LEN 32 //保留字个数#define STR_MAX_LEN 300 //标识符最大长度#define PRO_MAX_LEN 20480 //源程序最大长度#define STB_MAX_LEN 1000 //符号表最大容量#define CTB_MAX_LEN 1000 //常数表最大容量#define ERROR 0 //错误#define ID (KEYWORD_LEN+1) //标识符#define CONST (KEYWORD_LEN+2) //常量#define OPERAT (KEYWORD_LEN+3) //运算符#define DIVIDE (KEYWORD_LEN+4) //界符int errorLine=0; char proBuffer[PRO_MAX_LEN] = ""; //存储程序代码的全局缓冲区char ch; //读出来的当前字符char wordget[STR_MAX_LEN]; //标识符或常量int point = 0; //源程序当前位置指针char signTab[STB_MAX_LEN][STR_MAX_LEN]; //符号表int pointSTB = 0; //符号表指针char constTab[CTB_MAX_LEN][STR_MAX_LEN]; //常量表int pointCTB = 0; //常数表指针char kwTab[KEYWORD_LEN][10]={ //保留字表C语言一共有32个保留字[关键字]"auto", "break", "case", "char","const", "continue", "default","do", "double", "else", "enum","extern", "float", "for", "goto","if", "int", "long", "register","return", "short", "signed", "sizeof","static", "struct", "switch", "typedef","union", "unsigned", "void", "volatile", "while"};char errorTab[][50]={ //错误代码表/*0*/"未知错误", /*1*/"非法的字符", /*2*/"不正确的字符常量表达",/*3*/"不正确的字符串表达", /*4*/"不正确的数字表达", /*5*/"注释丢失'*/'"};typedef struct signDuality{int kind;int value;}*pDualistic, Dualistic;void pretreatment(); //预处理void ProcError(int id); //错误bool GetChar(); //获得一个字符不包括结束标记bool GetBC(); //获得一个非空白字符void Concat(char *str); //将ch连接到str后int Reserve(char *str); //对str字符串查找保留字表若是一个保留字-返回其编码否则返回0void Retract(); //将搜索指示器回调一个字符位置int InsertId(char *str);//将str串以标识符插入符号表,并返回符号表指针int InsertConst(char *str); //将str串以常数插入符号表,并返回常数表指针bool wordAnalyse(pDualistic pDu); //词法分析true正常//预处理将缓冲区内的源代码去掉注释和无效空格void pretreatment(){int lines=0;char tmp[PRO_MAX_LEN]; //先将处理结果保存到临时空间int tmpp = 0; //这个临时空间的末尾指针bool flg;char tmpc; //去掉注释先//注释有两种一种是// 另一种是/**/point = 0;do{flg = GetChar();if(ch == '/'){flg = GetChar();switch(ch){case '/':do{flg = GetChar();}while(!(ch == '\n' || flg == false));//注释一直到行尾或文件结束if(ch == '\n')Retract(); //归还换行break;case '*':do{flg = GetChar();tmpc = ch;//为了保证出错处理程序能正确定位出错位置保留注释中的换行if(tmpc == '\n')tmp[tmpp++] = tmpc;flg = GetChar();Retract(); //归还一个字符}while(flg && !(flg && tmpc == '*' && ch == '/'));flg = GetChar();if (!flg){ProcError(5);}break;default: //不是任何一种注释Retract();Retract();GetChar();tmp[tmpp++] = ch;flg = GetChar();tmp[tmpp++] = ch;}}else{tmp[tmpp++] = ch;}}while(flg);tmp[tmpp] = '\0';strcpy(proBuffer,tmp);}//错误void ProcError(int id){printf("\nError:第%d行,%s\n",errorLine, errorTab[id]);}//获得一个字符bool GetChar(){if(point < PRO_MAX_LEN && proBuffer[point] != '\0'){//如果当前下标合法且当前字符为结束标记则取字符增游标ch = proBuffer[point++];if (ch == '\n')errorLine ++;return true;}ch = '\0';return false;}//获得一个非空白字符bool GetBC(){do{if(!GetChar()) //获取字符失败{ch = '\0';return false;}}while(isspace(ch)); //直到获得一个非空白字符return true;}//将ch连接到str后void Concat(char *str){int i;for(i=0; str[i]; ++i);str[i] = ch;str[i+1] = '\0';}//对str字符串查找保留字表若是一个保留字-返回其编码否则返回0int Reserve(char *str){int i;for(i=0; i<KEYWORD_LEN; ++i) //从保留字表中查找str串{if(0 == strcmp(kwTab[i], str))return i+1; //注意,这里加一原因是0值被错误标记占用}return 0;}//将搜索指示器回调一个字符位置void Retract()///char *ch{if(proBuffer[point] == '\n' && errorLine > 0)errorLine --;point --;}//将str串以标识符插入符号表,并返回符号表指针int InsertId(char *str){int i;for(i=0; i < pointSTB; ++i)if(0 == strcmp(signTab[i], str))return i;strcpy(signTab[pointSTB++], str);return (pointSTB-1);}//将str串以常数插入常量表,并返回常数表指针int InsertConst(char *str){int i;for(i=0; i < pointCTB; ++i)if(0 == strcmp(constTab[i], str))return i;strcpy(constTab[pointCTB++], str);return (pointCTB-1);}//词法分析false--分析结束bool wordAnalyse(pDualistic pDu){int code, value;char judge; //这里有个技巧借用此变量巧妙的运用SWITCH结构int i = 0; //辅助GetBC();judge = ch;if (isalpha(ch) || ch == '_')judge='L';if (isdigit(ch))judge='D';switch(judge){case 'L':while(isalnum(ch) || ch == '_'){ //标识符wordget[i++] = ch;GetChar();}wordget[i] = '\0';Retract(); //回退一个字符code = Reserve(wordget);if(code == 0){value = InsertId(wordget);pDu->kind = ID;pDu->value = value;}else{pDu->kind = code;pDu->value = -1;}return true;case 'D':while(isdigit(ch)){wordget[i++] = ch;GetChar();}wordget[i] = '\0';Retract();value = InsertConst(wordget);pDu->kind = CONST;pDu->value= value;return true;//( ) [ ] . , ! != ~ sizeof < << <= > >> >= = == & && &= | || |= ?: + ++ +=// --> ---= * *= / /= % %= >>= <<= ^ ^=case '"': //字符串常量do{wordget[i++] = ch;GetChar();}while(ch != '"' && ch != '\0');wordget[i++] = ch;wordget[i] = '\0';if(ch == '\0'){printf("%s",wordget);ProcError(3);pDu->kind = ERROR;pDu->value = 0;}else{value = InsertConst(wordget);pDu->kind = CONST;pDu->value = value;}return true; //字符常量case '\'':wordget[i++] = ch; // 'GetChar();wordget[i++] = ch;if(ch == '\\') // '\n'{//如果是转义字符则要多接收一个字符GetChar(); // ch = 'wordget[i++] = ch;}GetChar();wordget[i++] = ch;wordget[i] = '\0';if(ch != '\''){//'\b'printf("%s",wordget);ProcError(2);pDu->kind = ERROR;pDu->value = 0;}else{value = InsertConst(wordget);pDu->kind = CONST;pDu->value = value;}return true;case '(':case ')':case '[':case ']':case '.':case ',':case '~':case '?':case ':':case ';':case '{':case '}':case '#':wordget[i++] = ch;wordget[i] = '\0';pDu->kind = DIVIDE; //界符pDu->value = -1;return true;case '!': //!=wordget[i++] = ch;GetChar();if (ch=='=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '<': // << <=wordget[i++] = ch;GetChar();if (ch == '<' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '>': // >> >=wordget[i++] = ch;GetChar();if (ch == '>' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '=': // ==wordget[i++] = ch;GetChar();if (ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '&': // && &=wordget[i++] = ch;GetChar();if (ch == '&' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break; case '|': // || |=wordget[i++] = ch;GetChar();if (ch == '|' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '+': // ++ +=wordget[i++] = ch;GetChar();if (ch == '+' || ch == '=')wordget[i++] = ch;else Retract();wordget[i]='\0';break;case '-': // ---= ->wordget[i++] = ch;GetChar();if (ch == '-' || ch == '=' || ch == '>')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '*':// ** *=wordget[i++] = ch;GetChar();if (ch == '*' || ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '/': // /=wordget[i++] = ch;GetChar();if (ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '%': // %=wordget[i++] = ch;GetChar();if (ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '^': // ^=wordget[i++] = ch;GetChar();if (ch == '=')wordget[i++] = ch;elseRetract();wordget[i]='\0';break;case '\0':return false;default:ProcError(1);return false;}pDu->kind = OPERAT;return true;}//主函数int main(){Dualistic tmp;pDualistic ptmp = &tmp;FILE *fin, *fout;int i;char c;char filename[20];printf("源代码读入\n");//scanf("%s",filename);//将源程序读入缓冲区if ((fin=fopen("Test.txt","r")) == NULL){printf("Cannot open infile\n");return 0;}i = 0;//c = fgetc(fin);while((c = fgetc(fin)) != EOF){if(i >= PRO_MAX_LEN-1){printf("\n程序代码太长,无法处理\a");return 0;}proBuffer[i++] = c;}fclose(fin); //关闭文件proBuffer[i++] = '\0';printf("\n***************************\n源代码读入成功,源代码如下:\n%s",proBuffer);printf("\n按任意键继续\n");getch(); //预处理printf("\n预处理\n");pretreatment();printf("\n***************************\n预处理成功,去掉注释后的源代码为:\n%s*",proBuffer);printf("\n按任意键继续\n");getch();printf("\n词法分析\n");point = 0;//词法分析if ((fout=fopen("Result.txt","wb")) == NULL){printf("建立文件Result.txt失败。
词法分析实验报告代码
一、实验目的1. 理解词法分析的概念和作用。
2. 掌握词法分析器的设计和实现方法。
3. 通过实验加深对编译原理中词法分析阶段的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.83. 开发工具:PyCharm三、实验内容1. 设计一个简单的词法分析器,能够识别并输出源代码中的单词。
2. 实现词法分析器的关键功能,包括:- 字符串预处理- 单词识别- 生成词法分析表四、实验步骤1. 字符串预处理- 读取源代码字符串。
- 移除字符串中的空白字符(空格、制表符、换行符等)。
- 转义字符串中的特殊字符。
2. 单词识别- 使用正则表达式匹配单词。
- 根据正则表达式匹配结果,将单词分类为关键字、标识符、常量等。
3. 生成词法分析表- 创建一个列表,用于存储词法分析表中的每个单词及其对应的类别。
- 遍历源代码字符串,将识别出的单词添加到词法分析表中。
五、实验代码```pythonimport re# 定义词法分析表结构class Token:def __init__(self, type, value):self.type = typeself.value = value# 单词识别函数def tokenize(source_code):# 移除空白字符source_code = re.sub(r'\s+', '', source_code)# 转义特殊字符source_code = re.sub(r'\\', '\\\\', source_code)# 使用正则表达式匹配单词tokens = re.findall(r'\b\w+\b', source_code)# 生成词法分析表token_table = []for token in tokens:if re.match(r'\bint\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\bfloat\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\bchar\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\bif\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\belse\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\breturn\b', token):token_table.append(Token('KEYWORD', token))elif re.match(r'\b\w+\b', token):token_table.append(Token('IDENTIFIER', token)) else:token_table.append(Token('CONSTANT', token)) return token_table# 主函数def main():# 读取源代码source_code = '''int main() {int a = 10;float b = 3.14;char c = 'A';if (a > b) {return a;} else {return b;}}'''# 进行词法分析token_table = tokenize(source_code)# 输出词法分析结果for token in token_table:print(f'Type: {token.type}, Value: {token.value}') if __name__ == '__main__':main()```六、实验结果运行实验代码后,输出如下:```Type: KEYWORD, Value: intType: IDENTIFIER, Value: mainType: KEYWORD, Value: (Type: KEYWORD, Value: )Type: KEYWORD, Value: intType: IDENTIFIER, Value: a Type: KEYWORD, Value: = Type: CONSTANT, Value: 10 Type: KEYWORD, Value: ; Type: KEYWORD, Value: float Type: IDENTIFIER, Value: b Type: KEYWORD, Value: = Type: CONSTANT, Value: 3.14 Type: KEYWORD, Value: ; Type: KEYWORD, Value: char Type: IDENTIFIER, Value: c Type: KEYWORD, Value: = Type: CONSTANT, Value: A Type: KEYWORD, Value: ; Type: KEYWORD, Value: if Type: IDENTIFIER, Value: ( Type: IDENTIFIER, Value: a Type: KEYWORD, Value: > Type: IDENTIFIER, Value: b Type: KEYWORD, Value: ) Type: KEYWORD, Value: { Type: KEYWORD, Value: return Type: IDENTIFIER, Value: aType: KEYWORD, Value: ;Type: KEYWORD, Value: }Type: KEYWORD, Value: elseType: KEYWORD, Value: {Type: KEYWORD, Value: returnType: IDENTIFIER, Value: bType: KEYWORD, Value: ;Type: KEYWORD, Value: }```七、实验总结通过本次实验,我们成功地设计并实现了一个简单的词法分析器,能够识别并输出源代码中的单词。
编译原理实验词法分析语法分析
本代码只供学习参考:词法分析源代码:#include<iostream>#include<fstream>#include<string>using namespace std;string key[8]={"do","end","for","if","printf","scanf","then","while"}; string optr[4]={"+","-","*","/"};string separator[6]={",",";","{","}","(",")"};char ch;//判断是否为保留字bool IsKey(string ss) {int i;for(i=0;i<8;i++)if(!strcmp(key[i].c_str(),ss.c_str()))return true;return false;}//字母判断函数bool IsLetter(char c) {if(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z')))return true;return false;}//数字判断函数bool IsDigit(char c) {if(c>='0'&&c<='9')return true;return false;}//运算符判断函数bool IsOptr(string ss) {int i;for(i=0;i<4;i++)if(!strcmp(optr[i].c_str(),ss.c_str()))return true ;return false;}//分界符判断函数bool IsSeparator(string ss) {int i;for(i=0;i<6;i++)if(!strcmp(separator[i].c_str(),ss.c_str()))return true;return false;}void analyse(ifstream &in) {string st="";char ch;int line=1,row=0;while((in.get(ch))) {st="";if((ch==' ')||(ch=='\t')){} //空格,tab健elseif(ch=='\n') {line++;row=0; } //换行行数加一处理elseif(IsLetter(ch)) //关键字、标识符的处理{row++;while(IsLetter(ch)||IsDigit(ch)){st+=ch;in.get(ch);}in.seekg(-1,ios::cur);//文件指针(光标)后退一个字节if(IsKey(st)) //判断是否为关键字查询关键字表;cout<<st<<"\t("<<st<<","<<1<<")"<<'\t'<<'\t'<<"关键字"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else //否则为标示符cout<<st<<"\t("<<st<<","<<2<<")"<<'\t'<<'\t'<<"标识符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}elseif(IsDigit(ch)) //无符号整数处理{row++;while(IsDigit(ch)){st+=ch;ch=in.get();}in.seekg(-1,ios::cur);cout<<st<<"\t("<<st<<","<<3<<")"<<'\t'<<'\t'<<"常数"<<'\t'<<"("<<line<<","<<row<<")"<<endl;// break;}else{st="";st+=ch;if(IsOptr(st)) //运算符处理{row++;cout<<st<<"\t("<<st<<","<<4<<")"<<'\t'<<'\t'<<"运算符"<<"("<<line<<","<<row<<")"<<endl;}elseif(IsSeparator(st))//分隔符处理{ row++;cout<<st<<"\t("<<st<<","<<5<<")"<<'\t'<<'\t'<<"分界符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}else{switch(ch){row++;case'=' : {row++;cout<<"="<<"\t("<<"="<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}case'>' :{row++;ch=in.get();if(ch=='=')cout<<">="<<'\t'<<"("<<">="<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else {cout<<">"<<"\t("<<">"<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;in.seekg(-1,ios::cur);}} break;case'<' :{row++;ch=in.get();if(ch=='=')cout<<"<="<<'\t'<<"("<<"="<<","<<"6"<<")"<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else if(ch=='>') cout<<"<>"<<'\t'<<"("<<"<>"<<","<<"6"<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;else{cout<<"<"<<"\t("<<"<"<<","<<"6"<<")"<<"\t"<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;in.seekg(-1,ios::cur);}}break;default :{row++; cout<<ch<<'\t'<<"\t$无法识别字符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;}}}}}}int main(){ifstream in;in.open("test.txt",ios::in);cout<<"关键字-》1 标识符-》2 常数-》3 运算符-》4 分隔符-》5"<<endl;if(in.is_open()){analyse(in);in.close();system("pause");}elsecout<<"文件操作出错"<<endl;}语法分析实验源代码LL#include<iostream>using namespace std;const int MaxLen=20; //初始化栈的长度const int Length=20;//初始化数组长度char Vn[5]={'E','G','T','S','F'};//非终结符数组char Vt[8]={'i','(',')','+','-','*','/','#'};//终结符数组char ch,X;//ch读当前字符,X获取栈顶元素char strToken[Length];//存储规约表达式struct LL//ll(1)分析表的构造字初始化{char*c;};LL E[8]={"TG","TG","error","error","error","error","error","error"};LL G[8]={"error","error","null","+TG","-TG","error","error","null"};LL T[8]={"FS","FS","error","error","error","error","error","error"};LL S[8]={"error","error","null","null","null","*FS","/FS","null"};LL F[8]={"i","(E)","error","error","error","error","error","error"};class stack//栈的构造及初始化{public:stack();//初始化bool empty() const;//是否为空bool full() const;//是否已满bool get_top(char &c)const;//取栈顶元素bool push(const char c);//入栈bool pop();//删除栈顶元素void out();//输出栈中元素~stack(){}//析构private:int count;//栈长度char data[MaxLen];//栈中元素};stack::stack(){count=0;}bool stack::empty() const{if(count==0)return true;return false;}bool stack::full() const{if(count==MaxLen)return true;return false;}bool stack::get_top(char &c)const{if(empty())return false;else{c=data[count-1];return true;}}bool stack::push(const char c){if(full())return false;data[count++]=c;return true;}bool stack::pop(){if(empty())return false;count--;return true;}void stack::out(){for(int i=0;i<count;i++)cout<<data[i];cout<<'\t';}int length(char *c){int l=0;for(int i=0;c[i]!='\0';i++)l++;return l;}void print(int i,char*c)//剩余输入串的输出{for(int j=i;j<Length;j++)cout<<c[j];cout<<'\t';}void run(){bool flag=true;//循环条件int step=0,point=0;//步骤、指针int len;//长度cout<<"输入规约的字符串:"<<endl;cin>>strToken;ch=strToken[point++];//读取第一个字符stack s;s.push('#');//栈中数据初始化s.push('E');s.get_top(X);//取栈顶元素cout<<"步骤\t"<<"分析栈\t"<<"剩余输入串\t\t"<<"所用产生式\t"<<"动作"<<endl;cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<'\t'<<"初始化"<<endl;while(flag){if((X==Vt[0])||(X==Vt[1])||(X==Vt[2])||(X==Vt[3])||(X==Vt[4])||(X==Vt[5])||(X==Vt[6])) //判断是否为终结符(不包括#){if(X==ch)//终结符,识别,进行下一字符规约{s.pop();s.get_top(X);ch=strToken[point++];cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<'\t'<<"GETNEXT(I)"<<endl;}else{flag=false;}}else if(X=='#')//规约结束{if(X==ch){cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<ch<<'\t'<<"结束"<<endl;s.pop();flag=false;}else{flag=false;}}else if(X==Vn[0]) //非终结符E{for(int i=0;i<8;i++)//查分析表if(ch==Vt[i]){if(strcmp(E[i].c,"error")==0)//出错{flag=false;}else{ //对形如X->X1X2的产生式进行入栈操作s.pop();len=length(E[i].c)-1;for(int j=len;j>=0;j--)s.push(E[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<E[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<E[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[1]) //同上,处理G{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(G[i].c,"null")==0){s.pop();cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<"ε"<<'\t'<<"POP"<<endl;s.get_top(X);}else if(strcmp(G[i].c,"error")==0){flag=false;}else{s.pop();len=length(G[i].c)-1;for(int j=len;j>=0;j--)s.push(G[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<G[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<G[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[2]) //同上处理T{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(T[i].c,"error")==0){flag=false;}else{s.pop();len=length(T[i].c)-1;for(int j=len;j>=0;j--)s.push(T[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<T[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<T[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[3])//同上处理S{for(int i=0;i<8;i++)if(ch==Vt[i]){if(strcmp(S[i].c,"null")==0){s.pop();cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<"ε"<<'\t'<<"POP"<<endl;s.get_top(X);}else if(strcmp(S[i].c,"error")==0){flag=false;}else{s.pop();len=length(S[i].c)-1;for(int j=len;j>=0;j--)s.push(S[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<S[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<S[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else if(X==Vn[4]) //同上处理F{for(int i=0;i<7;i++)if(ch==Vt[i]){if(strcmp(F[i].c,"error")==0){flag=false;}else{s.pop();len=length(F[i].c)-1;for(int j=len;j>=0;j--)s.push(F[i].c[j]);cout<<step++<<'\t';s.out();print(point-1,strToken);cout<<X<<"->"<<F[i].c<<'\t'<<"POP,PUSH(";for(int j=len;j>=0;j--)cout<<F[i].c[j];cout<<")"<<endl;s.get_top(X);}}}else //出错处理{flag= false;}}}int main(){cout<<"实验二"<<endl;run();system("pause");return 0;}语法实验源代码LR#include<iostream>using namespace std;const int MaxLen=20; //初始化栈的长度const int Length=20;//初始化数组长度char ch,Y;//全局变量,ch用于读当前字符,Y用于获取栈顶元素char strToken[Length];//存储规约表达式bool flag=true;//循环条件int point=0,step=1;//步骤、指针class stack//栈的构造及初始化{public:stack();//初始化bool empty() const;//是否为空bool full() const;//是否已满bool get_top(char &c)const;//取栈顶元素bool push(const char c);//入栈bool pop();void out();//输出栈中元素void out1();~stack(){}//析构private:int count;//栈长度char data[MaxLen];//栈中元素};stack l,r;//l代表符号栈,r代表状态栈stack::stack(){count=0;}bool stack::empty() const{if(count==0)return true;return false;}bool stack::full() const{if(count==MaxLen)return true;return false;}bool stack::get_top(char &c)const{if(empty())return false;else{c=data[count-1];return true;}}bool stack::push(const char c){if(full())return false;data[count++]=c;return true;}bool stack::pop(){if(empty())return false;count--;return true;}void stack::out(){for(int i=0;i<count;i++)cout<<data[i];cout<<'\t';}void stack::out1(){for(int i=0;i<count;i++)cout<<int(data[i]);cout<<'\t';}void print(int i,char*c)//剩余输入串的输出{for(int j=i;j<Length;j++)cout<<c[j];cout<<'\t';}void Goto(int i,char c)//状态转换函数,对应于表中GOTO {if(i==0){if(c=='E'){r.push(1);cout<<",GOTO(0,E)=1入栈"<<endl;}else if(c=='T'){r.push(2);cout<<",GOTO(0,T)=2入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(0,F)=3入栈"<<endl;}elseflag=false;}else if(i==4){if(c=='E'){r.push(8);cout<<",GOTO(4,E)=8入栈"<<endl;}else if(c=='T'){r.push(2);cout<<",GOTO(4,T)=2入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(4,F)=3入栈"<<endl;}elseflag=false;}else if(i==6){if(c=='T'){r.push(9);cout<<",GOTO(6,T)=9入栈"<<endl;}else if(c=='F'){r.push(3);cout<<",GOTO(6,F)=3入栈"<<endl;}elseflag=false;}else if(i==7){if(c=='F'){r.push(10);cout<<",GOTO(7,F)=10入栈"<<endl;}elseflag=false;}elseflag=false;}void Action0()//状态0时{if(ch=='i')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[0,i]=S5,状态5入栈"<<endl;r.push(5);l.push(ch);ch=strToken[point++];}else if(ch=='(')//下一个操作符为( ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[0,(]=S4,状态4入栈"<<endl;r.push(4);l.push(ch);ch=strToken[point++];}elseflag=false;}void Action1()//状态1{if(ch=='+')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[1,+]=S6,状态6入栈"<<endl;r.push(6);l.push(ch);ch=strToken[point++];}else if(ch=='#')//分析成功{flag=false;cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"Acc:分析成功"<<endl;}elseflag=false;}void Action2() //状态2{if(ch=='*')//下一个操作符为* ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[2,*]=S7,状态7入栈"<<endl;r.push(7);l.push(ch);ch=strToken[point++];}else if((ch=='+')||(ch==')')||(ch=='#'))//下一个操作符为+,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('E');print(point-1,strToken);cout<<"r2: E→T归约";r.pop();r.get_top(Y);Goto(int(Y),'E');}elseflag=false;}void Action3()//状态3{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('T');print(point-1,strToken);cout<<"r4: T→F归约";r.pop();r.get_top(Y);Goto(int(Y),'T');}elseflag=false;}void Action4_6_7(int x)//状态4,6,7{if(ch=='i')//下一个操作符为i ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[";cout<<x<<",i]=S5,状态5入栈"<<endl;r.push(5);l.push(ch);ch=strToken[point++];}else if(ch=='(')//下一个操作符为(,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[";cout<<x<<",(]=S4,状态4入栈"<<endl;r.push(4);l.push(ch);ch=strToken[point++];}elseflag=false;}void Action5()//状态5{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.push('F');print(point-1,strToken);cout<<"r6: F→i归约";r.pop();r.get_top(Y);Goto(int(Y),'F');}elseflag=false;}void Action8()//状态8{if(ch=='+')//下一个操作符为+ ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[8,+]=S6,状态6入栈"<<endl;r.push(6);l.push(ch);ch=strToken[point++];}else if(ch==')')//下一个操作符为),移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[8,)]=S11,状态11入栈"<<endl;r.push(11);ch=strToken[point++];}elseflag=false;}void Action9()//状态9{if(ch=='*')//下一个操作符为* ,移进{cout<<step++<<'\t';r.out1();l.out();print(point-1,strToken);cout<<"ACTION[9,*]=S7,状态7入栈"<<endl;r.push(7);l.push(ch);ch=strToken[point++];}else if((ch=='+')||(ch==')')||(ch=='#'))//下一个操作符为+,,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.pop();l.pop();l.push('E');print(point-1,strToken);cout<<"r1: E→E+T归约";r.pop();r.pop();r.pop();r.get_top(Y);Goto(int(Y),'E');}elseflag=false;}void Action10()//状态10{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';l.out();l.pop();l.pop();l.pop();l.push('T');print(point-1,strToken);cout<<"r3: T→T*F归约";r.pop();r.pop();r.pop();r.get_top(Y);Goto(int(Y),'T');}elseflag=false;}void Action11()//状态11{if((ch=='+')||(ch=='*')||(ch==')')||(ch=='#'))//下一个操作符为+,*,),#规约{cout<<step++<<'\t';r.out1();l.out();l.pop();l.pop();l.pop();l.push('F');print(point-1,strToken);cout<<"r5: F→(E)归约";r.pop();r.pop();r.pop();r.get_top(Y);Goto(int(Y),'F');}elseflag=false;}void run()//规约{cout<<"请输入要规约的字符串:"<<endl;cin>>strToken;cout<<"步骤\t"<<"状态栈\t"<<"符号栈\t"<<"输入串\t\t"<<"动作说明"<<endl;ch=strToken[point++];//读取第一个字符l.push('#');r.push(0);r.get_top(Y);while(flag)//循环规约{if(int(Y)==0)Action0();else if(int(Y)==1)Action1();else if(int(Y)==2)Action2();else if(int(Y)==3)Action3();else if((int(Y)==4)||(int(Y)==6)||(int(Y)==7))Action4_6_7(int(Y));else if(int(Y)==5)Action5();else if(int(Y)==8)Action8();else if(int(Y)==9)Action9();else if(int(Y)==10)Action10();else if(int(Y)==11)Action11();elseflag=false;r.get_top(Y);}}int main(){cout<<"实验三"<<endl;run();system("pause");return 0;}。
编译原理实验 词法分析&语法分析程序
编译原理实验词法分析程序实验一:词法分析程序1、实验目的从左至右逐个字符的对源程序进行扫描,产生一个个单词符号,把字符串形式的源程序改造成单词符号形式的中间程序。
2、实验内容表C语言子集的单词符号及内码值单词符号种别编码助记符内码值while 1 while --if 2 if --else 3 else --switch 4 switch --case 5 case --标识符 6 id id在符号表中的位置常数7 num num在常数表中的位置+ 8 + --- 9 - --* 10 * --<= 11 relop LE< 11 relop LT== 11 relop LQ= 12 = --; 13 ; --输入源程序如下if a==1 a=a+1;else a=a+2;输出对应的单词符号形式的中间程序3、实验过程实验上机程序如下:#include "stdio.h"#include "string.h"int i,j,k;char s ,a[20],token[20];int letter(){if((s>=97)&&(s<=122))return 1;else return 0;}int Digit(){if((s>=48)&&(s<=57))return 1;else return 0;}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(){if(strcmp(token, "while")==0)return 1;else if(strcmp(token, "if")==0)return 2;else if(strcmp(token,"else")==0)return 3;else if(strcmp(token,"switch")==0)return 4;else if(strcmp(token,"case")==0)return 5;else return 0;}void main(){printf("please input you source program,end('#'):\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=1;memset(token,0,sizeof(char)*10);j=0;get();while(s!='#'){if(s==' '||s==10||s==13)get();else{switch(s){case'a':case'b':case'c':case'd':case'e':case'f':case'g':case'h':case'i':case'j':case'k':case'l':case'm':case'n':case'o':case'p':case'q':case'r':case's':case't':case'u':case'v':case'w':case'x':case'y':case'z':while(Digit()||letter()){token[j]=s;j=j+1;get();}retract();k=lookup();if(k==0)printf("(6,%s)\n",token); elseprintf("(%d,null)\n",k); break;case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':while(Digit()){token[j]=s;j=j+1;get();}retract();printf("(%d,%s)\n",7,token); break;case'+':printf("(+,null)\n"); break;case'-':printf("(-,null)\n"); break;case'*':printf("(*,null)\n"); break;case'<':get();if(s=='=')printf("(relop,LE)\n"); else{retract();printf("(relop,LT)\n");}break;case'=':get();if(s=='=')printf("(relop,EQ)\n"); else{retract();printf("(=,null)\n");}break;case';':printf("(;,null)\n"); break;default:printf("(%c,error)\n",s);break;}memset(token,0,sizeof(char)*10);j=0;get();}}}4、实验结果实验结果分析:if是关键字,对应种别编码为2,输出(2,null)a是标识符,对应种别编码为6,值为a,输出(6,a)==的助记符是relop,内码值为LE,输出(relop,LE)1是常数,对应种别编码为7,值为1,输出(7,1)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)1是常数,对应种别编码为7,值为1,输出(7,1);是语句结束符号,直接输出(;,null)else是关键字,对应种别编码为3,输出(3,null)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)2是常数,对应种别编码为7,值为2,输出(7,2);是语句结束符号,直接输出(;,null)#是输入结束标志编译原理实验语法分析程序实验二:语法分析程序1、实验目的:将单词组成各类语法单位,讨论给类语法的形成规则,判断源程序是否符合语法规则3、实验内容:给定文法:G[E]:E→E+E|E-E|E*E|E/E|(E)E→0|1|2|3|4|5|6|7|8|9首先把G[E]构造为算符优先文法,即:G’[E]:E→E+T|TT→T-F|FF→F*G|GG→G/H|HH→(E)|i得到优先关系表如下:+ - * / i ( ) # + ·><·<·<·<·<··>·> - ·>·><·<·<·<··>·> * ·>·>·><·<·<··>·> / ·>·>·>·><·<··>·>i ·>·>·>·>·>·>( <·<·<·<·<·<·=) ·>·>·>·>·>·> # <·<·<·<·<·<·=构造出优先函数+ - * / i ( ) #f 6 8 10 12 12 2 12 2g 5 7 9 11 13 13 2 2要求输入算术表达式:(1+2)*3+2*(1+2)-4/2输出其对应的语法分析结果4、实验过程:上机程序如下:#include "stdio.h"#include "string.h"char a[20],optr[10],s,op;int i,j,k,opnd[10],x1,x2,x3;int operand(char s){if((s>=48)&&(s<=57))return 1;else return 0;}int f(char s){switch(s){case'+':return 6;case'-':return 8;case'*':return 10;case'/':return 12;case'(':return 2;case')':return 12;case'#':return 2;default:printf("error");}}int g(char s){switch(s){case'+':return 5;case'-':return 7;case'*':return 9;case'/':return 11;case'(':return 13;case')':return 2;case'#':return 2;default:printf("error");}}void get(){s=a[i];i=i+1;}void main(){printf("请输入算数表达式,并以‘#’结束:\n");i=0;do{scanf("%c",&a[i]);i++;}while(a[i-1]!='#');i=0;j=0;k=0;optr[j]='#';get();while((optr[j]!='#')||(s!='#')){if(operand(s)){opnd[k]=s-48;k=k+1;get();}else if(f(optr[j])<g(s)){j=j+1;optr[j]=s;get();}else if(f(optr[j])==g(s)){if(optr[j]=='('&&s==')'){j=j-1;get();}else if(optr[j]=='('&&s=='#'){printf("error\n");break;}else if(optr[j]=='#'&&s==')'){printf("error\n");break;}}else if(f(optr[j])>g(s)){op=optr[j];j=j-1;x2=opnd[k-1];x1=opnd[k-2];k=k-2;switch(op){case'+':x3=x1+x2;break;case'-':x3=x1-x2;break;case'*':x3=x1*x2;break;case'/':x3=x1/x2;break;}opnd[k]=x3;k=k+1;printf("(%c,%d,%d,%d)\n",op,x1,x2,x3);}else{printf("error\n");break;}}if(j!=0||k!=1)printf("error\n");}5、实验结果:实验结果分析:(1+2)*3+2*(1+2)-4/2#因为‘)’优先级大于‘*’,先计算1+2=3,并输出(+,1,2,3)原式变为:3*3+2*(1+2)-4/2#因为‘*’优先级大于‘+’,先计算3*3=9,并输出(*,3,3,9)原式变为:9+2*(1+2)-4/2#因为‘)’优先级大于‘-’,先计算1+2=3,并输出(+,1,2,3)原式变为:9+2*3-4/2#因为‘*’优先级大于‘-’,先计算2*3=6,并输出(*,2,3,6)原式变为:9+6-4/2#因为‘/’优先级大于‘#’,先计算4/2=2,并输出(/,4,2,2)原式变为:9+6-2#因为‘-’优先级大于‘#’,先计算6-2=4,并输出(-,6,2,4)原式变为:9+4#因为‘+’优先级大于‘#’,计算9+4=13,并输出(+,9,4,13)原式变为13#优先级等于#,跳出while循环,运算结束!。
编译原理实验报告——词法分析器(内含源代码)
编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。
该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。
二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。
四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。
int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。
void GetChar(char *ch); //将下一个输入字符读到ch中。
void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。
void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。
int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。
void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。
编译原理词法和语法分析报告+源码
词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
编译原理词法分析和语法分析报告+代码(C语言版)[1]
词法分析一、实验目的二、设计、编制并调试一个词法分析程序, 加深对词法分析原理的理解。
三、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符: = + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM), 通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID.SUM、运算符、界符和关键字, 词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:输入: 所给文法的源程序字符串。
输出: 二元组(syn,token或sum)构成的序列。
其中: syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如: 对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件, 经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号, 其基本思想是根据扫描到单词符号的第一个字符的种类, 拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理, 把它们预先安排在一张表格中(称为关键字表), 当扫描程序识别出标识符时, 查关键字表。
如能查到匹配的单词, 则该单词为关键字, 否则为一般标识符。
关键字表为一个字符串数组, 其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量: ①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn 用来存放单词符号的种别码。
编译原理-词法分析(附源码)
词法分析实验报告一、实验项目名称词法分析二、实验目的通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
三、实验环境Windows 10Microsoft Visual Studio 2015四、实验内容编制一个读单词过程,源程序为一个文件,读取该文件,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、界符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
单词的内部编码如下:1、保留字:if、int、for、while、do、return、break、continue;单词种别码为1;2、标识符:除保留字外的以字母开头,后跟字母、数字的字符序列;单词种别码为2;3、常数为无符号整形数;单词种别码为3;4、运算符包括:+、-、*、/、=;单词种别码为4;5、分隔符包括:,、;、{、}、(、);单词种别码为5。
五、实验步骤在词法分析中,自文件头开始扫描源程序字符,一旦发现符合“单词”定义的源程序字符串时,将它翻译成固定长度的单词内部表示,并填入适当的信息表。
经过词法分析后,源程序字符串(源程序的外部表示)被翻译成具有等长信息的单词串(源程序的内部表示),并产生两个表格:常数表和标识符表,它们分别包含了源程序中的所有常数和所有标识符。
(1) 定义部分:定义常量、变量、数据结构。
(2) 初始化:从文件将源程序全部输入到字符缓冲区中。
(3) 取单词前:去掉多余空白。
(4) 取单词:利用实验一的成果读出单词的每一个字符,组成单词,分析类型。
(5) 显示结果六、源程序清单、测试数据、结果#include<iostream>#include<string>#include<fstream>#define MAX 100using namespace std;void main(){//二维char数组主存储的初始化char a[MAX][15], ch = 'a', before;int i = 0, j = 0;for (i = 0; i < MAX; i++){for (j = 0; j < 15; j++){a[i][j] = NULL;}}i = 0;j = 0;fstream file;//文件打开并读入字符file.open("D:\\text.txt",ios::in);if (file){cout <<"文件打开成功"<< endl;}while (!file.eof())//换行是10,空格是32{before = ch;file.read(&ch, 1);//**********************************************************************符号*******************************************************************||||*************************************************************前一字符为符号当前为字母数字*************************************************************************************** *******************************************************************||if ( ((ch >= 32 && ch <= 47) || (ch == 10) || (ch >= 58 && ch <= 64) ||(ch >= 91 && ch <= 94 )||(ch==96)||( ch >= 123 && ch <= 126)) || (((before >= 32 && before <= 47) || (before == 10) || (before >= 58 && before <= 64) || (before >= 91 && before <= 94) || (before == 96) || (before >= 123 && before <= 126))) && (ch > 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch>=48 && ch<=57) ){if (ch != 32 && ch != 10){i++;j = 0;}}if (ch != 32 && ch != 10){a[i][j] = ch;j++;}}file.close();ofstream fileout("D:\\out.txt", ios::ate);//判断字符串并输出for (int k = 0; k < i; k++){if (a[k][0] >= 65 && a[k][0] <= 90 || a[k][0] >= 97 && a[k][0] <= 122)//判断第一个字符是字母{if (a[k][1] >= 65 && a[k][1] <= 90 || a[k][1] >= 97 && a[k][1] <= 122)//判断第二个字符是字母{//判断是不是保留字string AA(a[k]);if (pare("if") == 0){cout <<"(1,\"if\")"<< endl;fileout <<"(1,\"if\")\n";}else if (pare("int") == 0){cout <<"(1,\"int\")"<< endl;fileout <<"(1,\"int\")\n";}else if (pare("for") == 0){cout <<"(1,\"for\")"<< endl;fileout <<"(1,\"for\")\n";}else if (pare("while") == 0){cout <<"(1,\"while\")"<< endl;fileout <<"(1,\"while\")\n";}else if (pare("do") == 0){cout <<"(1,\"do\")"<< endl;fileout <<"(1,\"do\")\n";}else if (pare("return") == 0){cout <<"(1,\"return\")"<< endl;fileout <<"(1,\"return\")\n";}else if (pare("break") == 0){cout <<"(1,\"break\")"<< endl;fileout <<"(1,\"break\")\n";}else if (pare("continue") == 0){cout <<"(1,\"continue\")"<< endl;fileout <<"(1,\"break\")\n";}else{cout <<"(2,\""<< AA <<"\")"<< endl;fileout <<"(2,\""<< AA <<"\")\n";}}else if (a[k][1] >= '0' || a[k][1] <= '9'){string AA(a[k]);cout <<"(2,\""<< AA <<"\")"<< endl;fileout <<"(2,\""<< AA <<"\")\n";}}else if (a[k][0] >= '0' && a[k][0] <= '9'){int judge = 0;int sss = 1;while(a[k][sss]!=NULL){if (a[k][sss] < '0' || a[k][sss] > '9' ){judge = 1;}sss++;}string AA(a[k]);if (judge == 0){cout <<"(3,\""<< AA <<"\")"<< endl;fileout <<"(3,\""<< AA <<"\")\n";}else{cout <<"(错误的单词:"<< AA <<"\")"<< endl;fileout <<"(错误的单词:"<< AA <<"\")\n";}}else if (a[k][0] == 42 || a[k][0] == 43|| a[k][0] == 45 || a[k][0] == 47 ||a[k][0] == 61){string AA(a[k]);cout <<"(4,\""<< AA <<"\")"<< endl;fileout <<"(4,\""<< AA <<"\")\n";}else if (a[k][0] == 44 || a[k][0] == 59 || a[k][0] == 40 || a[k][0] == 41 || a[k][0] == 123 || a[k][0] == 125){string AA(a[k]);cout <<"(5,\""<< AA <<"\")"<< endl;fileout <<"(5,\""<< AA <<"\")\n";}else if(a[k][0]!=NULL){string AA(a[k]);cout <<"(不支持的符号:"<< AA <<"\")"<< endl;fileout <<"(不支持的符号:"<< AA <<"\")\n";}}fileout.close();}七、实验小结和思考在本次实验中,我遇到了很多小问题,值得一提的是在拆输入的字符串时如何拆分成正确的单词,这很重要,拆分单词时我用的是识别字符的ACSCii码以及字符前后的组合,将识别出的单词存入已初始化的字符数组中。
编译原理词法分析和语法分析报告+代码(C语言版)
编译原理词法分析和语法分析报告+代码(C语言版)-CAL-FENGHAI.-(YICAI)-Company One1信息工程学院实验报告(2010 ~2011 学年度第一学期)姓名:柳冠天学号:2081908318班级:083词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符: = + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
编译原理词法分析和语法分析报告+代码[C语言版]
词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};是图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
编译原理实验报告——词法分析器(内含源代码)
#include "string.h"
#include "iostream"
using namespace std;
char set[1000],str[500],strtaken[20]; char sign[50][10],constant[50][10];
//int Words[500][10]; char ch;//当前读入字符int sr,to=0;//数组str, strtaken int st=0,dcount=0;
{
printf( "cannot open file.\n");
void input();//向存放输入结果的字符数组输入一句语句。
void display();//输出一些程序结束字符显示样式
int analyzerSubFun();//词法分析器子程序,为了实现词法分析的主要功能。
五. 代码实现
//cifa.cpp:定义控制台应用程序的入口点
//#include "stdafx Nhomakorabeah"
3.实验任务
编制程序实现要求的功能,并能完成对测试样例程序的分析。
四. 实验原理
int Reserve(char *strTaken);//对strTaken中的字符串查找保留字表,若是一个保留
字返回它的数码,否则返回0。
void Retract(char *ch); //将搜索指针器回调一个字符位置,将ch置为空白字符。
};
typedef struct keytable{
char name[20]; int kind;
词法分析程序源代码C++版本(编译原理实验)
/*实验1 词法分析源码已经通过VS2010调试,亲测可用,有打开文件操作(在工程文件夹里建一个program.txt,输入程序串即可)。
也可从键盘直接输入源码,后面的语法分析也能用的上,欢迎使用。
*/#include<iostream>#include <fstream>#include<string.h>using namespace std;voidKeyFunction();voidReadTxt();void main(){int choose;cout<<"(1,2)"<<endl;cin>>choose;if(choose==1){cout<<"请输入程序段:以# 结束:"<<endl;KeyFunction();}if(choose==2){ReadTxt();}}voidKeyFunction(){inti=0,j,k=0,state=1,f=0,linenum=1;chara[12][10]={"const","var","call","begin","if","while","do","odd","end","then","procedure","int"};charb,d[40]={"\0"};b=getchar();while(b!='#')/*判断所输入字符是否为结束符*/{if(b==' '||b=='\n'||b=='\t')/*滤过空格、换行等分隔符号*/{if(b='\n') linenum++;b=getchar();}else if((b>='a'&&b<='z')||(b>='A'&&b<='Z'))/*识别标识符以及保留字*/{d[i++]=b;b=getchar();while((b>='a'&&b<='z')||(b>='A'&&b<='Z')||(b>='0'&&b<='9')){d[i++]=b;b=getchar();}for(j=0;j<12;j++)/*查询保留字表确定该单词是否是保留字*/{if(strcmp(d,a[j])==0){cout<<"关键字"<<d<<endl;k=1;break;}}if(k==0)/*在保留字表中没有查到该单词,是标识符*/cout<<"标识符"<<d<<endl;;for(j=0;j<=i;j++)d[j]='\0';i=0;k=0;}else if(b>='0'&&b<='9')/*识别常数*/{d[i++]=b;b=getchar();while(f!=1){switch (state) {case 1:if(b>='0'&&b<='9'){state=1;d[i++]=b;b=getchar();}else if(b=='.') { state=2;d[i++]=b;b=getchar();}else if(b=='E') { state=4;d[i++]=b;b=getchar();}else state=7;break;case 2:if(b>='0'&&b<='9'){state=3;d[i++]=b;b=getchar();}else state=8;break;case 3:if(b>='0'&&b<='9') {state=3;d[i++]=b;b=getchar();}else if(b=='#') { state=4;d[i++]=b;b=getchar();}else state=7;break;case 4:if(b=='+'||b=='-') { state=5;d[i++]=b;b=getchar();}else if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=getchar();}else state=8;break;case 5:if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=getchar();}else state=8;break;case 6:if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=getchar();}else state=7;break;case 7: f=1;break;case 8: f=1;break;}}if(state==7&&(b<'a'||b>'z')&&(b<'A'||b>'Z'))cout<<"数字"<<d<<endl;else if(state==7&&(b>='a'&&b<='z')||(b>='A'&&b<='Z'))/*数字后接字母的出错控制*/{while((b>='a'&&b<='z')||(b>='A'&&b<='Z')){d[i++]=b;b=getchar();}cout<<"error line!"<<endl;}elsecout<<"error line!"<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;f=0;state=1;}else if(b=='<')/*识别'<'、'<='和'<>'*/{d[i++]=b;b=getchar();if(b=='='||b=='>'){d[i++]=b;b=getchar();cout<<"运算符"<<d<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}else{cout<<"运算符"<<d<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}}else if(b=='>')/*识别'>'和'>='*/{d[i++]=b;b=getchar();if(b=='='){d[i++]=b;b=getchar();cout<<"运算符"<<d<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}else{cout<<"运算符"<<d<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}}else if(b==':')/*识别':='*/{d[i++]=b;b=getchar();if(b=='='){d[i++]=b;b=getchar();cout<<"符号"<<d<<endl;}else cout<<"error line!"<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}else if(b=='*'||b=='+'||b=='-'||b=='/'||b=='=')/*识别运算符*/{cout<<"运算符"<<b<<endl;b=getchar();}else if(b=='('||b==')'||b==','||b==';'||b=='.')/*识别分隔符*/{cout<<"分隔符"<<b<<endl;b=getchar();}else{cout<<"error line!"<<endl;b=getchar();}}}voidReadTxt(){ifstream out;out.open("program.txt");inti=0,j,k=0,state=1,f=0,linenum=1;chara[12][10]={"const","var","call","begin","if","while","do","odd","end","then","procedure","int"};charb,d[40]={"\0"};b=out.get();while(b!='#')/*判断所输入字符是否为结束符*/{if(b==' '||b=='\n'||b=='\t')/*滤过空格、换行等分隔符号*/{if(b='\n') linenum++;b=out.get();}else if((b>='a'&&b<='z')||(b>='A'&&b<='Z'))/*识别标识符以及保留字*/{d[i++]=b;b=out.get();while((b>='a'&&b<='z')||(b>='A'&&b<='Z')||(b>='0'&&b<='9')){d[i++]=b;b=out.get();}for(j=0;j<12;j++)/*查询保留字表确定该单词是否是保留字*/{if(strcmp(d,a[j])==0){cout<<"关键字"<<d<<endl;k=1;break;}}if(k==0)/*在保留字表中没有查到该单词,是标识符*/cout<<"标识符"<<d<<endl;;for(j=0;j<=i;j++)d[j]='\0';i=0;k=0;}else if(b>='0'&&b<='9')/*识别常数*/{d[i++]=b;b=out.get();while(f!=1){switch (state) {case 1:if(b>='0'&&b<='9'){state=1;d[i++]=b;b=out.get();}else if(b=='.') { state=2;d[i++]=b;b=getchar();}else if(b=='E') { state=4;d[i++]=b;b=getchar();}else state=7;break;case 2:if(b>='0'&&b<='9'){state=3;d[i++]=b;b=out.get();}else state=8;break;case 3:if(b>='0'&&b<='9') {state=3;d[i++]=b;b=out.get();}else if(b=='#') { state=4;d[i++]=b;b=out.get();}else state=7;break;case 4:if(b=='+'||b=='-') { state=5;d[i++]=b;b=out.get();}else if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=out.get();}else state=8;break;case 5:if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=out.get();}else state=8;break;case 6:if(b>='0'&&b<='9'){ state=6;d[i++]=b;b=out.get();}else state=7;break;case 7: f=1;break;case 8: f=1;break;}}if(state==7&&(b<'a'||b>'z')&&(b<'A'||b>'Z'))cout<<"数字"<<d<<endl;else if(state==7&&(b>='a'&&b<='z')||(b>='A'&&b<='Z'))/*数字后接字母的出错控制*/{while((b>='a'&&b<='z')||(b>='A'&&b<='Z')){d[i++]=b;b=out.get();}cout<<"error line!"<<endl;}elsecout<<"error line!"<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;f=0;state=1;}else if(b=='<')/*识别'<'、'<='和'<>'*/{d[i++]=b;b=out.get();if(b=='='||b=='>'){d[i++]=b;b=out.get();cout<<"运算符"<<d<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}else{cout<<"运算符"<<d<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}}else if(b=='>')/*识别'>'和'>='*/{d[i++]=b;b=out.get();if(b=='='){d[i++]=b;b=out.get();cout<<"运算符"<<d<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}else{cout<<"运算符"<<d<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}}else if(b==':')/*识别':='*/{d[i++]=b;b=out.get();if(b=='='){d[i++]=b;b=out.get();cout<<"符号"<<d<<endl;}elsecout<<"error line!"<<endl;for(j=0;j<=i;j++)d[j]='\0';i=0;}else if(b=='*'||b=='+'||b=='-'||b=='/'||b=='=')/*识别运算符*/{cout<<"运算符"<<b<<endl;b=out.get();}else if(b=='('||b==')'||b==','||b==';'||b=='.')/*识别分隔符*/{cout<<"分隔符"<<b<<endl;b=out.get();}else{cout<<"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"<<endl;cout<<"error line!"<<endl;b=out.get();}}out.close(); }。
编译原理词法分析和语法分析报告+代码(C语言版)[1]
词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
csu
cout<<"open file failed!"<<endl; exit(1); }
//从文件将源程序全部输入到字符缓冲区中 while((ch = fgetc(fp)) != EOF) {
buffer += ch; } cout<<buffer<<endl;
//词法分析过程 for(int i=0; i<buffer.size(); i++) {
"int",
"long",
"short", "double", "float",
"char", "wchar_t", "true",
"false", "bool",
"signed", "unsigned", "define",
"struct","enum", "union", "new",
"delete",
if (token.size() != 0) {
cout<<"(1, \""<<token<<"\")"<<endl; token = ""; } } //判断 token 是否为常量,若是则输出 token 并置空 else if ( isConstant(token) ) { if (token.size() != 0) {
#define MAX_KEYWORD 100 //关键字个数
#define MAX_OPERATE 50
//运算符个数
#define MAX_SEPARAROR 20 //分隔符个数
string keyword[MAX_KEYWORD] =
{"include", "main",
"void",
"using", "namespace",
csu
//token 既非关键字,又非常量,则判断为标识符,输出 token 并置空 else {
if (token.size() != 0) {
cout<<"(2, \""<<token<<"\")"<<endl; token = ""; } }
//输出分隔符,空格、换行符、制表符除外 if (buffer[i] == ' ' || buffer[i] == '\n' || buffer[i] == '\t') { } else {
csu
cout<<"(3, \""<<token<<"\")"<<endl; token = ""; } } //token 既非关键字,又非常量,则判断为标识符,输出 token 并置空 else { if (token.size() != 0) { cout<<"(2, \""<<token<<"\")"<<endl; token = ""; } }
i++; } i += 2; } else { //输出运算符
csu
cout<<uffer[i]<<"\")"<<endl; //$$$$$判断运算符是否为符合运算符,如+=, *=等 if ( isOperate(buffer[i+1]) ) {
cout<<"(4, \""<<buffer[i+1]<<"\")"<<endl; i++; } } } //既非分隔符,又非运算符,则把字符 ch 加到字符串 token 中 else { token += buffer[i]; } }
五、实验报告要求
详细说明你的程序的设计思路和实现过程。用有限自动机或者文法的形式 对词法定义做出详细说明,说明词法分析程序的工作过程,说明错误处理的实 现。
参考资料
一、程序要求
1、以下面一段程序为例
main() {
int a,b; a = 10; b = a + 20; }
2、需要识别的词
1. 关键字:if、int、for、while、do、return、break、continue;单 词种别码为 1。
"extern", "default","friend", "try",
"throw",
"typedef", "virtual" };
char operate[MAX_OPERATE] =
{'+', '-', '*', '/', '%', '=', '<', '>',
'|', '&', '!', '^'
csu
return true; } } return false; }
/* * 是否为常量 */
bool isConstant(string str) {
for (int i=0; i<str.size(); i++) {
if ( str[i]<'0' || str[i]>'9' ) {
return false; } }
cout<<"(5, \""<<buffer[i]<<"\")"<<endl; }
csu
} //如果是运算符,判断 token 并输出,且输出该运算符 else if ( isOperate(buffer[i]) ) {
//判断 token 是否为关键字,若是则输出 token 并置空 if ( isKeyword(token) ) {
//判断是否为单行注释 if (buffer[i] == '/' && buffer[i+1] =='/') {
//直到这一行结束为止
csu
while (buffer[i] != '\n') {
i++; } i += 2; } else if (buffer[i] == '/' && buffer[i+1] =='*') { //直到遇见*/为止 while ( !(buffer[i] == '*' && buffer[i+1] == '/') ) {
return 0; }
2. 标识符;单词种别码为 2。 3. 常数为无符号整形数;单词种别码为 3。
csu 4. 运算符包括:+、-、*、/、=、 、<、 =、<=、!= ;单词种别码为 4。 5. 分隔符包括:,、;、{、}、(、); 单词种别码为 5。 3、程序输出形式 要求输出下面的形式: (2,”main”) (5,”(“) (5,”)“) (5,”{“) (1,”int”) (2,”a”) (5,”,”) (2,”b”) (5,”;”) (2,”a”) (4,”=”) (3,”10”) (5,”;”) (2,”b”) (4,”=”) (2,”a”)
护符号表; 4. 对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错
误提示,保证顺利完成整个源程序的词法分析;
四、实验步骤
1. 定义目标语言的可用符号表和构词规则; 2. 依次读入源程序符号,对源程序进行单词切分和识别,直到源程序结
csu 束; 3. 对正确的单词,按照它的种别以<种别码,值>的形式保存在符号表中; 4. 对不正确的单词,做出错误处理。
1. 定义部分:定义常量、变量、数据结构。 2. 初始化:从文件将源程序全部输入到字符缓冲区中。 3. 取单词前:去掉多余空白。 4. 取单词:利用实验一的成果读出单词的每一个字符,组成单词,分析
类型。 5. 显示结果。
csu
程序源代码: #include<iostream> #include<fstream> #include<string> using namespace std;
for (int i=0; i<MAX_SEPARAROR; i++) {
if (ch == separator[i]) {
return true; } } return false; }
/* * 是否为运算符 */
bool isOperate(char ch) {
for (int i=0; i<MAX_OPERATE; i++)