From 527b3e33399dc4075339463f2b1f0478bb61ca6b Mon Sep 17 00:00:00 2001 From: André Aparício Date: Sat, 11 Aug 2012 02:17:05 +0100 Subject: Parser&Walker: Support nested command substitution --- bashast/bashast.g | 2 +- bashast/libbashWalker.g | 15 ++++++++++++--- scripts/command_execution.bash | 4 ++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/bashast/bashast.g b/bashast/bashast.g index 799b1cf..2226839 100644 --- a/bashast/bashast.g +++ b/bashast/bashast.g @@ -1197,7 +1197,7 @@ COMMAND_SUBSTITUTION_PAREN | . )+ )); -COMMAND_SUBSTITUTION_TICK : TICK (~(TICK))+ TICK; +COMMAND_SUBSTITUTION_TICK : TICK .+ (~ESC) TICK; ESC_LT : ESC'<'; ESC_GT : ESC'>'; diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g index 768129f..f50b32c 100644 --- a/bashast/libbashWalker.g +++ b/bashast/libbashWalker.g @@ -1132,13 +1132,22 @@ command_substitution returns[std::string libbash_value] @declarations { std::string subscript; std::stringstream out; + current_streams streams(walker->get_output_stream(), walker->get_error_stream(), walker->get_input_stream()); } :^(COMMAND_SUB { walker->set_output_stream(&out); } (libbash_string=any_string { subscript += libbash_string; })+) { - if(subscript[0] == '`') - bash_ast(std::stringstream(subscript.substr(1, subscript.size() - 2))).interpret_with(*walker); + if(subscript[0] == '`') { + std::string sub = subscript.substr(1, subscript.size() - 2); + // Escape \ and ' for nested command substitution + size_t pos = 0; + while((pos = sub.find("\\\\", pos)) != std::string::npos) + sub.erase(pos++, 1); + pos = 0; + while((pos = sub.find("\\`", pos)) != std::string::npos) + sub.erase(pos++, 1); + bash_ast(std::stringstream(sub)).interpret_with(*walker); + } else bash_ast(std::stringstream(subscript.substr(2, subscript.size() - 3))).interpret_with(*walker); - walker->restore_output_stream(); $libbash_value = out.str(); walker->trim_trailing_eols($libbash_value); }; diff --git a/scripts/command_execution.bash b/scripts/command_execution.bash index df6275b..248de63 100644 --- a/scripts/command_execution.bash +++ b/scripts/command_execution.bash @@ -79,6 +79,10 @@ echo "$(echo 'hi')" echo "`echo 'hi'`" array=(`echo 1` `echo 2` 3) echo ${array[@]} +echo `echo 1` +echo `echo 1 \`echo 2\` 3` +echo `echo 1 \`echo 2 \\\`echo 3\\\` 4\` 5` +echo $(echo 1 `echo 2 $(echo 3) 4` 5) ech\ o Hello\ world -- cgit v1.2.3-65-gdbad