在上一篇文章中,我们已经得到了LL(1)文法,现在,我们使用java编写递归向下的语法分析程序开建立语法分析树。
当一个文法满足LL(1)条件时,我们就可以为它构造一不带回溯的自上而下的分析程序,这个分析程序时由一组递归过程组成的,每个过程对应文法的一个非终结符。
程序实现代码:
Main
public class Main {
public static void main(String[] args) {
Parser par = new Parser();
Node root;
root=par.parseTree();
root.treePrint();
}
}
Node
import java.util.LinkedList;
public class Node
{
public Token tok;
private LinkedList<Node> cldList = new LinkedList<Node>();
public Node(Token tok)
{ this.tok = tok; }//leaf
public void addCld(Node nd)
{
cldList.add(nd);
}
public void treePrint()
{
treePrintLevel(this, 0);
return;
}
private void treePrintLevel(Node nd, int level)
{
int i;
if(nd!=null) //root
{
for(i=0;i<4*level;i++)
System.out.print("-");
nd.tok.emitToken();
}
if(nd.cldList.isEmpty()==false) //recursive
{
for (Node currNd: nd.cldList) {
treePrintLevel(currNd, level+1);
}
}
}
}
Parser
public class Parser
{
private Scanner scnr;
private Token currentToken;
public Parser()
{
scnr = new Scanner();
}
public Node parseTree(){
Node root;
currentToken=scnr.getNextToken();
root=program();
if(currentToken.matchToken(Tag.END))
return root;
else
{
System.out.println("syntax error: line " + scnr.line); //error
System.exit(-1);
}
return null;
}
private Node program()
{
Node nProg=new Node(new Token(Tag.PRO));
Node nBlock=block();
nProg.addCld(nBlock);
return nProg;
}
private Node block()
{
Node nLB, nDecls, nStmts, nRB, nBlock;
nBlock=new Node(new Token(Tag.BLO));
if(currentToken.matchToken(Tag.LB))
{
nLB=new Node(currentToken);
currentToken=scnr.getNextToken();
nDecls=decls();
nStmts=stmts();
if(currentToken.matchToken(Tag.RB))
{
nRB=new Node(currentToken);
currentToken=scnr.getNextToken();
nBlock.addCld(nLB);
nBlock.addCld(nDecls);
nBlock.addCld(nStmts);
nBlock.addCld(nRB);
return nBlock;
}
else
{
System.out.println("expecting }, unmatched: line " + scnr.line); //error
System.exit(-1);
}
}
else
{
System.out.println("expecting {, unmatched: line " + scnr.line); //error
System.exit(-1);
}
return null;
}
private Node decls()
{
Node nDecls, nDecl, nDeclsCld, nEps;
nDecls=new Node(new Token(Tag.DECLS));
if(currentToken.matchToken(Tag.INT) || currentToken.matchToken(Tag.BOOL))
{
nDecl=decl();
nDeclsCld=decls();
nDecls.addCld(nDecl);
nDecls.addCld(nDeclsCld);
return nDecls;
}
else
{
nEps=new Node(new Token(Tag.EPS));
nDecls.addCld(nEps);
return nDecls;
}
}
private Node decl()
{
Node nDecl, nType, nId, nSc;
nDecl=new Node(new Token(Tag.DECL));
if(currentToken.matchToken(Tag.INT) || currentToken.matchToken(Tag.BOOL))
{
nType=type();
if(currentToken.matchToken(Tag.ID))
{
nId=new Node(currentToken);
currentToken=scnr.getNextToken();
if(currentToken.matchToken(Tag.SC))
{
nSc=new Node(currentToken);
currentToken=scnr.getNextToken();
nDecl.addCld(nType);
nDecl.addCld(nId);
nDecl.addCld(nSc);
return nDecl;
}
else
{
System.out.println("expecting ;, unmatched: line " + scnr.line); //error
System.exit(-1);
}
}
else
{
System.out.println("expecting identifier, unmatched: line " + scnr.line); //error
System.exit(-1);
}
}
else
{
System.out.println("expecting type int or bool, unmatched: line " + scnr.line); //error
System.exit(-1);
}
return null;
}
private Node type()
{
Node nType, nBasic, nTypep;
nType = new Node(new Token(Tag.TYP));
if(currentToken.matchToken(Tag.INT) || currentToken.matchToken(Tag.BOOL))
{
nBasic=basic();
nTypep=typep();
nType.addCld(nBasic);
nType.addCld(nTypep);
return nType;
}
else
{
System.out.println("expecting type int or bool, unmatched: line " + scnr.line); //error
System.exit(-1);
}
return null;
}
private Node typep()
{
Node nTypep, nLsb, nNum, nRsb, nTypepCld, nEps;
nTypep=new Node(new Token(Tag.TYPP));
if(currentToken.matchToken(Tag.LSB))
{
nLsb=new Node(currentToken);
currentToken=scnr.getNextToken();
if(currentToken.matchToken(Tag.NUM))
{
nNum=new Node(currentToken);
currentToken=scnr.getNextToken();
if(currentToken.matchToken(Tag.RSB))
{
currentToken=scnr.getNextToken();
nRsb=new Node(currentToken);
nTypepCld=typep();
nTypep.addCld(nLsb);
nTypep.addCld(nNum);
nTypep.addCld(nRsb);
nTypep.addCld(nTypepCld);
return nTypep;
}
else
{
System.out.println("expecting ], unmatched: line " + scnr.line); //error
System.exit(-1);
}
}
else
{
System.out.println("expecting integer number, unmatched: line " + scnr.line); //error
System.exit(-1);
}
return null;
}
else
{
nEps=new Node(new Token(Tag.EPS));
nTypep.addCld(nEps);
return nTypep;
}
}
private Node basic()
{
Node nBasic;
nBasic = new Node(new Token(Tag.BASIC));
if(currentToken.matchToken(Tag.INT) || currentToken.matchToken(Tag.BOOL))
{
nBasic.addCld(new Node(currentToken));
currentToken=scnr.getNextToken();
return nBasic;
}
else
{
System.out.println("expecting type int or bool, unmatched: line " + scnr.line); //error
System.exit(-1);
}
return null;
}
private Node stmts()
{
Node nStmts, nStmt, nStmtsCld, nEps;
nStmts=new Node(new Token(Tag.STMTS));
if(currentToken.matchToken(Tag.IF) ||
currentToken.matchToken(Tag.WHILE) ||
currentToken.matchToken(Tag.DO) ||
currentToken.matchToken(Tag.