【编译原理实验】词法分析(Thompson)

  • 【实验目标】
  • 【实验算法】
  • 【实验完整代码】
  • 【实验示例】
  • 【注意事项】

实验使用 Code::Blocks C++编写

【实验目标】

  1. 编写一个词法分析程序,要求能够根据用户给定的任意正则表达式,测试数据是否符合给定的正则表达式规范。
  2. 采用Thompson算法将正规式转化为NFA并输出NFA状态转换矩阵;
  3. 利用子集法构造DFA并输出DFA状态转换矩阵;
  4. 用最小化算法得到最小DFA并输出该DFA的状态转换矩阵,用DFA的模拟器算法识别任意输入单词;
  5. 程序测试数据的一个示例如下:
    输入正则表达式:(a|b)*abb
    采用Thompson算法将正规式转化为NFA并输出NFA状态转换矩阵,利用子集法构造DFA并输出DFA状态转换矩阵,用最小化算法得到最小DFA并输出该DFA的状态转换矩阵,最后用DFA的模拟器算法识别任意输入单词:
    输入测试表达式: abb 输出判定结果:符合词法定义
    输入测试表达式:abab 输出判定结果:不符合词法定义

【实验算法】

(1)Thompson算法:语法树构造

算法1. 构造语法树
输入:正则表达式
输出:由正则表达式构建的语法分析树

  • 建符号栈和语法栈

  • 将#压入符号栈

  • 扫描正则表达式,直到扫到结束符#为止,对每次扫描的字符进行如下操作
    字符为操作数,则包装为叶子节点,节点指针入操作数栈;
    字符为操作符,做如下操作:

    1. 当操作符为’)‘时 ,将与第一个’('之间的操作符栈清空,具体方法如下:
      (1)读取栈顶,将栈顶操作符取出;
      (2)根据操作符对操作数栈实行相应操作;
      (循环(1)(2)步骤直到栈顶为’(’)
      (3)删除栈顶操作符‘(’;

    2. 当操作符为’'时,’’优先级最高,操作数栈顶,重新包装入栈。

    3. 当操作符‘|’、‘+’、‘(’时
      (1)与栈顶操作符进行优先级比较;
      (2)比栈顶优先级低,则栈顶运算符出栈,根据操作符对操作数栈实行相应操作; (循环(1)(2)直到不满足条件(2)条件)
      (3)此时操作符比栈顶优先级高,压入栈;

  • 此时正则表达式全部扫描结束,清空操作符栈,具体方法如下:
    (1)读取栈顶,将栈顶操作符取出;
    (2)根据操作符对操作数栈实行相应操作;
    (循环(1)(2)步骤直到栈顶为’#’)
    结束,此时操作数栈内唯一一个节点指针为语法树树根。

(2)Thompson算法:Thompson算法构造NFA

算法1. Thompson算法构造NFA
输入:语法树
输出:NFA状态转移矩阵Skips_graph

(3)由NFA到DFA

算法1. NFA到DFA(子集法)
输入:状态集Set,NFA的空跳转
输出:状态集Set的空闭包

(4)最小化DFA

算法1. 最小化DFA算法
输入:DFA
输出:最小化后的DFA

【实验完整代码】

#include <iostream>
#include <typeinfo>
#include <stdio.h>
#include <iomanip>
using namespace std;const int Maxnum=100;//数据结构
//根节点
typedef struct Node{char type;//根节点类型char Char;//叶子结点代表的字符Node *lchild;//左子树Node *rchild;//右子树int start_S;//起始状态int end_S;//终结状态}*Tree_root;
//初始化根节点
void default_Node(Node* N){N->lchild=N->rchild=NULL;
}
//包装叶子节点
Node* default_L_Node(char c){Node *N=new Node;default_Node(N);N->Char=c;N->type='l';return N;
}
//后根遍历语法树
int vist_Tree(Tree_root Tree){if(Tree->type=='l') //是根节点{cout<<Tree->Char<<" ";return 1;}else{vist_Tree(Tree->lchild);if(Tree->rchild!=NULL) vist_Tree(Tree->rchild);cout<<Tree->type<<" ";return 1;}
}//包装根节点
Node* default_R_Node(char type,Node* lchild,Node* rchild){Node *N=new Node;default_Node(N);N->type=type;N->lchild=lchild;N->rchild=rchild;return N;
}//符号栈
typedef struct operator_Stack{char* top;//栈顶char* bottom;//栈底char St[Maxnum]; //数组作为栈};//初始化栈
void default_op_stack(operator_Stack &S){S.top=S.bottom=S.St;
}
//入栈
void push_op(operator_Stack &S,char a){*(S.top)=a;S.top++;
}
//出栈
char pop_op(operator_Stack &S){S.top--;return *S.top;
}
//获得栈顶元素
char top_op(operator_Stack &S){return *(S.top-1);
}//语法栈
typedef struct syntax_Stack{int top;//栈顶int bottom;//栈底Node* St[Maxnum]; //节点数组作为栈};
//初始化栈
void default_sy_stack(syntax_Stack &S){S.top=S.bottom=0;
}
//入栈
void push_char(syntax_Stack &S,Node* a){S.St[S.top]=a;S.top++;
}
//出栈
Node* pop_char(syntax_Stack &S){S.top--;return S.St[S.top];
}//运算符转换对应优先级
int o_astype(char o){switch ( o ){case '#':return 1;case  '('   :return  2;case  '|':return 3;case  '+':return 4;case  ')':return 5;case '*':return 6;default  :return 0; //不是操作符}
}//判断是否加入连接运算符
bool if_cat(char l,char r){if(!o_astype(l)&&r=='(')  //char+(return 1;else if(!o_astype(l)&&!o_astype(r)) //char+charreturn 1;else if(l==')'&&!o_astype(r))  //)+charreturn 1;else if(l=='*'&&!o_astype(r))  //*+charreturn 1;else if(l==')'&&r=='(')  //)+(return 1;else if(l=='*'&&r=='(')  //*+(return 1;else return 0;}//输入正则表达式
string cin_Regular_Exp(){cout<<"请输入正则表达式:";string R_exp;cin>>R_exp;R_exp.insert(0,"#");R_exp.append("#");  //加入结束符//将正则表达式加入cat连接符int l=0,r=1;while(R_exp[r]!='#'){if(if_cat(R_exp[l],R_exp[r]))R_exp.insert(l+1,"+");l++;r++;}return R_exp;
}//比较运算符优先级
bool if_high(char odd_op,char new_op){int odd_=o_astype(odd_op);int new_=o_astype(new_op);if(new_>odd_) return 1;return 0;
}
//根据运算符连接节点
Node* Connect_Nodes(char op,syntax_Stack& char_st){switch ( op ){case  '|': //双目运算符return default_R_Node(op,pop_char(char_st),pop_char(char_st));case  '+': //双目运算符return default_R_Node(op,pop_char(char_st),pop_char(char_st));;case  '*': //单目运算符return default_R_Node(op,pop_char(char_st),NULL);}
}
//构造语法树
Tree_root Syntax_Tree(string exp){//建符号栈和语法栈operator_Stack op_st;syntax_Stack char_st;default_op_stack(op_st);default_sy_stack(char_st);//将#压入符号栈push_op(op_st,exp[0]);//扫描(除了开头和结尾的#)for(int i=1;i<exp.size()-1;i++){char c=exp[i];if(!o_astype(c)) //语法内容push_char(char_st,default_L_Node(c)); //包装叶子节点,压入语法栈else//符号{if(c=='('){push_op(op_st,'(');//直接入栈}else if(c==')') //将遇到'('之间栈清空{   while(top_op(op_st)!='('){char op=pop_op(op_st);push_char(char_st,Connect_Nodes(op,char_st));}pop_op(op_st);}else if(c=='*') //遇到最高运算符,直接操作push_char(char_st,Connect_Nodes(c,char_st));else{while(!if_high(top_op(op_st),c)) //循环比较,直到比栈顶操作符优先级高{char op=pop_op(op_st);//栈顶元素出栈push_char(char_st,Connect_Nodes(op,char_st));//得到新的根节点}push_op(op_st,c);//压入符号栈}}}//扫描全部结束 将栈内剩余部分连接while(top_op(op_st)!='#'){char op=pop_op(op_st);push_char(char_st,Connect_Nodes(op,char_st));}cout<<"结束"<<endl;return char_st.St[char_st.bottom];
}//在字符数组中加入新元素,若已经存在,则返回数组编号
int add_find_char(char *A,char a,int& size_){if(size_==0) {A[0]=a;size_++;return Maxnum;}else{int i;for(i=0;i<size_;i++)if(*(A+i)==a) return i;  //找到了 不添加A[i]=a;size_++;return Maxnum; //没找到,添加} }
//得到正则表达式的吸收符号
int Get_absorb_char(string exp,char *ab_chars){int char_size = 0;for(int i=0;i<exp.size();i++){if(!o_astype(exp[i])) //不是操作符add_find_char(ab_chars,exp[i],char_size);}return char_size;
}
//状态集
typedef struct states_set{int st_set[Maxnum];int length=0;};
//图的矩阵表示
typedef struct Skips_graph{int S_size;//状态数int ab_char_size; //吸收字符种类数char absorb_char[Maxnum]; //吸收字符int Skips[Maxnum][Maxnum]; //状态跳转int empty_Skips[Maxnum][Maxnum]; //空状态跳转 每行第一列放该状态的空跳转数int start_S; //起点int end_S; //终点(对nfa而言,只有一个终点)states_set end_set; //终点集(对于dfa而言,有多个终点)
};
//初始化状态转移矩阵
void default_graph(Skips_graph &S,char *ab_char,int ab_char_size){S.S_size=0;S.ab_char_size=ab_char_size;for(int i=0;i<ab_char_size;i++)S.absorb_char[i]=ab_char[i];for(int i=0;i<Maxnum;i++)for(int j=0;j<Maxnum;j++)S.Skips[i][j]=Maxnum;   //表示无跳转for(int i=0;i<Maxnum;i++)S.empty_Skips[i][0]=0;   //空跳转个数为0}
//添加新的状态跳转 图 起点 终点 吸收字符
void add_Skips(Skips_graph& S,int B,int E,char c){int ab_char=add_find_char(S.absorb_char,c,S.ab_char_size);S.Skips[B][ab_char]=E;}
void add_empty_Skips(Skips_graph& S,int B,int E){S.empty_Skips[B][0]=S.empty_Skips[B][0]+1; //空跳转数加一int size_=S.empty_Skips[B][0];S.empty_Skips[B][size_]=E;}
//构造叶子节点状态转移
void Leaf_Skip(Skips_graph& S,Node& N){N.start_S=S.S_size;S.S_size++;N.end_S=S.S_size;S.S_size++;add_Skips(S,N.start_S,N.end_S,N.Char); //添加始末状态转移}
//构造根状态转移
void root_Skip(Skips_graph& S,Node& N){//或根构造if(N.type=='|'){N.start_S=S.S_size;S.S_size++;N.end_S=S.S_size;S.S_size++;add_empty_Skips(S,N.start_S,N.lchild->start_S);add_empty_Skips(S,N.start_S,N.rchild->start_S);add_empty_Skips(S,N.lchild->end_S,N.end_S);add_empty_Skips(S,N.rchild->end_S,N.end_S);}//闭包构造else if(N.type=='*'){N.start_S=S.S_size;S.S_size++;N.end_S=S.S_size;S.S_size++;add_empty_Skips(S,N.start_S,N.lchild->start_S);add_empty_Skips(S,N.start_S,N.end_S);add_empty_Skips(S,N.lchild->end_S,N.lchild->start_S);add_empty_Skips(S,N.lchild->end_S,N.end_S);}//连接构造else if(N.type=='+'){N.start_S=N.lchild->start_S;N.end_S=N.rchild->end_S;add_empty_Skips(S,N.lchild->end_S,N.rchild->start_S);}else {cout<<"fault!";}
}//递归构造NFA
void NFA(Tree_root Tree, Skips_graph &S, string exp){//构造状态转移矩阵if(Tree->type=='l') //叶子状态转移Leaf_Skip(S,*Tree);else{NFA(Tree->lchild,S,exp); //构造左子树状态转移if(Tree->rchild!=NULL) NFA(Tree->rchild,S,exp); //构造右子树状态转移root_Skip(S,*Tree);//构造根状态转移}
}}void NFA_(Tree_root Tree, Skips_graph &S, string exp){//得到吸收符号char ab_chars[Maxnum]; //正则表达式中的吸收符号int ab_chars_size=Get_absorb_char(exp,ab_chars);//初始化状态转移(NFA)default_graph(S,ab_chars,ab_chars_size);//构造NFA(Tree,S,exp);S.start_S=Tree->start_S;S.end_S=Tree->end_S;}
//读NFA
void vist_Graph(Skips_graph &S,string type){cout<<"状态跳转矩阵:"<<endl;cout<<"状态";for(int i=0;i<S.ab_char_size;i++)cout<<setw(6)<<S.absorb_char[i];cout<<setw(8)<<"空跳转";cout<<endl;for(int i=0;i<S.S_size;i++){cout<<setw(3)<<i;for(int j=0;j<S.ab_char_size;j++)if(S.Skips[i][j]==Maxnum) cout<<setw(6)<<"-";else cout<<setw(6)<<S.Skips[i][j];//输出空跳转cout<<setw(6)<<" ";for(int j=0;j<S.empty_Skips[i][0];j++)cout<<S.empty_Skips[i][j+1]<<" ";cout<<endl;}cout<<"起点:"<<S.start_S<<" ";if(type=="nfa") cout<<"终点:"<<S.end_S<<" ";else{cout<<"终点:";for(int i=0;i<S.end_set.length;i++)cout<<S.end_set.st_set[i]<<" ";}cout<<endl;}//向状态集中添加元素
bool add_s_to_set(states_set &Set,int s){for(int i=0;i<Set.length;i++){if(Set.st_set[i]==s) return 0;}Set.st_set[Set.length]=s;Set.length++;return 1;
}
//求集合的空闭包 空跳转
void empty_closure(states_set &Set,int empty_Skips[][Maxnum]){for(int i=0;i<Set.length;i++){int p=Set.st_set[i];for(int j=0;j<empty_Skips[p][0];j++){add_s_to_set(Set,empty_Skips[p][j+1]);}}cout<<"闭包:"<<endl;for(int i=0;i<Set.length;i++) cout<<Set.st_set[i]<<" ";cout<<endl;
}//计算从当前状态集出发,经过a字符,能到的下一个状态集
void Smove(states_set Set,states_set &next_Set,int absorb_char,Skips_graph &nfa){//对每个状态都计算经过a得到的新状态for(int i=0;i<Set.length;i++){   int nfa_i=Set.st_set[i];  //在nfa中的状态if(nfa.Skips[nfa_i][absorb_char]!=Maxnum) //有跳转add_s_to_set(next_Set,nfa.Skips[nfa_i][absorb_char]);}
}
//判断当前状态集是否存在,若存在则返回新状态,若不存在则返回0
int if_exist(states_set *Sets,states_set Set,int sets_length){//找到长度相等的进行比对int T; //判断是否有相同的状态集for(int i=0;i<sets_length;i++){if(Sets[i].length==Set.length){T=1; //先假设该集合是for(int j=0;j<Set.length;j++){int t=0; //判断是否找到相同元素for(int k=0;k<Sets[i].length;k++)if(Set.st_set[j]==Sets[i].st_set[k]){t=1;break;}if(t==0) {T=0;break;} //找不到,该集合不是}if(T==1) return i;}}return 0;
}
//NFA转为DFA
void DFA(Skips_graph &nfa,Skips_graph &dfa,states_set *sets){for(int i=0;i<dfa.S_size;i++){//计算当前状态的跳转状态集 c为吸收字符for(int c=0;c<dfa.ab_char_size;c++){states_set next_set;Smove(sets[i],next_set,c,nfa);//计算Smove(j,char)if(next_set.length==0) continue; //该状态不吸收该字符empty_closure(next_set,nfa.empty_Skips);//计算Smove的空闭包//判断该状态集是否已经存在,如果不存在则作为新状态集加入dfaint S=if_exist(sets,next_set,dfa.S_size);if(!S){S=dfa.S_size;sets[S]=next_set;dfa.S_size++;}//在dfa上添加当前状态吸收字符的跳转dfa.Skips[i][c]=S;}}
}
//判断集合中是否有某个元素
bool find_s(states_set set_,int s){for(int i=0;i<set_.length;i++)if(set_.st_set[i]==s) return 1;return 0;}
void DFA_(Skips_graph &nfa,Skips_graph &dfa){//初始化dfadefault_graph(dfa,nfa.absorb_char,nfa.ab_char_size);states_set sets[Maxnum];//新旧状态表//先求起始状态的空闭包states_set begin_set;add_s_to_set(begin_set,nfa.start_S);empty_closure(begin_set,nfa.empty_Skips);//将起始状态集作为DFA的起始状态加入dfa.start_S=0;//将起始状态集加入状态集与新状态的对照表中sets[dfa.S_size]=begin_set;dfa.S_size++;DFA(nfa,dfa,sets);//找到dfa的所有终点状态int end_s=nfa.end_S;for(int i=0;i<dfa.S_size;i++){if(find_s(sets[i],end_s)){add_s_to_set(dfa.end_set,i);}}
}//将终点集根据吸收的字符划分
bool crack_end(Skips_graph &dfa,int *new_states,int &find_num){states_set new_end_sets;//将终态分出:构造nfa到dfa,每个状态只吸收一个符号,找到每个符号对应的终态集,将其标为相同的状态if(dfa.end_set.length==1){new_states[(dfa.end_set.st_set[0])]=dfa.end_set.st_set[0];find_num++;add_s_to_set(new_end_sets,dfa.end_set.st_set[0]);}else{int not_find_num=dfa.end_set.length; //未找到的元素for(int c=0;c<dfa.ab_char_size;c++){int T=Maxnum;  //表示还未找到第一个终态for(int i=dfa.S_size-1;i>=0;i--){ //从后往前找if(find_s(dfa.end_set,dfa.Skips[i][c])) //在接受该字符的跳转里找到终态{if(T==Maxnum){T=dfa.Skips[i][c];add_s_to_set(new_end_sets,T);}new_states[(dfa.Skips[i][c])]=T; //用第一个发现的终态 作为该吸收的终态not_find_num--;find_num++;}if(not_find_num==0) break;}if(not_find_num==0) break; }}dfa.end_set=new_end_sets;
}
//分裂,分裂成功返回1,不可再分返回0
bool crack(Skips_graph &dfa,int *new_states,int &find_num){for(int i=0;i<dfa.S_size;i++){if(new_states[i]!=Maxnum) continue;for(int c=0;c<dfa.ab_char_size;c++){int T=1;//表示是否可以区分for(int j=0;j<dfa.S_size;j++){if(i==j) continue;if(new_states[(dfa.Skips[i][c])]==new_states[(dfa.Skips[j][c])]) //跳转的结果在一个集合{T=0;break;}}//可再分if(T==1) {new_states[i]=i;find_num++;return 1;}}}return 0;//表示不可再分
}
//判断数组前n个是否出现过当前字符
bool find_int(int *array_,int n,int s){for(int i=0;i<n;i++){if(array_[i]==s) return 1;return 0;}
}
//查找旧状态为s的新状态
int find_s_in_array(int *array,int s,int length){for(int i=0;i<length;i++){if(array[i]==s) return i;
}}
//整理合并后的dfa
void combine(Skips_graph dfa,Skips_graph& min_dfa,int *old_states){default_graph(min_dfa,dfa.absorb_char,dfa.ab_char_size);//初始化int new_states[Maxnum];//将没有出现过的状态加入for(int i=0;i<dfa.S_size;i++){if(find_int(old_states,i,old_states[i])) continue;//判断之前是否出现过for(int c=0;c<dfa.ab_char_size;c++)min_dfa.Skips[min_dfa.S_size][c]=dfa.Skips[i][c];  //复制进去new_states[min_dfa.S_size]=old_states[i];//保存老状态min_dfa.S_size++;}//将所有状态调整for(int i=0;i<min_dfa.S_size;i++){for(int c=0;c<min_dfa.ab_char_size;c++)min_dfa.Skips[i][c]=find_s_in_array(new_states,min_dfa.Skips[i][c],min_dfa.S_size);}//记录起点min_dfa.start_S=find_s_in_array(new_states,dfa.start_S,min_dfa.S_size);//终结状态作调整for(int i=0;i<dfa.end_set.length;i++){add_s_to_set(min_dfa.end_set,find_s_in_array(new_states,dfa.end_set.st_set[i],min_dfa.S_size));}
//    cout<<min_dfa.end_set.length;
//        for(int i=0;i<min_dfa.end_set.length;i++)
//            cout<<min_dfa.end_set.st_set[i]<<" ";}
//最简化DFA
void minimize_DFA(Skips_graph dfa,Skips_graph &min_dfa){//新状态int find_num=0; //确定新状态的状态数int new_states[Maxnum];for(int i=0;i<dfa.S_size;i++) new_states[i]=Maxnum;//将终态分出:构造nfa到dfa,每个状态只吸收一个符号,找到每个符号对应的终态集,将其标位相同的状态crack_end(dfa,new_states,find_num);//将每个可区分的状态区分出来 条件:未找完或者还可以继续区分while(find_num!=dfa.S_size&&crack(dfa,new_states,find_num)){;}//将剩余状态划分为一个状态if(find_num!=dfa.S_size){int T=Maxnum;for(int i=0;i<dfa.S_size;i++){if(new_states[i]!=Maxnum) continue; //已经找到的if(T==Maxnum) T=i;new_states[i]=T;}}//将新旧状态不同的 修改符号for(int i=0;i<dfa.S_size;i++){if(i==new_states[i]) continue;for(int j=0;j<dfa.S_size;j++){for(int c=0;c<dfa.ab_char_size;c++){if(dfa.Skips[j][c]==i) dfa.Skips[j][c]=new_states[i];}}}dfa.start_S=new_states[dfa.start_S];//将改变的起点记录下来combine(dfa,min_dfa,new_states);
}
//返回吸收字母的数字
bool find_ab_char(char a,Skips_graph dfa,int &c){for(int i=0;i<dfa.ab_char_size;i++)if(dfa.absorb_char[i]==a){c=i;return 1;}return 0;}
//根据dfa作词法分析
bool  lexical_analysis(Skips_graph dfa){string exp;cout<<"输入词:";cin>>exp;cout<<"过程:";int p=dfa.start_S;cout<<p<<"->";//根据读入跳转for(int i=0;i<exp.size();i++){char char_=exp[i];int c; //字符在吸收字符数组中的位置//字符不可被接受if(!find_ab_char(char_,dfa,c)){cout<<"失败:"<<char_<<"输入字符不被接受"<<endl;return 0;}//可以被接受p=dfa.Skips[p][c];cout<<p<<"->";//无法跳转if(p==Maxnum){cout<<"失败:吸收"<<char_<<"跳转出错"<<endl;return 0;}}//全部字符读取成功:若能到达终点if(find_s(dfa.end_set,p)) //移动到终点处cout<<"成功"<<endl;elsecout<<"失败:未到达终点"<<endl;return 1;}int main()
{int start;cout<<"开始:";cin>>start;while(start){string exp=cin_Regular_Exp();cout<<exp<<endl;//构建语法树Node* Tree=Syntax_Tree(exp);//遍历语法树cout<<"后序遍历语法树: ";vist_Tree(Tree);cout<<endl;//构造NFAcout<<endl<<"********************Thompson算法构造NFA***********************"<<endl;Skips_graph nfa;NFA_(Tree,nfa,exp);vist_Graph(nfa,"nfa");//由NFA构造DFAcout<<endl<<"************************由NFA转为DFA**************************"<<endl;Skips_graph dfa;DFA_(nfa,dfa);vist_Graph(dfa,"dfa");//最小化dfacout<<endl<<"**************************最小化DFA**************************"<<endl;Skips_graph min_dfa;minimize_DFA(dfa,min_dfa);vist_Graph(min_dfa,"dfa");//进行词法分析cout<<"*********************************词法分析**************************"<<endl;char a;cin>>a;while(a!='#'){lexical_analysis(dfa);cin>>a;}cout<<endl<<"开始:";cin>>start;}
}

【实验示例】

【注意事项】

实验未实现 ‘+’,开始时要输入‘1’。

【编译原理实验】词法分析(Thompson)相关推荐

  1. 编译原理实验一 词法分析程序设计与实现

    一.实验目的 通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符流形式的源程序转化为一个由各类单词构成的序列的词法分析方法. 二.基本实验内容与要求 假定一种高级程序 ...

  2. 编译原理实验:词法分析

    编译原理实验:词法分析 1. 实验题目:词法分析 实验目的 实验内容 实验要求 输入输出 2. 设计思想 3.算法流程 4. 源程序 5. 调试数据 1. 实验题目:词法分析 实验目的 根据PL/0语 ...

  3. 词法分析程序的设计(编译原理实验一)

    词法分析程序的设计(编译原理实验一) 一.实验内容 ​ 编制一个能够分析三种整数.标识符.主要运算符和主要关键字的词法分析程序. 二.实验要求 编写程序,识别如下单词符号 标识符 <字母> ...

  4. html解析器编译原理,编译原理实验报告词法分析器(内含源代码).docx

    编译原理实验报告词法分析器(内含源代码) 编译原理实验(一) --词法分析器 实验描述 运行环境:vc++2008 对某特定语言A ,构造其词法规则. 该语言的单词符号包括: 1该程序能识别的单词符号 ...

  5. 编译原理中词法分析的递归下降分析法实例--能被5整除的二进制数---c语言实现

    一.前言 又到了一周一度的编译原理实验课,一次实验课上完了,又是大学生必备技能-写实验报告.行了,废话不多说,我直接展现,如何实现编译原理中词法分析的递归下降分析法实例–能被5整除的二进制数的思路.作 ...

  6. 编译原理实验:代码生成作业(1)

    编译原理实验4:中间代码生成实验包-C++文档类资源-CSDN下载编译原理实验4:中间代码生成实验包更多下载资源.学习资料请访问CSDN下载频道.https://download.csdn.net/d ...

  7. 编译原理--实验2 语法分析

    文章目录 前言 1.1实验目的 1.2 实验任务 1.3 实验内容 1.3.1 实验要求 1.3.2 输入格式 1.3.3 输出格式 1.3.4 样例 1.4 程序 1.4.1 程序流程图 1.4.2 ...

  8. 编译原理实验二:赋值语句的语法分析程序设计

    编译原理实验二:赋值语句的语法分析程序设计 1.1实验内容 目的: 在前面实验的基础上,通过设计.编制.调试一个典型的赋值语句的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查,进一步掌握 ...

  9. 编译原理实验:自上而下语法分析

    编译原理实验:自上而下语法分析 1. 实验题目:自上而下语法分析 实验目的 实验内容 实验要求 输入输出 2. 设计思想 3. 算法流程 4. 源程序 5. 调试数据 1. 实验题目:自上而下语法分析 ...

  10. 编译原理——java 词法分析【有穷自动机实现】

    编译原理--实验1 实验要求 1) 基于词法规则设计词法分析器(20分) 画出确定的有穷自动机(确定化),并提供必要的文字说明.提交状态转换图.doc 2) 词法分析程序的编程实现(80分) (1) ...

最新文章

  1. 【一通百通】Bash的单双括号建议:多用[[]], 少用[]
  2. 开源网站Open-Open
  3. 斯坦福机器学习公开课学习笔记(2)—监督学习 梯度下降
  4. 神圣的NLP!一文理解词性标注、依存分析和命名实体识别任务
  5. J-Link该如何升级固件?
  6. Unlicensed ARC session – terminating!
  7. MySQL创建不了计划任务_MySQL创建定时任务(或计划任务)
  8. 单元测试框架之Robolectric踩坑
  9. 算法高级(9)-线程池的实现方式
  10. 主机与设备之间文件拷贝的几种方式
  11. Python:渗透测试开源项目【源码值得精读】
  12. 发票管理软件_企业为什么需要采购管理软件?
  13. Unity自动修复Sentinel key not found (h0007)错误
  14. android手机电量测试,Android手机app耗电量测试工具 - Gsam Battery Monitor
  15. 最全最丰富的随机图片调用接口——三千之图
  16. 适合女生佩戴的蓝牙耳机有什么推荐?五款高性价比蓝牙耳机
  17. 下载了JFLASH安装后还出现The select device is unknown to this version of the J-LINK software
  18. 字符串的插入(不用库函数)
  19. List循环中指定删除元素(不止一个)
  20. Arduino TFT_eSPI库来驱动SPI接口的LCD显示文字详解

热门文章

  1. 使用pip出现报错:Could not find a version that satisfies the...No matching distribution distributio...
  2. 老罗如果输了整个民族都输了
  3. uboot利用uEnv.txt文件实现灵活功能(加载PL侧bit,修改uenvcmd,配置bootargs,配置bootm,配置bootz)
  4. u盘打不开,提示需要格式化怎么办?
  5. 【产品功能】弹性网卡支持私网多IP
  6. 李飞飞计算机视觉笔记(1)--数据驱动的图像分类方式:K最近邻与线性分类器
  7. macOS Big Sur 11.6.3 (20G415) 正式版 DMG、ISO、IPSW 下载
  8. 离散化 Gym 101964E Fishermen
  9. Dubbo-接口数据序列化Serialization
  10. 统计push点击次数的shell脚本最初版本1