mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	Fix parsing inner class declaration when "pass" keyword is on the same line
Implement a special case for allowing "pass" keyword in one-liner class declaration, to be consistent with Python style. ``` class TestClass: pass ``` This commit fixes #56703
This commit is contained in:
		
							parent
							
								
									3c35617c50
								
							
						
					
					
						commit
						5bcc3d476c
					
				
					 2 changed files with 62 additions and 19 deletions
				
			
		|  | @ -82,8 +82,51 @@ void GDScriptParser::_set_end_statement_error(String p_name) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { | bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { | ||||||
|  | 	if (!_parse_colon()) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { | ||||||
|  | 		// Be more Python-like.
 | ||||||
|  | 		IndentLevel current_level = indent_level.back()->get(); | ||||||
|  | 		indent_level.push_back(current_level); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return _parse_indent_block_newlines(p_block); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GDScriptParser::_enter_inner_class_indent_block() { | ||||||
|  | 	if (!_parse_colon()) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { | ||||||
|  | 		// Check Python-like one-liner class declaration "class Foo: pass".
 | ||||||
|  | 		// Note: only "pass" is allowed on the same line after the colon.
 | ||||||
|  | 		if (tokenizer->get_token() != GDScriptTokenizer::TK_CF_PASS) { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		GDScriptTokenizer::Token token = tokenizer->get_token(1); | ||||||
|  | 		if (token != GDScriptTokenizer::TK_NEWLINE && token != GDScriptTokenizer::TK_EOF) { | ||||||
|  | 			int line = tokenizer->get_token_line(); | ||||||
|  | 			int col = tokenizer->get_token_column(); | ||||||
|  | 			String message = "Invalid syntax: unexpected \""; | ||||||
|  | 			message += GDScriptTokenizer::get_token_name(token); | ||||||
|  | 			message += "\"."; | ||||||
|  | 			_set_error(message, line, col); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return _parse_indent_block_newlines(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool GDScriptParser::_parse_colon() { | ||||||
| 	if (tokenizer->get_token() != GDScriptTokenizer::TK_COLON) { | 	if (tokenizer->get_token() != GDScriptTokenizer::TK_COLON) { | ||||||
| 		// report location at the previous token (on the previous line)
 | 		// Report location at the previous token (on the previous line).
 | ||||||
| 		int error_line = tokenizer->get_token_line(-1); | 		int error_line = tokenizer->get_token_line(-1); | ||||||
| 		int error_column = tokenizer->get_token_column(-1); | 		int error_column = tokenizer->get_token_column(-1); | ||||||
| 		_set_error("':' expected at end of line.", error_line, error_column); | 		_set_error("':' expected at end of line.", error_line, error_column); | ||||||
|  | @ -95,19 +138,12 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { |  | ||||||
| 		// be more python-like
 |  | ||||||
| 		IndentLevel current_level = indent_level.back()->get(); |  | ||||||
| 		indent_level.push_back(current_level); |  | ||||||
| 	return true; | 	return true; | ||||||
| 		//_set_error("newline expected after ':'.");
 | } | ||||||
| 		//return false;
 |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
|  | bool GDScriptParser::_parse_indent_block_newlines(BlockNode *p_block) { | ||||||
| 	while (true) { | 	while (true) { | ||||||
| 		if (tokenizer->get_token() != GDScriptTokenizer::TK_NEWLINE) { | 		if (tokenizer->get_token(1) == GDScriptTokenizer::TK_EOF) { | ||||||
| 			return false; //wtf
 |  | ||||||
| 		} else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_EOF) { |  | ||||||
| 			return false; | 			return false; | ||||||
| 		} else if (tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) { | 		} else if (tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE) { | ||||||
| 			int indent = tokenizer->get_token_line_indent(); | 			int indent = tokenizer->get_token_line_indent(); | ||||||
|  | @ -126,14 +162,13 @@ bool GDScriptParser::_enter_indent_block(BlockNode *p_block) { | ||||||
| 			indent_level.push_back(new_indent); | 			indent_level.push_back(new_indent); | ||||||
| 			tokenizer->advance(); | 			tokenizer->advance(); | ||||||
| 			return true; | 			return true; | ||||||
| 
 |  | ||||||
| 		} else if (p_block) { | 		} else if (p_block) { | ||||||
| 			NewLineNode *nl = alloc_node<NewLineNode>(); | 			NewLineNode *nl = alloc_node<NewLineNode>(); | ||||||
| 			nl->line = tokenizer->get_token_line(); | 			nl->line = tokenizer->get_token_line(); | ||||||
| 			p_block->statements.push_back(nl); | 			p_block->statements.push_back(nl); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		tokenizer->advance(); // go to next newline
 | 		tokenizer->advance(); // Go to the next newline.
 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -3840,13 +3875,18 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (!_enter_indent_block()) { | 				if (!_enter_inner_class_indent_block()) { | ||||||
| 					_set_error("Indented block expected."); | 					if (!error_set) { | ||||||
|  | 						_set_error("Indented block or \"pass\" expected."); | ||||||
|  | 					} | ||||||
| 					return; | 					return; | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
|  | 				if (tokenizer->get_token() != GDScriptTokenizer::TK_CF_PASS) { | ||||||
| 					current_class = newclass; | 					current_class = newclass; | ||||||
| 					_parse_class(newclass); | 					_parse_class(newclass); | ||||||
| 					current_class = p_class; | 					current_class = p_class; | ||||||
|  | 				} | ||||||
| 
 | 
 | ||||||
| 			} break; | 			} break; | ||||||
| 			/* this is for functions....
 | 			/* this is for functions....
 | ||||||
|  |  | ||||||
|  | @ -599,6 +599,9 @@ private: | ||||||
| 
 | 
 | ||||||
| 	bool _parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete = false, bool p_parsing_constant = false); | 	bool _parse_arguments(Node *p_parent, Vector<Node *> &p_args, bool p_static, bool p_can_codecomplete = false, bool p_parsing_constant = false); | ||||||
| 	bool _enter_indent_block(BlockNode *p_block = nullptr); | 	bool _enter_indent_block(BlockNode *p_block = nullptr); | ||||||
|  | 	bool _enter_inner_class_indent_block(); | ||||||
|  | 	bool _parse_colon(); | ||||||
|  | 	bool _parse_indent_block_newlines(BlockNode *p_block = nullptr); | ||||||
| 	bool _parse_newline(); | 	bool _parse_newline(); | ||||||
| 	Node *_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign = false, bool p_parsing_constant = false); | 	Node *_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign = false, bool p_parsing_constant = false); | ||||||
| 	Node *_reduce_expression(Node *p_node, bool p_to_const = false); | 	Node *_reduce_expression(Node *p_node, bool p_to_const = false); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kirill Diduk
						Kirill Diduk