mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:42:45 +00:00 
			
		
		
		
	LibJS: Parse "try", "catch" and "finally"
This is the first step towards support exceptions. :^)
This commit is contained in:
		
							parent
							
								
									404de10a15
								
							
						
					
					
						commit
						c33d4aefc3
					
				
					 5 changed files with 132 additions and 1 deletions
				
			
		
							
								
								
									
										9
									
								
								Base/home/anon/js/try.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Base/home/anon/js/try.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| try { | ||||
|     console.log("you should see me"); | ||||
|     foo(); | ||||
|     console.log("not me"); | ||||
| } catch (e) { | ||||
|     console.log("catch"); | ||||
| } finally { | ||||
|     console.log("finally"); | ||||
| } | ||||
|  | @ -715,4 +715,44 @@ Value ArrayExpression::execute(Interpreter& interpreter) const | |||
|     return array; | ||||
| } | ||||
| 
 | ||||
| void TryStatement::dump(int indent) const | ||||
| { | ||||
|     ASTNode::dump(indent); | ||||
|     print_indent(indent); | ||||
|     printf("(Block)\n"); | ||||
|     block().dump(indent + 1); | ||||
| 
 | ||||
|     if (handler()) { | ||||
|         print_indent(indent); | ||||
|         printf("(Handler)\n"); | ||||
|         handler()->dump(indent + 1); | ||||
|     } | ||||
| 
 | ||||
|     if (finalizer()) { | ||||
|         print_indent(indent); | ||||
|         printf("(Finalizer)\n"); | ||||
|         finalizer()->dump(indent + 1); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void CatchClause::dump(int indent) const | ||||
| { | ||||
|     print_indent(indent); | ||||
|     printf("CatchClause"); | ||||
|     if (!m_parameter.is_null()) | ||||
|         printf(" (%s)", m_parameter.characters()); | ||||
|     printf("\n"); | ||||
|     body().dump(indent + 1); | ||||
| } | ||||
| 
 | ||||
| Value TryStatement::execute(Interpreter&) const | ||||
| { | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| Value CatchClause::execute(Interpreter&) const | ||||
| { | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -630,4 +630,49 @@ private: | |||
|     bool m_computed { false }; | ||||
| }; | ||||
| 
 | ||||
| class CatchClause final : public ASTNode { | ||||
| public: | ||||
|     CatchClause(const FlyString& parameter, NonnullRefPtr<BlockStatement> body) | ||||
|         : m_parameter(parameter) | ||||
|         , m_body(move(body)) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     const FlyString& parameter() const { return m_parameter; } | ||||
|     const BlockStatement& body() const { return m_body; } | ||||
| 
 | ||||
|     virtual void dump(int indent) const override; | ||||
|     virtual Value execute(Interpreter&) const override; | ||||
| 
 | ||||
| private: | ||||
|     virtual const char* class_name() const override { return "CatchClause"; } | ||||
| 
 | ||||
|     FlyString m_parameter; | ||||
|     NonnullRefPtr<BlockStatement> m_body; | ||||
| }; | ||||
| 
 | ||||
| class TryStatement final : public Statement { | ||||
| public: | ||||
|     TryStatement(NonnullRefPtr<BlockStatement> block, RefPtr<CatchClause> handler, RefPtr<BlockStatement> finalizer) | ||||
|         : m_block(move(block)) | ||||
|         , m_handler(move(handler)) | ||||
|         , m_finalizer(move(finalizer)) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     const BlockStatement& block() const { return m_block; } | ||||
|     const CatchClause* handler() const { return m_handler; } | ||||
|     const BlockStatement* finalizer() const { return m_finalizer; } | ||||
| 
 | ||||
|     virtual void dump(int indent) const override; | ||||
|     virtual Value execute(Interpreter&) const override; | ||||
| 
 | ||||
| private: | ||||
|     virtual const char* class_name() const override { return "TryStatement"; } | ||||
| 
 | ||||
|     NonnullRefPtr<BlockStatement> m_block; | ||||
|     RefPtr<CatchClause> m_handler; | ||||
|     RefPtr<BlockStatement> m_finalizer; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -197,6 +197,8 @@ NonnullRefPtr<Statement> Parser::parse_statement() | |||
|         return parse_for_statement(); | ||||
|     case TokenType::If: | ||||
|         return parse_if_statement(); | ||||
|     case TokenType::Try: | ||||
|         return parse_try_statement(); | ||||
|     default: | ||||
|         if (match_expression()) | ||||
|             return adopt(*new ExpressionStatement(parse_expression(0))); | ||||
|  | @ -518,6 +520,40 @@ NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration() | |||
|     return create_ast_node<VariableDeclaration>(create_ast_node<Identifier>(name), move(initializer), declaration_type); | ||||
| } | ||||
| 
 | ||||
| NonnullRefPtr<TryStatement> Parser::parse_try_statement() | ||||
| { | ||||
|     consume(TokenType::Try); | ||||
| 
 | ||||
|     auto block = parse_block_statement(); | ||||
| 
 | ||||
|     RefPtr<CatchClause> handler; | ||||
|     if (match(TokenType::Catch)) | ||||
|         handler = parse_catch_clause(); | ||||
| 
 | ||||
|     RefPtr<BlockStatement> finalizer; | ||||
|     if (match(TokenType::Finally)) { | ||||
|         consume(); | ||||
|         finalizer = parse_block_statement(); | ||||
|     } | ||||
| 
 | ||||
|     return create_ast_node<TryStatement>(move(block), move(handler), move(finalizer)); | ||||
| } | ||||
| 
 | ||||
| NonnullRefPtr<CatchClause> Parser::parse_catch_clause() | ||||
| { | ||||
|     consume(TokenType::Catch); | ||||
| 
 | ||||
|     String parameter; | ||||
|     if (match(TokenType::ParenOpen)) { | ||||
|         consume(); | ||||
|         parameter = consume(TokenType::Identifier).value(); | ||||
|         consume(TokenType::ParenClose); | ||||
|     } | ||||
| 
 | ||||
|     auto body = parse_block_statement(); | ||||
|     return create_ast_node<CatchClause>(parameter, move(body)); | ||||
| } | ||||
| 
 | ||||
| NonnullRefPtr<IfStatement> Parser::parse_if_statement() | ||||
| { | ||||
|     consume(TokenType::If); | ||||
|  | @ -660,7 +696,6 @@ bool Parser::match_statement() const | |||
|         || type == TokenType::Function | ||||
|         || type == TokenType::Return | ||||
|         || type == TokenType::Let | ||||
|         || type == TokenType::Catch | ||||
|         || type == TokenType::Class | ||||
|         || type == TokenType::Delete | ||||
|         || type == TokenType::Do | ||||
|  |  | |||
|  | @ -52,6 +52,8 @@ public: | |||
|     NonnullRefPtr<VariableDeclaration> parse_variable_declaration(); | ||||
|     NonnullRefPtr<ForStatement> parse_for_statement(); | ||||
|     NonnullRefPtr<IfStatement> parse_if_statement(); | ||||
|     NonnullRefPtr<TryStatement> parse_try_statement(); | ||||
|     NonnullRefPtr<CatchClause> parse_catch_clause(); | ||||
| 
 | ||||
|     NonnullRefPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right); | ||||
|     NonnullRefPtr<Expression> parse_primary_expression(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling