• 用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;
    }

  • 相关阅读:
    jquery-scrollstop
    Grunt usemin
    HTML5 之文件操作(file)
    启动mongodb bat
    判断是否支持WebP
    前端攻略系列(一)
    impress.js初体验
    JS应用实例3:定时弹出广告
    JS应用实例2:轮播图
    JS应用实例1:注册页面表单校验
  • 原文地址:https://www.cnblogs.com/lufeibin/p/10708317.html
Copyright © 2020-2023  润新知