@@ -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 ) {
0 commit comments