简单的词法设计——DFA模拟程序

简介: 简单的词法设计——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、利用合适数据结构存储自动机,如

1100338-20190104091016926-387059722.png

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

测试结果如下:

1100338-20190104091016703-377633325.png

1100338-20190104091016308-1465261023.png

目录
相关文章
|
5月前
|
自然语言处理 Java C++
递归下降子程序文法部分编写
`char`和`num dotdot num`的定义。如果遇到不匹配,原本计划调用`error`函数来报告错误,但在这个例子中,`error`函数并未实现。程序通过`main`函数获取用户输入并启动解析过程。
19 0
编译原理实验:NFA转化为DFA
编译原理实验:NFA转化为DFA
185 0
|
自然语言处理 C语言 C++
编译原理 实验二:词法分析器的手动实现(基于状态机的词法分析器)
编译原理 实验二:词法分析器的手动实现(基于状态机的词法分析器)
1071 0
编译原理 实验二:词法分析器的手动实现(基于状态机的词法分析器)
|
存储 Go C语言
编译原理,C语言实现LR(0)分析(扩展文法的生成、项目集规范簇的生成、ACTION GOTO表的生成、句子的分析)
注:代码生成的项目集规范簇、ACTION GOTO表的顺序可能和课本、教材、参考答案的顺序不同,但这并不影响分析过程的正确性,毕竟机器是按规律办事的😄
499 0
编译原理,C语言实现LR(0)分析(扩展文法的生成、项目集规范簇的生成、ACTION GOTO表的生成、句子的分析)
【计算理论】计算理论总结 ( 正则表达式转为非确定性有限自动机 NFA | 示例 ) ★★(二)
【计算理论】计算理论总结 ( 正则表达式转为非确定性有限自动机 NFA | 示例 ) ★★(二)
148 0
【计算理论】计算理论总结 ( 正则表达式转为非确定性有限自动机 NFA | 示例 ) ★★(二)
【计算理论】计算理论总结 ( 正则表达式转为非确定性有限自动机 NFA | 示例 ) ★★(一)
【计算理论】计算理论总结 ( 正则表达式转为非确定性有限自动机 NFA | 示例 ) ★★(一)
164 0
【计算理论】计算理论总结 ( 正则表达式转为非确定性有限自动机 NFA | 示例 ) ★★(一)
【计算理论】计算理论总结 ( 非确定性有限自动机 NFA 转为确定性有限自动机 DFA | 示例 ) ★★
【计算理论】计算理论总结 ( 非确定性有限自动机 NFA 转为确定性有限自动机 DFA | 示例 ) ★★
152 0
【计算理论】计算理论总结 ( 非确定性有限自动机 NFA 转为确定性有限自动机 DFA | 示例 ) ★★
【计算理论】下推自动机 PDA ( 设计下推自动机 | 上下文无关语法 CFG 等价于 下推自动机 PDA )(一)
【计算理论】下推自动机 PDA ( 设计下推自动机 | 上下文无关语法 CFG 等价于 下推自动机 PDA )(一)
342 0
【计算理论】下推自动机 PDA ( 设计下推自动机 | 上下文无关语法 CFG 等价于 下推自动机 PDA )(一)
|
vr&ar
【计算理论】下推自动机 PDA ( 设计下推自动机 | 上下文无关语法 CFG 等价于 下推自动机 PDA )(二)
【计算理论】下推自动机 PDA ( 设计下推自动机 | 上下文无关语法 CFG 等价于 下推自动机 PDA )(二)
402 0
【计算理论】下推自动机 PDA ( 设计下推自动机 | 上下文无关语法 CFG 等价于 下推自动机 PDA )(二)