C语言实现词法分析器

 更新时间:2019年01月31日 16:06:44   作者:flamingobaby  
这篇文章主要为大家详细介绍了C语言实现词法分析器,一个简单的词法分析程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

问题描述:

用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()输出

程序:

#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;
} 

运行结果:

s.txt

Result.txt

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Windows下sentry接入C/C++程序的详细过程

    Windows下sentry接入C/C++程序的详细过程

    sentry作为一个开源的软件,发展至今,已经非常成熟。它支持的平台众多,甚至于针对不同的工作者(后台、前端、客户端)都有相应的内容,这篇文章主要介绍了Windows下sentry接入C/C++程序,需要的朋友可以参考下
    2022-09-09
  • 基于OpenCv的运动物体检测算法

    基于OpenCv的运动物体检测算法

    这篇文章主要为大家详细介绍了基于OpenCv的运动物体检测算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C语言小知识之为什么要使用指针详析

    C语言小知识之为什么要使用指针详析

    指针是C语言中一个非常重要的概念,也是C语言的特色之一,使用指针可以对复杂数据进行处理,能对计算机的内存分配进行控制,在函数调用中使用指针还可以返回多个值,这篇文章主要给大家介绍了C语言小知识之为什么要使用指针的相关资料,需要的朋友可以参考下
    2021-10-10
  • C++中如何调用C语言的代码实现

    C++中如何调用C语言的代码实现

    这篇文章主要介绍了C++中如何调用C语言的代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • C语言实现数独程序的示例代码

    C语言实现数独程序的示例代码

    数独是源自瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。本文将利用C语言实现数独程序,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-03-03
  • C语言中大小端问题实例探索解决方法

    C语言中大小端问题实例探索解决方法

    这篇文章主要介绍了C语言中大小端问题实例,总的来说这并不是一道难题,那为什么要拿出这道题介绍?拿出这道题真正想要传达的是解题的思路,以及不断优化探寻最优解的过程。希望通过这道题能给你带来一种解题优化的思路
    2023-02-02
  • C++如何解决rand()函数生成的随机数每次都一样的问题

    C++如何解决rand()函数生成的随机数每次都一样的问题

    这篇文章主要介绍了C++如何解决rand()函数生成的随机数每次都一样的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • C语言结课设计之计算器功能

    C语言结课设计之计算器功能

    这篇文章主要为大家详细介绍了C语言结课设计之计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • 探讨C++中数组名与指针的用法比较分析

    探讨C++中数组名与指针的用法比较分析

    本篇文章是对C++中数组名与指针用法的比较进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • VScode platformio使用的详细步骤

    VScode platformio使用的详细步骤

    使用VSCode作为编辑器,同时借助PlatformIO插件,可以帮助开发者更加高效地进行嵌入式开发,本文主要介绍了VScode platformio使用的详细步骤,感兴趣的可以了解一下
    2023-10-10

最新评论