簡單的詞法設計——DFA模擬程序

實驗一、簡單的詞法設計——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 語言實現詞法分析的過程,需要處理 DFANFA 兩種狀態,所以在文末我們給出了測試樣例以及測試截圖,部分代碼給出了詳細的註釋。

實驗代碼如下:

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. 
 * 
 * */

測試結果如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章