Skip to content

Commit d643b21

Browse files
author
Test
committed
feat(parser): add Pipe token for pipeline support (Phase 6 M3 Component 1)
- Add Token::Pipe variant to Token enum - Tokenize '|' operator in tokenize() function - Add placeholder error for pipelines in parse_command() - Add 3 unit tests for pipe tokenization - All 93 tests passing (47 unit + 27 integration + 19 property) Part of Phase 6 Milestone 3: Pipeline implementation
1 parent ce407d8 commit d643b21

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

impl/rust-cli/src/parser.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ enum Token {
3535

3636
/// Both output redirection (bash extension): &>
3737
BothRedirect,
38+
39+
/// Pipeline operator: |
40+
Pipe,
3841
}
3942

4043
/// Parsed command with arguments and redirections.
@@ -219,6 +222,16 @@ fn tokenize(input: &str) -> Vec<Token> {
219222
}
220223
}
221224

225+
'|' => {
226+
// End current word
227+
if !current_word.is_empty() {
228+
tokens.push(Token::Word(current_word.clone()));
229+
current_word.clear();
230+
}
231+
232+
tokens.push(Token::Pipe);
233+
}
234+
222235
// Regular character
223236
_ => {
224237
current_word.push(ch);
@@ -319,6 +332,10 @@ pub fn parse_command(input: &str) -> Result<Command> {
319332
redirects.push(Redirection::BothOutput { file });
320333
i += 2;
321334
}
335+
336+
Token::Pipe => {
337+
return Err(anyhow!("Pipelines not yet implemented (Phase 6 M3)"));
338+
}
322339
}
323340
}
324341

@@ -709,6 +726,39 @@ mod tests {
709726
assert_eq!(tokens[1], Token::ErrorToOutput);
710727
}
711728

729+
#[test]
730+
fn test_tokenize_pipe() {
731+
let tokens = tokenize("ls | grep test");
732+
assert_eq!(tokens.len(), 4);
733+
assert_eq!(tokens[0], Token::Word("ls".to_string()));
734+
assert_eq!(tokens[1], Token::Pipe);
735+
assert_eq!(tokens[2], Token::Word("grep".to_string()));
736+
assert_eq!(tokens[3], Token::Word("test".to_string()));
737+
}
738+
739+
#[test]
740+
fn test_tokenize_multi_pipe() {
741+
let tokens = tokenize("cat file.txt | grep foo | wc -l");
742+
assert_eq!(tokens.len(), 8);
743+
assert_eq!(tokens[0], Token::Word("cat".to_string()));
744+
assert_eq!(tokens[1], Token::Word("file.txt".to_string()));
745+
assert_eq!(tokens[2], Token::Pipe);
746+
assert_eq!(tokens[3], Token::Word("grep".to_string()));
747+
assert_eq!(tokens[4], Token::Word("foo".to_string()));
748+
assert_eq!(tokens[5], Token::Pipe);
749+
assert_eq!(tokens[6], Token::Word("wc".to_string()));
750+
assert_eq!(tokens[7], Token::Word("-l".to_string()));
751+
}
752+
753+
#[test]
754+
fn test_tokenize_pipe_with_redirect() {
755+
let tokens = tokenize("ls | grep test > output.txt");
756+
assert_eq!(tokens.len(), 6);
757+
assert_eq!(tokens[1], Token::Pipe);
758+
assert_eq!(tokens[4], Token::OutputRedirect);
759+
assert_eq!(tokens[5], Token::Word("output.txt".to_string()));
760+
}
761+
712762
#[test]
713763
fn test_parse_empty() {
714764
assert!(parse_command("").is_err());

0 commit comments

Comments
 (0)