资讯详情

buct编译原理个人作业

提示:文章完成后,目录可以自动生成,如何生成可以参考右边的帮助文档

buct课设作业的编译原理

  • 一、正则表达式 -> DFA -> 最小化DFA
  • 二、LL(1)
  • 三、LR(0)
  • 四、LR(1)
  • 五、SLR(1)

一、正则表达式 -> DFA -> 最小化DFA

#include<iostream> #include<cstring> #include<string> #include<stack> #include<vector> #include<set> #include<queue>  #define MAX 128  using namespace std;  typedef set<int> IntSet; typedef set<char> CharSet;  /********************表达式转NFA********************/  struct NfaState    /*定义NFA状态*/ { 
            int index;    /*NFA状态号*/     char input;    /*NFA状态弧上的值*/  int chTrans;   /*NFA状态弧转移到状态号*/     IntSet epTrans;   /*当前状态通过ε转移状态号集合*/  };  struct NFA { 
            NfaState *head;   /*NFA的头指针*/  NfaState *tail;   /*NFA的尾指针*/ };  NfaState NfaStates[MAX]; /*NFA状态数组*/  int nfaStateNum = 0;  /*NFA状态总数*/   /*从状态n1到状态n2添加弧,弧上的值为ch*/ void add(NfaState *n1, NfaState */span>n2, char ch) { 
          n1->input = ch; n1->chTrans = n2->index; } /*从状态n1到状态n2添加一条弧,弧上的值为ε*/ void add(NfaState *n1, NfaState *n2) { 
          n1->epTrans.insert(n2->index); } /*新建一个NFA(即从NFA状态数组中取出两个状态)*/ NFA creatNFA(int sum) { 
          NFA n; n.head = &NfaStates[sum]; n.tail = &NfaStates[sum + 1]; return n; } /*在字符串s第n位后面插入字符ch*/ void insert(string &s, int n, char ch) { 
          s += '#'; for(int i = s.size() - 1; i > n; i--) { 
          s[i] = s[i - 1]; } s[n] = ch; } /*对字符串s进行预处理,在第一位是操作数、‘*’或‘)’且第二位是操作数或‘(’之间加入连接符‘&’*/ void preprocess(string &s) { 
          int i = 0 , length = s.size(); while(i < length) { 
          if((s[i] >= 'a' && s[i] <= 'z') || (s[i] == '*') || (s[i] == ')')) { 
          if((s[i + 1] >= 'a' && s[i + 1] <= 'z') || s[i + 1] == '(') { 
          insert(s, i+1 , '&'); length ++; } } i++; } } /*中缀转后缀时用到的优先级比较,即为每个操作符赋一个权重,通过权重大小比较优先级*/ int priority(char ch) { 
          if(ch == '*') { 
          return 3; } if(ch == '&') { 
          return 2; } if(ch == '|') { 
          return 1; } if(ch == '(') { 
          return 0; } } /*中缀表达式转后缀表达式*/ string infixToSuffix(string s) { 
          preprocess(s); /*对字符串进行预处理*/ string str; /*要输出的后缀字符串*/ stack<char> oper; /*运算符栈*/ for(int i = 0; i < s.size(); i++) { 
          if(s[i] >= 'a' && s[i] <= 'z') /*如果是操作数直接输出*/ { 
          str += s[i]; } else /*遇到运算符时*/ { 
          if(s[i] == '(') /*遇到左括号压入栈中*/ { 
          oper.push(s[i]); } else if(s[i] == ')') /*遇到右括号时*/ { 
          char ch = oper.top(); while(ch != '(') /*将栈中元素出栈,直到栈顶为左括号*/ { 
          str += ch; oper.pop(); ch = oper.top(); } oper.pop(); /*最后将左括号出栈*/ } else /*遇到其他操作符时*/ { 
          if(!oper.empty()) /*如果栈不为空*/ { 
          char ch = oper.top(); while(priority(ch) >= priority(s[i])) /*弹出栈中优先级大于等于当前运算符的运算符*/ { 
          str += ch; oper.pop(); if(oper.empty()) /*如果栈为空则结束循环*/ { 
          break; } else ch = oper.top(); } oper.push(s[i]); /*再将当前运算符入栈*/ } else /*如果栈为空,直接将运算符入栈*/ { 
          oper.push(s[i]); } } } } /*最后如果栈不为空,则出栈并输出到字符串*/ while(!oper.empty()) { 
          char ch = oper.top(); oper.pop(); str += ch; } cout<<"*******************************************"<<endl<<endl; cout<<"中缀表达式为:"<<s<<endl<<endl; cout<<"后缀表达式为:"<<str<<endl<<endl; return str; } /*后缀表达式转nfa*/ NFA strToNfa(string s) { 
          stack<NFA> NfaStack; /*定义一个NFA栈*/ for(int i = 0; i < s.size(); i++) /*读取后缀表达式,每次读一个字符*/ { 
          if(s[i] >= 'a' && s[i] <= 'z') /*遇到操作数*/ { 
          NFA n = creatNFA(nfaStateNum); /*新建一个NFA*/ nfaStateNum += 2; /*NFA状态总数加2*/ add(n.head, n.tail, s[i]); /*NFA的头指向尾,弧上的值为s[i]*/ NfaStack.push(n); /*将该NFA入栈*/ } else if(s[i] == '*') /*遇到闭包运算符*/ { 
          NFA n1 = creatNFA(nfaStateNum); /*新建一个NFA*/ nfaStateNum += 2; /*NFA状态总数加2*/ NFA n2 = NfaStack.top(); /*从栈中弹出一个NFA*/ NfaStack.pop(); add(n2.tail, n1.head); /*n2的尾通过ε指向n1的头*/ add(n2.tail, n1.tail); /*n2的尾通过ε指向n1的尾*/ add(n1.head, n2.head); /*n1的头通过ε指向n2的头*/ add(n1.head, n1.tail); /*n1的头通过ε指向n1的尾*/ NfaStack.push(n1); /*最后将新生成的NFA入栈*/ } else if(s[i] == '|') /*遇到或运算符*/ { 
          NFA n1, n2; /*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/ n2 = NfaStack.top(); NfaStack.pop(); n1 = NfaStack.top(); NfaStack.pop(); NFA n = creatNFA(nfaStateNum); /*新建一个NFA*/ nfaStateNum +=2; /*NFA状态总数加2*/ add(n.head, n1.head); /*n的头通过ε指向n1的头*/ add(n.head, n2.head); /*n的头通过ε指向n2的头*/ add(n1.tail, n.tail); /*n1的尾通过ε指向n的尾*/ add(n2.tail, n.tail); /*n2的尾通过ε指向n的尾*/ NfaStack.push(n); /*最后将新生成的NFA入栈*/ } else if(s[i] == '&') /*遇到连接运算符*/ { 
          NFA n1, n2, n; /*定义一个新的NFA n*/ n2 = NfaStack.top(); /*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/ NfaStack.pop(); n1 = NfaStack.top(); NfaStack.pop(); add(n1.tail, n2.head); /*n1的尾通过ε指向n2的尾*/ n.head = n1.head; /*n的头为n1的头*/ n.tail = n2.tail; /*n的尾为n2的尾*/ NfaStack.push(n); /*最后将新生成的NFA入栈*/ } } return NfaStack.top(); /*最后的栈顶元素即为生成好的NFA*/ } /*打印NFA函数*/ void printNFA(NFA nfa) { 
          cout<<"*************** NFA ***************"<<endl<<endl; cout<<"NFA总共有"<<nfaStateNum<<"个状态,"<<endl; cout<<"初态为"<<nfa.head->index<<",终态为" <<nfa.tail->index<<"。"<<endl<<endl<<"转移函数为:"<<endl; for(int i = 0; i < nfaStateNum; i++) /*遍历NFA状态数组*/ { 
          if(NfaStates[i].input != '#') /*如果弧上的值不是初始时的‘#’则输出*/ { 
          cout<<NfaStates[i].index<<"-->'"<<NfaStates[i].input<<"'-->"<<NfaStates[i].chTrans<<'\t'; } IntSet::iterator it; /*输出该状态经过ε到达的状态*/ for(it = NfaStates[i].epTrans.begin(); it != NfaStates[i].epTrans.end(); it++) { 
          cout<<NfaStates[i].index<<"-->'"<<' '<<"'-->"<<*it<<'\t'; } cout<<endl; } } /********************NFA转DFA********************/ struct Edge /*定义DFA的转换弧*/ { 
          char input; /*弧上的值*/ int Trans; /*弧所指向的状态号*/ }; struct DfaState /*定义DFA状态*/ { 
          bool isEnd; /*是否为终态,是为true,不是为false*/ int index; /*DFA状态的状态号*/ IntSet closure; /*NFA的ε-move()闭包*/ int edgeNum; /*DFA状态上的射出弧数*/ Edge Edges[10]; /*DFA状态上的射出弧*/ }; DfaState DfaStates[MAX]; /*DFA状态数组*/ int dfaStateNum = 0; /*DFA状态总数*/ struct DFA /*定义DFA结构*/ { 
          int startState; /*DFA的初态*/ set<int> endStates; /*DFA的终态集*/ set<char> terminator; /*DFA的终结符集*/ int trans[MAX][26]; /*DFA的转移矩阵*/ }; /*求一个状态集的ε-cloure*/ IntSet epcloure(IntSet s) { 
          stack<int> epStack; /*(此处栈和队列均可)*/ IntSet::iterator it; for(it = s.begin(); it != s.end(); it++) { 
          epStack.push(*it); /*将该状态集中的每一个元素都压入栈中*/ } while(!epStack.empty()) /*只要栈不为空*/ { 
          int temp = epStack.top(); /*从栈中弹出一个元素*/ epStack.pop(); IntSet::iterator iter; for(iter = NfaStates[temp].epTrans.begin(); iter != NfaStates[temp].epTrans.end(); iter++) { 
          if(!s.count(*iter)) /*遍历它通过ε能转换到的状态集*/ { 
          /*如果当前元素没有在集合中出现*/ s.insert(*iter); /*则把它加入集合中*/ epStack.push(*iter); /*同时压入栈中*/ } } } return s; /*最后的s即为ε-cloure*/ } /*求一个状态集s的ε-cloure(move(ch))*/ IntSet moveEpCloure(IntSet s, char ch) { 
          IntSet temp; IntSet::iterator it; for(it = s.begin(); it != s.end(); it++) /*遍历当前集合s中的每个元素*/ { 
          if(NfaStates[*it].input == ch) /*如果对应转换弧上的值为ch*/ { 
          temp.insert(NfaStates[*it].chTrans); /*则把该弧通过ch转换到的状态加入到集合temp中*/ } } temp = epcloure(temp); /*最后求temp的ε闭包*/ return temp; } /*判断一个状态是否为终态*/ bool IsEnd(NFA n, IntSet s) { 
          IntSet::iterator it; for(it = s.begin(); it != s.end(); it++) /*遍历该状态所包含的nfa状态集*/ { 
          if(*it == n.tail->index) /*如果包含nfa的终态,则该状态为终态,返回true*/ { 
          return true; } } return false; /*如果不包含,则不是终态,返回false*/ } /*nfa转dfa主函数*/ DFA nfaToDfa(NFA n, string str) /*参数为nfa和后缀表达式*/ { 
          cout<<"*************** DFA ***************"<<endl<<endl; int i; DFA d; set<IntSet> states; /*定义一个存储整数集合的集合,用于判断求出一个状态集s的ε-cloure(move(ch))后是否出现新状态*/ memset(d.trans, -1, sizeof(d.trans)); /*初始化dfa的转移矩阵*/ for(i = 0; i < str.size(); i++) /*遍历后缀表达式*/ { 
          if(str[i] >= 'a' && str[i] <= 'z') /*如果遇到操作数,则把它加入到dfa的终结符集中*/ { 
          d.terminator.insert(str[i]); } } d.startState = 0; /*dfa的初态为0*/ IntSet tempSet; tempSet.insert(n.head->index); /*将nfa的初态加入到集合中*/ DfaStates[0].closure = epcloure(tempSet); /*求dfa的初态*/ DfaStates[0].isEnd = IsEnd(n, DfaStates[0].closure); /*判断初态是否为终态*/ dfaStateNum++; /*dfa数量加一*/ queue<int> q; q.push(d.startState); /*把dfa的初态存入队列中(此处栈和队列均可)*/ while(!q.empty()) /*只要队列不为空,就一直循环*/ { 
          int num = q. 

标签: itt连接器kpse08f24

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台