词法分析器(含完整源码)
编译原理词法分析器-ll1-lr0-python实现代码
编译原理词法分析器-ll1-lr0-python实现代码计算机科学与通信工程学院编译原理实验报告题目: 1.词法分析器2. LL(1)分析器3. LR(0)分析器班级:姓名:学号:指导老师:2017年月目录一、实验题目 (1)二、实验目的和要求 (1)三、代码实现 (2)四、总结 (25)一、实验题目1.词法分析器分析一段程序代码,将代码中的单词符号分解出来,并对其进行检查,输出token表和error表2.LL(1)文法分析器分析给定文法。
求出文法的FIRST集,FOLLOW集,并构建分析表,对给定输入串进行分析。
3.LR(0)文法分析器分析给定文法。
用Ꜫ_CLOSURE方法构造文法的LR(0)项目集规范族,根据状态转换函数GO构造出文法的DFA,并转换为分析表,对给定输入串进行分析。
二、实验目的和要求1.学会词法分析器的实现思路。
2.学会求解FIRST集, FOLLOW集,构造LL(1)分析表。
3.学会Ꜫ_CLOSURE方法,状态转换函数GO, 构造LR(0)分析表。
三、代码实现1.词法分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i代码:KEYWORD_LIST = ['while', 'if', 'else', 'switch', 'case']SEPARATOR_LIST = [';', ':', ',', '(', ')', '[', ']', '{', '}']OPERATOR_LIST1 = ['+', '-', '*']OPERATOR_LIST2 = ['<=', '<', '==', '=', '>', '>=']CATEGORY_DICT = {# KEYWORD"while": {"while": ""},"if": {"if": ""},"else": {"else": ""},"switch": {"switch": ""},"case": {"case": ""},# OPERATOR"+": {"+": ""},"-": {"-": ""},"*": {"*": ""},"<=": {"relop": "LE"},"<": {"relop": "LT"},">=": {"relop": "GE"},">": {"relop": "GT"},"==": {"relop": "EQ"},"=": {"=": ""},# SEPARATOR";": {";": ""},":": {":": ""},",": {",": ""},"(": {"(": ""},")": {")": ""},"[": {"]": ""},"]": {"]": ""},"{": {"{": ""},"}": {"}": ""},}CONSTANTTABLE = []TOKENTABLE = []OPERATORTABLE = []KEYWORDTABLE = []SEPARATORTABLE = []UNDEFINEDTABLE = []# READ FILEdef read_file(path, method):temp_str = ""try:file = open(path, method)for line in file:line = line.replace('\n', " ") temp_str += linetemp_str = str(temp_str)except IOError as e:print(e)exit()finally:file.close()return temp_str.strip() + " "# GETBEdef getbe():global tokengetchar()token = ""return# GETCHARdef getchar():global characterglobal locationwhile all_string[location] == " ":location = location + 1character = all_string[location]return character# LINK TOKENdef concatenation():global tokenglobal charactertoken = token + character# IS NUMBERdef digit():if '0' <= character <= '9':return Truereturn False# IS ALPHABETdef letter():if 'A' <= character <= 'Z' or 'a' <= character <= 'z': return Truereturn False# IS IDENTIFIERdef reserve():if token in KEYWORD_LIST:return CATEGORY_DICT[token]else:return 0# RETRACTdef retract():global locationglobal character# location = location - 1character = ""return# MAIN FUNCTIONdef main():global tokenglobal characters = getchar()getbe()if 'a' <= s <= 'z' or 'A' <= s <= 'Z':while letter() or digit():concatenation()location = location + 1character = all_string[location]retract()c = reserve()if c == 0:TOKENTABLE.append(token)print("这是标识符:{'", token, "':'", TOKENTABLE.index(token), "'}") else:KEYWORDTABLE.append(token)print("这是保留字:", CATEGORY_DICT[token])elif '0' <= s <= '9':while digit():concatenation()location = location + 1character = all_string[location]retract()CONSTANTTABLE.append(token)print("这是常数:{'", token, "':'", CONSTANTTABLE.index(token), "'}") elif s in OPERATOR_LIST1:location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in OPERATOR_LIST2:location = location + 1character = all_string[location]if character == '=':OPERATORTABLE.append(s + character)print("这是双操作符:", CATEGORY_DICT[s + character])else:retract()location = location + 1OPERATORTABLE.append(s)print("这是单操作符:", CATEGORY_DICT[s])elif s in SEPARATOR_LIST:location = location + 1SEPARATORTABLE.append(s)print("这是分隔符:", CATEGORY_DICT[s])else:UNDEFINEDTABLE.append(s)print("error:undefined identity :'", s, "'")if __name__ == '__main__':character = ""token = ""all_string = read_file("program.txt", "r")location = 0while location + 1 < len(all_string):main()print('KEYWORDTABLE:', KEYWORDTABLE)print('TOKENTABLE:', TOKENTABLE)print('CONSTANTTABLE:', CONSTANTTABLE)print('OPERATORTABLE:', OPERATORTABLE)print('SEPARATORTABLE:', SEPARATORTABLE)运行结果:2.LL(1)分析器program.txt 中存放要分析的文法:E->TRR->+TR|-TR|~T->FGG->*FG|/FG|~F->(E)|i输入串:i+i*i代码:NonTermSet = set() # 非终结符集合TermSet = set() # 终结符集合First = {} # First集Follow = {} # Follow集GramaDict = {} # 处理过的产生式Code = [] # 读入的产生式AnalysisList = {} # 分析表StartSym = "" # 开始符号EndSym = '#' # 结束符号为“#“Epsilon = "~" # 由于没有epsilon符号用“~”代替# 构造First集def getFirst():global NonTermSet, TermSet, First, Follow, FirstAfor X in NonTermSet:First[X] = set() # 初始化非终结符First集为空for X in TermSet:First[X] = set(X) # 初始化终结符First集为自己Change = Truewhile Change: # 当First集没有更新则算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:k = 0Continue = Truewhile Continue and k < len(Y):if not First[Y[k]] - set(Epsilon) <= First[X]: # 没有一样的就添加,并且改变标志if Epsilon not in First[Y[k]] and Y[k] in NonTermSet and k > 0: # Y1到Yi候选式都有~存在Continue = Falseelse:First[X] |= First[Y[k]] - set(Epsilon)Change = Trueif Epsilon not in First[Y[k]]:Continue = Falsek += 1if Continue: # X->~或者Y1到Yk均有~产生式First[X] |= set(Epsilon)# FirstA[Y] |= set(Epsilon)# 构造Follow集def getFollow():global NonTermSet, TermSet, First, Follow, StartSymfor A in NonTermSet:Follow[A] = set()Follow[StartSym].add(EndSym) # 将结束符号加入Follow[开始符号]中Change = Truewhile Change: # 当Follow集没有更新算法结束Change = Falsefor X in NonTermSet:for Y in GramaDict[X]:for i in range(len(Y)):if Y[i] in TermSet:continueFlag = Truefor j in range(i + 1, len(Y)): # continueif not First[Y[j]] - set(Epsilon) <= Follow[Y[i]]:Follow[Y[i]] |= First[Y[j]] - set(Epsilon) # 步骤2 FIRST(β)/~ 加入到FOLLOW(B)中。
编译原理----词法分析程序----C语言版
编译原理----词法分析程序----C语⾔版#include<stdio.h>#include<string.h>#include<stdlib.h>char KeyWord[20][100]={"begin","end","if","while","var","procedure","else","for","do","int","read","write"};char yunsuanfu[]="+-*/<>%=";char fenjiefu[]=",;(){}:";int main(){char test[]="var a=10;\nvar b,c;\nprocedure p; \n\tbegin\n\t\tc=a+b\n\tend\n";int len_yunsuanfu=strlen(yunsuanfu);int len_fenjiefu=strlen(fenjiefu);puts(test);int length=strlen(test),i,j,k;for(i=0;i<length;i++){if(test[i]==' '||test[i]=='\n'||test[i]=='\t')continue;int tag=0;for(j=0;j<len_fenjiefu;j++){if(fenjiefu [j]==test[i]){printf("分界符\t%c\n",test[i]);tag=1;break;}}if(tag==1)continue;tag=0;for(j=0;j<len_yunsuanfu;j++){if(yunsuanfu[j]==test[i]){printf("运算符\t%c\n",test[i]);tag=1;break;}}if(tag==1)continue;if(test[i]>='0'&&test[i]<='9'){printf("数字\t");while(test[i]>='0'&&test[i]<='9'){printf("%c",test[i]);i++;}printf("\n");continue;}char temp[100];j=0;while(test[i]>='0'&&test[i]<='9'||test[i]>='a'&&test[i]<='z'||test[i]>='A'&&test[i]<='Z'||test[i]=='_') {temp[j++]=test[i];i++;}i--;temp[j++]='\0';tag=0;for(j=0;j<20;j++){if(strcmp(temp,KeyWord[j])==0){tag=1;printf("关键字\t%s\n",temp);break;}}if(tag==0)printf("标识符\t%s\n",temp);}}。
编译原理词法分析器代码
#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失败。
【编译原理】词法分析(CC++源代码+实验报告)
【编译原理】词法分析(CC++源代码+实验报告)⽂章⽬录1 实验⽬的和内容1.1实验⽬的(1)根据 PL/0 语⾔的⽂法规范,编写PL/0语⾔的词法分析程序;或者调研词法分析程序的⾃动⽣成⼯具LEX或FLEX,设计并实现⼀个能够输出单词序列的词法分析器。
(2)通过设计调试词法分析程序,实现从源程序中分离出各种类型的单词;加深对课堂教学的理解;提⾼词法分析⽅法的实践能⼒。
(3)掌握从源程序⽂件中读取有效字符的⽅法和产⽣源程序的内部表⽰⽂件的⽅法。
(4)掌握词法分析的实现⽅法。
(5)上机调试编出的词法分析程序。
1.2实验内容根据PL/0语⾔的⽂法规范,编写PL/0语⾔的词法分析程序。
要求:(1)把词法分析器设计成⼀个独⽴⼀遍的过程。
(2)词法分析器的输出形式采⽤⼆元式序列,即:(单词种类, 单词的值)2 设计思想2.1单词种类及其正规式(1)基本字单词的值单词类型正规式rbegin beginsym begincall callsym callconst constsym constdo dosym doend endsym endif ifsym ifodd oddsym oddprocedure proceduresym procedureread readsym readthen thensym thenvar varsym varwhile whilesym whilewrite writesym write(2)标识符单词的值单词类型正规式r标识符ident(字母)(字母|数字)*(3)常数单词的值单词类型正规式r常数number(数字)(数字)*(4)运算符单词的值单词类型正规式r+plus+-minus-*times*/slash/=eql=<>neq<><lss<<=leq<=>gtr>>=geq>=:=becomes:=(5)界符单词的值单词类型正规式r(lparen()rparen),comma,;semicolon;.period.2.2 根据正规式构造NFA下⾯我们根据上述的正规式来构造该⽂法的NFA,如下图所⽰,其中状态0为初态,凡带双圈的状态均为终态,状态24是识别不出单词符号的出错情形,其他状态的识别情况如下图中右边的注释所⽰。
基于LEX的C语言词法分析器
基于LEX的C语言词法分析器下面是一个基于LEX的C语言词法分析器的示例代码:```c#include <stdio.h>%}letter [a-zA-Z]digit [0-9]id {letter}({letter},{digit})*number {digit}+(\.{digit}+)?([eE][+-]?{digit}+)?%%{number} { printf("Number: %s\n", yytext); }{if} { printf("If: %s\n", yytext); }{else} { printf("Else: %s\n", yytext); }{while} { printf("While: %s\n", yytext); }{for} { printf("For: %s\n", yytext); }{id} { printf("Identifier: %s\n", yytext); }[ \t\n]+ // ignore white space. { printf("Unrecognized character: %c\n", yytext[0]); }%%int maiyylex(;return 0;```在上述代码中,首先是一些初始化的定义,定义了一些正则表达式模式,例如`letter`表示字母,`digit`表示数字,`id`表示标识符,`number`表示数字。
然后是各个模式的匹配规则和对应的处理逻辑。
其中,`{number}`表示如果匹配到了数字模式,就打印出该数字;`{if}`、`{else}`、`{while}`、`{for}`和`{id}`分别表示匹配到了if、else、while、for关键字和标识符,就打印出对应的信息;`[ \t\n]+`表示忽略空格和换行符;`.`表示匹配到了其他未定义的字符,就打印出异常信息。
(完整版)词法分析器(c语言实现)
词法分析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 各种单词符号对应的种别码:输入:所给文法的源程序字符串。
输出:二元组(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)……三、词法分析程序的C语言程序源代码:#include <stdio.h>#include <string.h>char prog[80],token[8],ch;int syn,p,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};scaner();main(){p=0;printf("\n please input a string(end with '#'):/n");do{scanf("%c",&ch);prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){case 11:printf("( %-10d%5d )\n",sum,syn);break;case -1:printf("you have input a wrong string\n");getch();exit(0);default: printf("( %-10s%5d )\n",token,syn);break;}}while(syn!=0);getch();}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;ch=prog[p++];m=0;while((ch==' ')||(ch=='\n'))ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch;ch=prog[p++];}p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){ syn=n+1;break;}}else if((ch>='0')&&(ch<='9')) { while((ch>='0')&&(ch<='9')) { sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=22;token[m++]=ch;}else{ syn=20;p--;}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=24;token[m++]=ch;}else{ syn=23;p--;}break;case '+': token[m++]=ch;ch=prog[p++];if(ch=='+'){ syn=17;token[m++]=ch;}else{ syn=13;p--;}break;ch=prog[p++];if(ch=='-'){ syn=29;token[m++]=ch;}else{ syn=14;p--;}break;case '!':ch=prog[p++];if(ch=='='){ syn=21;token[m++]=ch;}else{ syn=31;p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=25;token[m++]=ch;}else{ syn=18;p--;}break;case '*': syn=15;token[m++]=ch;break;case '/': syn=16;token[m++]=ch;break;case '(': syn=27;token[m++]=ch;break;case ')': syn=28;break;case '{': syn=5;token[m++]=ch;break;case '}': syn=6;token[m++]=ch;break;case ';': syn=26;token[m++]=ch;break;case '\"': syn=30;token[m++]=ch;break;case '#': syn=0;token[m++]=ch;break;case ':':syn=17;token[m++]=ch;break;default: syn=-1;break;}token[m++]='\0';}四、结果分析:输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图5-1所示:。
词法分析器源代码
词法分析器源代码#include <iostream> #include <vector> #include <string> #include<fstream>/*单词种别码*/#define _CHAR 1 #define _INT 2#define _SHORT 3 #define _LONG 4 #define _SIGNED 5 #define _UNSIGNED 6 #define _FLOAT 7 #define _DOUBLE 8 #define _CONST 9 #define _VOID 10 #define _VOLATILE 11 #define _ENUM 12 #define _STRUCT 13 #define _UNION 14 #define _TYPEDEF 15 #define _AUTO 16 #define _EXTERN 17 #define_STATIC 18 #define _REGISTER 19 #define _IF 20#define _ELSE 21 #define _SWITCH 22 #define _CASE 23 #define_DEFAULT 24 #define _WHILE 25 #define _DO 26#define _FOR 27 #define _BREAK 28 #define _CONTINUE 29 #define _GOTO 30 #define _RETURN 31 #define _SIZEOF 32 #define _INCLUDE 33 #define_DEFINE 34 /*以上为关键字的种别码*/#define _ID 40 //标识符#define _NUM 50 //数#define _AS 51 //= #define _PLUS 52 //+ #define _SUB 53 //- #define _TIMES 54 // * #define _DIV 55 // / #define _LP 56 // ( #define _RP 57 // ) #define _LB1 58 // [ #define _RB1 59 // ] #define _LB2 60 //{ #define _RB2 61 // } #define _COM 62 // , #define _COL 63 // : #define_SEM 64 // #define _POINT 65 // . #define _LG 66 // > #define _LT 67 // < #define _ME 68 // >= #define _LE 69 // <= #define _EQ 70 // == #define _NE 71 // != #define _A 72 // >> #define _B 73 // >>= #define _C 74 // << #define _D 75 // <<= #define _E 76 // & #define _F 76 // && #define _G 77 // &= #define _H 78 // | #define _I 79 // || #define _J 80 // |= #define _K 81 // ~ #define _L 82 // ++ #define _M 83 // -- #define _N 84 // -> #define _O 85 // += #define _P 86 // -= #define _Q 87 // *=#define _R 88 // /= #define _S 89 // %=#define _T 90 // ^=#define _U 91 // %#define _V 92 // "#define _W 93 // '#define _X 94 // ?#define _EROOR -1 // 错误using namespace std;int ERROR_NUM=0; //记载词法编译错误个数bool isnum(string str) //判断是不是合法的数字{int y;int i;int j=0;int k=0;for(i=0;i<str.size();i++){if(!(str[i]<='9'&&str[i]>='0')){k++;if((k-j)>1){cout<<"数字串"<<str<<"出现词法错误~"<<endl;return false;} if(str[i]=='.') {j++;if(j>1) {cout<<"数字串"<<str<<"出现词法错误~"<<endl;return false;} }else if((str[i]=='E'||str[i]=='e')&&(str[i-1]<='9'&&str[i-1]>='0')&&((str[i+1]<='9'&&str[i+1]>='0')||(y=i+1)==str.size())) continue;else{cout<<"数字串"<<str<<"出现词法错误~"<<endl;return false;} }}return true;}/*该函数用来略过空格和换行符,找到有效字符的位置第一个参数为目标字符串,第二个参数为开始位置返回值为连续的空格和换行后的第一个有效字符在字符串的位置*/int valuable(string str,int i) {while(true){if(str[i]!=' '&&str[i]!='\n')return i;i++;}}int isexp(string str,int i) {if(str[i]=='/'&&str[i+1]=='/'){while(str[i]!='\n'){i++;}}return i;}int iskey(string str) //判断是不是关键字{stringp[34]={"char","int","short","long","signed","unsigned","float","double", "const","void","volatile","enum","struct","union","typedef","auto"," extern","static","register","if","else","switch","case","default","while","do", "for","break","continue","goto","return","size of","#include","#define"};vector<string> ppp(p,p+34); int u;for(u=0;u<ppp.size();u++)if(!pare(ppp[u]))return u+1;return 0;}vector<pair<int,string> > scan(vector<string> vec)//本次程序的主要分析程序 {vector<pair<int,string> > temp;int i;for(i=0;i<vec.size();i++){if(vec[i].size()==1){if(vec[i]==">"){if(vec[i+1]=="="){string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_ME,jk);temp.push_back(pp);continue;}else if(vec[i+1]==">"&&vec[i+2]!="=") { string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_A,jk);temp.push_back(pp);continue; }else if(vec[i+1]==">"&&vec[i+2]=="="){ string jk=vec[i];jk.append(vec[++i],0,1);jk.append(vec[++i],0,1);pair<int,string> pp(_B,jk);temp.push_back(pp);continue;}else {pair<int,string> pp(_LG,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]=="<") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_LE,jk);temp.push_back(pp);continue; }else if(vec[i+1]=="<"&&vec[i+2]!="=") { string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_C,jk);temp.push_back(pp);continue;}else if(vec[i+1]=="<"&&vec[i+2]=="=") { string jk=vec[i];jk.append(vec[++i],0,1);jk.append(vec[++i],0,1);pair<int,string> pp(_D,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_LT,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]=="!") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_LE,jk);temp.push_back(pp);continue;}else {pair<int,string> pp(_NE,vec[i]);//标识符temp.push_back(pp);}else if(vec[i]=="=") {if(vec[i+1]=="="){string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_EQ,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_AS,vec[i]);//标识符temp.push_back(pp); }}else if(vec[i]=="&") {if(vec[i+1]=="&") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_F,jk);temp.push_back(pp);continue;}else if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_G,jk);temp.push_back(pp);continue;}else {pair<int,string> pp(_E,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]=="|"){if(vec[i+1]=="|") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_I,jk);temp.push_back(pp);continue;}else if(vec[i+1]=="="){string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_J,jk);temp.push_back(pp);continue;}else {pair<int,string> pp(_H,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]=="(") {{pair<int,string> pp(_LP,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i]==")"){{pair<int,string> pp(_RP,vec[i]);//标识符temp.push_back(pp); }}else if(vec[i]=="["){{pair<int,string> pp(_LB1,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="]") {{pair<int,string> pp(_RB1,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="~") {{pair<int,string> pp(_K,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]==",") {{pair<int,string> pp(_COM,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="{") {{pair<int,string> pp(_LB2,vec[i]);//标识符temp.push_back(pp);} }else if(vec[i]==":") {{pair<int,string> pp(_COL,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]==";") {{pair<int,string> pp(_SEM,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="}") {{pair<int,string> pp(_RB2,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="*") {if(vec[i+1]=="="){string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_Q,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_TIMES,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="/") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_R,jk);temp.push_back(pp);continue; }else if(vec[i+1]=="*") {i=i+4;while(i<vec.size()&&(vec[i-1]!="*"||vec[i]!="/"))i++; cont inue; }else {pair<int,string> pp(_DIV,vec[i]);//标识符temp.push_back(pp); }}else if(vec[i]=="%") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_S,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_U,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i][0]=='"') {pair<int,string> pp(_V,vec[i]);//标识符temp.push_back(pp);}else if(vec[i][0]=='\'') {pair<int,string> pp(_W,vec[i]);//标识符temp.push_back(pp);}else if(vec[i][0]=='?'){pair<int,string> pp(_X,vec[i]);//标识符temp.push_back(pp); }else if(vec[i]=="+") {if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_O,jk);temp.push_back(pp);continue; }else if(vec[i+1]=="+") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_L,jk);temp.push_back(pp);continue; }else if((vec[i-1]=="="||vec[i-1]=="(")&&isnum(vec[i+1])) {string jk=vec[i]; jk.append(vec[++i]);pair<int,string> pp(_NUM,jk);temp.push_back(pp);continue; }else{pair<int,string> pp(_PLUS,vec[i]);//标识符temp.push_back(pp); } }else if(vec[i]=="-"){if(vec[i+1]=="=") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_P,jk);temp.push_back(pp);continue;}else if(vec[i+1]=="-") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_M,jk);temp.push_back(pp);continue; }else if(vec[i+1]==">") {string jk=vec[i];jk.append(vec[++i],0,1);pair<int,string> pp(_N,jk);temp.push_back(pp);continue;} else if((vec[i-1]=="="||vec[i-1]=="(")&&isnum(vec[i+1])) { string jk=vec[i]; jk.append(vec[++i]);pair<int,string> pp(_NUM,jk);temp.push_back(pp);continue; }else {pair<int,string> pp(_SUB,vec[i]);//标识符temp.push_back(pp);}}else if(vec[i][0]<='9'&&vec[i][0]>='0'){pair<int,string> pp(_NUM,vec[i]);temp.push_back(pp);}else{pair<int,string> pp(_ID,vec[i]);//标识符temp.push_back(pp);}}else if((vec[i][0]<='9'&&vec[i][0]>='0')||vec[i][0]=='.'){if(!isnum(vec[i]))ERROR_NUM++;else if((vec[i+1][0]=='+'||vec[i+1][0]=='-')&&isnum(vec[i+2])) { string jk=vec[i];jk.append(vec[++i]);jk.append(vec[++i]);pair<int,string> pp(_NUM,jk);temp.push_back(pp);continue;}else{pair<int,string> pp(_NUM,vec[i]);temp.push_back(pp);}}else if(iskey(vec[i])){pair<int,string> pp(iskey(vec[i]),vec[i]);temp.push_back(pp);}else{pair<int,string> pp(_ID,vec[i]);temp.push_back(pp);}}return temp;}void OutFile(vector<pair<int,string> > v) {int i;for(i=0;i<v.size();i++)outfile<<"<"<<v[i].first<<" , \""<<v[i].second<<"\">"<<endl; return;}。
实验一、词法分析器(含源代码)
词法分析器实验报告一、实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。
运行环境:硬件:windows xp软件:visual c++6.0二、实验步骤1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。
通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
三、实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。
将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。
在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。
标识符、常数是在分析过程中不断形成的。
对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。
输出形式例如:void $关键字流程图、程序流程图:程序:#include<string.h>#include<stdio.h>#include<stdlib.h>#include<ctype.h>//定义关键字char*Key[10]={"main","void","int","char","printf","scanf","else","if","return"}; char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsNum(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;return 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[20]={'\0'};char ch;int i,c;ch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0'; //'\0' 代表字符结束(空格)fseek(fp,-1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字if(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字else if(c==2) printf("%s\t$主函数\n\n",Word);else printf("%s\t$关键字\n\n",Word); //输出关键字 }else //开始判断的字符不是字母if(IsNum(ch)){ //判断是否是数字Word[0]=ch;ch=fgetc(fp);i=1;while(IsNum(ch)){Word[i]=ch;i++;ch=fgetc(fp);}Word[i]='\0';fseek(fp,-1,1); //回退printf("%s\t$无符号实数\n\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':case']':case'(':case')':case'{':case'}':case',':case'"':case';':printf("%s\t$界符\n\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);//运算符“+=”}else if(ch=='+'){printf("%s\t$运算符\n\n",Word); //判断结果为“++”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“+”}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); }else if(ch=='-'){printf("%s\t$运算符\n\n",Word); //判断结果为“--”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”}break;case'*':case'/':case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("%s\t$运算符\n\n",Word);}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word); //判断结果为运算符“<=”}else if(ch=='<'){printf("%s\t$运算符\n\n",Word); //判断结果为“<<”}else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“<”}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("%s\t$运算符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$运算符\n\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("%s\t$运算符\n\n",Word);}if(IsAlpha(ch)) printf("%s\t$类型标识符\n\n",Word);else {fseek(fp,-1,1);printf("%s\t$取余运算符\n\n",Word);}break;default:printf("无法识别字符!\n\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(1){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n******************* 词法分析结果如下 *******************\n");do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。
词法分析器源代码
1.实验目的及要求设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
2.实验要求一、词法分析程序的功能:二、输入:所给文法的源程序字符串。
三、输出:二元组(syn,token或sum)构成的序列。
四、其中:syn为单词种别码;五、token为存放的单词自身字符串;六、sum为整型常数。
各种单词符号对应的种别码单词符号种别码单词符号种别码begin 1 : 17if 2 := 18then 3 > 20while 4 <> 21do 5 <= 22end 6 < 23 letter(letter| digit)* 10 >= 24 digit digit * 11 = 25 * 13 ; 26/ 14 ( 27+ 15 ) 28- 16 # 03源代码#include<stdio.h>#include<string.h>#include<iostream.h>char prog[80],token[8];char ch;int syn,p,m=0,n,row,sum=0;char *rwtab[6]={"begin","if","then","while","do","end"};void scaner(){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((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0'&&ch<='9')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=11;if(sum>32767)syn=-1;}else switch(ch){case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break; case'/':syn=14;token[0]=ch;break; case'+':syn=15;token[0]=ch;break; case'-':syn=16;token[0]=ch;break; case'=':syn=25;token[0]=ch;break; case';':syn=26;token[0]=ch;break; case'(':syn=27;token[0]=ch;break; case')':syn=28;token[0]=ch;break;case'#':syn=0;token[0]=ch;break;case'\n':syn=-2;break;default: syn=-1;break;}}void main(){p=0;row=1;cout<<"请输入字符串:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){case 11: 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;}}while (syn!=0);}4 结果验证给定源程序begin x:=12; if x>0 then x:=3-4*2+3/2; end#源程序(包括上式未有的while、do以及判断错误语句):begin x<=$; while a<0 do b<..>9-x; end#5 心得体会通过此次实验,我更加深入的了解了词法构造,词法分析编制程序并调试,熟悉了构造词法分析程序的手工方式的相关原理,还有特别要注意种别码不能写错,必须一一对应,否则会很难检查出来。
词法分析器(含完整源码)
void Scanner(char ch[],int chLen,Table table[Max],int nLine) {
int chIndex = 0;
while(chIndex < chLen) //对输入的字符扫描 { /**************************处理空格和 tab ************************/
六、总结:
词法分析是构造编译器的起始阶段,也是相应比较简单的一个环节。词法分析的主要任 务是:根据构造的状态转换图,从左到右逐个字符地対源程序进行扫描,识别开源程序中具 有独立含义的最小语法单位——符号或单词,如变量标识符,关键字,常量,运算符,界符 等。
然后将提取出的标识符以内码的形式表示,即用 int 类型的数字来表示其类型和在 display 表中的位置,而无须保留原来标识符本身的字符串,这不仅节省了内存空间,也有 利于下一阶段的分析工作。
typedef struct DisplayTable {
int Index; //标识符所在表的下标 int type; //标识符的类型 int line; //标识符所在表的行数 char symbol[20]; //标识符所在表的名称 }Table;
int TableNum = 0; //display 表的下标 char Word[WordMaxNum][20]; //标识符表 char Digit[WordMaxNum][20]; //数字表 int WordNum = 0; //变量表的下标 int DigNum = 0; //常量表的下标 bool errorFlag = 0; //错误标志
当然,在扫描源程序串的同时,进行一些简单的处理,如删除空格、tab、换行等无效 字符,也进行了一些基本的错误处理,如变量长度的判别,有些不合词法规则的标识符判别 等。总之,严格说来,词法分析程序只进行和词法分析相关的工作。
编译原理词法分析和语法分析报告+代码(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用来存放单词符号的种别码。
编译原理实验报告--词法分析器
编译原理实验—词法分析器一、实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
二、实验内容及要求对某特定语言A ,构造其词法规则。
该语言的单词符号包括:保留字(见左下表)、标识符(字母大小写不敏感)、整型常数、界符及运算符(见右下表) 。
功能要求如下所示:·按单词符号出现的顺序,返回二元组序列,并输出。
·出现的标识符存放在标识符表,整型常数存放在常数表,并输出这两个表格。
·如果出现词法错误,报出:错误类型,位置(行,列)。
·处理段注释(/* */),行注释(//)。
·有段注释时仍可以正确指出词法错误位置(行,列)。
三、实验过程1、词法形式化描述使用正则文法进行描述,则可以得到如下的正规式:其中ID表示标识符,NUM表示整型常量,RES表示保留字,DEL表示界符,OPR表示运算符。
A→(ID | NUM | RES | DEL | OPR) *ID→letter(letter | didit)*NUM→digit digit*letter→a | … | z | A | … | Zdigit→ 0 | … | 9RES→ program | begin | end | var | int | and | or | not | if | then | else | while | doDEL→( | ) | . | ; | ,OPR→+ | * | := | > | < | = | >= | <= | <>如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。
空格由空白、制表符和换行符组成。
2、单词种别定义;A语言中的单词符号及其对应的种别编码如下表所示:单词符号种别编码单词符号种别编码3、状态转换图;语言A的词法分析的状态转换图如下所示:空格符,制表符或回车符字母或数字4、java旗舰版5、关键算法的流程图及文字解释;程序中用到的函数列表:A类定义各种类函数以及包含主函数public static void main()变量ch储存当前最新读进的字符的地址strToken存放当前字符串main() //主函数Analysis()//分析函数,每次读入一行文件,进行识别处理;char GetChar(); //取得当前位置的字符的内容放入ch,并提前指向下一个字符;char GetNextChar();//取得当前位置的下一位置的字符,String ConCat(); //将ch指向的字符连接到strToken后面isLetter(); //判断ch指向的字符是否字母isDigit(); //判断ch指向的字符是否数字add(p,str); //向p表中插入当前strToken的字符串Boolean findKeyWord(str); //检测当前strToken中的字符串是否保留字,若是,则执行getKeyWordKey(str),返回保留字的id,否则,判别其是否是已存在的标示符,若是,返回标示符的id以及该标示符在表中的位置;findPunctuation()//判断是否是一个保留的符号;getindex() //返回已经识别的标示符或者是数字的位置下标;Boolean exist(); //检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回true,否则返回falsevoid callError(); //出错处理过程,将错误的位置报告出来(1)main()函数的流程图如下:)具体分析流程图:开始类初始化,变量的初始化,准备执行main()函数调用Analyse()函数分析输出结果表结束Analyse(str)函数读取第一个字符赋给变量Ch继续判读IndexoutofBound6、测试报告(测试用例,测试结果);首先输入一个不含错误的程序(两种注释)进行检测:运行后在控制台上得到的结果如下所示:得到的二元组序列如下:经检验,输出的是正确的二元组序列。
词法分析器源代码
/*****************************重要数据结构的声明结束*************************/
/*********************************全局变量声明开始**************************/
int place=1;
/*26*/{999,12,999,999,999,999,999,9,999,999,999,11,13,999,999,999,33,10,999,999},
/*27*/{999,999,68,999,999,68,68,999,999,20,21,999,999,999,999,999,999,999,999,999},
#define op_add 9 //+
#define op_mul 10 //*
#define op_2star 11 //**
#define div_fenhao 12 //;
#define syl_ls 13 //(
#define syl_rs 14 //)
#define syl_lb 15 //{
/*4*/{999,999,999,999,7,999,999,999,999,999,999,999,999,999,999,999,999,999,999,999},
/*5*/{999,999,999,999,999,999,999,999,999,999,999,999,999,61,999,999,999,999,999,999},
/*30*/{999,999,72,72,999,72,72,999,72,72,72,999,999,72,999,999,999,999,999,999},
编译原理词法分析和语法分析报告+代码[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用来存放单词符号的种别码。
词法分析设计实验报告(附代码)
实验一词法分析设计实验学时:4实验类型:综合实验要求:必修一、实验目的通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。
二、实验内容用VC++/VB/JAVA语言实现对C语言子集的源程序进行词法分析。
通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。
以下是实现词法分析设计的主要工作:(1)从源程序文件中读入字符。
(2)统计行数和列数用于错误单词的定位。
(3)删除空格类字符,包括回车、制表符空格。
(4)按拼写单词,并用(内码,属性)二元式表示。
(属性值——token的机内表示)(5)如果发现错误则报告出错(6)根据需要是否填写标识符表供以后各阶段使用。
单词的基本分类:◆关键字:由程序语言定义的具有固定意义的标识符。
也称为保留字例如if、 for、while、printf ;单词种别码为1。
◆标识符:用以表示各种名字,如变量名、数组名、函数名;◆常数:任何数值常数。
如 125, 1,0.5,3.1416;◆运算符:+、-、*、/;◆关系运算符: <、<=、= 、>、>=、<>;◆分界符:;、,、(、)、[、];三、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
2、将标识符填写的相应符号表须提供给编译程序的以后各阶段使用。
3、根据测试数据进行测试。
测试实例应包括以下三个部分:◆全部合法的输入。
◆各种组合的非法输入。
◆由记号组成的句子。
4、词法分析程序设计要求输出形式:例:输入VC++语言的实例程序:If i=0 then n++;a﹤= 3b %);输出形式为:单词二元序列类型位置(行,列)(单词种别,单词属性)for (1,for ) 关键字(1,1)i ( 6,i ) 标识符(1,2)= ( 4,= ) 关系运算符(1,3)0 ( 5,0 ) 常数(1,4)then ( 1,then) 关键字(1,5)n (6,n ) 标识符(1,6)++ Error Error (1,7); ( 2, ; ) 分界符(1,8)a (6,a ) 标识符(2,1)﹤= (4,<= ) 关系运算符(2,2)3b Error Error (2,4)% Error Error (2,4)) ( 2, ) ) 分界符(2,5); ( 2, ; ) 分界符(2,6)实验报告正文:◆功能描述:该程序具有词法分析功能,即面对一段程序源代码,通过该程序,能检查出源代码是否由词法错误。
词法分析程序(c语言版)
源代码:1、词法分析/*cifa fenxi chengxu*/#include <stdio.h>#include <ctype.h>#include <alloc.h>#include <stdlib.h>#include <string.h>#define NULL 0FILE *fp;char cbuffer;char*key[8]={"if","else","for","while","do","return","break","continue"}; 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(i+1);}}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);labelnum++;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("c:\\example.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");getchar();}}2、递归向下分析#include <stdio.h>#include<dos.h>#include<stdlib.h>#include<string.h>char a[50] ,b[50],d[200],e[10];char ch;int n1,i1=0,flag=1,n=5;int E();int E1();int T();int G();int S();int F();void input();void input1();void output();void main() /*递归分析*/{int f,p,j=0;char x;d[0]='E';d[1]='=';d[2]='>';d[3]='T';d[4]='G';d[5]='#';printf("请输入字符串(长度<50,以#号结束)\n");do{scanf("%c",&ch);a[j]=ch;j++;}while(ch!='#');n1=j;ch=b[0]=a[0];printf("文法\t分析串\t\t分析字符\t剩余串\n");f=E1();if (f==0) return;if (ch=='#'){ printf("accept\n");p=0;x=d[p];while(x!='#') {printf("%c",x);p=p+1;x=d[p]; /*输出推导式*/}}else {printf("error\n");printf("回车返回\n");getchar();getchar();return;}printf("\n");printf("回车返回\n");getchar();getchar();}int E1(){ int f,t;printf("E TG\t");flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}int E(){ int f,t;printf("E→TG\t");e[0]='E';e[1]='=';e[2]='>';e[3]='T';e[4]='G';e[5]='#';output();flag=1;input();input1();f=T();if (f==0) return(0);t=G();if (t==0) return(0);else return(1);}int T(){ int f,t;printf("T→FS\t");e[0]='T';e[1]='=';e[2]='>';e[3]='F';e[4]='S';e[5]='#';output();flag=1;input();input1();f=F();if (f==0) return(0);t=S();if (t==0) return(0);else return(1);}int G(){ int f;if(ch=='+') {b[i1]=ch;printf("G→+TG\t");e[0]='G';e[1]='=';e[2]='>';e[3]='+';e[4]='T';e[5]='G';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=T();if (f==0) return(0);G();return(1);}printf("G→^\t");e[0]='G';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;input();input1();return(1);}int S(){int f,t;if(ch=='*') {b[i1]=ch;printf("S→*FS\t");e[0]='S';e[1]='=';e[2]='>';e[3]='*';e[4]='F';e[5]='S';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=F();if (f==0) return(0);t=S();if (t==0) return(0);else return(1);}printf("S→^\t");e[0]='S';e[1]='=';e[2]='>';e[3]='^';e[4]='#';output();flag=1;a[i1]=ch;input();input1();return(1);}int F(){ int f;if(ch=='(') {b[i1]=ch;printf("F→(E)\t");e[0]='F';e[1]='=';e[2]='>';e[3]='(';e[4]='E';e[5]=')';e[6]='#';output();flag=0;input();input1();ch=a[++i1];f=E();if (f==0) return(0);if(ch==')') {b[i1]=ch;printf("F→(E)\t");flag=0;input();input1();ch=a[++i1];}else {printf("error\n");return(0);}}else if(ch=='i') {b[i1]=ch;printf("F→i\t");e[0]='F';e[1]='=';e[2]='>';e[3]='i';e[4]='#';output();flag=0;input();input1();ch=a[++i1];}else {printf("error\n");return(0);}return(1);}void input(){int j=0;for (;j<=i1-flag;j++)printf("%c",b[j]); /*输出分析串*/printf("\t\t");printf("%c\t\t",ch); /*输出分析字符*/ }void input1(){int j;for (j=i1+1-flag;j<n1;j++)printf("%c",a[j]); /*输出剩余字符*/ printf("\n");void output(){ /*推导式计算*/ int m,k,j,q;int i=0;m=0;k=0;q=0;i=n;d[n]='=';d[n+1]='>';d[n+2]='#';n=n+2;i=n;i=i-2;while(d[i]!='>'&&i!=0) i=i-1;i=i+1;while(d[i]!=e[0]) i=i+1;q=i;m=q;k=q;while(d[m]!='>') m=m-1;m=m+1;while(m!=q) {d[n]=d[m];m=m+1;n=n+1;}d[n]='#';for(j=3;e[j]!='#';j++){d[n]=e[j];n=n+1;}k=k+1;while(d[k]!='=') {d[n]=d[k];n=n+1;k=k+1;}d[n]='#';}3、LL(1)/*LL(1)分析法源程序,只能在VC++中运行 */#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','*','(',')','#'};/*终结符 */char v2[20]={'E','G','T','S','F'};/*非终结符 */int j=0,b=0,top=0,l;/*L为输入串长度 */typedef struct type/*产生式类型定义 */ {char origin;/*大写字符 */char array[5];/*产生式右边字符 */int length;/*字符个数 */}type;type e,t,g,g1,s,s1,f,f1;/*结构体变量 */ type C[10][10];/*预测分析表 */void print()/*输出分析栈 */{int a;/*指针*/for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*//*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提示:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n");printf("请输入要分析的字符串:");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+')&&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')){printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n"); do{x=A[top--];/*x为当前栈顶字符*/printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)/*判断是否为终结符*/if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/printf("acc!\n");/*接受 */getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(1);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*行号*/break;}for(j=0;j<=5;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c->",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j=0;j--)/*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(1);}/*else*/}/*else*/}while(finish==0);}/*main*/4、LL(2)/*LL(1)分析法源程序,只能在VC++中运行 */#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','*','(',')','#'};/*终结符 */ char v2[20]={'E','G','T','S','F'};/*非终结符 */int j=0,b=0,top=0,l;/*L为输入串长度 */typedef struct type/*产生式类型定义 */{char origin;/*大写字符 */char array[5];/*产生式右边字符 */int length;/*字符个数 */}type;type e,t,g,g1,s,s1,f,f1;/*结构体变量 */type C[10][10];/*预测分析表 */void print()/*输出分析栈 */{int a;/*指针*/for(a=0;a<=top;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*/ /*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("提示:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n");printf("请输入要分析的字符串:");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+')&&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')){printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#';A[++top]='E';/*'#','E'进栈*/x=A[top];/*x为当前栈顶字符*/printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n");loop: printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)/*判断是否为终结符*/if(x==v1[j]) flag=1;if(flag==1)/*如果是终结符*/{if(x=='#'){printf("acc!\n");/*接受 */getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);top--;/*栈顶出栈*/ch=B[++b];/*下一个输入字符*/x=A[top];flag=0;/*恢复标记*/goto loop;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(0);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j])m=j;/*行号*/for(j=0;j<=5;j++)if(ch==v1[j])n=j;/*列号*/cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c-",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");top--;for(j=(cha.length-1);j=0;j--)/*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;x=A[top];goto loop;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(0);}/*else*/}/*else*/}/*main*/5、逆波兰式include<stdio.h>#include<math.h>#define max 100char ex[max]; /*存储后缀表达式*/void trans(){ /*将算术表达式转化为后缀表达式*/char str[max]; /*存储原算术表达式*/char stack[max]; /*作为栈使用*/char ch;int sum,i,j,t,top=0;printf("*****************************************\n");printf("*输入一个求值的表达式,以#结束。
词法分析器(含完整源码)
词法分析实验报告一、实验目的与要求:1、了解字符串编码组成的词的内涵,感觉一下字符串编码的方法和解读2、了解和掌握自动机理论和正规式理论在词法分析程序和控制理论中的应用二、实验内容:构造一个自己设计的小语言的词法分析器:1、这个小语言能说明一些简单的变量识别诸如begin,end,if,while等保留字;识别非保留字的一般标识符(有下划线、字符、数字,且第一个字符不能是数字)。
识别数字序列(整数和小数);识别:=,<=,>=之类的特殊符号以及;,(,)等界符。
2、相关过程(函数):Scanner()词法扫描程序,提取标识符并填入display表中3、这个小语言有顺序结构的语句4、这个小语言能表达分支结构的语句5、这个小语言能够输出结果总之这个小语言词法分析器能提供以上所说明到的语法描述的功能……三、实验步骤:1、测试评价(1)、测试1:能说明一些简单的变量,如关键字、一般标识符、界符等;(2)、测试2:能输出结果:单词符号(内码形式)、各种信息表(如符号表、常量表等);(3)、测试程序:var x,y,z;beginx:=2;y:=3;if (x+5>=y*y) thenbeginz:=y*y-x;z:=z+x*x;endelsez:=x+y;prn z;end.(4)、结果:①、从键盘读入;部分结果如下:(类型:该标识符所属的类型,如关键字,变量等;下标:该标识符所对应表(如变量标识符表,常量标识符表等)中其相应的位置,下同)②、从文件读入,输出到文件;部分结果如下:其他测试及结果如下:③、出错处理;注:若有错误,则只指出错误,不输出各个表;(5)、评价:这个小语言程序基本上能完成词法分析阶段的工作,识别诸如begin,if等保留字;识别非保留字的一般标识符(有下划线、字符、数字,且第一个字符不能是数字)。
识别数字序列(整数和小数);识别:=,<=,>=之类的特殊符号以及;,(,)等界符。
(完整)编译原理实验报告(词法分析器 语法分析器)
编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字。
标示符。
无符号整数.运算符.和界符。
三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号.2、程序流程图(1)主程序(2)扫描子程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符.字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。
2 实验词法分析器源程序:#include 〈stdio.h〉#include <math.h>#include <string。
h>int i,j,k;char c,s,a[20],token[20]={’0’};int letter(char s){if((s〉=97)&&(s〈=122)) return(1);else return(0);}int digit(char s){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(char token[20]){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 string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);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(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
词法分析实验报告一、实验目的与要求:1、了解字符串编码组成的词的涵,感觉一下字符串编码的方法和解读2、了解和掌握自动机理论和正规式理论在词法分析程序和控制理论中的应用二、实验容:构造一个自己设计的小语言的词法分析器:1、这个小语言能说明一些简单的变量识别诸如begin,end,if,while等保留字;识别非保留字的一般标识符(有下划线、字符、数字,且第一个字符不能是数字)。
识别数字序列(整数和小数);识别:=,<=,>=之类的特殊符号以及;,(,)等界符。
2、相关过程(函数):Scanner()词法扫描程序,提取标识符并填入display表中3、这个小语言有顺序结构的语句4、这个小语言能表达分支结构的语句5、这个小语言能够输出结果总之这个小语言词法分析器能提供以上所说明到的语法描述的功能……三、实验步骤:1、测试评价(1)、测试1:能说明一些简单的变量,如关键字、一般标识符、界符等;(2)、测试2:能输出结果:单词符号(码形式)、各种信息表(如符号表、常量表等);(3)、测试程序:var x,y,z;beginx:=2;y:=3;if (x+5>=y*y) thenbeginz:=y*y-x;z:=z+x*x;endelsez:=x+y;prn z;end.(4)、结果:①、从键盘读入;部分结果如下:(类型:该标识符所属的类型,如关键字,变量等;下标:该标识符所对应表(如变量标识符表,常量标识符表等)中其相应的位置,下同)②、从文件读入,输出到文件;部分结果如下:其他测试及结果如下:③、出错处理;注:若有错误,则只指出错误,不输出各个表;(5)、评价:这个小语言程序基本上能完成词法分析阶段的工作,识别诸如begin,if等保留字;识别非保留字的一般标识符(有下划线、字符、数字,且第一个字符不能是数字)。
识别数字序列(整数和小数);识别:=,<=,>=之类的特殊符号以及;,(,)等界符。
在扫描源程序串的同时,能进行一些简单的处理,如删除空格、tab、换行等无效字符,也进行了一些基本的错误处理,如变量长度的判别等。
遇到的问题:(a)、判别标识符超过规定长度(20)时,未输出处理结果;(b)、整数长度过长输出结果仍为整数类型3;(c)、对于小数如﹒045,被解释为界符和整数;(d)、对以数字开头的一般标识符的处理,如100nuts被解释为整数类型和标识符,未给出错误提示。
如上测试,出现前两个问题时已报错并输出所在行,而后两个问题待解决。
2、对小语言的词法规则(正规式)画出一个确定的有限自动机(见附录2、3)四、实验的源代码:(见附录1)五、实验中发现的问题和遇到的困难及解决方法:由于以前未曾接触过编译原理,在该实验的设计中,的确遇到一定的困难。
主要是display表结构的设计,由于语法分析和语义分析还未学习,无法站在全局的角度统筹兼顾,在表结构设计时,不知该往表结构体中添加哪些容,可以为后续的工作做铺垫,这是刚开始就遇到的最大的困难,也是最难的。
经过分析,我们在现有局限性的基础上,设计出一种折中的表结构,即在表结构中只添加标识符在其相应表中的对应下表,标记符类型码等关键的几处,这样既能唯一确定一标识符,达到该实验的要求,同时又为表保留了很好的扩充性,以达到后续实验的要求。
表结构设计好后,其余的工作就是提取字符串和写入display表,在提取单字符还是双字符组成的运算符时有些麻烦,不过利用数据结构的相关知识也是容易做到。
六、总结:词法分析是构造编译器的起始阶段,也是相应比较简单的一个环节。
词法分析的主要任务是:根据构造的状态转换图,从左到右逐个字符地対源程序进行扫描,识别开源程序中具有独立含义的最小语法单位——符号或单词,如变量标识符,关键字,常量,运算符,界符等。
然后将提取出的标识符以码的形式表示,即用int类型的数字来表示其类型和在display表中的位置,而无须保留原来标识符本身的字符串,这不仅节省了存空间,也有利于下一阶段的分析工作。
当然,在扫描源程序串的同时,进行一些简单的处理,如删除空格、tab、换行等无效字符,也进行了一些基本的错误处理,如变量长度的判别,有些不合词法规则的标识符判别等。
总之,严格说来,词法分析程序只进行和词法分析相关的工作。
七、实验感想:通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。
另外,也让我重新熟悉了C++语言的相关容,加深了对C++语言的用途的理解。
附录1(代码)#include <iostream>#include <fstream>#include <string>#include <math.h>#include <ctype.h>#include <cstdlib>using namespace std;#define Max 655 //最大代码长度#define WordMaxNum 256 //变量最大个数#define DigitNum 256 //常量最大个数#define MaxKeyWord 32 //关键字数量#define MaxOptANum 8 //运算符最大个数#define MaxOptBNum 4 //运算符最大个数#define MaxEndNum 11 //界符最大个数typedef struct DisplayTable{int Index; //标识符所在表的下标int type; //标识符的类型int line; //标识符所在表的行数char symbol[20]; //标识符所在表的名称}Table;int TableNum = 0; //display表的下标char Word[WordMaxNum][20]; //标识符表char Digit[WordMaxNum][20]; //数字表int WordNum = 0; //变量表的下标int DigNum = 0; //常量表的下标bool errorFlag = 0; //错误标志const char* const KeyWord[MaxKeyWord] = {"and", "array", "begin", "case","char""constant", "do", "else", "end", "false","for", "if", "input", "integer", "not", "of", "or", "output","packed","procedure", "program", "read", "real","repeat", "set", "then", "to", "type", "until", "var","while", "with","prn"}; //关键字const char OptA[] = {'+','-','*','/','=','#','<','>'}; // 单目运算const char *OptB[] = {"<=",">=",":=","<>"}; //双目运算符const char End[] = {'(', ')' , ',' , ';' , '.' , '[' , ']' , ':' , '{' , '}' , '"'}; // 界符void error(char str[20],int nLine, int errorType){cout <<" \nError : ";switch(errorType){case 1:cout << "第" << nLine-1 <<"行" << str << " 变量的长度超过限制!\n";errorFlag = 1;break;case 2:cout << "第" << nLine-1 <<"行" << str << " 小数点错误!\n";errorFlag = 1;break;case 3:cout << "第" << nLine-1 <<"行" << str << " 常量的长度超过限制!\n";errorFlag = 1;break;}}//errorvoid Scanner(char ch[],int chLen,Table table[Max],int nLine){int chIndex = 0;while(chIndex < chLen) //对输入的字符扫描{/**************************处理空格和tab ************************/ while(ch[chIndex] == ' ' || ch[chIndex] == 9 ) //忽略空格和tab{ chIndex ++; }/***************************处理换行符*************************************/ while(ch[chIndex] == 10) //遇到换行符,行数加1{ nLine++;chIndex ++;}/***************************标识符***************************************/ if( isalpha(ch[chIndex])) //以字母、下划线开头{char str[256];int strLen = 0;while(isalpha(ch[chIndex]) || ch[chIndex] == '_' ) //是字母、下划线{str[strLen ++] = ch[chIndex];chIndex ++;while(isdigit(ch[chIndex]))//不是第一位,可以为数字{str[strLen ++] = ch[chIndex];chIndex ++;}}str[strLen] = 0; //字符串结束符if(strlen(str) > 20) //标识符超过规定长度,报错处理{error(str,nLine,1);}else{ int i;for(i = 0;i < MaxKeyWord; i++) //与关键字匹配if(strcmp(str, KeyWord[i]) == 0) //是关键字,写入table表中{strcpy(table[TableNum].symbol,str);table[TableNum].type = 1; //关键字table[TableNum].line = nLine;table[TableNum].Index = i;TableNum ++;break;}if(i >= MaxKeyWord) //不是关键字{table[TableNum].Index = WordNum;strcpy(Word[WordNum++],str);table[TableNum].type = 2; //变量标识符strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;TableNum ++;}}}/**********************************常数***********************///else if(isdigit(ch[chIndex])&&ch[chIndex]!='0') //遇到数字else if(isdigit(ch[chIndex])) //遇到数字{int flag = 0;char str[256];int strLen = 0;while(isdigit(ch[chIndex]) || ch[chIndex] == '.') //数字和小数点{if(ch[chIndex] == '.') //flag表记小数点的个数,0时为整数,1时为小数,2时出错flag ++;str[strLen ++] = ch[chIndex];chIndex ++;}str[strLen] = 0;if(strlen(str) > 20) //常量标识符超过规定长度20,报错处理{error(str,nLine,3);}if(flag == 0){table[TableNum].type = 3; //整数}if(flag == 1){table[TableNum].type = 4; //小数}if(flag > 1){error(str,nLine,2);}table[TableNum].Index = DigNum;strcpy(Digit[DigNum ++],str);strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;TableNum ++;}/*******************************运算符************************************/else{int errorFlag; //用来区分是不是无法识别的标识符,0为运算符,1为界符char str[3];str[0] = ch[chIndex];str[1] = ch[chIndex + 1];str[3] = 0;for(int i = 0;i < MaxOptBNum;i++)//MaxOptBNum)if(strcmp(str,OptB[i]) == 0){errorFlag = 0;table[TableNum].type = 6;strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;table[TableNum].Index = i;TableNum ++;chIndex = chIndex + 2;break;}if(i >= MaxOptBNum){for( int k = 0;k < MaxOptANum; k++)if(OptA[k] == ch[chIndex]){errorFlag = 0;table[TableNum].type = 5;table[TableNum].symbol[0] = ch[chIndex];table[TableNum].symbol[1] = 0;table[TableNum].line = nLine;table[TableNum].Index = k;TableNum ++;chIndex ++;break;}/*************************界符*****************************************/ for(int j = 0;j < MaxEndNum;j ++)if(End[j] ==ch[chIndex]){errorFlag = 1;table[TableNum].line = nLine;table[TableNum].symbol[0] = ch[chIndex];table[TableNum].symbol[1] = 0;table[TableNum].Index = j;table[TableNum].type = 7;TableNum ++;chIndex ++;}/********************其他无法识别字符*************************************/ if(errorFlag != 0 && errorFlag != 1) //开头的不是字母、数字、运算符、界符{char str[256];int strLen = -1;str[strLen ++] = ch[chIndex];chIndex ++;while(*ch != ' ' || *ch != 9 || ch[chIndex] != 10)//{str[strLen ++] = ch[chIndex];chIndex ++;}str[strLen] = 0;table[TableNum].type = 8;strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;table[TableNum].Index = -2;TableNum ++;}}}}}void Trans(double x,int p) //把十进制小数转为16进制{int i=0; //控制保留的有效位数while(i<p){if(x==0) //如果小数部分是0break; //则退出循环else{int k=int(x*16); //取整数部分x=x*16-int(k); //得到小数部分if(k<=9)cout<<k;elsecout<<char(k+55);};i++;};};int main(){ifstream in;ofstream out,outVar,outCon;char in_file_name[26],out_file_name[26]; //读入文件和写入文件的名称char ch[Max]; //存放输入代码的缓冲区int nLine = 1; //初始化行数Table *table = new Table[Max];int choice;cout << "请输入读入方式:1:从文件中读,2:从键盘读(输入结束标志位#):\n";cin >> choice;switch(choice){int i;/****************************从文件读取***************************/ case 1:cout<<"Enter the input file name:\n";cin>>in_file_name;in.open(in_file_name);if(in.fail()) //打开display表读文件失败{cout<<"Inputput file opening failed.\n";exit(1);}cout<<"Enter the output file name:\n";cin>>out_file_name;out.open(out_file_name);outVar.open("变量表.txt");outCon.open("常量表.txt");if(out.fail()) //打开display表写文件失败{cout<<"Output file opening failed.\n";exit(1);}if(outVar.fail()) //打开变量表写文件失败{cout<<"VarOutput file opening failed.\n";exit(1);}if(outCon.fail()) //打开常量表写文件失败{cout<<"ConstOutput file opening failed.\n";exit(1);}in.getline(ch,Max,'#');Scanner(ch, strlen(ch),table,nLine); //调用扫描函数if(errorFlag == 1) //出错处理return 0;/*******************************把结果打印到各个表中***********************/ out <<"类型"<<" "<<"下标" <<endl;for( i = 0; i < TableNum;i ++)//打印displayout<< "(0x" <<hex << table[i].type<< " , "<< "0x" << hex << table[i].Index<< ")" <<endl; //在文件testout.txt中输出outCon << "下标" << " " << "常量值" << endl;for(i = 0;i < TableNum;i++) //打印常量表{if(table[i].type == 3){long num1;num1 = atoi(table[i].symbol);outCon<< "(0x" <<hex << table[i].Index << " , "<< "0x" << hex << num1 << ")" <<endl;}if(table[i].type == 4){double num2;num2 = atof(table[i].symbol);outCon<< "(0x" <<hex << table[i].Index << " , "<< "0x" << hex << num2<< ")" <<endl;}}outVar <<"类型"<<" "<< "变量名称" <<endl;for( i = 0; i < WordNum;i ++)//打印变量表outVar<< "(0x" <<hex << i<< " " << Word[i] << ")" <<endl; //在文件testout.txt中输出in.close();//关闭文件out.close();outVar.close();outCon.close();break;/***********************************从键盘输入****************************/ case 2:cin.getline(ch,Max,'#');Scanner(ch, strlen(ch),table,nLine); //调用扫描函数if(errorFlag == 1)return 0;cout << "\nDisplay表: \n";cout <<"类型"<<" "<<"下标" <<endl; //dos界面下for( i = 0; i < TableNum;i ++)cout<< "(0x" <<hex << table[i].type<< " , "<< "0x" << hex << table[i].Index<< ")" <<endl;cout << "\n常量表:\n" << "下标" << " " << "常量值" << endl;for(i = 0;i < TableNum;i++) //打印常量表{if(table[i].type == 3){long num1;num1 = atoi(table[i].symbol);cout<< "(0x" <<hex << table[i].Index << " , "<< "0x" << hex << num1 << ")" <<endl;}if(table[i].type == 4){char *num2;float num,num3;num = atof(table[i].symbol);num2 = gcvt(16,strlen(table[i].symbol),table[i].symbol);num3 = num - floor(num);cout << "(0x" << hex << table[i].Index << " , " << num2;Trans(num3,5) ;cout << ")" <<endl;}}cout <<"\n变量表:\n类型"<<" "<< "变量名称" <<endl;for( i = 0; i < WordNum;i ++)//打印变量表cout<< "(0x" <<hex << i<< " " << Word[i] << ")" <<endl; //在文件testout.txt中输出break;}return 0;}附录2:在状态转换图中各个状态表示的种类、种别编码、解释如下表:附录3:(状态转换图)空格换行tab。