C语言实现词法分析器 https://www.jb51.net/article/155782.htm 问题描述: 用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表。如果产生词法错误,则显示错误信息、位置,并试图从错误中恢复。简单的恢复方法是忽略该字符(或单词)重新开始扫描。 相关词法规则 <标识符>::=<字母> <标识符>::=<标识符><字母> <标识符>::=<标识符><数字> <常量>::=<无符号整数> <无符号整数>::=<数字序列> <数字序列>::=<数字序列><数字> <数字序列>::=<数字> <字母>::=a|b|c|……|x|y|z <数字>::=0|1|2|3|4|5|6|7|8|9 <加法运算符>::=+|- <乘法运算符>::=*|/ <关系运算符>::=<|>|!=|>=|<=|== <分界符>::=,|;|(|)|{|} <保留字>::=main|int|if|else|while|do 编写词法分析程序的步骤: (1)确定所要翻译的语言(或其子集)。 C语言 (2)设计属性字,及各类表格,如标识符表、常量表、符号及其机内表示对照表等。 与词法分析有关的表格: 1. 字符表 保留字:main,int,if,else,while,do 字母(全小写):a|b|c|……|x|y|z 数字:0,1,2,3,4,5,6,7,8,9 运算符和界符:<,>,!=,>=,<=,==,,,;,(,),{,} 2. 特定单词机内表示表 3.画出总控流程图及各个子程序的流程图。 4. 程序 输入:一个存放C语言程序的s.txt文件 输出:存放以(单词,种别码)形式输出的result.txt文件 需要6个数组: 1. 存储关键字 key[6] 2. 存储对应下标关键字的种别码 keyNum[6] 3. 存储运算符和界符 symbol[17] 4. 存储运算符对应下标的种别码 symbolNum[17] 5. 存储从文件中取出的每个字符(不包括括号)letter[1000] 主要函数: TakeWord(); 功能:将文件letter[]中每个字符进行提取,找出关键字,输出种别码 Num作为全局变量保存提取到字符的哪个下标 1. 先提取一个字符,如果是字母,进入case1,调用identifier(),不断的提取字母或数字进行连接,没连接一个字符用int isKeyWord()程序(返回关键字种别码)判断是否为关键字,是就退出函数返回string,不是就继续执行函数,直到连接的字符不再是字母或数字,即此时字符串为标识符 2. 如果是数字,进入case 2,调用Number()函数,不断进行字符串连接,知道下一个连接字符不再是数字 3. 如果是符号,进入case 3,调用symbolStr()函数,如果是=,>,<,!,则要继续进行下个字符判断,其余符号可以直接返回 其他辅助函数: int isSymbol()判断运算符和界符,并返回种别码 bool isNum() 判断是否为数字 bool isLetter()判断是否为字母 int isKeyWord()判断是否为关键字,是返回种别码 int typeword()返回单个字符的类型 string identifier()标识符的连接 string symbolStr()符号和界符的连接 string Number()数字的连接 void print()输出 程序: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | #include <iostream> #include<stdio.h> #include<string.h> #include<stdlib.h> using namespace std; string key[6]={"main","int","if","else","while","do"}; int keyNum[6]={1,2,3,4,5,6}; string symbol[17]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="}; int symbolNum[17]={7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}; string letter[1000]; string words[1000]; int length; int num; int isSymbol(string s){ int i; for(i=0;i<17;i++){ if(s==symbol[i]) return symbolNum[i]; } return 0; } bool isNum(string s){ if(s>="0" && s<="9") return true; return false; } bool isLetter(string s) { if(s>="a" && s<="z") return true; return false; } int isKeyWord(string s){ int i; for(i=0;i<6;i++){ if(s==key[i]) return keyNum[i]; } return 0; } int typeword(string str){ if(str>="a" && str<="z") return 1; if(str>="0" && str<="9") return 2; if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}" ||str=="+"||str=="-"||str=="*"||str=="/") return 3; } string identifier(string s,int n){ int j=n+1; int flag=1; while(flag){ if(isNum(letter[j]) || isLetter(letter[j])){ s=(s+letter[j]).c_str(); if(isKeyWord(s)){ j++; num=j; return s; } j++; } else{ flag=0; } } num=j; return s; } string symbolStr(string s,int n){ int j=n+1; string str=letter[j]; if(str==">"||str=="="||str=="<"||str=="!") { s=(s+letter[j]).c_str(); j++; } num=j; return s; } string Number(string s,int n){ int j=n+1; int flag=1; while(flag){ if(isNum(letter[j])){ s=(s+letter[j]).c_str(); j++; } else{ flag=0; } } num=j; return s; } void print(string s,int n){ cout<<"("<<s<<","<<n<<")"<<endl; } void TakeWord(){ int k; for(num=0;num<length;){ string str1,str; str=letter[num]; k=typeword(str); switch(k){ case 1: { str1=identifier(str,num); if(isKeyWord(str1)) print(str1,isKeyWord(str1)); else print(str1,0); break; } case 2: { str1=Number(str,num); print(str1,24); break; } case 3: { str1=symbolStr(str,num); print(str1,isSymbol(str1)); break; } } } } int main(){ char w; int i,j; freopen("s.txt","r",stdin); freopen("result.txt","w",stdout); length=0; while(cin>>w){ if(w!=' '){ letter[length]=w; length++; } } TakeWord(); fclose(stdin); fclose(stdout); return 0; } | 运行结果: s.txt Result.txt
|