llvmir some opt

This commit is contained in:
邓智航
2025-12-10 17:58:17 +08:00
commit 84827838e2
103 changed files with 5838 additions and 0 deletions

BIN
frontend/.DS_Store vendored Normal file

Binary file not shown.

BIN
frontend/ast/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,63 @@
package frontend.ast;
import java.util.ArrayList;
import error.Errors;
import frontend.ast.decl.Decl;
import frontend.ast.func.FuncDef;
import frontend.ast.func.MainFuncDef;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
public class CompUnit extends Node {
public CompUnit(TokenStream ts) {
super(SyntaxType.COMP_UNIT, ts);
}
public void parse(Errors errors) {
while (getCurrToken() != null) {
if (this.ts.peek(1).getType() == TokenType.MAINTK) {
MainFuncDef mainFuncDef = new MainFuncDef(this.ts);
mainFuncDef.parse(errors);
addChild(mainFuncDef);
} else if (this.ts.peek(2).getType() == TokenType.LPARENT) {
FuncDef funcdef = new FuncDef(this.ts);
funcdef.parse(errors);
addChild(funcdef);
} else {
Decl decl = new Decl(this.ts);
decl.parse(errors);
addChild(decl);
}
}
}
public ArrayList<Decl> GetDecls() {
ArrayList<Decl> decls = new ArrayList<Decl>();
for (int i = 0; i < this.getChildren().size(); i++) {
if (this.getChild(i) instanceof Decl) {
decls.add((Decl) this.getChild(i));
}
}
return decls;
}
public ArrayList<FuncDef> GetFuncDefs() {
ArrayList<FuncDef> funcDefs = new ArrayList<FuncDef>();
for (int i = 0; i < this.getChildren().size(); i++) {
if (this.getChild(i) instanceof FuncDef) {
funcDefs.add((FuncDef) this.getChild(i));
}
}
return funcDefs;
}
public MainFuncDef GetMainFuncDef() {
for (int i = 0; i < this.getChildren().size(); i++) {
if (this.getChild(i) instanceof MainFuncDef) {
return (MainFuncDef) this.getChild(i);
}
}
return null;
}
}

248
frontend/ast/Node.java Normal file
View File

@@ -0,0 +1,248 @@
package frontend.ast;
import frontend.ast.decl.Decl;
import frontend.ast.func.MainFuncDef;
import frontend.lexer.Token;
import frontend.lexer.TokenStream;
import frontend.ast.block.BlockItem;
import frontend.ast.block.ForStmt;
import frontend.ast.block.Block;
import frontend.ast.decl.ConstDecl;
import frontend.ast.decl.ConstDef;
import frontend.ast.decl.VarDef;
import frontend.ast.exp.UnaryExp;
import frontend.ast.func.FuncDef;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenType;
import frontend.ast.exp.LVal;
import frontend.ast.block.Stmt;
import frontend.ast.exp.Exp;
import error.Errors;
import error.Error;
import error.ErrorType;
import midend.symbol.FuncSymbol;
import midend.symbol.SymbolManager;
import midend.symbol.SymbolType;
import midend.symbol.Symbol;
import java.util.ArrayList;
import java.util.HashMap;
public class Node {
private SyntaxType type;
private ArrayList<Node> children;
protected TokenStream ts;
public Node(SyntaxType type, TokenStream ts) {
this.type = type;
this.ts = ts;
this.children = new ArrayList<>();
}
public void addChild(Node child) {
this.children.add(child);
}
public String toString() {
return "<" + type.toString() + ">\n";
}
public Token getCurrToken() {
return ts.peek(0);
} // not change index in ts
public Token read() {
return ts.read();
} // change index in ts
public String getInfo() {
String info = "";
for (Node child : children) {
info += child.getInfo();
}
if (!(this instanceof Decl || this instanceof BlockItem)) {
info += this.toString();
}
return info;
}
public ArrayList<Node> getChildren() {
return children;
}
public Node getChild(int index) {
return children.get(index);
}
public void fillSymbolTable(boolean isInFunc,
boolean isInFor, Errors errors) {
if (this instanceof CompUnit || (this instanceof Block && !isInFunc)) {
SymbolManager.addSymbolTable();
}
if (this instanceof Decl) {
handleDecl(errors);
}
if (this instanceof FuncDef) {
handleFuncDef(errors);
return;
}
if (this instanceof UnaryExp && children.get(0) instanceof TokenNode) {
handleFuncCall(errors);
return;
}
if (this instanceof Stmt && getChild(0) instanceof TokenNode
&& ((TokenNode) getChild(0)).getType() == TokenType.FORTK) {
for (Node child: children) {
child.fillSymbolTable(false, true, errors);
}
return;
}
if (this instanceof Stmt && getChild(0) instanceof TokenNode
&& (((TokenNode) getChild(0)).getType() == TokenType.BREAKTK
|| ((TokenNode) getChild(0)).getType() == TokenType.CONTINUETK)) {
if (!isInFor) {
errors.addError(new Error(((TokenNode) getChild(0)).getLine(), ErrorType.m));
}
}
if (this instanceof TokenNode) {
handleTokenNode(errors);
}
if (this instanceof Stmt && getChild(0) instanceof LVal) { // error handle
handleErrorhInStmt(errors);
}
if (this instanceof ForStmt) {
handleErrorhInStmt(errors);
}
if (this instanceof Stmt && getChild(0) instanceof TokenNode
&& ((TokenNode) getChild(0)).getType() == TokenType.PRINTFTK) {
handleMatchFormat(errors);
}
if (this instanceof MainFuncDef) {
((MainFuncDef) this).checkReturnNode(errors);
}
for (Node child : children) {
child.fillSymbolTable(false, isInFor, errors);
}
if (this instanceof CompUnit || this instanceof Block) {
SymbolManager.releaseSymbolTable();
// System.out.println("release a symbol table");
}
// !注意哪些是直接return的这些直接return的是否处理完整因为他们直接省略了后续的递归要么在子方法里重新递归了要么没有递归的必要仔细检查
}
public void handleDecl(Errors errors) {
if (this.children.get(0) instanceof ConstDecl) {
Node constdecl = this.children.get(0);
for (int i = 2; i < constdecl.children.size(); i = i + 2) {
SymbolManager.addSymbol(((ConstDef) constdecl.children.get(i)).getSymbol(), errors);
}
} else {
Node vardecl = this.children.get(0);
if (((TokenNode) vardecl.children.get(0)).getType() == TokenType.STATICTK) {
for (int i = 2; i < vardecl.children.size(); i = i + 2) {
SymbolManager.addSymbol(
((VarDef) vardecl.children.get(i)).getSymbol(1), errors);
// System.out.println(((VarDef)
// vardecl.children.get(i)).getSymbol(1).toString());
}
} else {
for (int i = 1; i < vardecl.children.size(); i = i + 2) {
SymbolManager.addSymbol(
((VarDef) vardecl.children.get(i)).getSymbol(0), errors);
// System.out.println(((VarDef)
// vardecl.children.get(i)).getSymbol(0).toString());
}
}
}
}
public void handleFuncDef(Errors errors) {
FuncDef funcdef = (FuncDef) this;
Symbol funcSymbol = funcdef.getSymbol();
// System.out.println(funcSymbol.toString());
// System.out.println(SymbolManager.getSymbolTableSize());
SymbolManager.addSymbol(funcSymbol, errors);
SymbolManager.addSymbolTable();
funcdef.addParamSymbol(funcSymbol, errors);
if (funcSymbol.getType() == SymbolType.VOID_FUNC) {
// int returnStatus = funcdef.getReturnStatus();
// TokenNode returnNode = funcdef.getReturnNode();
HashMap<TokenNode, Integer> returnNodes = new HashMap<>();
funcdef.getReturnNodes(returnNodes);
for (TokenNode returnNode : returnNodes.keySet()) {
if (returnNodes.get(returnNode) == 2) {
errors.addError(new Error(returnNode.getLine(), ErrorType.f));
}
}
} else if (funcSymbol.getType() == SymbolType.INT_FUNC) {
funcdef.checkReturnNode(errors);
}
// 填参数和块里定义的参数,一个问题是这时的释放是该如何判断
for (Node child : children) {
if (child instanceof Block) {
((Block) child).fillSymbolTable(true, false, errors);
}
}
}
public void handleTokenNode(Errors errors) {
TokenNode tokenNode = (TokenNode) this;
if (tokenNode.getType() == TokenType.IDENFR && !tokenNode.getName().equals("getint")) {
Symbol symbol = SymbolManager.getSymbol(tokenNode.getName());
if (symbol == null) {
errors.addError(new Error(tokenNode.getLine(), ErrorType.c));
}
}
}
public void handleFuncCall(Errors errors) {
UnaryExp ue = (UnaryExp) this;
ue.handleFuncCall(errors);
}
public void getReturnNodes(HashMap<TokenNode, Integer> returnNodess) { // 0: no return, 1: return void, 2: return int
for (int i = 0; i < children.size(); i++) {
if (getChild(i) instanceof TokenNode &&
((TokenNode) getChild(i)).getType() == TokenType.RETURNTK) {
if (i == children.size() - 1) {
returnNodess.put((TokenNode) getChild(i), 1);
}else if (getChild(i+1) instanceof TokenNode) {
returnNodess.put((TokenNode) getChild(i), 1);
}else {
returnNodess.put((TokenNode) getChild(i), 2);
}
} else if (!(getChild(i) instanceof TokenNode)) {
getChild(i).getReturnNodes(returnNodess);
}
}
}
public void handleErrorhInStmt(Errors errors) {
for (int i = 0; 4 * i < children.size(); i++){
TokenNode idenfr = (TokenNode) getChild(4 * i).getChild(0);
Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
if (symbol != null) {
if (symbol.getType() == SymbolType.CONST_INT
|| symbol.getType() == SymbolType.CONST_INT_ARRAY) {
errors.addError(new Error(idenfr.getLine(), ErrorType.h));
}
}
}
}
public void handleMatchFormat(Errors errors) {
TokenNode strCons = (TokenNode) getChild(2);
int formatNum = strCons.getFormatNum();
int expNum = 0;
for (Node child : children) {
if (child instanceof Exp) {
expNum++;
}
}
if (formatNum != expNum) {
errors.addError(new Error(((TokenNode) getChild(0)).getLine(), ErrorType.l));
}
}
}

View File

@@ -0,0 +1,23 @@
package frontend.ast;
import java.util.ArrayList;
public class NodeStack {
private ArrayList<Node> stack;
public NodeStack() {
stack = new ArrayList<Node>();
}
public void push(Node node) {
stack.add(node);
}
public Node pop() {
return stack.remove(stack.size() - 1);
}
public int size() {
return stack.size();
}
}

View File

@@ -0,0 +1,66 @@
package frontend.ast;
public enum SyntaxType {
COMP_UNIT("CompUnit"),
BTYPE("BType"),
DECL("Decl"),
CONST_DECL("ConstDecl"),
VAR_DECL("VarDecl"),
CONST_DEF("ConstDef"),
CONST_INIT_VAL("ConstInitVal"),
VAR_DEF("VarDef"),
INIT_VAL("InitVal"),
FUNC_DEF("FuncDef"),
MAIN_FUNC_DEF("MainFuncDef"),
FUNC_TYPE("FuncType"),
FUNC_FORMAL_PARAM("FuncFParam"),
FUNC_FORMAL_PARAM_S("FuncFParams"),
FUNC_REAL_PARAM_S("FuncRParams"),
BLOCK("Block"),
BLOCK_ITEM("BlockItem"),
STMT("Stmt"),
FOR_STMT("ForStmt"),
UNARY_OP("UnaryOp"),
IDENT("Ident"),
EXP("Exp"),
LVAL_EXP("LVal"),
PRIMARY_EXP("PrimaryExp"),
UNARY_EXP("UnaryExp"),
MUL_EXP("MulExp"),
ADD_EXP("AddExp"),
REL_EXP("RelExp"),
EQ_EXP("EqExp"),
LAND_EXP("LAndExp"),
LOR_EXP("LOrExp"),
CONST_EXP("ConstExp"),
COND_EXP("Cond"),
NUMBER("Number"),
CHARACTER("Character"),
INT_CONST("IntConst"),
STRING_CONST("StringConst"),
CHAR_CONST("CharConst"),
TOKEN("Token");
private final String Name;
SyntaxType(String Name) {
this.Name = Name;
}
@Override
public String toString() {
return this.Name;
}
}

View File

@@ -0,0 +1,49 @@
package frontend.ast.block;
import java.util.ArrayList;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
public class Block extends Node {
private boolean isFuncBlock;
public Block(TokenStream ts) {
super(SyntaxType.BLOCK, ts);
isFuncBlock = false;
}
public void parse(Errors errors) {
TokenNode lbrace = new TokenNode(this.ts);
addChild(lbrace);
while (getCurrToken().getType() != TokenType.RBRACE) {
BlockItem bit = new BlockItem(this.ts);
bit.parse(errors);
addChild(bit);
}
TokenNode rbrace = new TokenNode(this.ts);
addChild(rbrace);
}
public ArrayList<BlockItem> getBlockItems() {
ArrayList<BlockItem> blockItems = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof BlockItem) {
blockItems.add((BlockItem) getChild(i));
}
}
return blockItems;
}
public boolean isFuncBlock() {
return isFuncBlock;
}
public void setIsFuncBlock(boolean isFuncBlock) {
this.isFuncBlock = isFuncBlock;
}
}

View File

@@ -0,0 +1,28 @@
package frontend.ast.block;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.decl.Decl;
public class BlockItem extends Node {
public BlockItem(TokenStream ts) {
super(SyntaxType.BLOCK_ITEM, ts);
}
public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.CONSTTK
|| getCurrToken().getType() == TokenType.STATICTK
|| getCurrToken().getType() == TokenType.INTTK) {
Decl decl = new Decl(this.ts);
decl.parse(errors);
addChild(decl);
} else {
Stmt stmt = new Stmt(this.ts);
stmt.parse(errors);
addChild(stmt);
}
}
}

View File

@@ -0,0 +1,57 @@
package frontend.ast.block;
import frontend.ast.SyntaxType;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.Node;
import frontend.ast.exp.Exp;
import frontend.ast.exp.LVal;
import java.util.ArrayList;
import error.Errors;
public class ForStmt extends Node {
public ForStmt(TokenStream ts) {
super(SyntaxType.FOR_STMT, ts);
}
public void parse(Errors errors) {
handleAssign(errors);
while (getCurrToken().getType() == TokenType.COMMA) {
addChild(new TokenNode(ts)); // comma
handleAssign(errors);
}
}
public void handleAssign(Errors errors) {
LVal lval = new LVal(this.ts);
lval.parse(errors);
addChild(lval);
addChild(new TokenNode(ts)); // assign
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
}
public ArrayList<LVal> getLValList() {
ArrayList<LVal> lvalList = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof LVal) {
lvalList.add((LVal) getChild(i));
}
}
return lvalList;
}
public ArrayList<Exp> getExpList() {
ArrayList<Exp> expList = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof Exp) {
expList.add((Exp) getChild(i));
}
}
return expList;
}
}

View File

@@ -0,0 +1,274 @@
package frontend.ast.block;
import error.Errors;
import java.util.ArrayList;
import error.Error;
import error.ErrorType;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import frontend.ast.exp.Exp;
import frontend.ast.exp.Cond;
import frontend.ast.exp.LVal;
public class Stmt extends Node {
private boolean getint;
public Stmt(TokenStream ts) {
super(SyntaxType.STMT, ts);
getint = false;
}
public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.LBRACE) {
Block block = new Block(this.ts);
block.parse(errors);
addChild(block);
} else if (getCurrToken().getType() == TokenType.IFTK) {
handleIf(errors);
} else if (getCurrToken().getType() == TokenType.FORTK) {
handleFor(errors);
} else if (getCurrToken().getType() == TokenType.BREAKTK) {
TokenNode breakkk = new TokenNode(this.ts);
addChild(breakkk);
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
} else if (getCurrToken().getType() == TokenType.CONTINUETK) {
TokenNode continuekk = new TokenNode(this.ts);
addChild(continuekk);
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
} else if (getCurrToken().getType() == TokenType.RETURNTK) {
handleReturn(errors);
} else if (getCurrToken().getType() == TokenType.PRINTFTK) {
handlePrintf(errors);
} else {
handleAssign(errors);
}
}
public void handleIf(Errors errors) {
TokenNode ifkk = new TokenNode(this.ts);
addChild(ifkk);
TokenNode lparent = new TokenNode(this.ts);
addChild(lparent);
Cond cond = new Cond(this.ts);
cond.parse(errors);
addChild(cond);
if (getCurrToken().getType() == TokenType.RPARENT) {
TokenNode rparent = new TokenNode(this.ts);
addChild(rparent);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
}
Stmt stmt = new Stmt(this.ts);
stmt.parse(errors);
addChild(stmt);
if (getCurrToken().getType() == TokenType.ELSETK) {
TokenNode elsekk = new TokenNode(this.ts);
addChild(elsekk);
Stmt elseStmt = new Stmt(this.ts);
elseStmt.parse(errors);
addChild(elseStmt);
}
}
public void handleFor(Errors errors) {
TokenNode forkk = new TokenNode(this.ts);
addChild(forkk);
TokenNode lparent = new TokenNode(this.ts);
addChild(lparent);
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
ForStmt fst = new ForStmt(this.ts);
fst.parse(errors);
addChild(fst);
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
}
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
Cond cond = new Cond(this.ts);
cond.parse(errors);
addChild(cond);
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
}
if (getCurrToken().getType() == TokenType.RPARENT) {
TokenNode rparent = new TokenNode(this.ts);
addChild(rparent);
} else {
ForStmt fst = new ForStmt(this.ts);
fst.parse(errors);
addChild(fst);
TokenNode rparent = new TokenNode(this.ts);
addChild(rparent);
}
Stmt stmt = new Stmt(this.ts);
stmt.parse(errors);
addChild(stmt);
}
public void handleReturn(Errors errors) {
TokenNode returnkk = new TokenNode(this.ts);
addChild(returnkk);
if (currentIsExp()) {
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
}
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicolon = new TokenNode(this.ts);
addChild(semicolon);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
}
public void handlePrintf(Errors errors) {
TokenNode printfkk = new TokenNode(this.ts);
addChild(printfkk);
addChild(new TokenNode(this.ts)); // lparent
addChild(new TokenNode(this.ts)); // strconst
while (getCurrToken().getType() == TokenType.COMMA) {
addChild(new TokenNode(this.ts)); // comma
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
}
if (getCurrToken().getType() != TokenType.RPARENT) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
} else {
addChild(new TokenNode(this.ts)); // rparent
}
if (getCurrToken().getType() != TokenType.SEMICN) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} else {
addChild(new TokenNode(this.ts)); // semicolon
}
}
public void handleAssign(Errors errors) {
if (getCurrToken().getType() == TokenType.IDENFR) {
if (this.ts.peek(1).getType() == TokenType.ASSIGN) {
LVal lval = new LVal(this.ts);
lval.parse(errors);
addChild(lval);
addChild(new TokenNode(this.ts)); // assign
if (getCurrToken().getValue().equals("getint")) {
getint = true;
}
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
} else if (this.ts.peek(1).getType() == TokenType.LBRACK) {
int start = this.ts.getCurrentIndex();
LVal lval = new LVal(this.ts);
lval.parse(errors);
if (getCurrToken().getType() == TokenType.ASSIGN) {
addChild(lval);
addChild(new TokenNode(this.ts)); // assign
if (getCurrToken().getValue().equals("getint")) {
getint = true;
}
handleExpInAssign(errors);
} else {
this.ts.resetIndex(start);
// parse exp ;
handleExpInAssign(errors);
}
} else {
handleExpInAssign(errors);
}
} else {
if (currentIsExp()) {
handleExpInAssign(errors);
} else {
if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
}
}
}
public void handleExpInAssign(Errors errors) {
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
if (getCurrToken().getType() == TokenType.SEMICN) {
addChild(new TokenNode(this.ts)); // semicolon
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
}
public boolean currentIsExp() {
TokenType t = getCurrToken().getType();
return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT
|| t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON;
}
public boolean isGetint() {
return getint;
}
public ArrayList<Exp> getExpList() {
ArrayList<Exp> expList = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof Exp) {
expList.add((Exp) getChild(i));
}
}
return expList;
}
public Cond getCond() { //just for fortype stmt
for (int i = 0; i < getChildren().size(); i++) {
if (getChild(i) instanceof Cond) {
return (Cond) getChild(i);
}
}
return null;
}
public ForStmt getinitStmt() {
if (getChild(2) instanceof ForStmt) {
return (ForStmt) getChild(2);
}
return null;
}
public ForStmt getStepStmt() {
if (getChild(getChildren().size() - 3) instanceof ForStmt) {
return (ForStmt) getChild(getChildren().size() - 3);
}
return null;
}
public Stmt getBodyStmt() {
return (Stmt) getChild(getChildren().size() - 1);
}
}

View File

@@ -0,0 +1,51 @@
package frontend.ast.decl;
import error.Errors;
import error.ErrorType;
import java.util.ArrayList;
import error.Error;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
public class ConstDecl extends Node {
public ConstDecl(TokenStream ts) {
super(SyntaxType.CONST_DECL, ts);
}
public void parse(Errors errors) {
TokenNode constkk = new TokenNode(this.ts);
addChild(constkk);
TokenNode intkk = new TokenNode(this.ts);
addChild(intkk);
while (true) {
ConstDef cdef = new ConstDef(this.ts);
cdef.parse(errors);
addChild(cdef);
if (getCurrToken().getType() != TokenType.COMMA) {
break;
} else {
TokenNode comma = new TokenNode(this.ts);
addChild(comma);
}
}
if (getCurrToken().getType() != TokenType.SEMICN) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
} else {
TokenNode semicoln = new TokenNode(this.ts);
addChild(semicoln);
}
}
public ArrayList<ConstDef> GetConstDefs() {
ArrayList<ConstDef> constDefs = new ArrayList<>();
for (int i = 2; i < getChildren().size(); i += 2) {
constDefs.add((ConstDef) getChild(i));
}
return constDefs;
}
}

View File

@@ -0,0 +1,66 @@
package frontend.ast.decl;
import error.Error;
import error.ErrorType;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.exp.ConstExp;
import frontend.ast.token.TokenNode;
import frontend.ast.val.ConstInitVal;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import midend.symbol.ArraySymbol;
import midend.symbol.Symbol;
import midend.symbol.SymbolType;
public class ConstDef extends Node {
private boolean isArray;
public ConstDef(TokenStream ts) {
super(SyntaxType.CONST_DEF, ts);
isArray = false;
}
public void parse(Errors errors) {
TokenNode ident = new TokenNode(this.ts);
addChild(ident);
if (getCurrToken().getType() == TokenType.LBRACK) {
TokenNode lbrack = new TokenNode(this.ts);
addChild(lbrack);
isArray = true;
ConstExp cep = new ConstExp(this.ts);
cep.parse(errors);
addChild(cep);
if (getCurrToken().getType() == TokenType.RBRACK) {
TokenNode rbrack = new TokenNode(this.ts);
addChild(rbrack);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
}
}
TokenNode assign = new TokenNode(this.ts);
addChild(assign);
ConstInitVal civ = new ConstInitVal(this.ts);
civ.parse(errors);
addChild(civ);
}
public Symbol getSymbol() {
if (isArray) {
TokenNode tn = (TokenNode) getChild(0);
ArraySymbol arraySymbol = new ArraySymbol(tn.getName(),
SymbolType.CONST_INT_ARRAY, tn.getLine(),
((ConstExp) getChild(2)).getValue());
arraySymbol.addValue(((ConstInitVal) getChild(getChildren().size() - 1)).getValue());
arraySymbol.fullValue();
return arraySymbol;
} else {
TokenNode tn = (TokenNode) getChild(0);
Symbol valueSymbol = new Symbol(tn.getName(),
SymbolType.CONST_INT, tn.getLine());
valueSymbol.addValue(((ConstInitVal) getChild(getChildren().size() - 1)).getValue());
return valueSymbol;
}
}
}

View File

@@ -0,0 +1,25 @@
package frontend.ast.decl;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
public class Decl extends Node {
public Decl(TokenStream ts) {
super(SyntaxType.DECL, ts);
}
public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.CONSTTK) {
ConstDecl cd = new ConstDecl(this.ts);
cd.parse(errors);
addChild(cd);
} else {
VarDecl vd = new VarDecl(this.ts);
vd.parse(errors);
addChild(vd);
}
}
}

View File

@@ -0,0 +1,59 @@
package frontend.ast.decl;
import error.ErrorType;
import error.Errors;
import java.util.ArrayList;
import error.Error;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
public class VarDecl extends Node {
public VarDecl(TokenStream ts) {
super(SyntaxType.VAR_DECL, ts);
}
public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.STATICTK) {
TokenNode staitckk = new TokenNode(ts);
addChild(staitckk);
}
TokenNode intkk = new TokenNode(ts);
addChild(intkk);
while (true) {
VarDef vdf = new VarDef(ts);
vdf.parse(errors);
addChild(vdf);
if (getCurrToken().getType() == TokenType.COMMA) {
TokenNode comma = new TokenNode(ts);
addChild(comma);
} else {
break;
}
}
if (getCurrToken().getType() == TokenType.SEMICN) {
TokenNode semicn = new TokenNode(ts);
addChild(semicn);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.i));
}
}
public ArrayList<VarDef> GetVarDefs() {
ArrayList<VarDef> varDefs = new ArrayList<VarDef>();
if (getChild(1) instanceof VarDef) {
for (int i = 1; i < getChildren().size(); i += 2) {
varDefs.add((VarDef) getChild(i));
}
} else {
for (int i = 2; i < getChildren().size(); i += 2) {
varDefs.add((VarDef) getChild(i));
}
}
return varDefs;
}
}

View File

@@ -0,0 +1,117 @@
package frontend.ast.decl;
import error.Errors;
import error.Error;
import error.ErrorType;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.exp.ConstExp;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.val.InitVal;
import midend.symbol.Symbol;
import midend.symbol.SymbolManager;
import midend.symbol.SymbolType;
import midend.symbol.ArraySymbol;
public class VarDef extends Node {
private boolean isArray;
public VarDef(TokenStream ts) {
super(SyntaxType.VAR_DEF, ts);
isArray = false;
}
public void parse(Errors errors) {
TokenNode ident = new TokenNode(this.ts);
addChild(ident);
if (getCurrToken().getType() == TokenType.LBRACK) {
TokenNode lbrack = new TokenNode(this.ts);
addChild(lbrack);
isArray = true;
ConstExp cep = new ConstExp(this.ts);
cep.parse(errors);
addChild(cep);
if (getCurrToken().getType() == TokenType.RBRACK) {
TokenNode rbrack = new TokenNode(this.ts);
addChild(rbrack);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
}
}
if (getCurrToken().getType() == TokenType.ASSIGN) {
TokenNode assign = new TokenNode(this.ts);
addChild(assign);
InitVal itv = new InitVal(this.ts);
itv.parse(errors);
addChild(itv);
}
}
public Symbol getSymbol(int isStatic) {
if (isStatic == 1) { //static修饰的变量有初值
if (isArray) {
TokenNode tn = (TokenNode) getChild(0);
ArraySymbol arraySymbol = new ArraySymbol(tn.getName(),
SymbolType.STATIC_INT_ARRAY, tn.getLine(),
((ConstExp) getChild(2)).getValue());
if (HaveInitVal()) {
arraySymbol.addValue(((InitVal) getChild(getChildren().size() - 1)).getValue());
}
arraySymbol.fullValue();
return arraySymbol;
} else {
TokenNode tn = (TokenNode) getChild(0);
Symbol valueSymbol = new Symbol(tn.getName(),
SymbolType.STATIC_INT, tn.getLine());
if (HaveInitVal()) {
valueSymbol.addValue(((InitVal) getChild(getChildren().size() - 1)).getValue());
} else {
valueSymbol.addValue(0);
}
return valueSymbol;
}
} else { //要判断是否为全局变量,如果为全局变量,也应该赋初值
if (isArray) {
TokenNode tn = (TokenNode) getChild(0);
ArraySymbol arraySymbol = new ArraySymbol(tn.getName(),
SymbolType.INT_ARRAY, tn.getLine(),
((ConstExp) getChild(2)).getValue());
if (SymbolManager.IsGlobal()) {
if (HaveInitVal()) {
arraySymbol.addValue(((InitVal) getChild(
getChildren().size() - 1)).getValue());
}
arraySymbol.fullValue();
}
return arraySymbol;
} else {
TokenNode tn = (TokenNode) getChild(0);
Symbol symbol = new Symbol(tn.getName(),
SymbolType.INT, tn.getLine());
if (SymbolManager.IsGlobal()) {
if (HaveInitVal()) {
symbol.addValue(((InitVal) getChild(
getChildren().size() - 1)).getValue());
} else {
symbol.addValue(0);
}
}
return symbol;
}
}
}
public boolean HaveInitVal() {
return getChild(getChildren().size() - 1) instanceof InitVal;
}
public InitVal getInitVal() {
if (HaveInitVal()) {
return (InitVal) getChild(getChildren().size() - 1);
}
return null;
}
}

View File

@@ -0,0 +1,73 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.NodeStack;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import midend.symbol.SymbolManager;
import error.Errors;
public class AddExp extends Node {
public AddExp(TokenStream ts) {
super(SyntaxType.ADD_EXP, ts);
}
public void parse(Errors errors) {
NodeStack stack = new NodeStack();
while (true) {
MulExp mep = new MulExp(this.ts);
mep.parse(errors);
stack.push(mep);
if (isAddOp()) {
stack.push(new TokenNode(ts)); // addop
} else {
break;
}
}
if (stack.size() == 1) {
this.addChild((MulExp) stack.pop());
} else {
AddExp temp = this;
while (stack.size() > 1) {
AddExp ae = new AddExp(this.ts);
MulExp mep = (MulExp) stack.pop();
TokenNode op = (TokenNode) stack.pop();
temp.addChild(ae);
temp.addChild(op);
temp.addChild(mep);
temp = ae;
}
temp.addChild((MulExp) stack.pop());
}
}
public boolean isAddOp() {
TokenType t = getCurrToken().getType();
return t == TokenType.PLUS || t == TokenType.MINU;
}
public int getType() {
if (getChildren().size() == 1) {
return ((MulExp) getChild(0)).getType();
} else {
return ((AddExp) getChild(0)).getType()
| ((MulExp) getChild(2)).getType();
}
}
public int getValue() {
if (getChild(0) instanceof MulExp) {
return ((MulExp) getChild(0)).getValue();
} else {
int left = ((AddExp) getChild(0)).getValue();
int right = ((MulExp) getChild(2)).getValue();
if (((TokenNode) getChild(1)).getType() == TokenType.PLUS) {
return left + right;
} else {
return left - right;
}
}
}
}

View File

@@ -0,0 +1,18 @@
package frontend.ast.exp;
import frontend.ast.SyntaxType;
import error.Errors;
import frontend.lexer.TokenStream;
import frontend.ast.Node;
public class Cond extends Node {
public Cond(TokenStream ts) {
super(SyntaxType.COND_EXP, ts);
}
public void parse(Errors errors) {
LOrExp lep = new LOrExp(this.ts);
lep.parse(errors);
addChild(lep);
}
}

View File

@@ -0,0 +1,22 @@
package frontend.ast.exp;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
public class ConstExp extends Node {
public ConstExp(TokenStream ts) {
super(SyntaxType.CONST_EXP, ts);
}
public void parse(Errors errors) {
AddExp ade = new AddExp(ts);
ade.parse(errors);
addChild(ade);
}
public int getValue() {
return ((AddExp) getChild(0)).getValue();
}
}

View File

@@ -0,0 +1,49 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.NodeStack;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import error.Errors;
public class EqExp extends Node {
public EqExp(TokenStream ts) {
super(SyntaxType.EQ_EXP, ts);
}
public void parse(Errors errors) {
NodeStack stack = new NodeStack();
while (true) {
RelExp relexp = new RelExp(this.ts);
relexp.parse(errors);
stack.push(relexp);
if (isEqOp()) {
stack.push(new TokenNode(ts)); // eqop
} else {
break;
}
}
if(stack.size() == 1) {
this.addChild((RelExp)stack.pop());
} else {
EqExp temp = this;
while (stack.size() > 1) {
EqExp eep = new EqExp(this.ts);
RelExp relexp = (RelExp)stack.pop();
TokenNode eqop = (TokenNode)stack.pop();
temp.addChild(eep);
temp.addChild(eqop);
temp.addChild(relexp);
temp = eep;
}
temp.addChild((RelExp)stack.pop());
}
}
public boolean isEqOp() {
TokenType t = getCurrToken().getType();
return t == TokenType.EQL || t == TokenType.NEQ;
}
}

27
frontend/ast/exp/Exp.java Normal file
View File

@@ -0,0 +1,27 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import midend.symbol.SymbolManager;
import error.Errors;
public class Exp extends Node {
public Exp(TokenStream ts) {
super(SyntaxType.EXP, ts);
}
public void parse(Errors errors) {
AddExp addexp = new AddExp(this.ts);
addexp.parse(errors);
addChild(addexp);
}
public int getType() {
return ((AddExp) getChild(0)).getType();
}
public int getValue() {
return ((AddExp) getChild(0)).getValue();
}
}

View File

@@ -0,0 +1,44 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.NodeStack;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import error.Errors;
public class LAndExp extends Node {
public LAndExp(TokenStream ts) {
super(SyntaxType.LAND_EXP, ts);
}
public void parse(Errors errors) {
NodeStack stack = new NodeStack();
while (true) {
EqExp eep = new EqExp(this.ts);
eep.parse(errors);
stack.push(eep);
if (getCurrToken().getType() == TokenType.AND) {
stack.push(new TokenNode(ts)); // landop
} else {
break;
}
}
if (stack.size() == 1) {
this.addChild((EqExp)stack.pop());
} else {
LAndExp temp = this;
while(stack.size() > 1) {
LAndExp lae = new LAndExp(this.ts);
EqExp eep = (EqExp)stack.pop();
TokenNode landop = (TokenNode)stack.pop();
temp.addChild(lae);
temp.addChild(landop);
temp.addChild(eep);
temp = lae;
}
temp.addChild((EqExp)stack.pop());
}
}
}

View File

@@ -0,0 +1,44 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.NodeStack;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import error.Errors;
public class LOrExp extends Node {
public LOrExp(TokenStream ts) {
super(SyntaxType.LOR_EXP, ts);
}
public void parse(Errors errors) {
NodeStack stack = new NodeStack();
while (true) {
LAndExp andexp = new LAndExp(this.ts);
andexp.parse(errors);
stack.push(andexp);
if (getCurrToken().getType() == TokenType.OR) {
stack.push(new TokenNode(ts)); // lorop
} else {
break;
}
}
if (stack.size() == 1) {
this.addChild((LAndExp)stack.pop());
} else {
LOrExp temp = this;
while(stack.size() > 1) {
LOrExp loe = new LOrExp(this.ts);
LAndExp lae = (LAndExp)stack.pop();
TokenNode lorop = (TokenNode)stack.pop();
temp.addChild(loe);
temp.addChild(lorop);
temp.addChild(lae);
temp = loe;
}
temp.addChild((LAndExp)stack.pop());
}
}
}

View File

@@ -0,0 +1,59 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import midend.symbol.SymbolManager;
import midend.symbol.Symbol;
import midend.symbol.ArraySymbol;
import error.Errors;
import error.Error;
import error.ErrorType;
public class LVal extends Node {
public LVal(TokenStream ts) {
super(SyntaxType.LVAL_EXP, ts);
}
public void parse(Errors errors) {
addChild(new TokenNode(this.ts)); // idenfr
if (getCurrToken().getType() == TokenType.LBRACK) {
addChild(new TokenNode(this.ts)); // lbrack
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
if (getCurrToken().getType() == TokenType.RBRACK) {
addChild(new TokenNode(this.ts)); // rbrack
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
}
}
}
public int getType() {
if (getChildren().size() == 1) {
TokenNode idenfr = (TokenNode) getChild(0);
Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
if (symbol instanceof ArraySymbol) {
return 1;
}
return 0;
} else {
return 0;
}
}
public int getValue() {
TokenNode idenfr = (TokenNode) getChild(0); //idenfr一定是个常量可在符号表找到且有值
if (getChildren().size() == 1) {
Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
return symbol.getValue(0);
} else {
int index = ((Exp) getChild(2)).getValue();
Symbol symbol = SymbolManager.getSymbol(idenfr.getName());
return symbol.getValue(index);
}
}
}

View File

@@ -0,0 +1,75 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import frontend.ast.NodeStack;
import midend.symbol.SymbolManager;
import error.Errors;
public class MulExp extends Node {
public MulExp(TokenStream ts) {
super(SyntaxType.MUL_EXP, ts);
}
public void parse(Errors errors) {
NodeStack stack = new NodeStack();
while (true) {
UnaryExp uep = new UnaryExp(this.ts);
uep.parse(errors);
stack.push(uep);
if (isMulOp()) {
stack.push(new TokenNode(ts)); // mulop
} else {
break;
}
}
if (stack.size() == 1) {
addChild((UnaryExp)stack.pop());
} else {
MulExp temp = this;
while (stack.size() > 1) {
MulExp mep = new MulExp(this.ts);
UnaryExp uep = (UnaryExp) stack.pop();
TokenNode mulop = (TokenNode) stack.pop();
temp.addChild(mep);
temp.addChild(mulop);
temp.addChild(uep);
temp = mep;
}
temp.addChild((UnaryExp)stack.pop());
}
}
public boolean isMulOp() {
TokenType t = getCurrToken().getType();
return t == TokenType.MULT || t == TokenType.DIV || t == TokenType.MOD;
}
public int getType() {
if (getChildren().size() == 1) {
return ((UnaryExp) getChild(0)).getType();
} else {
return ((MulExp) getChild(0)).getType()
| ((UnaryExp) getChild(2)).getType();
}
}
public int getValue() {
if (getChild(0) instanceof UnaryExp) {
return ((UnaryExp) getChild(0)).getValue();
} else {
int left = ((MulExp) getChild(0)).getValue();
int right = ((UnaryExp) getChild(2)).getValue();
if (((TokenNode) getChild(1)).getType() == TokenType.MULT) {
return left * right;
} else if (((TokenNode) getChild(1)).getType() == TokenType.DIV) {
return left / right;
} else {
return left % right;
}
}
}
}

View File

@@ -0,0 +1,21 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import error.Errors;
import frontend.ast.token.TokenNode;
public class NumberExp extends Node {
public NumberExp(TokenStream ts) {
super(SyntaxType.NUMBER, ts);
}
public void parse(Errors errors) {
addChild(new TokenNode(ts)); //intconst
}
public int getValue() {
return Integer.parseInt(((TokenNode) getChild(0)).getValue());
}
}

View File

@@ -0,0 +1,58 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import error.Errors;
import error.Error;
import error.ErrorType;
public class PrimaryExp extends Node {
public PrimaryExp(TokenStream ts) {
super(SyntaxType.PRIMARY_EXP, ts);
}
public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.LPARENT) {
addChild(new TokenNode(ts)); // lparent
Exp exp = new Exp(this.ts);
exp.parse(errors);
addChild(exp);
if (getCurrToken().getType() == TokenType.RPARENT) {
addChild(new TokenNode(ts)); // rparent
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
}
} else if (getCurrToken().getType() == TokenType.IDENFR) {
LVal lval = new LVal(this.ts);
lval.parse(errors);
addChild(lval);
} else {
NumberExp num = new NumberExp(this.ts);
num.parse(errors);
addChild(num);
}
}
public int getType() {
if (getChild(0) instanceof TokenNode) {
return ((Exp) getChild(1)).getType();
} else if (getChild(0) instanceof LVal) {
return ((LVal) getChild(0)).getType();
} else {
return 0;
}
}
public int getValue() {
if (getChild(0) instanceof TokenNode) {
return ((Exp) getChild(1)).getValue();
} else if (getChild(0) instanceof LVal) {
return ((LVal) getChild(0)).getValue();
} else {
return ((NumberExp) getChild(0)).getValue();
}
}
}

View File

@@ -0,0 +1,50 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.NodeStack;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import error.Errors;
public class RelExp extends Node {
public RelExp(TokenStream ts) {
super(SyntaxType.REL_EXP, ts);
}
public void parse(Errors errors) {
NodeStack stack = new NodeStack();
while (true) {
AddExp addexp = new AddExp(this.ts);
addexp.parse(errors);
stack.push(addexp);
if (isRelOp()) {
stack.push(new TokenNode(ts)); // relop
} else {
break;
}
}
if (stack.size() == 1) {
this.addChild((AddExp)stack.pop());
} else {
RelExp temp = this;
while(stack.size() > 1) {
RelExp rexp = new RelExp(this.ts);
AddExp addexp = (AddExp)stack.pop();
TokenNode relop = (TokenNode)stack.pop();
temp.addChild(rexp);
temp.addChild(relop);
temp.addChild(addexp);
temp = rexp;
}
temp.addChild((AddExp)stack.pop());
}
}
public boolean isRelOp() {
TokenType t = getCurrToken().getType();
return t == TokenType.LSS || t == TokenType.GRE
|| t == TokenType.LEQ || t == TokenType.GEQ;
}
}

View File

@@ -0,0 +1,124 @@
package frontend.ast.exp;
import java.util.ArrayList;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import frontend.ast.func.FuncRParams;
import midend.symbol.FuncSymbol;
import midend.symbol.SymbolManager;
import error.Errors;
import error.Error;
import error.ErrorType;
public class UnaryExp extends Node {
public UnaryExp(TokenStream ts) {
super(SyntaxType.UNARY_EXP, ts);
}
public void parse(Errors errors) {
if (isUnaryOp()) {
UnaryOp uop = new UnaryOp(ts);
uop.parse(errors);
addChild(uop);
UnaryExp uep = new UnaryExp(ts);
uep.parse(errors);
addChild(uep);
} else if (getCurrToken().getType() == TokenType.IDENFR
&& this.ts.peek(1).getType() == TokenType.LPARENT) {
addChild(new TokenNode(ts)); // idenfr
addChild(new TokenNode(ts)); // lparent
if (isExp()) {
FuncRParams frp = new FuncRParams(ts);
frp.parse(errors);
addChild(frp);
}
if (getCurrToken().getType() == TokenType.RPARENT) {
addChild(new TokenNode(ts)); // rparent
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
}
} else {
PrimaryExp pme = new PrimaryExp(ts);
pme.parse(errors);
addChild(pme);
}
}
public boolean isUnaryOp() {
return getCurrToken().getType() == TokenType.PLUS
|| getCurrToken().getType() == TokenType.MINU
|| getCurrToken().getType() == TokenType.NOT;
}
public boolean isExp() {
TokenType t = getCurrToken().getType();
return t == TokenType.PLUS || t == TokenType.MINU || t == TokenType.NOT
|| t == TokenType.IDENFR || t == TokenType.LPARENT || t == TokenType.INTCON;
}
public void handleFuncCall(Errors errors) { // 当其为函数调用形式时才会调用
TokenNode funcIdenfr = (TokenNode) getChild(0);
if (funcIdenfr.getName().equals("getint")) {
if (getChildren().size() == 4) {
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.d));
}
return;
}
FuncSymbol funcSymbol = (FuncSymbol) SymbolManager.getSymbol(funcIdenfr.getName());
if (funcSymbol == null) {
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.c));
return;
}
int fparaNum = funcSymbol.getParamNum();
int rparaNum = 0;
if (getChildren().size() >= 3 && getChild(2) instanceof FuncRParams) {
FuncRParams frp = (FuncRParams) getChild(2);
rparaNum = frp.getParamNum();
if (rparaNum == fparaNum) {
frp.checkParamType(funcSymbol, errors, funcIdenfr.getLine());
}
}
if (fparaNum != rparaNum) {
errors.addError(new Error(funcIdenfr.getLine(), ErrorType.d));
}
}
public int getType() {
if (getChild(0) instanceof PrimaryExp) {
return ((PrimaryExp) getChild(0)).getType();
} else if (getChild(0) instanceof TokenNode) {
return 0;
} else {
return ((UnaryExp) getChild(1)).getType();
}
}
public int getValue() {
if (getChild(0) instanceof UnaryOp) {
UnaryOp uop = (UnaryOp) getChild(0);
TokenNode opToken = (TokenNode) uop.getChild(0);
return opToken.getType() == TokenType.PLUS ? ((UnaryExp) getChild(1)).getValue()
: -((UnaryExp) getChild(1)).getValue();
} else if (getChild(0) instanceof PrimaryExp) {
return ((PrimaryExp) getChild(0)).getValue();
} else {
return 0; // 0表示这个是函数getvalue只是对于常量或常量表达式取值所以正常情况调用getvalue函数时是不会跳转到这个分支的
}
}
public ArrayList<Exp> getParamList() {
if (!(getChild(0) instanceof TokenNode)) {
return null;
} else {
if (getChildren().size() >= 3 && (getChild(2) instanceof FuncRParams)) {
return ((FuncRParams) getChild(2)).getParamList();
}
return new ArrayList<Exp>();
}
}
}

View File

@@ -0,0 +1,17 @@
package frontend.ast.exp;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import error.Errors;
import frontend.ast.token.TokenNode;
public class UnaryOp extends Node {
public UnaryOp(TokenStream ts) {
super(SyntaxType.UNARY_OP, ts);
}
public void parse(Errors errors) {
addChild(new TokenNode(ts)); // unary op
}
}

View File

@@ -0,0 +1,108 @@
package frontend.ast.func;
import java.util.ArrayList;
import error.Error;
import error.ErrorType;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.block.Block;
import frontend.ast.block.BlockItem;
import frontend.ast.decl.Decl;
import midend.symbol.Symbol;
import midend.symbol.SymbolType;
import midend.symbol.FuncSymbol;
import midend.symbol.ArraySymbol;
import midend.symbol.SymbolManager;
public class FuncDef extends Node {
public FuncDef(TokenStream ts) {
super(SyntaxType.FUNC_DEF, ts);
}
public void parse(Errors errors) {
FuncType ft = new FuncType(this.ts);
ft.parse(errors);
addChild(ft);
TokenNode ident = new TokenNode(this.ts);
addChild(ident);
TokenNode lparen = new TokenNode(this.ts);
addChild(lparen);
if (getCurrToken().getType() != TokenType.RPARENT &&
getCurrToken().getType() != TokenType.LBRACE) {
FuncFParams ffp = new FuncFParams(this.ts);
ffp.parse(errors);
addChild(ffp);
if (getCurrToken().getType() == TokenType.RPARENT) {
TokenNode rparen = new TokenNode(this.ts);
addChild(rparen);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
}
} else if (getCurrToken().getType() == TokenType.LBRACE) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
} else {
TokenNode rparen = new TokenNode(this.ts);
addChild(rparen);
}
Block block = new Block(this.ts);
block.setIsFuncBlock(true);
block.parse(errors);
addChild(block);
}
public Symbol getSymbol() {
if (((FuncType) getChild(0)).isVoid()) {
TokenNode tn = (TokenNode) getChild(1);
return new FuncSymbol(tn.getName(),
SymbolType.VOID_FUNC, tn.getLine(), 0);
} else {
TokenNode tn = (TokenNode) getChild(1);
return new FuncSymbol(tn.getName(),
SymbolType.INT_FUNC, tn.getLine(), 1);
}
}
public void addParamSymbol(Symbol funcSymbol, Errors errors) {
if (getChild(3) instanceof FuncFParams) {
FuncFParams ffp = (FuncFParams) getChild(3);
ArrayList<FuncFParam> paramList = ffp.getParamList();
for (FuncFParam param : paramList) {
Symbol paramSymbol = param.getSymbol();
SymbolManager.addSymbol(paramSymbol, errors);
((FuncSymbol) funcSymbol).addParamSymbol(paramSymbol); // 将形参存到函数的符号中
if (paramSymbol instanceof ArraySymbol) {
((FuncSymbol) funcSymbol).addParam(1);
} else {
((FuncSymbol) funcSymbol).addParam(0);
}
}
}
}
public void checkReturnNode(Errors errors) {
Block block = (Block) getChild(getChildren().size() - 1);
TokenNode rbrace = (TokenNode) block.getChild(block.getChildren().size() - 1);
if (block.getChildren().size() == 2) {
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
} else {
BlockItem bit = (BlockItem) block.getChild(block.getChildren().size() - 2);
if (bit.getChild(0) instanceof Decl) {
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
} else {
if (!(bit.getChild(0).getChild(0) instanceof TokenNode)) {
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
} else {
TokenNode returnNode = (TokenNode) bit.getChild(0).getChild(0);
if (returnNode.getType() != TokenType.RETURNTK) {
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
}
}
}
}
}
}

View File

@@ -0,0 +1,49 @@
package frontend.ast.func;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import midend.symbol.Symbol;
import midend.symbol.SymbolType;
import midend.symbol.ArraySymbol;
import error.Errors;
import frontend.ast.token.TokenNode;
import error.ErrorType;
import error.Error;
public class FuncFParam extends Node {
public FuncFParam(TokenStream ts) {
super(SyntaxType.FUNC_FORMAL_PARAM, ts);
}
public void parse(Errors errors) {
TokenNode intkk = new TokenNode(this.ts);
addChild(intkk);
TokenNode ident = new TokenNode(this.ts);
addChild(ident);
if (getCurrToken().getType() == TokenType.LBRACK) {
TokenNode lbrack = new TokenNode(this.ts);
addChild(lbrack);
if (getCurrToken().getType() == TokenType.RBRACK) {
TokenNode rbrack = new TokenNode(this.ts);
addChild(rbrack);
} else {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.k));
}
}
}
public Symbol getSymbol() {
if (getChildren().size() == 2) {
TokenNode tn = (TokenNode) getChild(1);
return new Symbol(tn.getName(), SymbolType.INT, tn.getLine());
} else {
TokenNode tn = (TokenNode) getChild(1);
return new ArraySymbol(tn.getName(), SymbolType.INT_ARRAY, tn.getLine(), -1);
//这里不求维数,因为函数形参为数组只是相当于一个指针
}
}
}

View File

@@ -0,0 +1,38 @@
package frontend.ast.func;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import java.util.ArrayList;
public class FuncFParams extends Node {
public FuncFParams(TokenStream ts) {
super(SyntaxType.FUNC_FORMAL_PARAM_S, ts);
}
public void parse(Errors errors) {
while (true) {
FuncFParam ffp = new FuncFParam(this.ts);
ffp.parse(errors);
addChild(ffp);
if (getCurrToken().getType() == TokenType.COMMA) {
TokenNode comma = new TokenNode(this.ts);
addChild(comma);
} else {
break;
}
}
}
public ArrayList<FuncFParam> getParamList() {
ArrayList<FuncFParam> paramList = new ArrayList<>();
for (int i = 0; i < getChildren().size(); i += 2) {
paramList.add((FuncFParam) getChild(i));
}
return paramList;
}
}

View File

@@ -0,0 +1,57 @@
package frontend.ast.func;
import java.util.ArrayList;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import error.Errors;
import error.Error;
import error.ErrorType;
import frontend.ast.token.TokenNode;
import frontend.ast.exp.Exp;
import midend.symbol.FuncSymbol;
public class FuncRParams extends Node {
public FuncRParams(TokenStream ts) {
super(SyntaxType.FUNC_REAL_PARAM_S, ts);
}
public void parse(Errors errors) {
while (true) {
Exp ep = new Exp(ts);
ep.parse(errors);
addChild(ep);
if (getCurrToken().getType() == TokenType.COMMA) {
addChild(new TokenNode(ts)); // comma
} else {
break;
}
}
}
public int getParamNum() {
return (getChildren().size() + 1) / 2;
}
public void checkParamType(FuncSymbol funcSymbol, Errors errors, int line) {
int fparaNum = funcSymbol.getParamNum();
int rparaNum = getParamNum();
int size = rparaNum < fparaNum ? rparaNum : fparaNum;
for (int i = 0; i < size; i++) {
Exp exp = (Exp) getChild(i * 2);
if (exp.getType() != funcSymbol.getParamType(i)) {
errors.addError(new Error(line, ErrorType.e));
}
}
}
public ArrayList<Exp> getParamList() {
ArrayList<Exp> paramList = new ArrayList<Exp>();
for (int i = 0; i < getChildren().size(); i += 2) {
paramList.add((Exp) getChild(i));
}
return paramList;
}
}

View File

@@ -0,0 +1,27 @@
package frontend.ast.func;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
public class FuncType extends Node {
public FuncType(TokenStream ts) {
super(SyntaxType.FUNC_TYPE, ts);
}
public void parse(Errors errors) {
TokenNode ident = new TokenNode(this.ts);
addChild(ident);
}
public boolean isVoid() {
return ((TokenNode) getChild(0)).getType() == TokenType.VOIDTK;
}
public boolean isInt() {
return ((TokenNode) getChild(0)).getType() == TokenType.INTTK;
}
}

View File

@@ -0,0 +1,60 @@
package frontend.ast.func;
import error.ErrorType;
import error.Errors;
import error.Error;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.block.BlockItem;
import frontend.ast.decl.Decl;
import frontend.lexer.TokenStream;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenType;
import frontend.ast.block.Block;
public class MainFuncDef extends Node {
public MainFuncDef(TokenStream ts) {
super(SyntaxType.MAIN_FUNC_DEF, ts);
}
public void parse(Errors errors) {
TokenNode intkk = new TokenNode(this.ts);
addChild(intkk);
TokenNode mainkk = new TokenNode(this.ts);
addChild(mainkk);
TokenNode lparent = new TokenNode(this.ts);
addChild(lparent);
if (getCurrToken().getType() != TokenType.RPARENT) {
errors.addError(new Error(this.ts.peek(-1).getLine(), ErrorType.j));
} else {
TokenNode rparent = new TokenNode(this.ts);
addChild(rparent);
}
Block block = new Block(this.ts);
block.setIsFuncBlock(true);
block.parse(errors);
addChild(block);
}
public void checkReturnNode(Errors errors) {
Block block = (Block) getChild(getChildren().size() - 1);
TokenNode rbrace = (TokenNode) block.getChild(block.getChildren().size() - 1);
if (block.getChildren().size() == 2) {
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
} else {
BlockItem bit = (BlockItem) block.getChild(block.getChildren().size() - 2);
if (bit.getChild(0) instanceof Decl) {
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
} else {
if (!(bit.getChild(0).getChild(0) instanceof TokenNode)) {
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
} else {
TokenNode returnNode = (TokenNode) bit.getChild(0).getChild(0);
if (returnNode.getType() != TokenType.RETURNTK) {
errors.addError(new Error(rbrace.getLine(), ErrorType.g));
}
}
}
}
}
}

View File

@@ -0,0 +1,50 @@
package frontend.ast.token;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.Token;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
public class TokenNode extends Node {
private Token token;
public TokenNode(TokenStream ts) {
super(SyntaxType.TOKEN, ts);
token = ts.read();
}
@Override
public String toString() {
return token.toString();
}
public String getValue() {
return token.getValue();
}
public int getLine() {
return token.getLine();
}
public String getName() {
return token.getValue();
}
public TokenType getType() {
return token.getType();
}
public int getFormatNum() {
int num = 0;
String str = token.getValue();
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '%' && i + 1 < str.length()
&& str.charAt(i + 1) == 'd') {
num++;
i++;
}
}
return num;
}
}

View File

@@ -0,0 +1,58 @@
package frontend.ast.val;
import java.util.ArrayList;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.ast.exp.ConstExp;
import frontend.ast.token.TokenNode;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
public class ConstInitVal extends Node {
public ConstInitVal(TokenStream ts) {
super(SyntaxType.CONST_INIT_VAL, ts);
}
public void parse(Errors errors) {
if (getCurrToken().getType() != TokenType.LBRACE) {
ConstExp cep = new ConstExp(this.ts);
cep.parse(errors);
addChild(cep);
} else {
TokenNode lbrace = new TokenNode(this.ts);
addChild(lbrace);
if (getCurrToken().getType() != TokenType.RBRACE) {
while (true) { // judge rbrace or not ??
ConstExp cep = new ConstExp(this.ts);
cep.parse(errors);
addChild(cep);
if (getCurrToken().getType() == TokenType.COMMA) {
TokenNode comma = new TokenNode(this.ts);
addChild(comma);
} else {
break;
}
}
}
TokenNode rbrace = new TokenNode(this.ts);
addChild(rbrace);
}
}
public ArrayList<Integer> getValue() {
ArrayList<Integer> valueList = new ArrayList<>();
if (getChild(0) instanceof ConstExp) {
valueList.add(((ConstExp) getChild(0)).getValue());
return valueList;
} else {
for (int i = 1; i < getChildren().size(); i += 2) {
if (getChild(i) instanceof ConstExp) {
valueList.add(((ConstExp) getChild(i)).getValue());
}
}
return valueList;
}
}
}

View File

@@ -0,0 +1,71 @@
package frontend.ast.val;
import java.util.ArrayList;
import error.Errors;
import frontend.ast.Node;
import frontend.ast.SyntaxType;
import frontend.lexer.TokenStream;
import frontend.lexer.TokenType;
import frontend.ast.token.TokenNode;
import frontend.ast.exp.Exp;
public class InitVal extends Node {
public InitVal(TokenStream ts) {
super(SyntaxType.INIT_VAL, ts);
}
public void parse(Errors errors) {
if (getCurrToken().getType() == TokenType.LBRACE) {
TokenNode lbrace = new TokenNode(this.ts);
addChild(lbrace);
if (getCurrToken().getType() != TokenType.RBRACE) {
while (true) {
Exp ep = new Exp(this.ts);
ep.parse(errors);
addChild(ep);
if (getCurrToken().getType() == TokenType.COMMA) {
TokenNode comma = new TokenNode(this.ts);
addChild(comma);
} else {
break;
}
}
}
TokenNode rbrace = new TokenNode(this.ts);
addChild(rbrace);
} else {
Exp ep = new Exp(this.ts);
ep.parse(errors);
addChild(ep);
}
}
public ArrayList<Integer> getValue() {
ArrayList<Integer> values = new ArrayList<>();
if (getChild(0) instanceof Exp) {
values.add(((Exp) getChild(0)).getValue());
} else {
for (int i = 1; i < getChildren().size(); i += 2) {
if (getChild(i) instanceof Exp) {
values.add(((Exp) getChild(i)).getValue());
}
}
}
return values;
}
public ArrayList<Exp> getExpList() {
ArrayList<Exp> expList = new ArrayList<>();
if (getChild(0) instanceof Exp) {
expList.add((Exp) getChild(0));
} else {
for (int i = 1; i < getChildren().size(); i += 2) {
if (getChild(i) instanceof Exp) {
expList.add((Exp) getChild(i));
}
}
}
return expList;
}
}

245
frontend/lexer/Lexer.java Normal file
View File

@@ -0,0 +1,245 @@
package frontend.lexer;
import java.util.ArrayList;
import error.Error;
import error.ErrorType;
import error.Errors;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
public class Lexer {
private String input;
private ArrayList<Token> tokens;
private int position;
private int line;
private char currentChar;
public Lexer(String input) {
this.input = input;
this.tokens = new ArrayList<Token>();
this.position = 0;
this.line = 1;
}
public void lex(Errors errors) {
int sigComment = 0;
while (this.position < this.input.length()) {
currentChar = this.input.charAt(this.position);
if (currentChar == ' ' || currentChar == '\t') {
this.position++;
continue;
}
if (currentChar == '\n' || currentChar == '\r') {
if (currentChar == '\r') {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '\n') {
this.position++;
}
}
this.line++;
this.position++;
if (sigComment == 1) {
sigComment = 0;
}
continue;
}
if (sigComment == 0) {
if (currentChar == '/') {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '/') {
sigComment = 1;
this.position += 2;
continue;
}
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '*') {
sigComment = 2;
this.position += 2;
continue;
}
}
if (this.isIntCons()) {
lexInt();
continue;
}
if (this.isStrCons()) {
lexStr();
continue;
}
if (this.isIdenfr()) {
lexIdenfr();
continue;
}
lexOp(errors);
}
if (sigComment == 2) {
if (this.position + 1 < this.input.length() &&
this.currentChar == '*' && this.input.charAt(this.position + 1) == '/') {
sigComment = 0;
this.position += 2;
continue;
}
}
if (sigComment != 0) {
this.position++;
}
}
}
public boolean isIntCons() {
return Character.isDigit(this.currentChar);
}
public boolean isStrCons() {
return this.currentChar == '"';
}
public boolean isIdenfr() {
return Character.isLowerCase(this.currentChar) || Character.isUpperCase(this.currentChar)
|| this.currentChar == '_';
}
public boolean isNotWp() {
return !Character.isWhitespace(this.currentChar);
}
public boolean isOp() {
return !this.isIntCons() && !this.isStrCons() && !this.isIdenfr();
}
public void lexInt() {
StringBuilder sb = new StringBuilder();
while (this.position < this.input.length() && this.isIntCons()) {
sb.append(this.currentChar);
this.position++;
updateCurrentChar();
}
this.tokens.add(new Token(sb.toString(), this.line));
}
public void lexStr() {
StringBuilder sb = new StringBuilder();
sb.append(this.currentChar);
this.position++;
updateCurrentChar();
while (this.position < this.input.length() && this.currentChar != '"') {
sb.append(this.currentChar);
this.position++;
updateCurrentChar();
}
if (this.position < this.input.length() && this.currentChar == '"') {
sb.append(this.currentChar);
this.position++;
}
this.tokens.add(new Token(sb.toString(), this.line));
}
public void lexIdenfr() {
StringBuilder sb = new StringBuilder();
while (this.position < this.input.length() && (this.isIdenfr() || this.isIntCons())) {
sb.append(this.currentChar);
this.position++;
updateCurrentChar();
}
this.tokens.add(new Token(sb.toString(), this.line));
}
public void lexOp(Errors errors) {
StringBuilder sb = new StringBuilder();
if (this.currentChar == '/' && this.position + 1 < this.input.length() &&
(this.input.charAt(this.position + 1) == '/' ||
this.input.charAt(this.position + 1) == '*')) {
return;
}
sb.append(this.currentChar);
switch (this.currentChar) {
case '&':
readAnd(sb);
break;
case '|':
readOr(sb);
break;
case '<':
readEq(sb);
break;
case '>':
readEq(sb);
break;
case '=':
readEq(sb);
break;
case '!':
readEq(sb);
break;
default:
break;
}
this.position++;
if (sb.toString().equals("&") || sb.toString().equals("|")) {
errors.addError(new Error(this.line, ErrorType.a));
}
this.tokens.add(new Token(sb.toString(), this.line));
}
public void readAnd(StringBuilder sb) {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '&') {
this.position++;
currentChar = this.input.charAt(this.position);
sb.append(currentChar);
}
}
public void readOr(StringBuilder sb) {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '|') {
this.position++;
currentChar = this.input.charAt(this.position);
sb.append(currentChar);
}
}
public void readEq(StringBuilder sb) {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '=') {
this.position++;
currentChar = this.input.charAt(this.position);
sb.append(currentChar);
}
}
public void updateCurrentChar() {
if (this.position < this.input.length()) {
currentChar = this.input.charAt(this.position);
}
}
public void printTokens() {
for (Token token : this.tokens) {
token.adjustType();
System.out.println(token.getType() + " " + token.getValue() + " " + token.getLine());
}
}
public void writeToFile(String fileName) {
try {
StringBuilder sb = new StringBuilder();
for (Token token : this.tokens) {
token.adjustType();
sb.append(token.toString());
}
Files.write(Paths.get(fileName), sb.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public ArrayList<Token> getTokens() {
for (Token token : this.tokens) {
token.adjustType();
}
return this.tokens;
}
}

42
frontend/lexer/Token.java Normal file
View File

@@ -0,0 +1,42 @@
package frontend.lexer;
public class Token {
private TokenType type;
private String value;
private int line;
public Token(String value, int line) {
this.value = value;
this.type = TokenType.isWhatType(value);
this.line = line;
}
public void adjustType() {
if (this.type == TokenType.IDENFR) {
if (this.value.charAt(0) == '\"' &&
this.value.charAt(this.value.length() - 1) == '\"') {
this.type = TokenType.STRCON;
}
String regex = "^\\d+$";
if (this.value.matches(regex)) {
this.type = TokenType.INTCON;
}
}
}
public String getValue() {
return this.value;
}
public TokenType getType() {
return this.type;
}
public int getLine() {
return this.line;
}
public String toString() {
return this.type + " " + this.value + "\n";
}
}

View File

@@ -0,0 +1,42 @@
package frontend.lexer;
import java.util.ArrayList;
public class TokenStream {
private ArrayList<Token> tokens;
private int currentIndex;
public TokenStream(ArrayList<Token> tokens) {
this.tokens = tokens;
}
public Token read() {
if (currentIndex < tokens.size()) {
return tokens.get(currentIndex++);
} else {
return null;
}
}
public void recall() {
if (currentIndex > 0) {
currentIndex--;
}
}
public int getCurrentIndex() {
return currentIndex;
}
public void resetIndex(int index) {
currentIndex = index;
}
public Token peek(int step) {
if (currentIndex + step < tokens.size()) {
return tokens.get(currentIndex + step);
} else {
return null;
}
}
}

View File

@@ -0,0 +1,123 @@
package frontend.lexer;
public enum TokenType {
IDENFR,
INTCON,
STRCON,
CONSTTK,
INTTK,
STATICTK,
BREAKTK,
CONTINUETK,
IFTK,
MAINTK,
ELSETK,
NOT,
AND,
OR,
FORTK,
RETURNTK,
VOIDTK,
PLUS,
MINU,
PRINTFTK,
MULT,
DIV,
MOD,
LSS,
LEQ,
GRE,
GEQ,
EQL,
NEQ,
SEMICN,
COMMA,
LPARENT,
RPARENT,
LBRACK,
RBRACK,
LBRACE,
RBRACE,
ASSIGN;
public static TokenType isWhatType(String str) {
switch (str) {
case "const":
return TokenType.CONSTTK;
case "int":
return TokenType.INTTK;
case "static":
return TokenType.STATICTK;
case "break":
return TokenType.BREAKTK;
case "continue":
return TokenType.CONTINUETK;
case "if":
return TokenType.IFTK;
case "main":
return TokenType.MAINTK;
case "else":
return TokenType.ELSETK;
case "!":
return TokenType.NOT;
case "&&":
return TokenType.AND;
case "&":
return TokenType.AND;
case "||":
return TokenType.OR;
case "|":
return TokenType.OR;
case "for":
return TokenType.FORTK;
case "return":
return TokenType.RETURNTK;
case "void":
return TokenType.VOIDTK;
case "+":
return TokenType.PLUS;
case "-":
return TokenType.MINU;
case "printf":
return TokenType.PRINTFTK;
case "*":
return TokenType.MULT;
case "/":
return TokenType.DIV;
case "%":
return TokenType.MOD;
case "<":
return TokenType.LSS;
case "<=":
return TokenType.LEQ;
case ">":
return TokenType.GRE;
case ">=":
return TokenType.GEQ;
case "==":
return TokenType.EQL;
case "!=":
return TokenType.NEQ;
case ";":
return TokenType.SEMICN;
case ",":
return TokenType.COMMA;
case "(":
return TokenType.LPARENT;
case ")":
return TokenType.RPARENT;
case "[":
return TokenType.LBRACK;
case "]":
return TokenType.RBRACK;
case "{":
return TokenType.LBRACE;
case "}":
return TokenType.RBRACE;
case "=":
return TokenType.ASSIGN;
default:
return TokenType.IDENFR;
}
}
}

View File

@@ -0,0 +1,38 @@
package frontend.parser;
import frontend.ast.CompUnit;
import frontend.lexer.TokenStream;
import java.nio.file.Files;
import error.Errors;
import java.nio.file.Paths;
import java.io.IOException;
public class Parser {
private TokenStream ts;
private CompUnit compUnit;
public Parser(TokenStream ts) {
this.ts = ts;
this.compUnit = new CompUnit(this.ts);
}
public void parse(Errors errors) {
compUnit.parse(errors);
}
public CompUnit getCompUnit() {
return compUnit;
}
public void writeToFile(String fileName) {
try {
String info = this.compUnit.getInfo();
Files.write(Paths.get(fileName), info.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}