编译原理递归下降实现语法分析 JAVA实现

目的:熟练掌握自上而下的语法分析方法,并能用程序实现。

 

FIRST(E) = FIRST(T) = FIRST(F) = { ( , id }

FIRST(E ') = {+, e}

FRIST(T ') = {*, e}

FOLLOW(E) = FOLLOW(E ') = { ), $}

FOLLOW(T) = FOLLOW (T ') = { +, ), $}

FOLLOW(F) = {+, *, ), $}

要求

1. 使用的文法如下:

E -> TE '

   E '-> + TE ' | e

      T ->FT '

      T '-> * FT '| e

      F -> (E) | id

2. 对于任意给定的输入串(词法记号流)进行语法分析,递归下降方法实现。

3. 要有一定的错误处理功能。即对错误能提示,并且能在一定程度上忽略尽量少的记号来进行接下来的分析。可以参考书上介绍的同步记号集合来处理。

可能的出错情况:idid*id,  id**id,  (id+id, +id*+id ……

4. 输入串以#结尾,输出推导过程中使用到的产生式。例如:

   输入:id+id*id#

   输出:E -> TE '

         T -> FT '

F -> id

E '->+ TE '

T -> FT '

         ……

有余力的同学可进一步考虑如下扩展:

  1. 在语法分析的过程中调用词法分析的上机结果,即利用词法分析器来返回一个记号给语法分析器。
  2. 调用求first集合函数。
  3. 编写Follow函数,实现其求解过程。
import java.util.Scanner;

public class Test  {

	private static String Str = null; // 输入的表达式
	private static String lookahead = null;// 当前记号
	private static String Sub = null;// 剩余的子串
	//private static boolean flag = false;

	public static void match(String s) {
		if (lookahead.equals(s)) {

			lookahead = nextToken();
			System.out.println("匹配" + s);
		} else {
			error();
		}

	}

	public static void error() {
		System.out.println("匹配失败");

	}

	public static String nextToken() {
		if (Sub.length() >= 2) {
			if (Sub.substring(0, 2).equals("id")) {
				Sub = Sub.substring(2, Sub.length());
				lookahead = "id";
			} else {
				lookahead = Sub.substring(0, 1);
				Sub = Sub.substring(1, Sub.length());
			}
		} else if (Sub.length() == 1) {
			lookahead = Sub.substring(0, 1);
		}
		return lookahead;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner in = new Scanner(System.in);
		System.out.println("请输入一个表达式:");
		Str = in.nextLine();
		Sub = Str;
		lookahead = nextToken();
		in.close();
		E();
	}

	public static void E() {
		if (lookahead.equals("(") || lookahead.equals("id"))// First(T)={(,id};
		{
			System.out.println("E -> TE'");
			T();
			E1();
		} else if (lookahead.equals(")") || lookahead.equals("#"))// Follow(E')加入到E的同步记号集合中
		{
			error();
			// 出错,但不作任何处理
		} else {
			lookahead = nextToken();
			error();
			E();
		}
	}

	public static void E1() {
		if (lookahead.equals("+")) {
			System.out.println("E1 -> TE'");
			match("+");
			T();
			E1();
		} else if (lookahead.equals(")") || lookahead.equals("#"))
		// Follow(E') = { ) , # };
		{
			System.out.println("E' -> ^");
			if (lookahead.equals("#"))
				{match("#");System.exit(0);}

		} else// 出错,当前记号不在E'的同步记号集合中,跳过当前符号
		{
			error();
			lookahead = nextToken();
			E1();
		}
	}

	public static void T() {
		if (lookahead.equals("(") || lookahead.equals("id"))// First(F)={ ( , id };
		{
			System.out.println("T -> FT'");
			F();
			T1();
		} else if (lookahead.equals("+") || lookahead.equals(")") || lookahead.equals("#"))
		// Follow(T)加入到T的同步记号集合中
		{
			error();
			if (lookahead.equals("#")) {
				match("#");
				System.exit(0);
			}
			// 出错,但无需跳过任何记号,跳过T即可,即不做任何处理
		} else {
			// 出错,当前记号不在T的同步记号集合中,跳过当前记号
			error();
			lookahead = nextToken();
			T();
		}
	}

	public static void T1() {

		if (lookahead.equals("*")) {
			System.out.println("T' -> *FT'");
			match("*");
			F();
			T1();
		} else if (lookahead.equals("+") || lookahead.equals(")") || lookahead.equals("#")) {
			System.out.println("T' -> ^");
			if (lookahead.equals("#")) {
				match("#");
				System.exit(0);
			}
		} else// 出错,当前记号不在T1的同步记号集合中,跳过当前记号
		{
			error();
			lookahead = nextToken();
			T1();
		}
	}

	public static void F() {

		if (lookahead.equals("(")) {
			match("(");
			E();
			match(")");
			System.out.println("F -> (E)");
		} else if (lookahead.equals("id")) {
			System.out.println("F -> id");
			match("id");
		} else if (lookahead.equals("+") || lookahead.equals("*") || lookahead.equals(")") || lookahead.equals("#"))
		// Follow(F)集合加入到F的同步记号集合中
		{
			error();
			// 出错,但无须跳过任何记号,跳过 F 即可,即不作任何处理
		} else// 出错,当前记号不在F的同步记号集合中,跳过当前符号
		{
			error();
			lookahead = nextToken();
			F();
		}
	}

}

运行结果如下:

 

2、输入有错误的情况:

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值