用C语言编写一个简单的词法分析程序

问题描述:ios

用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表。若是产生词法错误,则显示错误信息、位置,并试图从错误中恢复。简单的恢复方法是忽略该字符(或单词)从新开始扫描。数组

相关词法规则 ide

<标识符>::=<字母>
<标识符>::=<标识符><字母>
<标识符>::=<标识符><数字>
<常量>::=<无符号整数>
<无符号整数>::=<数字序列>
<数字序列>::=<数字序列><数字>
<数字序列>::=<数字>
<字母>::=a|b|c|……|x|y|z
<数字>::=0|1|2|3|4|5|6|7|8|9
<加法运算符>::=+|-
<乘法运算符>::=*|/
<关系运算符>::=<|>|!=|>=|<=|==
<分界符>::=,|;|(|)|{|}
<保留字>::=main|int|if|else|while|do函数

编写词法分析程序的步骤:
spa

(1)肯定所要翻译的语言(或其子集)。翻译

C语言设计

(2)设计属性字,及各种表格,如标识符表、常量表、符号及其机内表示对照表等。code

与词法分析有关的表格:blog

1. 字符表ci

保留字: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()输出

#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]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="}; //char symbol[12]={'<','>','!=','>=','<=','==',',',';','(',')','{','}'}; //运算符和界符的种别码 
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(); // for(j=0;j<length;j++){ // cout<<letter[j]<<endl; // } 
 fclose(stdin);//关闭文件 
 fclose(stdout);//关闭文件 
 return 0; }

相关文章
相关标签/搜索