【编译原理】非递归的预测分析法 JAVA实现

定义一个语法分析接口

public interface GrammarHandler {
    //用来代替空符
    char NULL_WORD_CHAR = '☯';
    String NULL_WORD_STR = "☯";
    /**
     * 添加文法规则
     * @param k 非终结符
     * @param s 规则
     */
    void addGrammar(char k, String s);

    /**
     * 输入语句验证是否符合文法规则
     * @param s 被验证语句
     * @return 成功返回true
     */
    boolean isMatch(String s);

    /**
     * 添加文法完毕后初始化才可验证语句
     * @param firstK 启始非终结符
     */
    void init(char firstK);
}

定义LL1语法分析实现类


import org.apache.commons.lang.StringUtils;

import java.util.*;

/**
 * @auther Buynow Zhao
 * @create 2017/11/12
 */
public class LL1Handler implements GrammarHandler{
    //文法map 存储文法 key为非终结符
    //用list储存该非终结符的所有规则
    private Map> grammarMap = new HashMap>();
    //选择集 map
    private Map> selectMap = new HashMap>();
    //标志位  是否初始化
    //未初始化不得开始验证语句
    private boolean isInit = false;
    //启始非终结符
    private Character firstK = null;


    @Override
    public void addGrammar(char k, String s) {
        if (!grammarMap.containsKey(k)) {
            grammarMap.put(k, new HashSet());
        }
        grammarMap.get(k).add(s);
    }

    @Override
    public boolean isMatch(String s) {
        Stack gStack = new Stack();
        Stack sStack = new Stack();
        //添加结尾标记
        gStack.push('#');
        sStack.push('#');
        //init gStack & sStack
        gStack.push(firstK);
        for (int i=s.length()-1;i>=0;i--) {
            sStack.push(s.charAt(i));
        }
        String s1 = null;
        //分析核心
        while (!(gStack.isEmpty()||sStack.isEmpty())) {
            while (!(gStack.isEmpty() || sStack.isEmpty()) 
                            && gStack.peek() == sStack.peek()) {
                gStack.pop();
                sStack.pop();
            }
            //通过表查询 获得对应文法规则
            if (gStack.isEmpty() || sStack.isEmpty()) {
                break;
            }
            s1 = null;
            if (selectMap.get(gStack.peek()) != null) {
                s1 = selectMap.get(gStack.pop()).get(sStack.peek());
            }
            if (s1 == null) {
                return false;
            }
            if (GrammarHandler.NULL_WORD_STR.equals(s1)) {
                continue;
            }
            for (int i=s1.length()-1;i>=0;i--) {
                gStack.push(s1.charAt(i));
            }

        }
        //分析成功
        if (sStack.isEmpty()&&gStack.isEmpty()){
            return true;
        }
        return false;
    }

    @Override
    public void init(char firstK) {
        if (this.isInit) {
            return;
        }
        this.firstK = firstK;
        //计算SELECT集
        getSelectMap();
        this.isInit = true;
    }

    private void getSelectMap() {
        //遍历非终结符
        for (Character k : grammarMap.keySet()) {
            select(k);
        }
    }
    //求select
    private void select(char k) {
        if (selectMap.containsKey(k)) {
            return;
        }
        selectMap.put(k, new HashMap());
        //遍历该终结符的所有规则
        for (String s : grammarMap.get(k)) {
            //空
            if (StringUtils.isEmpty(s)) {
                follow(k);
            }else{
                //select 集为 s的first
                selectMap.get(k).put(s.charAt(0),s);
            }
        }
    }
    //求follow
    private void follow(char k) {
        char[] charArr = null;
        for (Character k1 : grammarMap.keySet()) {
            for (String s : grammarMap.get(k1)) {
                charArr = s.toCharArray();
                for (int i=0;iif (charArr[i] == k) {
                        if (i == charArr.length - 1) {
                            selectMap.get(k).put('#',GrammarHandler.NULL_WORD_STR);
                            //后继为空
                        }else{
                            select(charArr[i+1]);
                            for (Character c : selectMap.get(charArr[i + 1]).keySet()) {
                                selectMap.get(k).put(c,GrammarHandler.NULL_WORD_STR);
                            }
                        }

                    }
                }
            }
        }
    }


    public static void main(String[] args) {
        //构造一个LL1文法分析器
        GrammarHandler handler = new LL1Handler();
        //添加文法规则
        handler.addGrammar('S',"dABA");//S->dABA
        handler.addGrammar('A',"");//A->NULL
        handler.addGrammar('A',"a");//A->a
        handler.addGrammar('B',"bb");//B->bb
        //初始化分析器 并设置启始非终结符
        handler.init('S');
        //待验证数组
        String[] sArr = new String[]{"dbb","dab","dabba"};
        //得出结果
        for (String s : sArr) {
            boolean result = handler.isMatch(s);
            System.out.println(s+":"+result);
        }
    }
}

运行演示

  • 测试的文法规则
    • S->dABA
    • A->NULL
    • A->a
    • B->bb
  • 添加规则到GrammarHandler
    • handler.addGrammar(‘S’,”dABA”);
    • handler.addGrammar(‘A’,”“);//A->NULL
    • handler.addGrammar(‘A’,”a”);//A->a
    • handler.addGrammar(‘B’,”bb”);//B->bb
  • 被测试的句子
    • String[] sArr = new String[]{“dbb”,”dab”,”dabba”};
  • 循环遍历数组中的句子验证是否符合
//得出结果
for (String s : sArr) {
    boolean result = handler.isMatch(s);
    System.out.println(s+":"+result);
}
  • 测试结果
    运行结果

你可能感兴趣的:(算法,java,编译原理)