diff options
| author | Lucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br> | 2025-12-05 06:49:44 +0000 |
|---|---|---|
| committer | Lucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br> | 2025-12-05 06:49:44 +0000 |
| commit | ed5493f9825d7244bb489d160208bf708641d0b8 (patch) | |
| tree | a412af2160d7a8ce1d6a240e3eaed839138a8115 /src/parser.zig | |
| parent | 6f1c762e789cd746e20cd7597aab0316d2c2fcd9 (diff) | |
| download | shell-zig-ed5493f9825d7244bb489d160208bf708641d0b8.tar.gz shell-zig-ed5493f9825d7244bb489d160208bf708641d0b8.zip | |
codecrafters submit [skip ci]
Diffstat (limited to 'src/parser.zig')
| -rw-r--r-- | src/parser.zig | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/src/parser.zig b/src/parser.zig index 680eadb..33b3c3a 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -4,6 +4,7 @@ pub const ParsedCommand = struct { name: []const u8, args: ?[]const u8, output_redirect: ?[]const u8, + error_redirect: ?[]const u8, }; pub fn parseCommand(input: []const u8) ParsedCommand { @@ -14,7 +15,7 @@ pub fn parseCommand(input: []const u8) ParsedCommand { while (i < input.len and input[i] == ' ') : (i += 1) {} if (i >= input.len) { - return .{ .name = "", .args = null, .output_redirect = null }; + return .{ .name = "", .args = null, .output_redirect = null, .error_redirect = null }; } if (input[i] == '\'' or input[i] == '"') { @@ -38,21 +39,40 @@ pub fn parseCommand(input: []const u8) ParsedCommand { while (i < input.len and input[i] == ' ') : (i += 1) {} var redirect_pos: ?usize = null; + var error_redirect_pos: ?usize = null; var j = i; while (j < input.len) : (j += 1) { - if (input[j] == '>' or (input[j] == '1' and j + 1 < input.len and input[j + 1] == '>')) { + if (j + 1 < input.len and input[j] == '2' and input[j + 1] == '>') { + error_redirect_pos = j; + j += 1; + } else if (input[j] == '1' and j + 1 < input.len and input[j + 1] == '>') { + redirect_pos = j; + j += 1; + } else if (input[j] == '>') { redirect_pos = j; - break; } } const cmd_name = cmd_buf.toOwnedSlice(std.heap.page_allocator) catch ""; var args: ?[]const u8 = null; var output_redirect: ?[]const u8 = null; + var error_redirect: ?[]const u8 = null; + var args_end = input.len; if (redirect_pos) |pos| { - if (pos > i) args = input[i..pos]; + if (pos < args_end) args_end = pos; + } + if (error_redirect_pos) |pos| { + if (pos < args_end) args_end = pos; + } + + while (args_end > i and input[args_end - 1] == ' ') : (args_end -= 1) {} + + if (args_end > i) { + args = input[i..args_end]; + } + if (redirect_pos) |pos| { var k = pos; if (input[k] == '1') k += 1; if (k < input.len and input[k] == '>') k += 1; @@ -63,16 +83,29 @@ pub fn parseCommand(input: []const u8) ParsedCommand { var redir_buf = std.ArrayList(u8){}; defer redir_buf.deinit(std.heap.page_allocator); - while (k < input.len and input[k] != ' ') : (k += 1) { + while (k < input.len and input[k] != ' ' and !(k + 1 < input.len and input[k] == '2' and input[k + 1] == '>')) : (k += 1) { _ = redir_buf.append(std.heap.page_allocator, input[k]) catch {}; } output_redirect = redir_buf.toOwnedSlice(std.heap.page_allocator) catch null; } - } else if (i < input.len) { - args = input[i..]; } - return .{ .name = cmd_name, .args = args, .output_redirect = output_redirect }; + if (error_redirect_pos) |pos| { + var k = pos + 2; + while (k < input.len and input[k] == ' ') : (k += 1) {} + + if (k < input.len) { + var redir_buf = std.ArrayList(u8){}; + defer redir_buf.deinit(std.heap.page_allocator); + + while (k < input.len and input[k] != ' ') : (k += 1) { + _ = redir_buf.append(std.heap.page_allocator, input[k]) catch {}; + } + error_redirect = redir_buf.toOwnedSlice(std.heap.page_allocator) catch null; + } + } + + return .{ .name = cmd_name, .args = args, .output_redirect = output_redirect, .error_redirect = error_redirect }; } pub fn parseArgs(allocator: std.mem.Allocator, cmd_name: []const u8, args_str: ?[]const u8) ![]const []const u8 { |