實驗一、簡單的詞法設計——DFA模擬程序
一、實驗目的
通過實驗教學,加深學生對所學的關於編譯的理論知識的理解,增強學生對所學知識的綜合應用能力,並通過實踐達到對所學的知識進行驗證。通過對 DFA
模擬程序實驗,使學生掌握詞法分析的實現技術,及具體實現方法。通過本實驗加深對詞法分析程序的功能及實現方法的理解 。
二、實驗環境
供 Windows
系統的 PC
機,可用 C++/C#/Java
等編程工具編寫,語言不限。
三、實驗內容
1、自己定義一個 DFA
或者一個右線性正規文法
示例如(僅供參考) G[S]:S→aU|bV U→bV|aQ
V→aU|bQ Q→aQ|bQ|e
2、利用合適數據結構存儲自動機,如
3、利用有窮確定自動機M=(K,Σ,f, S,Z)行為模擬程序算法,來對於任意給定的串,若屬於該語言時,該過程經有限次計算后就會停止並回答“是”,若不屬於,要么能停止並回答“不是”
K:=S;
c:=getchar;
while c<>eof do
{K:=f(K,c);
c:=getchar; };
if K is in Z then return (‘yes’)
else return (‘no’)
四、實驗方式與要求
1、設計的自動機程序要具有通用性,上機編程實現;
2、實驗報告格式要求書寫要點:概要設計(總體設計思想);詳細設計(程序主流程、自動機的存儲格式、關鍵函數的流程圖);結果分析(輸入與輸出結果、存在問題及有待改進善的地方、實驗心得);
3、實驗報告限4頁內。
設計思路:我們主要是用 Java
語言實現詞法分析的過程,需要處理 DFA
和 NFA
兩種狀態,所以在文末我們給出了測試樣例以及測試截圖,部分代碼給出了詳細的注釋。
實驗代碼如下:
package python;
import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;
/**
* @author Angel_Kitty
* @createTime 2018年11月21日 上午2:23:33
*/
/**狀態轉換式構造類*/
class edge {
char PriorityState;
char ch;
char NextState;
edge(char p,char c, char n){
PriorityState = p;
ch = c;
NextState = n;
}
@Override
public String toString() {
return "edge [PriorityState=" + PriorityState + ", ch=" + ch + ", NextState=" + NextState + "]";
}
}
/**DFA的構造*/
public class DFA {
static List<edge> listEdge = new ArrayList<edge>();//狀態集
//static HashMap<edge, Character> mapEdge = new HashMap<>();
static String S;//初態集
static String Z;//終態集
//flag is here
static boolean judeZ(char ch){
int j=0;
for(; j<Z.length(); j++){
if(Z.charAt(j)==ch) return true;
}
return false;
}
static void input() {
Scanner in = new Scanner(System.in);
String instr = null;
String subStr[] = null;
System.out.println("請輸入開始符:");
S = in.next();
System.out.println("請輸入終態集(終集符組成的一個字符串):");
Z = in.next();
System.out.println("請輸入正規文法以end結尾(形式如下圖):");
System.out.println("----------");
System.out.println("| S-aU |");
System.out.println("| S-bV |");
System.out.println("| U-bV |");
System.out.println("| .... |");
System.out.println("| end |");
System.out.println("----------");
while(in.hasNext()){
instr = in.next();
if("end".equals(instr)) break;
subStr = instr.split("-|\\|");
String s = subStr[0];//讀取一行f(轉換函數)
for(int i=1; i<subStr.length; i++){
edge e = null;
if(subStr[i].length()==2){
char c = subStr[i].charAt(0);//有窮符號表
char n = subStr[i].charAt(1);//狀態集
listEdge.add(new edge(s.charAt(0),c,n));//f(S,a)=U
}
if(subStr[i].length()==1){
char c = subStr[i].charAt(0);
listEdge.add(new edge(s.charAt(0),c,Z.charAt(0)));
}
}
}
}
static char judeNextState(char s,char ch){
for(int i=0; i<listEdge.size(); i++){
if(s==listEdge.get(i).PriorityState && ch==listEdge.get(i).ch){
return listEdge.get(i).NextState;
}
}
return '0';
}
static void judeDFA(){
Scanner in = new Scanner(System.in);
System.out.println("請輸入要判斷的字符串:");
while(in.hasNext()){
String str = in.next();
if(str.equals("#")){
System.out.println("程序已退出,歡迎下次使用!");
return;
}
char temp = S.charAt(0);
int i=0;
//System.out.println(temp+" "+mapEdge.get(e));
for(; i<str.length(); i++){
//System.out.println("temp="+temp);
if(str.charAt(i)=='a'){
temp = judeNextState(temp, 'a');
}
else if(str.charAt(i)=='b'){
temp = judeNextState(temp, 'b');
}
else break;
}
//flag is here
if(i>=str.length() && judeZ(temp)) System.out.println("此字符串“屬於”該文法!");
else System.out.println("此字符串“不屬於”該文法!");
System.out.println("再次判斷請輸入字符串(退出程序輸入#):");
}
}
/*main*/
public static void main(String[] args) {
// TODO Auto-generated method stub
DFA.input();
DFA.judeDFA();
}
}
/*test example*/
/*
*
//start symbol
S
//end symbol
Q
//Regular Grammar1
S-aU
S-bV
U-bV
U-aQ
V-aU
V-bQ
Q-aQ
Q-bQ
end
//judge string
->test sample1: baab
->test sample2: abab
//start symbol
S
//end symbol
Q,V
//Regular Grammer2
S-aU
S-bV
U-bV
U-aQ
Q-aQ
Q-bQ
end
//judge string
-> test sample1: ab
-> test sample2: abb
if you input '#',The program will exit.
*
* */
測試結果如下: