mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:22:45 +00:00 
			
		
		
		
	Shell: Provide completions to Tilde and its Juxtaposition.
This commit also removes the ExecutionInputType and directly uses RefPtr<Shell> instead, since nothing else is needed for execution purposes, and also makes the shell refuse to evaluate commands with any sort of syntax error.
This commit is contained in:
		
							parent
							
								
									c5d0aa9a44
								
							
						
					
					
						commit
						3a37e8c56f
					
				
					 5 changed files with 350 additions and 196 deletions
				
			
		|  | @ -112,7 +112,16 @@ RefPtr<AST::Node> Parser::parse() | |||
| { | ||||
|     m_offset = 0; | ||||
| 
 | ||||
|     return parse_toplevel(); | ||||
|     auto toplevel = parse_toplevel(); | ||||
| 
 | ||||
|     if (m_offset < m_input.length()) { | ||||
|         // Parsing stopped midway, this is a syntax error.
 | ||||
|         auto error_start = push_start(); | ||||
|         m_offset = m_input.length(); | ||||
|         return create<AST::Join>(move(toplevel), create<AST::SyntaxError>()); | ||||
|     } | ||||
| 
 | ||||
|     return toplevel; | ||||
| } | ||||
| 
 | ||||
| RefPtr<AST::Node> Parser::parse_toplevel() | ||||
|  | @ -207,9 +216,10 @@ RefPtr<AST::Node> Parser::parse_variable_decls() | |||
|         if (peek() == '(') { | ||||
|             consume(); | ||||
|             auto command = parse_pipe_sequence(); | ||||
|             expect(')'); | ||||
|             if (!command) | ||||
|                 m_offset = start->offset; | ||||
|             else if (!expect(')')) | ||||
|                 command->set_is_syntax_error(); | ||||
|             expression = command; | ||||
|         } | ||||
|     } | ||||
|  | @ -504,18 +514,26 @@ RefPtr<AST::Node> Parser::parse_string() | |||
|     if (peek() == '"') { | ||||
|         consume(); | ||||
|         auto inner = parse_doublequoted_string_inner(); | ||||
|         if (!expect('"') || !inner) | ||||
|             return create<AST::SyntaxError>(); | ||||
|         if (!inner) | ||||
|             inner = create<AST::SyntaxError>(); | ||||
|         if (!expect('"')) { | ||||
|             inner = create<AST::DoubleQuotedString>(move(inner)); | ||||
|             inner->set_is_syntax_error(); | ||||
|             return inner; | ||||
|         } | ||||
|         return create<AST::DoubleQuotedString>(move(inner)); // Double Quoted String
 | ||||
|     } | ||||
| 
 | ||||
|     if (peek() == '\'') { | ||||
|         consume(); | ||||
|         auto text = consume_while(is_not('\'')); | ||||
|         bool is_error = false; | ||||
|         if (!expect('\'')) | ||||
|             return create<AST::SyntaxError>(); | ||||
| 
 | ||||
|         return create<AST::StringLiteral>(move(text)); // String Literal
 | ||||
|             is_error = true; | ||||
|         auto result = create<AST::StringLiteral>(move(text)); // String Literal
 | ||||
|         if (is_error) | ||||
|             result->set_is_syntax_error(); | ||||
|         return move(result); | ||||
|     } | ||||
| 
 | ||||
|     return nullptr; | ||||
|  | @ -648,11 +666,11 @@ RefPtr<AST::Node> Parser::parse_evaluate() | |||
|     if (peek() == '(') { | ||||
|         consume(); | ||||
|         auto inner = parse_pipe_sequence(); | ||||
|         if (!inner || !expect(')')) | ||||
|         if (!inner) | ||||
|             inner = create<AST::SyntaxError>(); | ||||
|         else | ||||
|             inner = create<AST::Execute>(move(inner), true); | ||||
|         return inner; | ||||
|         if (!expect(')')) | ||||
|             inner->set_is_syntax_error(); | ||||
|         return create<AST::Execute>(move(inner), true); | ||||
|     } | ||||
|     auto inner = parse_expression(); | ||||
| 
 | ||||
|  | @ -718,9 +736,12 @@ RefPtr<AST::Node> Parser::parse_bareword() | |||
|     if (builder.is_empty()) | ||||
|         return nullptr; | ||||
| 
 | ||||
|     auto current_end = m_offset; | ||||
|     auto string = builder.to_string(); | ||||
|     if (string.starts_with('~')) { | ||||
|         String username; | ||||
|         RefPtr<AST::Node> tilde, text; | ||||
| 
 | ||||
|         auto first_slash_index = string.index_of("/"); | ||||
|         if (first_slash_index.has_value()) { | ||||
|             username = string.substring_view(1, first_slash_index.value() - 1); | ||||
|  | @ -729,21 +750,33 @@ RefPtr<AST::Node> Parser::parse_bareword() | |||
|             username = string.substring_view(1, string.length() - 1); | ||||
|             string = ""; | ||||
|         } | ||||
|         auto current_end = m_offset; | ||||
|         m_offset -= string.length(); | ||||
|         auto tilde = create<AST::Tilde>(move(username)); | ||||
|         auto text_start = push_start(); | ||||
|         m_offset = current_end; | ||||
| 
 | ||||
|         // Synthesize a Tilde Node with the correct positioning information.
 | ||||
|         { | ||||
|             m_offset -= string.length(); | ||||
|             tilde = create<AST::Tilde>(move(username)); | ||||
|         } | ||||
| 
 | ||||
|         if (string.is_empty()) | ||||
|             return tilde; | ||||
|         return create<AST::StringPartCompose>(move(tilde), create<AST::BarewordLiteral>(move(string))); // Compose Varible Bareword
 | ||||
| 
 | ||||
|         // Synthesize a BarewordLiteral Node with the correct positioning information.
 | ||||
|         { | ||||
|             m_offset = tilde->position().end_offset; | ||||
|             auto text_start = push_start(); | ||||
|             m_offset = current_end; | ||||
|             text = create<AST::BarewordLiteral>(move(string)); | ||||
|         } | ||||
| 
 | ||||
|         return create<AST::Juxtaposition>(move(tilde), move(text)); // Juxtaposition Varible Bareword
 | ||||
|     } | ||||
| 
 | ||||
|     if (string.starts_with("\\~")) { | ||||
|         // Un-escape the tilde, but only at the start (where it would be an expansion)
 | ||||
|         string = string.substring(1, string.length() - 1); | ||||
|     } | ||||
| 
 | ||||
|     return create<AST::BarewordLiteral>(builder.to_string()); // Bareword Literal
 | ||||
|     return create<AST::BarewordLiteral>(move(string)); // Bareword Literal
 | ||||
| } | ||||
| 
 | ||||
| RefPtr<AST::Node> Parser::parse_glob() | ||||
|  | @ -757,17 +790,17 @@ RefPtr<AST::Node> Parser::parse_glob() | |||
|     char ch = peek(); | ||||
|     if (ch == '*' || ch == '?') { | ||||
|         consume(); | ||||
|         // FIXME: Join all parts before making AST nodes
 | ||||
|         StringBuilder textbuilder; | ||||
|         if (bareword_part) { | ||||
|             ASSERT(bareword_part->is_bareword() || bareword_part->is_tilde()); | ||||
|             StringView text; | ||||
|             if (bareword_part->is_tilde()) { | ||||
|             if (bareword_part->is_bareword()) { | ||||
|                 auto bareword = static_cast<AST::BarewordLiteral*>(bareword_part.ptr()); | ||||
|                 text = bareword->text(); | ||||
|             } else { | ||||
|                 auto tilde = static_cast<AST::Tilde*>(bareword_part.ptr()); | ||||
|                 text = tilde->text(); | ||||
|                 // FIXME: Allow composition of tilde+bareword with globs: '~/foo/bar/baz*'
 | ||||
|                 putback(); | ||||
|                 bareword_part->set_is_syntax_error(); | ||||
|                 return bareword_part; | ||||
|             } | ||||
|             textbuilder.append(text); | ||||
|         } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 AnotherTest
						AnotherTest