NFA转成DFA、词法分析程序

该实验报告详细介绍了如何将非确定有限状态自动机(NFA)转换为确定有限状态自动机(DFA),并实现了一个词法分析程序。NFA转换部分通过读取正规文法的三元组数据,利用e_closure和move函数完成转换。词法分析程序则能识别并输出程序中的关键字、运算符和标识符,对给定的C++源代码进行词法分析。
摘要由CSDN通过智能技术生成

编译原理实验报告

NFA->DFA 、lexical analyzer



一、NFA转成DFA

在这里插入图片描述

1.源代码

#include<set> 
#include<stack>
#include<iostream>
using namespace std;
//Triad(三元组): S→aB即(S,a,B) .
struct Triad{
    char start;
    char edge;
    char end;
};
set<char>e_closure(set<char>, Triad[], int); 
set<char>move(set<char>,char, Triad[], int);
void determined(Triad [], int, char*, int);
const int MAX_NODES =20;
int main(){
    int N;
    cout<<"请输入边数:"<<endl;
    cin>>N;
    Triad* G=new Triad[N];
    cout<<"请输入正规文法(*代表E ,#代表终态,约定输入时先输入以始态开始的三元组):"<<endl;
    for(int i=0; i<N; i++){ 
    cin>>G[i].start>>G[i].edge>>G[i].end;
    
    }   

    set<char> Edge;
    for(int j=0; j<N; j++)
    {
        Edge.insert(G[j].edge);
    }
    int n=Edge.size();
    char*input=new char[n];
    set<char>::iterator it;
    int j=0;
    for (it = Edge.begin(); it!= Edge.end(); it++){
        input[j]=*it;
        j++;
    }
    determined(G, N, input, n);
    system("pause");
    return 0;
}
set<char> e_closure(set<char> T,Triad G[], int N){
    set<char> U=T;
    stack<char> S;
    set<char>::iterator it;
    for (it = U.begin(); it != U.end(); it++)
    {
        S.push(*it);
    }    
    char t;
    while (!S.empty()){
        t = S.top();
        S.pop();
        for (int i=0;i<N;i++){
            if(G[i].start== t && G[i].edge=='*'){
                U.insert(G[i].end);
                S.push(G[i].end);
            }
        }
    }
    return U;
}


set<char> move(set<char> I, char a,Triad G[], int N){
    set<char> U;
    set<char>::iterator it;
    for (it = I.begin(); it !=I.end(); it++)
        for(int i=0; i<N; i++){
            if(G[i].start==*it && G[i].edge==a)
            U.insert(G[i].end);
        }
    return U;
}

void determined(Triad G[], int N, char*input, int n){
    cout<<endl<<"确定后的DFA:"<<endl;
    bool marked[MAX_NODES];
    for(int i=0; i<MAX_NODES; i++)
        marked[i]=false;
    set<char> C[MAX_NODES];
    char s0=G[0].start;
    set<char> T0,T1;
    T0.insert(s0);
    T1=e_closure(T0,G, N);
    C[0]=T1;
    int i=0;
    while(!C[i].empty() && marked[i]==false && i<MAX_NODES){
        marked[i]=true;
        //下面被注释代码可用于输出图中求出来的集合
        /*
        set<char>::iterator it;
        cout<<i<<":";
        for (it = C[i].begin(); it != C[i].end(); it++)
        cout<<*it<<",";
        cout<<endl;
        */
        for(int j=0; j<n; j++){
            if(input[j] != '*'){
                set<char> U=e_closure(move(C[i], input[j],G,N),G,N);
                if(!U.empty()){
                    bool inC=false;
                    int k=0;
                    while(!C[k].empty() && k<MAX_NODES){
                        if(U==C[k]){
                        inC=true;
                        break;
                        }
                        k++;
                    }
                    if(!inC){
                        k=0;
                        while(!C[k].empty() && k<MAX_NODES)
                        {
                            k++;
                        }
                        C[k]=U;
                    }
                    cout<<j<<"—"<<input[j]<<""<<k<<endl;
                    }
                }
            }
            i++;
        }
//下面求出确定化后的终态
        cout<<"终态为:";
        i=0;
        while(!C[i].empty()){
            bool is_final_state=false;
            set<char>::iterator it;
            for ( it=C[i].begin(); it != C[i].end(); it++){
                if(*it== '#'){
                    is_final_state=true;

                    break;
                }
            }
            if(is_final_state) cout<<i<<",";
                i++;
        }
        cout<<endl;
        
}

2.读入数据

测试数据:课本P50例3.6
在这里插入图片描述

3.运行结果:

在这里插入图片描述

二、词法分析程序

在这里插入图片描述
在这里插入图片描述

1.源代码

#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; 
return 0;
}
 
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("D:\\VS1\\code2\\NFAconverttoDFA\\lexicalanalyzer\\s.txt","r",stdin);
 freopen("D:\\VS1\\code2\\NFAconverttoDFA\\lexicalanalyzer\\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);//关闭文件 
 system("puase");
 return 0;
}

2.读入数据

s.txt如下:

int main(){
    int a,b;
    a=103;
    if(a>=b){
        a=a*b;
    }
}

注意修改路径

freopen("D:\\VS1\\code2\\NFAconverttoDFA\\lexicalanalyzer\\s.txt","r",stdin);
freopen("D:\\VS1\\code2\\NFAconverttoDFA\\lexicalanalyzer\\result.txt","w",stdout); //从控制台输出,而不是文本输出

3.运行结果:

result.txt

(int,2)
(main,1)
((,15)
(),16)
({,17)
(int,2)
(a,0)
(,,13)
(b,0)
(;,14)
(a,0)
(=,23)
(103,24)
(;,14)
(if,3)
((,15)
(a,0)
(>=,10)
(b,0)
(),16)
({,17)
(a,0)
(=,23)
(a,0)
(*,21)
(b,0)
(;,14)
(},18)
(},18)
i
n
t
m
a
i
n
(
)
{
i
n
t
a
,
b
;
a
=
1
0
3
;
i
f
(
a
>
=
b
)
{
a
=
a
*
b
;
}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值