Java实现LL1文法的判别器,实现计算FIRST集、FOLLOW集、SELECT集

这篇博客介绍了如何用Java实现LL1文法的判定器,包括计算FIRST集合、FOLLOW集合和SELECT集合的详细步骤。通过递归方法处理文法规则,判断给定文法是否为LL1类型。文章提供了完整的代码实现,并链接到GitHub上的实验项目。
摘要由CSDN通过智能技术生成

写在前面

编译原理课程的实验,实现 pl0 的LL1文法判别。

git地址为:https://github.com/HiHaker/PL0-compiler

LL1文法的判定

需要编写一个程序,判定一个给定的文法是不是LL1文法的,重点在于实现文法的机内表示以及判定算法

关于文法的机内表示,终结符号集和非终结符号集可以用Set<String>来表示,为什么不使用 Character类呢?,主要考虑到一些符号是形如E'这样的,产生试集合可以使用一种数据结构,映射,一个左部对应一个右部列表,Map<String, String[]>

首先定义好一些成员变量:

// 存储文法的映射(产生式规则集合)
private Map<String, String[]> P;
// 文法的开始符号
private String start;
// 非终结符号集
private Set<String> nonEndChars;
// 终结符号集
private Set<String> endChars;

// FIRST集合
private Map<String, Set<String>> FIRST;
// FOLLOW集合
private Map<String, Set<String>> FOLLOW;
// SELECT集合
private Map<String, Set<String>> SELECT;

读取文法并且存储入映射:

    // 存储文法
private void storeGrammar(String[] Vn, String[] Vt, String[] P, String start){
   

        this.nonEndChars = new HashSet<>();
        this.endChars = new HashSet<>();
        this.start = start;
        this.P = new HashMap<>();

        try{
   
            // 存储产生式
            for (String value : P) {
   
                // 分割左部、右部
                String[] split1 = value.split("->");
                // 分割右部的不同产生式
                String[] split2 = split1[1].split("\\|");
                this.P.put(split1[0], split2);
            }

            // 存储符号集
            Collections.addAll(nonEndChars, Vn);
            Collections.addAll(endChars, Vt);
        } catch (Exception e){
   
            System.out.println("输入文法有错误!");
            e.printStackTrace();
        }
    }
计算FIRST集合

对于FIRST(x)集合,按照以下的处理方式计算:

  • 如果x是终结符,FIRST(x){x}
  • 如果x是空串,FIRST(x){空串}
  • 如果x是非终结符,x->Y1Y2Y3...,逐步地从Y1计算起,如果Y1的FIRST集包含空串,将FIRST(Y1)-空串加入到FIRST(X),继续计算FIRST(Y2),… ,如果计算到某个符号Yn不包含空串,就结束计算。如果计算到最后一个符号也包含空串,也就是说Y1Y2Y3...->空串,则加入最后一个符号的FIRST集。

从以上处理方式我们看出,需要递归地进行处理,先写一个方法,递归的求出某符号的FIRST集:

// 递归地计算某符号的FIRST
    private Set<String> FIRSTx(String x){
   

        Set<String> first = new HashSet<>();

        // 如果x是终结符,FIRST集就是它本身
        // 这里,空串也包含在终结符号里
        if (endChars.contains(x)){
   
            first.add(x);
            return first;
        } else {
   
            // 否则,就等于其右部各个符号的FIRST集相加
            String[] rightItems = P.get(x);
            // 遍历每一个右部
            for 
  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值