编译原理语法分析实验(Java实现)

import java.util.Stack;

public class LL1 {

	//加入同步符号的LL(1)分析表
	private  String [][] analysisTable = new String[][]{
			{"TZ","","","TZ","synch","synch"},
			{"","+TZ","","","ε","ε"},
			{"FY","synch","","FY","synch","synch"},
			{"","ε","*FY","","ε","ε"},
			{"i","synch","synch","(E)","synch","synch"}
	};

	//存储终结符
	private String [] VT = new String[]{"i","+","*","(",")","#"};

	//存储终结符
	private String [] VN = new String[]{"E","Z","T","Y","F"};

	//输入串
	private StringBuilder strToken = new StringBuilder(")i*+i");

	//分析栈
	private Stack<String> stack = new Stack<String>();

	//a保存从输入串中读取的一个输入符号,当前符号
	private String a = null;

	//X中保存stack栈顶符号
	private String X = null;

	//flag标志预测分析是否成功
	private boolean flag = true;

	//记录输入串中当前字符的位置
	private int cur = 0;

	//记录步数
	private int count = 0;

	//初始化
	protected void init(){
		strToken.append("#");
		stack.push("#");
		System.out.printf("%-9s %-38s %6s %-20s\n","步骤 ","符号栈 ","输入串 ","所用产生式 ");
		stack.push("E");
		curCharacter();
		System.out.printf("%-6d %-20s %6s \n",count,stack.toString(),strToken.substring(cur, strToken.length()));
	}

	//读取当前栈顶符号
	protected String stackPeek(){
		X = stack.peek();
		return X;
	}

	//返回输入串中当前位置的字母
	private String curCharacter(){
			a = String.valueOf(strToken.charAt(cur));
		return a;
	}

	//判断X是否是终结符
	protected boolean XisVT(){
		for(int i = 0 ; i < (VT.length - 1); i++){
			if(VT[i].equals(X)){
				return true;
			}
		}
		return false;
	}

	//查找X在非终结符中分析表中的横坐标
	protected String VNTI(){
		int Ni = 0 , Tj = 0;
		for(int i = 0 ; i < VN.length ; i++){
			if(VN[i].equals(X)){
				Ni = i;
			}
		}
		for(int j = 0 ; j < VT.length ; j++){
			if(VT[j].equals(a)){
				Tj = j;
			}
		}
		return analysisTable[Ni][Tj];
	}

	//判断M[A,a]={X->X1X2...Xk}
	//把X1X2...Xk推进栈
	//X1X2...Xk=ε,不推什么进栈
	protected boolean productionType(){
		if(VNTI() != ""){
			return true;
		}
		return false;
	}

	//推进stack栈
	protected void pushStack(){
		stack.pop();
		String M = VNTI();
		String ch;
		for(int i = (M.length() -1) ; i >= 0 ; i--){
			ch = String.valueOf(M.charAt(i));
			stack.push(ch);
		}
		System.out.printf("%-6d %-20s %6s %-1s->%-12s\n",(++count),stack.toString(),strToken.substring(cur, strToken.length()),X,M);
	}

	//总控程序
	protected void totalControlProgram(){
		while(flag == true){
			stackPeek();
			if(XisVT() == true){
				if(X.equals(a)){
					cur++;
					a = curCharacter();
					stack.pop();
					System.out.printf("%-6d %-20s %6s \n",(++count),stack.toString(),strToken.substring(cur, strToken.length()));
				}else{
					ERROR();
				}
			}else if(X.equals("#")){
				if(X.equals(a)){
					flag = false;
				}else{
					ERROR();
				}
			}else if(productionType() == true){
				if(VNTI().equals("synch")){
					ERROR();
				}else if(VNTI().equals("ε")){
					stack.pop();
					System.out.printf("%-6d %-20s %6s %-1s->%-12s\n",(++count),stack.toString(),strToken.substring(cur, strToken.length()),X,VNTI());
				}else{
					pushStack();
				}
			}else{
				ERROR();
			}
		}
	}

	//出现错误
	protected void ERROR(){
		System.out.println("输入串出现错误,无法进行分析");
		System.exit(0);
	}

	//打印存储分析表
	protected void printf(){
		if(flag == false){
			System.out.println("========分析成功");
		}else {
			System.out.println("========分析失败");
		}

	}

	public static void main(String[] args) {
		LL1 ll1 = new LL1();
		ll1.init();
		ll1.totalControlProgram();
		ll1.printf();
	}

}

测试数据1:i*i+i

测试结果1:

步骤        符号栈                                      输入串  所用产生式
0      [#, E]               i*i+i#
1      [#, Z, T]            i*i+i# E->TZ
2      [#, Z, Y, F]         i*i+i# T->FY
3      [#, Z, Y, i]         i*i+i# F->i
4      [#, Z, Y]             *i+i#
5      [#, Z, Y, F, *]       *i+i# Y->*FY
6      [#, Z, Y, F]           i+i#
7      [#, Z, Y, i]           i+i# F->i
8      [#, Z, Y]               +i#
9      [#, Z]                  +i# Y->ε
10     [#, Z, T, +]            +i# Z->+TZ
11     [#, Z, T]                i#
12     [#, Z, Y, F]             i# T->FY
13     [#, Z, Y, i]             i# F->i
14     [#, Z, Y]                 #
15     [#, Z]                    # Y->ε
16     [#]                       # Z->ε
========分析成功

测试数据2:)i*+i

测试结果2:

步骤        符号栈                                      输入串  所用产生式
0      [#, E]               )i*+i#
输入串出现错误,无法进行分析
时间: 2024-10-12 07:50:13

编译原理语法分析实验(Java实现)的相关文章

学了编译原理能否用 Java 写一个编译器或解释器?

16 个回答 默认排序? RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和解释器.其实用什么语言来实现编译器并不是最重要的部分(虽然Java也不是实现编译器最方便的语言),最初用啥语言都可以. 我在大学的时候,我们的软件工程和计算机科学的编译原理课的作业好像都是可以用Java来写的.反正我印象中我给这两门课写的作业都是用的Java. ===================

编译原理的实验报告一

实验一 词法分析程序实验 专业 商软2班   姓名 黄仲浩  学号 201506110166 一. 实验目的      编制一个词法分析程序. 二. 实验内容和要求 输入:源程序字符串 输出:二元组(种别,单词符号本身). 三. 实验方法.步骤及结果测试 源程序名:bianyiyuanli.c 可执行程序名:bianyiyuanli.exe 原理分析及流程图 通过一些for循环和while循环进行一个个的翻译. 源程序如下: #include<stdio.h> #include<stri

哈工大2015秋 编译原理课程实验1:词法分析

经过一年的C#的历练,确实算是挺喜欢C#的了,这次的编译原理尤为用心.既已提交作业,便拿出来共享一下,或许某学弟学妹能看到呢[偷笑]. 图1 项目资源管理器截图 工程: | Class.cs 主要是Record ErrorRecord Data类的定义,存储词法分析的结果 | Form1.cs WinForm窗体 | Program.cs 自动生成的主程序 | test.cs 主要参与运算的类,通过字符的判断将分析结果及错误提示存储到Data类 运行截图: 图2 运行截图 保存文件: 图3 项目

编译原理--词法分析--实验报告(此文章在管理-发表文章 里也有)

实验一.词法分析实验 专业:信息技术与工程学院   姓名:吕军  学号:201506110159    一.        实验目的   目的:主要是为了编辑一个词法分析程序.了解计算机的识别源程序字符串的过程. 二.        实验内容和要求   实验内容:通过了解 各种单词符号对应的种别码表,编写一个简单的词法分析程序,通过计算机识别字符串,反映其中的单词符号和所对应的种别码. 实验要求:用户输入源程序字符串,输出:二元组(种别,单词本身) 三.        实验方法.步骤及结果测试

编译原理 - 语法分析(1): 自上而下的语法分析

为什么我们不用词法分析那一套方式(正则文法.有限状态机等)来解决语法分析? 正则文法通常什么样? 对于文法G=(V, T, S, P),如果产生式的形式如下: A -> xBA -> x 其中A, B属于V,x属于T*,则称为右线性文法:相似的,如果产生式的形式如下: A -> BxA -> x 则称为左线性文法.右线性文法和左线性文法统称为正则文法. 例子: G(S): S->aS|bS S->aA A->aB|bB B->a|b 上下文无关文法通常什么样

读龙书学编译原理 语法分析(12)...

那么最后我就来看看这个所谓的lr(0)分析表生成算法 : 这个算法乍一看好像又和前面脱节了, 但是如果仔细看之前的讲解, 比如下图, 仔细比较, 感受一下 ... 你会发现 : 每次产生的D其实就相当于是一个新的状态, 那么再看一下closure 和 goto的具体实现 : 不难发现closure其实就是把所有原推导式左侧点的右侧的非终结符(也就是即将探索的第一个非终结符)的推导式全部加入这个集合, 那么为什么要这样做呢 ? 因为这个算法是并行的, 比如上图, 在执行推导式0的时候, 他需要先完

读龙书学编译原理 语法分析(1)...

首先我们来分析一下语法分析器的任务 : 将由词法分析器返回的Tokens(记号流)经过检查和处理生成根据规定的语法规则来生成抽象语法树... 最终大概是这样 (两个输入 一个输出): 然后是语法树, 大概是这样 : 那么接下来看看在这一阶段所需要学习的内容 : 大概就是这样...

读龙书学编译原理 语法分析(6)...

这两天都没更, 主要是马上要连着要考三门(16, 18, 20), 都没时间学编译器了, 等过了这段时间应该能有很多时间来搞这个, 之后我准备先把之前写的那个词法分析器生成器改造一下, 弄个最简版的正则引擎出来玩玩, 不过这些都是后话了, 今天似乎也没什么时间, 也就把这单元的作业写了一下... 代码比较简单就不多做解释了... 1 #include <ctype.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 voi

读龙书学编译原理 语法分析(15)...

到这里词法分析模块就接近尾声了, 下面对词法分析模块进行总结 : 递归下降本质上也算是自顶向下的分析算法, 适合手工编码, 它相对来说更加灵活, 能够对于特定的DSL进行更加灵活的处理优化, 但是相对来说比较慢.而自动生成器则恰好相反, 接下来是一个LR(1)语法生成器的实例 -- YACC. 首先这是yacc所需的源文件的结构, 通过输入这个文件yacc能为我们生成实际的语法分析器的代码... 由图中可以看出该文件分为三个部分, 下面是实例代码 : 1 %{ 2 #include <stdio