LL(1)分析器的Java实现

1. 基本思路

1.       从外部文件读入文法规则;

2.       分析是否存在左递归,如果存在则消除之;

3.       求取每个候选式的FIRST集;

4.       求各非终结符的FOLLOW集;

5.       根据LL(1)文法的3个判定条件判断其是否是LL(1)文法;

6.       如果是LL(1)文法就构造分析表,并判断输入的句子是否是该文法的句子。

 

2. 类设计

依照基本思路,每一项都用一个类来实现,再都多一个共用的存储文法规则的类。一共7个类,主要功能如下:

2.1 LL1类

入口类,一个main函数和一个无实参构造函数。构造函数实现读入文法规则的功能,并将每一行文法规则送Language类存储,最后调用LL1Help类对象,将控制权转给LL1Help类对象。

2.1.1 属性

private BufferedReader buffer;
private Language language;
private LL1Help ll1Help;

2.1.2 方法

public LL1()
public static void main(String[] args)

2.2 LL1Help类

辅助类,通过displayMessage方法控制程序的输入和输出。

2.2.1 属性

private Language language;
private LeftRecursive leftRecursive;
private FirstCollection firstCollection;
private FollowCollectionfollowCollection;
private AnalysisTable analysisTable;

2.2.2 方法

public LL1Help(Languagelanguage)
public void displayMessage()    //控制程序的输入和输出
public boolean isLL_1()     //判断输入的文法是否是LL(1)文法
privateSet<String> getMixed(List<Set<String>> sets)
                            // 得到多个集合的交集,用于判断LL(1)文法
private StringdisplaySet(Set<String> elementSet)
                            // 辅助集合的输出,如{a, b, c, d}

2.3 Language类

存储文法规则。由于它存储了文法,其他类都会用到Language类对象,Language类也定义了很多用于处理文法、语句的方法,供其他类调用。其中,很多方法都是基于可扩展的考虑。由于用例都是单个英文字母表示,没有用真实语言中的单词、语句这些来表示,所以为了今后的可扩展,预留了这些方法。

2.3.1 属性

public static String EmptyCharactor= "?";    //"?"表示“空”
private String startCharactor;            // 开始字符
private boolean startSwitch= true;           // 辅助记录开始字符
privateLinkedHashMap<String, List<String>> grammar;
       // 存储文法规则的LinkedHashMap,键--非终结字符,值--候选式(列表)
privateHashSet<String> terminalSet;          // 终端字符集

2.3.2 方法

public Language()
public boolean addProduction(String sentence) // 给定一条语句添加文法
public void changeProduction(String nonTerminal,
List<String>rightParts) // 按产生式的左右两部分修改文法规则
public void removeProduction(String nonTerminal)
// 删除非终端字符参数所在的产生式
publicSet<String> getNonTerminalSet()        // 返回非终端字符集
publicSet<String> getTerminalSet()               // 返回终端字符集
publicList<String> getRightPartsOfProduction(String nonTerminal)
                         // 返回产生式的右部,即各候选式
public boolean isTerminal(String charactor)       // 判断是否是终端字符
public void displayLanguage()                     // 输出文法规则
public StringgetStartCharactor()             // 返回开始字符
public StringgetFirstWord(String sentence)   // 返回候选式的首字符
public StringgetLastWord(String sentence)        // 返回候选式的末字符
publicList<String> getEachWord(String sentence)// 返回候选式的每个字符

2.4 LeftRecursive类

处理左递归。没有单独的去判断文法是否存在左递归,而是在消除左递归的过程中间接判断是否存在左递归。

2.4.1 属性

private Language language;
public boolean doneRemove;             // 标记是否存在左递归

2.4.2 方法

publicLeftRecursive(Language language)
private void removeLeftRecursive()     // 消除文法中的左递归
private boolean removeDirectLeftRecursive(String nonTerminal,
           List<String> newRightParts, Map<String,String> mapping)
                                       // 消除直接左递归
private StringgetNewNonTerminal()     // 得到一个新的非终结字符
private void removeUnnecessary()          // 清除多余的产生式

2.5 FirstCollection类

处理FIRST集。主要是一个计算每个非终端字符FIRST集的setFirst方法和一个返回查询字符串的FIRST集的getFirst方法。

2.5.1 属性

private Language language;
private final Map<String, Set<String>> firstCollection;
// 存储各非终端字符的FIRST集,键--非终端字符,值--其FIRST集的字符集合

2.5.2 方法

publicFirstCollection(Language language)
private void initFirstCollection() /* 初始化FIRST集,就是给每个非终端字符调用setFirst方法,并将返回的集合保存到实例变量firstCollection */
privateSet<String> setFirst(String word) // 求非终端字符的FIRST集
publicSet<String> getFirst(String sentence)
// 返回查询字符串的FIRST集

2.6 FollowCollection类

处理FOLLOW集。其结构和FirstCollection类相同。

2.6.1 属性

private Language language;
private FirstCollection firstCollection;
private final Map<String, Set<String>> followCollection;
// 存储各非终端字符的FOLLOW集,键--非终端字符,值--其FOLLOW集的字符集合

2.6.2 方法

publicFollowCollection(Language language,
FirstCollectionfirstCollection)
private void initFollowCollection()
privateSet<String> setFollow(String nonTerminal, String from)
// 注意这里有个from参数,是为了防止无限的递归调用
publicSet<String> getFollow(String nonTerminal)

2.7 AnalysisTable类

存储LL(1)文法分析表,由此实现LL(1)分析器。

2.7.1 属性

private Language language;
private FirstCollection firstCollection;
private FollowCollectionfollowCollection;
private Map<String,Map<String, String>> table;
       // LL(1)文法分析表,键--非终端字符,值--终端字符以及对应的候选式
publicSet<String> columnSet;
// LL(1)文法分析表的终端字符和句子终结符“#”
privateStack<String> workStack = new Stack<String>();
                         // LL(1)分析器的分析栈
privateStack<String> inputStack = new Stack<String>();
                          // 对读入的句子,也存在一个栈中

2.7.2 方法

publicAnalysisTable(Language language, FirstCollection
firstCollection, FollowCollection followCollection)
private void initAnalysisTable()          // 得到LL(1)文法分析表
public void displayAnalysisTable()     // 输出LL(1)文法分析表
public boolean analyseSentence(String sentence)
           // 根据分析表分析输入的句子是否是该文法的句子,是的话返回true
private void displayStack(String option, Stringoutput)
                                       // 输出栈内容


源码+报告:DBank



评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值