LL(1)分析器的Java实现

来源:互联网 发布:优化设计吧 编辑:程序博客网 时间:2024/06/07 02:18

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, FirstCollectionfirstCollection, FollowCollection followCollection)private void initAnalysisTable()          // 得到LL(1)文法分析表public void displayAnalysisTable()     // 输出LL(1)文法分析表public boolean analyseSentence(String sentence)           // 根据分析表分析输入的句子是否是该文法的句子,是的话返回trueprivate void displayStack(String option, Stringoutput)                                       // 输出栈内容


源码+报告:DBank