oysh/crates/oyster_parser/tests/it/cst.rs
Charlotte Meyer cfd15122ab fix(parser): make ; be part of the statement
Signed-off-by: Charlotte Meyer <dev@buffet.sh>
2022-11-07 13:41:28 +00:00

1105 lines
40 KiB
Rust

use expect_test::{expect, Expect};
use oyster_parser::ParseTree;
fn check(s: &str, expect: Expect) {
let actual = ParseTree::from(s);
expect.assert_debug_eq(&actual);
}
#[test]
fn empty() {
check(
"",
expect![[r#"
Tree {
kind: Program,
children: [],
}
"#]],
);
}
#[test]
fn word() {
check(
"word",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 4,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn word_with_escape() {
check(
r"hello\#world",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 5,
},
Leaf {
kind: EscapedChar,
len: 2,
},
Leaf {
kind: PlainText,
len: 5,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn unicode() {
check(
"谚语",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn simple_command() {
check(
"echo hi",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 4,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 2,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn semicolon() {
check(
"hello; hi",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 5,
},
],
},
],
},
Leaf {
kind: Semicolon,
len: 1,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 2,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn comment() {
let source = r"# a
# b";
check(
source,
expect![[r#"
Tree {
kind: Program,
children: [
Leaf {
kind: Comment,
len: 3,
},
Leaf {
kind: Newlines,
len: 1,
},
Leaf {
kind: Comment,
len: 3,
},
],
}
"#]],
);
}
#[test]
fn inline_comment() {
check(
"whoami # hello",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
Leaf {
kind: Comment,
len: 7,
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn pipeline() {
check(
"whoami | cat",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
],
},
Leaf {
kind: Pipe,
len: 1,
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 3,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn multiline_pipeline() {
let source = r"whoami |
wc -l";
check(
source,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
],
},
Leaf {
kind: Pipe,
len: 1,
},
Leaf {
kind: Newlines,
len: 1,
},
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 2,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 2,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn comment_in_pipeline() {
let source = r"whoami | # comment
wc -l";
check(
source,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
],
},
Leaf {
kind: Pipe,
len: 1,
},
Leaf {
kind: Whitespace,
len: 1,
},
Leaf {
kind: Comment,
len: 9,
},
Leaf {
kind: Newlines,
len: 1,
},
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 2,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 2,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn reject_leading_pipe() {
let source = r"whoami
| cat";
check(
source,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
],
},
],
},
Leaf {
kind: Newlines,
len: 1,
},
Error {
kind: UnexpectedPipe,
len: 1,
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 3,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn reject_trailing_pipe() {
check(
"whoami |",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
],
},
Leaf {
kind: Pipe,
len: 1,
},
Error {
kind: UnexpectedEof,
len: 0,
},
],
},
],
}
"#]],
);
}
#[test]
fn reject_pipe_semicolon() {
let source = "whoami | ; cat";
check(
source,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
],
},
Leaf {
kind: Pipe,
len: 1,
},
Leaf {
kind: Whitespace,
len: 1,
},
Error {
kind: UnexpectedSemicolon,
len: 1,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 3,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn reject_double_pipe() {
check(
"whoami | | cat",
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
],
},
Leaf {
kind: Pipe,
len: 1,
},
Leaf {
kind: Whitespace,
len: 1,
},
Error {
kind: UnexpectedPipe,
len: 1,
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 3,
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn double_quote_string() {
check(
r#""hello world""#,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Tree {
kind: DQuotedString,
children: [
Leaf {
kind: DoubleQuote,
len: 1,
},
Leaf {
kind: PlainText,
len: 11,
},
Leaf {
kind: DoubleQuote,
len: 1,
},
],
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn escaped_char_in_double_quotes() {
check(
r#""hello \" world""#,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Tree {
kind: DQuotedString,
children: [
Leaf {
kind: DoubleQuote,
len: 1,
},
Leaf {
kind: PlainText,
len: 6,
},
Leaf {
kind: EscapedChar,
len: 2,
},
Leaf {
kind: PlainText,
len: 6,
},
Leaf {
kind: DoubleQuote,
len: 1,
},
],
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn unterminated_double_quotes() {
check(
r#""hello world"#,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Tree {
kind: DQuotedString,
children: [
Leaf {
kind: DoubleQuote,
len: 1,
},
Leaf {
kind: PlainText,
len: 11,
},
Error {
kind: UnexpectedEof,
len: 0,
},
],
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn command_substitution() {
check(
r#"echo (whoami)"#,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 4,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Word,
children: [
Tree {
kind: CommandSubstitution,
children: [
Leaf {
kind: OpeningParenthesis,
len: 1,
},
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
],
},
],
},
Leaf {
kind: ClosingParenthesis,
len: 1,
},
],
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn quoted_command_substitution() {
let source = r#"echo "(whoami)
""#;
check(
source,
expect![[r#"
Tree {
kind: Program,
children: [
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 4,
},
],
},
Leaf {
kind: Whitespace,
len: 1,
},
Tree {
kind: Word,
children: [
Tree {
kind: DQuotedString,
children: [
Leaf {
kind: DoubleQuote,
len: 1,
},
Tree {
kind: CommandSubstitution,
children: [
Leaf {
kind: OpeningParenthesis,
len: 1,
},
Tree {
kind: Pipeline,
children: [
Tree {
kind: Command,
children: [
Tree {
kind: Word,
children: [
Leaf {
kind: PlainText,
len: 6,
},
],
},
],
},
],
},
Leaf {
kind: ClosingParenthesis,
len: 1,
},
],
},
Leaf {
kind: PlainText,
len: 9,
},
Leaf {
kind: DoubleQuote,
len: 1,
},
],
},
],
},
],
},
],
},
],
}
"#]],
);
}
#[test]
fn empty_pipeline() {
check(
";",
expect![[r#"
Tree {
kind: Program,
children: [
Leaf {
kind: Semicolon,
len: 1,
},
],
}
"#]],
);
}