项目的完整代码在 C2j-Compilerjava
这个系列算做为我本身在学习写一个编译器的过程的一些记录,算法之类的都没有记录原理性的东西,想知道原理的在龙书里都写得很是清楚,可是我本身一开始是不怎么看得下来,到如今都尚未完整的看完,它像是一本给已经有基础的人写的书。git
在parse包里一共有8个文件,就是语法分析阶段写的全部东西啦github
项目的完整代码在 C2j-Compiler算法
在上一篇说了,居然要验证句子正确与否,天然就须要语法,也就是给出相应的语法推导式数据结构
全部语法的初始化工做都在SyntaxProductionInit里完成工具
///EXT_DECL_LIST ->EXT_DECL_LIST COMMA EXT_DECL right = getProductionRight(new int[]{Token.EXT_DECL_LIST.ordinal(), Token.COMMA.ordinal(), Token.EXT_DECL.ordinal()}); production = new Production(productionNum, Token.EXT_DECL_LIST.ordinal(), 0, right); productionNum++; addProduction(production, false);
好比下面这个就对应C语言的变量声明语句的推导式,PROGRAM是整个推导式的开始符号,EXT_DEF_LIST就是声明列表,这里的EXT_DEF_LIST -> EXT_DEF_LIST EXT_DEF须要注意一下是左递归状况,LR语法是能够处理的,关于这个能够看以前的博文。学习
好比EXT_DECL_LIST -> EXT_DECL -> VAR_DECL 多个变量名称声明能够推导是一个变量名称声明或者多个变量名称声明 + 逗号 + 变量名称声明ui
VAR_DECL 则能够是一个标识符或者一个多重指针this
即一个从叶子节点不断的推导,读入终结符,最后推导到开始符号,且输入流也已经读完指针
/* * PROGRAM -> EXT_DEF_LIST * * EXT_DEF_LIST -> EXT_DEF_LIST EXT_DEF * * EXT_DEF -> OPT_SPECIFIERS EXT_DECL_LIST SEMI * | OPT_SPECIFIERS SEMI * * * EXT_DECL_LIST -> EXT_DECL * | EXT_DECL_LIST COMMA EXT_DECL * * EXT_DECL -> VAR_DECL * * OPT_SPECIFIERS -> CLASS TTYPE * | TTYPE * | SPECIFIERS * | EMPTY? * * SPECIFIERS -> TYPE_OR_CLASS * | SPECIFIERS TYPE_OR_CLASS * * * TYPE_OR_CLASS -> TYPE_SPECIFIER * | CLASS * * TYPE_SPECIFIER -> TYPE * * NEW_NAME -> NAME * * NAME_NT -> NAME * * VAR_DECL -> | NEW_NAME * * | START VAR_DECL * */
在语法推导式初始化的过程一共要构建三个数据结构
private HashMap<Integer, ArrayList<Production>> productionMap = new HashMap<>(); private HashMap<Integer, Symbols> symbolMap = new HashMap<>(); private ArrayList<Symbols> symbolArray = new ArrayList<>();
Symbol相似Production,也是用来表示产生式的,可是稍有点不一样,也还包括终结符,在后面也会有不一样的做用,
//Symbols public int value; public ArrayList<int[]> productions; public ArrayList<Integer> firstSet = new ArrayList<>(); public boolean isNullable;
若是一个非终结符,它能够推导出空集,那么这样的非终结符咱们称之为nullable的非终结符
在上一篇里说到验证语法的过程就是在一堆对应语法产生式中推导出答案,Production类就是来表示一个产生式
private int dotPos = 0; private int left; private ArrayList<Integer> right; private ArrayList<Integer> lookAhead = new ArrayList<>(); private int productionNum = -1; public Production(int productionNum, int left, int dot, ArrayList<Integer> right) { this.left = left; this.right = right; this.productionNum = productionNum; lookAhead.add(Token.SEMI.ordinal()); if (dot >= right.size()) { dot = right.size(); } this.dotPos = dot; }
这一篇主要介绍了几个数据结构,这几个数据结构都是以后构建有限状态自动机的基础。原本想把状态机的构建也写在这一篇,可是若是加上去以后,篇幅太长,加一部分会感受不成模块,有点分散,因此自动机的构建就写在下一篇。
另外个人github博客:https://dejavudwh.cn/