From 142b9db16f007ebbc8fb51deb03d0ac513738c69 Mon Sep 17 00:00:00 2001 From: prsabahrami Date: Sat, 7 Sep 2024 18:08:06 -0400 Subject: [PATCH] Complex commands parsing fix --- crates/deno_task_shell/src/grammar.pest | 38 +++++++++++++------------ crates/deno_task_shell/src/parser.rs | 2 -- scripts/for_loop.sh | 23 +++++++++++++++ scripts/if_else.sh | 5 ++++ scripts/while_loop.sh | 5 ++++ 5 files changed, 53 insertions(+), 20 deletions(-) create mode 100644 scripts/for_loop.sh create mode 100644 scripts/if_else.sh create mode 100644 scripts/while_loop.sh diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest index 600cedd..0b270ee 100644 --- a/crates/deno_task_shell/src/grammar.pest +++ b/crates/deno_task_shell/src/grammar.pest @@ -7,12 +7,12 @@ COMMENT = _{ "#" ~ (!NEWLINE ~ ANY)* } // Basic tokens QUOTED_WORD = { DOUBLE_QUOTED | SINGLE_QUOTED } -UNQUOTED_PENDING_WORD = ${ - (!(WHITESPACE | OPERATOR | NEWLINE) ~ ( +UNQUOTED_PENDING_WORD = ${ !OPERATOR ~ + (!(WHITESPACE | NEWLINE) ~ ( EXIT_STATUS | UNQUOTED_ESCAPE_CHAR | SUB_COMMAND | - ("$" ~ VARIABLE) | + ("$" ~ "{" ~ VARIABLE ~ "}" | "$" ~ VARIABLE) | UNQUOTED_CHAR | QUOTED_WORD ) @@ -24,18 +24,18 @@ QUOTED_PENDING_WORD = ${ ( EXIT_STATUS | QUOTED_ESCAPE_CHAR | SUB_COMMAND | - ("$" ~ VARIABLE) | + ("$" ~ "{" ~ VARIABLE ~ "}" | "$" ~ VARIABLE) | QUOTED_CHAR )* } -UNQUOTED_ESCAPE_CHAR = ${ ("\\" ~ "$" | "$" ~ !"(" ~ !VARIABLE) | "\\" ~ (" " | "`" | "\"" | "(" | ")")* } -QUOTED_ESCAPE_CHAR = ${ "\\" ~ "$" | "$" ~ !"(" ~ !VARIABLE | "\\" ~ ("`" | "\"" | "(" | ")" | "'")* } +UNQUOTED_ESCAPE_CHAR = ${ ("\\" ~ "$" | "$" ~ !"(" ~ !"{" ~ !VARIABLE) | "\\" ~ (" " | "`" | "\"" | "(" | ")")* } +QUOTED_ESCAPE_CHAR = ${ "\\" ~ "$" | "$" ~ !"(" ~ !"{" ~ !VARIABLE | "\\" ~ ("`" | "\"" | "(" | ")" | "'")* } -UNQUOTED_CHAR = ${ ("\\" ~ " ") | !("(" | ")" | "{" | "}" | "<" | ">" | "|" | "&" | ";" | "\"" | "'" | "$") ~ ANY } +UNQUOTED_CHAR = ${ ("\\" ~ " ") | !("]]" | "[[" | "(" | ")" | "<" | ">" | "|" | "&" | ";" | "\"" | "'" | "$") ~ ANY } QUOTED_CHAR = ${ !"\"" ~ ANY } VARIABLE = ${ (ASCII_ALPHANUMERIC | "_")+ } -SUB_COMMAND = { "$(" ~ complete_command ~ ")" } +SUB_COMMAND = { "$(" ~ complete_command ~ ")"} DOUBLE_QUOTED = @{ "\"" ~ QUOTED_PENDING_WORD ~ "\"" } SINGLE_QUOTED = @{ "'" ~ (!"'" ~ ANY)* ~ "'" } @@ -64,7 +64,7 @@ EXIT_STATUS = ${ "$?" } // Operators OPERATOR = _{ AND_IF | OR_IF | DSEMI | DLESS | DGREAT | LESSAND | GREATAND | LESSGREAT | DLESSDASH | CLOBBER | - "(" | ")" | "{" | "}" | ";" | "&" | "|" | "<" | ">" + "," |"(" | ")" | "{" | "}" | ";" | "&" | "|" | "<" | ">" } // Reserved words @@ -102,12 +102,13 @@ pipeline = !{ Bang? ~ pipe_sequence } pipe_sequence = !{ command ~ ((StdoutStderr | Stdout) ~ linebreak ~ pipe_sequence)? } command = !{ - simple_command | compound_command ~ redirect_list? | + simple_command | function_definition } compound_command = { + double_square_bracket | brace_group | subshell | for_clause | @@ -123,10 +124,12 @@ term = !{ and_or ~ (separator ~ and_or)* } for_clause = { For ~ name ~ linebreak ~ - (linebreak ~ In ~ wordlist? ~ sequential_sep)? ~ - linebreak ~ do_group + (In ~ (brace_group | wordlist)? ~ sequential_sep)? ~ + do_group } +double_square_bracket = !{ "[[" ~ compound_list ~ "]]" } + case_clause = !{ Case ~ UNQUOTED_PENDING_WORD ~ linebreak ~ linebreak ~ In ~ linebreak ~ @@ -156,14 +159,13 @@ pattern = !{ if_clause = !{ If ~ compound_list ~ - Then ~ compound_list ~ - else_part? ~ - Fi + linebreak ~ Then ~ linebreak ~ compound_list ~ linebreak ~ + else_part? ~ linebreak ~ Fi } else_part = !{ - Elif ~ compound_list ~ Then ~ else_part | - Else ~ compound_list + Elif ~ compound_list ~ Then ~ linebreak ~ else_part | + Else ~ linebreak ~ compound_list } while_clause = !{ While ~ compound_list ~ do_group } @@ -185,7 +187,7 @@ simple_command = !{ cmd_prefix = !{ (io_redirect | ASSIGNMENT_WORD)+ } cmd_suffix = !{ (io_redirect | UNQUOTED_PENDING_WORD)+ } -cmd_name = @{ (RESERVED_WORD | UNQUOTED_PENDING_WORD) } +cmd_name = @{ !RESERVED_WORD ~ UNQUOTED_PENDING_WORD } cmd_word = @{ (ASSIGNMENT_WORD | UNQUOTED_PENDING_WORD) } redirect_list = !{ io_redirect+ } diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index 27919df..53aebb2 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -332,8 +332,6 @@ struct ShellParser; pub fn parse(input: &str) -> Result { let mut pairs = ShellParser::parse(Rule::FILE, input)?; - // println!("pairs: {:?}", pairs); - parse_file(pairs.next().unwrap()) } diff --git a/scripts/for_loop.sh b/scripts/for_loop.sh new file mode 100644 index 0000000..9174943 --- /dev/null +++ b/scripts/for_loop.sh @@ -0,0 +1,23 @@ +# for i in {1..10}; do +# echo $i +# done + + +for i in $(seq 1 2 20); do + echo $i +done + + +# for i in {1..10..2}; do +# echo $i +# done + + +# for i in $(1,2,3,4,5); do +# echo $i +# done + + +for i in $(ls); do + printf "%s\n" "$i" +done \ No newline at end of file diff --git a/scripts/if_else.sh b/scripts/if_else.sh new file mode 100644 index 0000000..eaa9fa9 --- /dev/null +++ b/scripts/if_else.sh @@ -0,0 +1,5 @@ +if [[ $FOO == "bar" ]] then + echo "FOO is bar" +else + echo "FOO is not bar" +fi \ No newline at end of file diff --git a/scripts/while_loop.sh b/scripts/while_loop.sh new file mode 100644 index 0000000..eb0a5ea --- /dev/null +++ b/scripts/while_loop.sh @@ -0,0 +1,5 @@ +COUNTER=-5 +while [[ $COUNTER -lt 5 ]]; do + echo The counter is $COUNTER + let COUNTER=COUNTER+1 +done \ No newline at end of file