Skip to content

Commit 322566f

Browse files
authored
Merge branch 'main' into main
2 parents 2de2085 + cbe3e86 commit 322566f

33 files changed

+1064
-186
lines changed

src/main/java/com/ExpressionParserMain.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public class ExpressionParserMain {
77
public static void main(String[] args) throws Exception {
88
com.compiler.Lexer lexer = new com.compiler.Lexer();
99
com.compiler.ExpressionParser parser = new com.compiler.ExpressionParser(lexer);
10-
com.compiler.ast.ASTExprNode expr = parser.parseExpression("30 + 12 - 5");
10+
com.compiler.ast.ASTExprNode expr = parser.parseExpression("CALL foo(30) + CALL(12,13) - CALL()");
1111
int result = expr.eval();
1212
System.out.println(result);
1313
OutputStreamWriter out = new OutputStreamWriter(System.out);

src/main/java/com/InterpreterMain.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ public static void main(String[] args) throws Exception {
2323
outStream.flush();
2424
}
2525

26-
}
26+
}

src/main/java/com/StmtParserMain.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ public static void main(String[] args) throws Exception {
1212
DECLARE b;
1313
a = 1 + 2;
1414
b = 5;
15+
FUNCTION foo(c,d){
16+
RETURN 0;
17+
};
18+
c = 1;
19+
PRINT c;
1520
PRINT a ? b + 1 : -1;
16-
PRINT 1 + 2;
21+
PRINT CALL foo(a,b);
1722
PRINT 3 + 4;
1823
}
1924
""";

src/main/java/com/compiler/ExpressionParser.java

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@
22
import com.compiler.TokenIntf.Type;
33
import com.compiler.ast.*;
44

5+
import java.util.ArrayList;
6+
import java.util.List;
7+
58
public class ExpressionParser {
69
private Lexer m_lexer;
710
private SymbolTableIntf m_symbolTable;
11+
private FunctionTableIntf m_functionTable;
812

913
public ExpressionParser(Lexer lexer) {
1014
m_lexer = lexer;
1115
m_symbolTable = new SymbolTable();
16+
m_functionTable = new FunctionTable();
1217
}
1318

14-
public ExpressionParser(Lexer lexer, SymbolTableIntf symbolTable) {
19+
public ExpressionParser(Lexer lexer, SymbolTableIntf symbolTable, FunctionTableIntf functionTable) {
1520
m_lexer = lexer;
1621
m_symbolTable = symbolTable;
22+
m_functionTable = functionTable;
1723
}
1824

1925
public ASTExprNode parseExpression(String val) throws Exception {
@@ -55,11 +61,11 @@ ASTExprNode getVariableExpr() throws Exception {
5561
}
5662

5763
ASTExprNode getDashExpr() throws Exception {
58-
ASTExprNode result = getParantheseExpr();
64+
ASTExprNode result = getCallExpr();
5965
while (m_lexer.lookAhead().m_type == Type.TDASH) {
6066
Token curToken = m_lexer.lookAhead();
6167
m_lexer.advance();
62-
ASTExprNode operand = getParantheseExpr();
68+
ASTExprNode operand = getCallExpr();
6369
result = new ASTTDashNode(result, operand);
6470
}
6571
return result;
@@ -220,6 +226,47 @@ ASTExprNode getAndOrExpr() throws Exception {
220226
return getOrExpr();
221227
}
222228

229+
ASTExprNode getCallExpr() throws Exception {
230+
// callExpr: CALL IDENTIFIER LPAREN argList RPAREN
231+
if(m_lexer.m_currentToken.m_type != TokenIntf.Type.CALL) {
232+
return getParantheseExpr();
233+
}else {
234+
m_lexer.advance();
235+
String funcName = m_lexer.m_currentToken.m_value;
236+
m_lexer.expect(TokenIntf.Type.IDENT);
237+
FunctionInfo functionInfo = m_functionTable.getFunction(funcName);
238+
if(functionInfo == null) {
239+
m_lexer.throwCompilerException(String.format("%s not declared" , funcName), "");
240+
}
241+
242+
m_lexer.expect(TokenIntf.Type.LPAREN);
243+
List<ASTExprNode> argumentList = getArgumentList();
244+
if(argumentList.size() != functionInfo.varNames.size()){
245+
m_lexer.throwCompilerException(String.format("%s function parameters for function %s" , argumentList.size() < functionInfo.varNames.size()? "Not enough": "To many", funcName), "");
246+
}
247+
248+
m_lexer.expect(TokenIntf.Type.RPAREN);
249+
return new ASTCallExprNode(funcName, argumentList);
250+
}
251+
252+
}
253+
254+
private List<ASTExprNode> getArgumentList() throws Exception {
255+
// argList: expr argListPost | eps
256+
// argListPost: eps | COMMA expr argListPost
257+
List<ASTExprNode> argumentList = new ArrayList<>();
258+
if(m_lexer.m_currentToken.m_type == Type.RPAREN){
259+
return argumentList;
260+
}else {
261+
argumentList.add(getQuestionMarkExpr());
262+
while (m_lexer.m_currentToken.m_type == Type.COMMA) {
263+
m_lexer.advance();
264+
argumentList.add(getQuestionMarkExpr());
265+
}
266+
return argumentList;
267+
}
268+
}
269+
223270
ASTExprNode getQuestionMarkExpr() throws Exception {
224271
ASTExprNode predicate = getAndOrExpr();
225272

src/main/java/com/compiler/StmtParser.java

Lines changed: 107 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ public class StmtParser {
1515
public StmtParser(Lexer lexer) {
1616
m_lexer = lexer;
1717
m_symbolTable = new SymbolTable();
18-
m_exprParser = new ExpressionParser(lexer, m_symbolTable);
19-
m_functionTable = null;
18+
m_functionTable = new FunctionTable();
19+
m_exprParser = new ExpressionParser(lexer, m_symbolTable, m_functionTable);
2020
}
2121

2222
public StmtParser(Lexer lexer, SymbolTable symbolTable, FunctionTable functionTable) {
2323
m_lexer = lexer;
2424
m_symbolTable = symbolTable;
2525
m_functionTable = functionTable;
26-
m_exprParser = new ExpressionParser(lexer, m_symbolTable);
26+
m_exprParser = new ExpressionParser(lexer, m_symbolTable, m_functionTable);
2727
}
2828

2929
public ASTStmtNode parseProgram(String program) throws Exception {
@@ -65,7 +65,9 @@ public ASTStmtNode parseStmt() throws Exception {
6565
if (type == TokenIntf.Type.BLOCK) {
6666
return parseJumpBlockStmt();
6767
}
68-
68+
if (type == Type.FUNCTION) {
69+
return parseFunctionStmt();
70+
}
6971
if (type == TokenIntf.Type.WHILE) {
7072
return parseWhileLoopStmt();
7173
}
@@ -85,13 +87,79 @@ public ASTStmtNode parseStmt() throws Exception {
8587
return parseSwitchStmt();
8688
}
8789

90+
if (type == Type.IF) {
91+
return parseIfElseStmt();
92+
}
93+
8894
m_lexer.throwCompilerException("Invalid begin of statement", "DECLARE or IDENTIFIER or PRINT or NUMERIC_IF");
8995
return null; // unreachable
9096
}
9197

98+
public ASTStmtNode parseFunctionStmt() throws Exception {
99+
// functionDecl: FUNCTION IDENTIFIER RPAREN paramList RPAREN LBRACE functionBody RBRACE SEMICOLON
100+
m_lexer.expect(Type.FUNCTION);
101+
String functionName = m_lexer.m_currentToken.m_value;
102+
103+
m_lexer.expect(TokenIntf.Type.IDENT);
104+
m_lexer.expect(Type.LPAREN);
105+
106+
List<String> parameterList = parseParameterList();
107+
parameterList.forEach(m_symbolTable::createSymbol);
108+
m_functionTable.createFunction(functionName, parameterList);
109+
110+
m_lexer.expect(TokenIntf.Type.RPAREN);
111+
m_lexer.expect(TokenIntf.Type.LBRACE);
112+
113+
List<ASTStmtNode> functionBody = parseFunctionBody();
114+
115+
m_lexer.expect(TokenIntf.Type.RBRACE);
116+
m_lexer.expect(Type.SEMICOLON);
117+
118+
return new ASTFunctionStmtNode(functionName, parameterList, functionBody);
119+
}
120+
121+
private List<ASTStmtNode> parseFunctionBody() throws Exception {
122+
// functionBody: returnStmt | stmt functionBody
123+
List<ASTStmtNode> stmtList = new ArrayList<>();
124+
while(m_lexer.m_currentToken.m_type != Type.RETURN){
125+
if(m_lexer.m_currentToken.m_type == Type.RBRACE){
126+
m_lexer.throwCompilerException("Invalid end of function body", "RETURN");
127+
}
128+
stmtList.add(parseStmt());
129+
}
130+
stmtList.add(parseReturnStmt());
131+
return stmtList;
132+
}
133+
134+
private ASTStmtNode parseReturnStmt() throws Exception {
135+
// returnStmt: RETURN expr
136+
m_lexer.expect(Type.RETURN);
137+
ASTStmtNode returnStmtNode = new ASTReturnStmtNode(m_exprParser.getQuestionMarkExpr());
138+
m_lexer.expect(Type.SEMICOLON);
139+
return returnStmtNode;
140+
}
141+
142+
private List<String> parseParameterList() throws Exception {
143+
// paramList: IDENTIFIER paramListPos | eps
144+
// paramListPost: eps | COMMA IDENFIER paramListPost
145+
List<String> parameterList = new ArrayList<>();
146+
if(m_lexer.m_currentToken.m_type != Type.IDENT){
147+
return parameterList;
148+
} else {
149+
parameterList.add(m_lexer.m_currentToken.m_value);
150+
m_lexer.advance();
151+
152+
while (m_lexer.m_currentToken.m_type == Type.COMMA) {
153+
m_lexer.advance();
154+
parameterList.add(m_lexer.m_currentToken.m_value);
155+
m_lexer.expect(Type.IDENT);
156+
}
157+
return parameterList;
158+
}
159+
}
160+
92161
public ASTStmtNode parsePrintStmt() throws Exception {
93162
m_lexer.expect(Type.PRINT);
94-
95163
ASTPrintStmtNode astPrintStmtNode = new ASTPrintStmtNode(m_exprParser.getQuestionMarkExpr());
96164
m_lexer.expect(Type.SEMICOLON);
97165
return astPrintStmtNode;
@@ -152,14 +220,44 @@ ASTStmtNode parseJumpBlockStmt() throws Exception {
152220
}
153221

154222

223+
ASTStmtNode parseIfElseStmt() throws Exception {
224+
225+
// ifStmt -> IF LPAREN condition RPAREN LBRACE stmtList RBRACE elseStmt
226+
// elseStmt -> eps
227+
// elseStmt -> ELSE continueStmt
228+
// continueStmt -> ifStmt
229+
// continueStmt -> LBRACE stmtList RBRACE
230+
231+
m_lexer.expect(Type.IF);
232+
m_lexer.expect(Type.LPAREN);
233+
ASTExprNode condition = this.m_exprParser.getQuestionMarkExpr();
234+
m_lexer.expect(Type.RPAREN);
235+
m_lexer.expect(Type.LBRACE);
236+
ASTStmtListNode ifStmtList = this.parseStmtlist();
237+
m_lexer.expect(Type.RBRACE);
238+
239+
if(m_lexer.lookAhead().m_type == Type.ELSE) {
240+
m_lexer.expect(Type.ELSE);
241+
if(m_lexer.lookAhead().m_type == Type.LBRACE) {
242+
m_lexer.expect(Type.LBRACE);
243+
ASTStmtListNode elseStmtList = this.parseStmtlist();
244+
m_lexer.expect(Type.RBRACE);
245+
return new ASTIfElseNode(condition, ifStmtList, elseStmtList);
246+
}
247+
if(m_lexer.lookAhead().m_type == Type.IF) {
248+
return new ASTIfElseNode(condition, ifStmtList, parseStmtlist());
249+
}
250+
}
251+
return new ASTIfElseNode(condition, ifStmtList, null);
252+
}
253+
254+
155255
ASTStmtNode parseNumericIfStmt() throws Exception {
156-
// NUMERIC_IF LPAR expr RPAR LBRACE numericIfBlock RBRACE
256+
// NUMERIC_IF LPAR expr RPAR numericIfBlock
157257
m_lexer.expect(Type.NUMERIC_IF);
158258
m_lexer.expect(Type.LPAREN);
159259
final ASTExprNode predicate = this.m_exprParser.getQuestionMarkExpr();
160260
m_lexer.expect(Type.RPAREN);
161-
m_lexer.expect(Type.LBRACE);
162-
163261

164262
// numericIfBlock positiveBlock negativeBlock zeroBlock
165263
// positiveBlock: POSITIVE LBRACE stmtlist RBRACE
@@ -171,8 +269,6 @@ ASTStmtNode parseNumericIfStmt() throws Exception {
171269
// zeroBlock: ZERO LBRACE stmtlist RBRACE
172270
final ASTStmtListNode zeroStmtList = parseNumericIfBlock(Type.ZERO);
173271

174-
175-
m_lexer.expect(Type.RBRACE);
176272
return new ASTNumericIfNode(predicate, positiveStmtList, negativeStmtList, zeroStmtList);
177273
}
178274

@@ -213,7 +309,7 @@ ASTDoWhileLoopStmtNode parseDoWhileLoopStmt() throws Exception {
213309
}
214310

215311
ASTStmtNode parseExecuteNTimesStmt() throws Exception {
216-
// EXECUTE integer|identifier TIMES LBRACE stmtList RBRACE
312+
// EXECUTE integer|identifier TIMES LBRACE stmtList RBRACE SEMICOLON
217313
m_lexer.expect(Type.EXECUTE);
218314

219315
if(m_lexer.m_currentToken.m_type != Type.INTEGER && m_lexer.m_currentToken.m_type != Type.IDENT) {

src/main/java/com/compiler/ast/ASTBitAndExprNode.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import com.compiler.CompileEnvIntf;
44
import com.compiler.InstrIntf;
5-
import com.compiler.Token;
65
import com.compiler.TokenIntf;
76
import com.compiler.instr.InstrBitAnd;
7+
import com.compiler.instr.InstrIntegerLiteral;
88

99
import java.io.OutputStreamWriter;
1010

@@ -13,6 +13,7 @@ public class ASTBitAndExprNode extends ASTExprNode {
1313
ASTExprNode m_operand0;
1414
ASTExprNode m_operand1;
1515
TokenIntf.Type m_operator;
16+
Integer m_constValue;
1617

1718
public ASTBitAndExprNode(final ASTExprNode operand0, final ASTExprNode operand1, final TokenIntf.Type operator) {
1819
m_operand0 = operand0;
@@ -38,10 +39,30 @@ public void print(final OutputStreamWriter outStream, final String indent) throw
3839

3940
@Override
4041
public InstrIntf codegen(final CompileEnvIntf env) {
42+
constFold();
43+
if(m_constValue != null) {
44+
final InstrIntegerLiteral constInstr = new InstrIntegerLiteral(m_constValue.toString());
45+
env.addInstr(constInstr);
46+
return constInstr;
47+
}
4148
final InstrIntf operand0 = m_operand0.codegen(env);
4249
final InstrIntf operand1 = m_operand1.codegen(env);
4350
final InstrIntf bitAnd = new InstrBitAnd(m_operator, operand0, operand1);
4451
env.addInstr(bitAnd);
4552
return bitAnd;
4653
}
54+
55+
56+
@Override
57+
public Integer constFold() {
58+
final Integer lhsConst = m_operand0.constFold();
59+
final Integer rhsConst = m_operand1.constFold();
60+
61+
if(lhsConst != null && rhsConst != null) {
62+
m_constValue = lhsConst & rhsConst;
63+
} else {
64+
m_constValue = null;
65+
}
66+
return m_constValue;
67+
}
4768
}

src/main/java/com/compiler/ast/ASTBitOrExprNode.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.compiler.CompileEnvIntf;
44
import com.compiler.InstrIntf;
55
import com.compiler.instr.InstrBitOr;
6+
import com.compiler.instr.InstrIntegerLiteral;
67

78
import java.io.OutputStreamWriter;
89

@@ -11,6 +12,8 @@ public class ASTBitOrExprNode extends ASTExprNode {
1112
ASTExprNode m_operand0;
1213
ASTExprNode m_operand1;
1314
com.compiler.TokenIntf.Type m_operator;
15+
Integer m_constValue;
16+
1417

1518
public ASTBitOrExprNode(final ASTExprNode operand0, final ASTExprNode operand1, final com.compiler.TokenIntf.Type operator) {
1619
m_operand0 = operand0;
@@ -36,10 +39,30 @@ public void print(final OutputStreamWriter outStream, final String indent) throw
3639

3740
@Override
3841
public InstrIntf codegen(final CompileEnvIntf env) {
42+
constFold();
43+
if(m_constValue != null) {
44+
final InstrIntegerLiteral constInstr = new InstrIntegerLiteral(m_constValue.toString());
45+
env.addInstr(constInstr);
46+
return constInstr;
47+
}
3948
final InstrIntf operand0 = m_operand0.codegen(env);
4049
final InstrIntf operand1 = m_operand1.codegen(env);
4150
final InstrIntf bitOr = new InstrBitOr(m_operator, operand0, operand1);
4251
env.addInstr(bitOr);
4352
return bitOr;
4453
}
54+
55+
56+
@Override
57+
public Integer constFold() {
58+
final Integer lhsConst = m_operand0.constFold();
59+
final Integer rhsConst = m_operand1.constFold();
60+
61+
if(lhsConst != null && rhsConst != null) {
62+
m_constValue = lhsConst | rhsConst;
63+
} else {
64+
m_constValue = null;
65+
}
66+
return m_constValue;
67+
}
4568
}

0 commit comments

Comments
 (0)