mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 00:42:44 +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; |     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 }; |     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(); |         return parse_for_statement(); | ||||||
|     case TokenType::If: |     case TokenType::If: | ||||||
|         return parse_if_statement(); |         return parse_if_statement(); | ||||||
|  |     case TokenType::Try: | ||||||
|  |         return parse_try_statement(); | ||||||
|     default: |     default: | ||||||
|         if (match_expression()) |         if (match_expression()) | ||||||
|             return adopt(*new ExpressionStatement(parse_expression(0))); |             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); |     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() | NonnullRefPtr<IfStatement> Parser::parse_if_statement() | ||||||
| { | { | ||||||
|     consume(TokenType::If); |     consume(TokenType::If); | ||||||
|  | @ -660,7 +696,6 @@ bool Parser::match_statement() const | ||||||
|         || type == TokenType::Function |         || type == TokenType::Function | ||||||
|         || type == TokenType::Return |         || type == TokenType::Return | ||||||
|         || type == TokenType::Let |         || type == TokenType::Let | ||||||
|         || type == TokenType::Catch |  | ||||||
|         || type == TokenType::Class |         || type == TokenType::Class | ||||||
|         || type == TokenType::Delete |         || type == TokenType::Delete | ||||||
|         || type == TokenType::Do |         || type == TokenType::Do | ||||||
|  |  | ||||||
|  | @ -52,6 +52,8 @@ public: | ||||||
|     NonnullRefPtr<VariableDeclaration> parse_variable_declaration(); |     NonnullRefPtr<VariableDeclaration> parse_variable_declaration(); | ||||||
|     NonnullRefPtr<ForStatement> parse_for_statement(); |     NonnullRefPtr<ForStatement> parse_for_statement(); | ||||||
|     NonnullRefPtr<IfStatement> parse_if_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_expression(int min_precedence, Associativity associate = Associativity::Right); | ||||||
|     NonnullRefPtr<Expression> parse_primary_expression(); |     NonnullRefPtr<Expression> parse_primary_expression(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling