aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMu Qiao <qiaomuf@gentoo.org>2011-07-06 22:08:44 +0800
committerMu Qiao <qiaomuf@gentoo.org>2011-07-20 16:29:56 +0800
commit3c33fa7935f0ba4294241944295b343f8165412d (patch)
treebd46151753135832dd085706a22b6101f958d7b9 /bashast
parentParser: fix a bug in escaped double quote handling (diff)
downloadlibbash-3c33fa7935f0ba4294241944295b343f8165412d.tar.gz
libbash-3c33fa7935f0ba4294241944295b343f8165412d.tar.bz2
libbash-3c33fa7935f0ba4294241944295b343f8165412d.zip
Parser: handle command substitution in lexer rules
Inside command substitution, many characters are allowed. For example, MY_PV="$(replace_version_separator 1 '')" will reserve the single quotes for command substitution. Now we support this by handling command substitution in the lexer rules and call back to parser in walker grammar.
Diffstat (limited to 'bashast')
-rw-r--r--bashast/bashast.g32
-rw-r--r--bashast/features_script/features.sh.ast2
-rw-r--r--bashast/features_script/features.sh.tokens10
-rw-r--r--bashast/features_script/features.sh.walker.tokens2
-rw-r--r--bashast/gunit/array.gunit4
-rw-r--r--bashast/gunit/command_sub.gunit10
-rw-r--r--bashast/gunit/compound.gunit14
-rw-r--r--bashast/gunit/expansions.gunit2
-rw-r--r--bashast/gunit/fname.gunit6
-rw-r--r--bashast/gunit/simp_prog.gunit2
-rw-r--r--bashast/libbashWalker.g12
11 files changed, 65 insertions, 31 deletions
diff --git a/bashast/bashast.g b/bashast/bashast.g
index c69edea..1b4548e 100644
--- a/bashast/bashast.g
+++ b/bashast/bashast.g
@@ -126,6 +126,7 @@ tokens{
return input.LA(index);
}
#endif
+ int paren_level = 0;
}
#ifdef OUTPUT_C
@@ -297,8 +298,8 @@ brace_expansion_part
| -> ^(STRING);
commasep: brace_expansion_part(COMMA! brace_expansion_part)+;
command_sub
- : DOLLAR LPAREN clist BLANK? RPAREN -> ^(COMMAND_SUB clist)
- | TICK clist BLANK? TICK -> ^(COMMAND_SUB clist) ;
+ : COMMAND_SUBSTITUTION_PAREN -> ^(COMMAND_SUB COMMAND_SUBSTITUTION_PAREN)
+ | COMMAND_SUBSTITUTION_TICK -> ^(COMMAND_SUB COMMAND_SUBSTITUTION_TICK);
//compound commands
compound_command
: for_expr
@@ -767,6 +768,33 @@ ESC_RPAREN
: ESC RPAREN;
ESC_LPAREN
: ESC LPAREN;
+ESC_DOLLAR
+ : ESC DOLLAR;
+ESC_TICK
+ : ESC TICK;
+COMMAND_SUBSTITUTION_PAREN
+ :
+ {LA(1) == '$' && LA(2) == '(' && LA(3) != '('}?
+ => (DOLLAR LPAREN ({ paren_level = 1; }
+ (
+ ESC_LPAREN
+ |ESC_RPAREN
+ |LPAREN { ++paren_level; }
+ |RPAREN { if(--paren_level == 0) {
+#ifdef OUTPUT_C
+ LEXSTATE->type = _type;
+#else
+ state.type = _type;
+ state.channel = _channel;
+#endif
+ return;
+ }
+ }
+ |.
+ )+
+ ));
+COMMAND_SUBSTITUTION_TICK
+ : TICK (~(TICK))+ TICK;
ESC_LT : ESC'<';
ESC_GT : ESC'>';
//Handle ANSI C escaped characters: escaped octal, escaped hex, escaped ctrl+ chars, then all others
diff --git a/bashast/features_script/features.sh.ast b/bashast/features_script/features.sh.ast
index ad37b9c..26c634d 100644
--- a/bashast/features_script/features.sh.ast
+++ b/bashast/features_script/features.sh.ast
@@ -1 +1 @@
-(LIST (COMMAND (function (STRING lots_o_echo) (CURRENT_SHELL (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING The number of tests that have failed : (VAR_REF failedtests)))) (COMMAND (STRING echo) (STRING (SINGLE_QUOTED_STRING '$failedtests'))) (COMMAND (STRING echo) (STRING (VAR_REF failedtests))))))) (COMMAND (function (STRING do_some_arith) (CURRENT_SHELL (LIST (COMMAND (ARITHMETIC_EXPRESSION (* 5 4))) (COMMAND (ARITHMETIC_EXPRESSION (** 5 4))) (COMMAND (ARITHMETIC_EXPRESSION (+ (VAR_REF failedtests) (/ 5 4)))) (COMMAND (ARITHMETIC_EXPRESSION (+ (VAR_REF z) (MINUS_SIGN 3)))))))) (COMMAND (function (STRING arrays) (SUBSHELL (LIST (COMMAND (VARIABLE_DEFINITIONS (= asdf (ARRAY (STRING a) (STRING b) (STRING c) (STRING d))))) (COMMAND (STRING echo) (STRING (VAR_REF (asdf 3)))) (COMMAND (VARIABLE_DEFINITIONS (= foo (ARRAY (STRING (COMMAND_SUB (LIST (COMMAND (STRING echo) (STRING 6))))) (STRING b) (STRING c) (STRING d))))) (COMMAND (VARIABLE_DEFINITIONS (= (arr (VAR_REF foo)) (STRING 3)))) (COMMAND (VARIABLE_DEFINITIONS (= bar (ARRAY (STRING a) (STRING b) (= 5 (STRING c)))))))))) (COMMAND (STRING echo) (STRING (BRACE_EXP (STRING a) (STRING b)))) (COMMAND (STRING echo) (STRING (BRACE_EXP (.. a d)))) (COMMAND (STRING echo) (STRING (BRACE_EXP (STRING (BRACE_EXP (STRING a) (STRING b))) (STRING c) (STRING d)))) (COMMAND (STRING echo) (STRING a (BRACE_EXP (STRING b) (STRING c)))) (COMMAND (STRING (COMMAND_SUB (LIST (COMMAND (STRING echo) (STRING foobar)))))) (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING gunit) (REDIR >> (STRING filelist)))) (COMMAND (case (STRING (COMMAND_SUB (LIST (COMMAND (STRING echo) (STRING asdf))))) (CASE_PATTERN (STRING gz) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING yay)))) (CASE_PATTERN (STRING bzip) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING three)))) (CASE_PATTERN (STRING MATCH_ALL) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING woo)))))) (COMMAND (for each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING log)))))) (LIST (COMMAND (STRING echo) (STRING (VAR_REF each))) (COMMAND (STRING cat) (STRING each))))) (COMMAND (CFOR (FOR_INIT (+ 5 3)) (FOR_COND (+ 6 2)) (LIST (COMMAND (STRING echo) (STRING yay))) (FOR_MOD (+ 3 1)))) (COMMAND (select each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING output)))))) (LIST (COMMAND (STRING echo) (STRING asdf) (STRING 2) (REDIR > (STRING / dev / null)))))) (COMMAND (IF_STATEMENT (if (LIST (COMMAND (STRING echo) (STRING yay2))) (LIST (COMMAND (STRING echo) (STRING yay)))))) (COMMAND (until (LIST (COMMAND (COMPOUND_COND (KEYWORD_TEST (a (STRING this / is . afile)))))) (LIST (COMMAND (STRING touch) (STRING this / is . afile))))) (COMMAND (while (LIST (COMMAND (COMPOUND_COND (BUILTIN_TEST (n (STRING foobar)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))) (COMMAND (IF_STATEMENT (if (LIST (COMMAND (COMPOUND_COND (BUILTIN_TEST (eq (STRING 5) (STRING 6)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING something ' s wrong))))))) (COMMAND (STRING echo) (STRING this) (STRING command) (STRING has) (STRING multiple) (STRING arguments)) (COMMAND (STRING wc) (PROCESS_SUBSTITUTION < (LIST (COMMAND (STRING cat) (STRING / usr / share / dict / linux . words))))) (|| (&& (&& (&& (COMMAND (STRING cd) (STRING build)) (COMMAND (STRING . / configure))) (COMMAND (STRING make))) (COMMAND (STRING make_install))) (COMMAND (STRING echo) (STRING fail))) (COMMAND (STRING cd) (STRING / usr / bin)) (| (COMMAND (STRING ls) (STRING - al)) (COMMAND (STRING grep) (STRING more))) (COMMAND (VARIABLE_DEFINITIONS (= asdf (STRING parameters)))) (COMMAND (STRING (VAR_REF (USE_DEFAULT_WHEN_UNSET_OR_NULL asdf (STRING foo))))) (COMMAND (STRING (VAR_REF (OFFSET asdf 8)))) (COMMAND (STRING (VAR_REF (! asdf *)))) (COMMAND (STRING (VAR_REF (! asdf @)))) (COMMAND (STRING (VAR_REF (# foo)))) (COMMAND (STRING (VAR_REF (REPLACE_FIRST replaice (STRING with) (STRING pattern))))) (COMMAND (STRING (VAR_REF (LAZY_REMOVE_AT_START asdf (STRING bar))))) (COMMAND (STRING (VAR_REF (REPLACE_AT_START asdf (STRING bar))))) (COMMAND (STRING (VAR_REF (LAZY_REMOVE_AT_END asdf (STRING bar))))) (COMMAND (STRING (VAR_REF (LAZY_REMOVE_AT_END asdf (STRING bar))))) (COMMAND (STRING (VAR_REF 1)) (STRING (VAR_REF @)) (STRING (VAR_REF *))) (COMMAND (STRING (VAR_REF ?))) (COMMAND (STRING (VAR_REF (REPLACE_ALL PV (STRING .) (STRING _))))) (COMMAND (STRING (VAR_REF (REPLACE_AT_START PV (STRING foo) (STRING bar))))) (COMMAND (STRING (VAR_REF (REPLACE_AT_END PV (STRING foo) (STRING bar))))) (COMMAND (VARIABLE_DEFINITIONS (= MY_PN (STRING (VAR_REF (REPLACE_FIRST PN (STRING asterisk -))))))) (| (COMMAND (STRING cat) (STRING asdf)) (COMMAND (STRING grep) (STRING three) (STRING 2) (REDIR >& (FILE_DESCRIPTOR 1)) (REDIR > (STRING / dev / null)))) (COMMAND (STRING echo) (STRING asdf) (REDIR >> (STRING APPEND))) (COMMAND (STRING echo) (STRING cat) (<<< (STRING word))))
+(LIST (COMMAND (function (STRING lots_o_echo) (CURRENT_SHELL (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING The number of tests that have failed : (VAR_REF failedtests)))) (COMMAND (STRING echo) (STRING (SINGLE_QUOTED_STRING '$failedtests'))) (COMMAND (STRING echo) (STRING (VAR_REF failedtests))))))) (COMMAND (function (STRING do_some_arith) (CURRENT_SHELL (LIST (COMMAND (ARITHMETIC_EXPRESSION (* 5 4))) (COMMAND (ARITHMETIC_EXPRESSION (** 5 4))) (COMMAND (ARITHMETIC_EXPRESSION (+ (VAR_REF failedtests) (/ 5 4)))) (COMMAND (ARITHMETIC_EXPRESSION (+ (VAR_REF z) (MINUS_SIGN 3)))))))) (COMMAND (function (STRING arrays) (SUBSHELL (LIST (COMMAND (VARIABLE_DEFINITIONS (= asdf (ARRAY (STRING a) (STRING b) (STRING c) (STRING d))))) (COMMAND (STRING echo) (STRING (VAR_REF (asdf 3)))) (COMMAND (VARIABLE_DEFINITIONS (= foo (ARRAY (STRING (COMMAND_SUB `echo 6`)) (STRING b) (STRING c) (STRING d))))) (COMMAND (VARIABLE_DEFINITIONS (= (arr (VAR_REF foo)) (STRING 3)))) (COMMAND (VARIABLE_DEFINITIONS (= bar (ARRAY (STRING a) (STRING b) (= 5 (STRING c)))))))))) (COMMAND (STRING echo) (STRING (BRACE_EXP (STRING a) (STRING b)))) (COMMAND (STRING echo) (STRING (BRACE_EXP (.. a d)))) (COMMAND (STRING echo) (STRING (BRACE_EXP (STRING (BRACE_EXP (STRING a) (STRING b))) (STRING c) (STRING d)))) (COMMAND (STRING echo) (STRING a (BRACE_EXP (STRING b) (STRING c)))) (COMMAND (STRING (COMMAND_SUB $(echo foobar)))) (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING gunit) (REDIR >> (STRING filelist)))) (COMMAND (case (STRING (COMMAND_SUB `echo asdf`)) (CASE_PATTERN (STRING gz) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING yay)))) (CASE_PATTERN (STRING bzip) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING three)))) (CASE_PATTERN (STRING MATCH_ALL) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING woo)))))) (COMMAND (for each (STRING (COMMAND_SUB `ls |grep log`)) (LIST (COMMAND (STRING echo) (STRING (VAR_REF each))) (COMMAND (STRING cat) (STRING each))))) (COMMAND (CFOR (FOR_INIT (+ 5 3)) (FOR_COND (+ 6 2)) (LIST (COMMAND (STRING echo) (STRING yay))) (FOR_MOD (+ 3 1)))) (COMMAND (select each (STRING (COMMAND_SUB `ls |grep output`)) (LIST (COMMAND (STRING echo) (STRING asdf) (STRING 2) (REDIR > (STRING / dev / null)))))) (COMMAND (IF_STATEMENT (if (LIST (COMMAND (STRING echo) (STRING yay2))) (LIST (COMMAND (STRING echo) (STRING yay)))))) (COMMAND (until (LIST (COMMAND (COMPOUND_COND (KEYWORD_TEST (a (STRING this / is . afile)))))) (LIST (COMMAND (STRING touch) (STRING this / is . afile))))) (COMMAND (while (LIST (COMMAND (COMPOUND_COND (BUILTIN_TEST (n (STRING foobar)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))) (COMMAND (IF_STATEMENT (if (LIST (COMMAND (COMPOUND_COND (BUILTIN_TEST (eq (STRING 5) (STRING 6)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING something ' s wrong))))))) (COMMAND (STRING echo) (STRING this) (STRING command) (STRING has) (STRING multiple) (STRING arguments)) (COMMAND (STRING wc) (PROCESS_SUBSTITUTION < (LIST (COMMAND (STRING cat) (STRING / usr / share / dict / linux . words))))) (|| (&& (&& (&& (COMMAND (STRING cd) (STRING build)) (COMMAND (STRING . / configure))) (COMMAND (STRING make))) (COMMAND (STRING make_install))) (COMMAND (STRING echo) (STRING fail))) (COMMAND (STRING cd) (STRING / usr / bin)) (| (COMMAND (STRING ls) (STRING - al)) (COMMAND (STRING grep) (STRING more))) (COMMAND (VARIABLE_DEFINITIONS (= asdf (STRING parameters)))) (COMMAND (STRING (VAR_REF (USE_DEFAULT_WHEN_UNSET_OR_NULL asdf (STRING foo))))) (COMMAND (STRING (VAR_REF (OFFSET asdf 8)))) (COMMAND (STRING (VAR_REF (! asdf *)))) (COMMAND (STRING (VAR_REF (! asdf @)))) (COMMAND (STRING (VAR_REF (# foo)))) (COMMAND (STRING (VAR_REF (REPLACE_FIRST replaice (STRING with) (STRING pattern))))) (COMMAND (STRING (VAR_REF (LAZY_REMOVE_AT_START asdf (STRING bar))))) (COMMAND (STRING (VAR_REF (REPLACE_AT_START asdf (STRING bar))))) (COMMAND (STRING (VAR_REF (LAZY_REMOVE_AT_END asdf (STRING bar))))) (COMMAND (STRING (VAR_REF (LAZY_REMOVE_AT_END asdf (STRING bar))))) (COMMAND (STRING (VAR_REF 1)) (STRING (VAR_REF @)) (STRING (VAR_REF *))) (COMMAND (STRING (VAR_REF ?))) (COMMAND (STRING (VAR_REF (REPLACE_ALL PV (STRING .) (STRING _))))) (COMMAND (STRING (VAR_REF (REPLACE_AT_START PV (STRING foo) (STRING bar))))) (COMMAND (STRING (VAR_REF (REPLACE_AT_END PV (STRING foo) (STRING bar))))) (COMMAND (VARIABLE_DEFINITIONS (= MY_PN (STRING (VAR_REF (REPLACE_FIRST PN (STRING asterisk -))))))) (| (COMMAND (STRING cat) (STRING asdf)) (COMMAND (STRING grep) (STRING three) (STRING 2) (REDIR >& (FILE_DESCRIPTOR 1)) (REDIR > (STRING / dev / null)))) (COMMAND (STRING echo) (STRING asdf) (REDIR >> (STRING APPEND))) (COMMAND (STRING echo) (STRING cat) (<<< (STRING word))))
diff --git a/bashast/features_script/features.sh.tokens b/bashast/features_script/features.sh.tokens
index 104a000..25c95d3 100644
--- a/bashast/features_script/features.sh.tokens
+++ b/bashast/features_script/features.sh.tokens
@@ -38,7 +38,7 @@
38 FUNCTION BLANK NAME LPAREN RPAREN BLANK LPAREN EOL
39 BLANK NAME EQUALS LPAREN LETTER BLANK LETTER BLANK LETTER BLANK LETTER RPAREN EOL
40 BLANK NAME BLANK DOLLAR LBRACE NAME LSQUARE DIGIT RSQUARE RBRACE EOL
-41 BLANK NAME EQUALS LPAREN TICK NAME BLANK DIGIT TICK BLANK LETTER BLANK LETTER BLANK LETTER RPAREN EOL
+41 BLANK NAME EQUALS LPAREN COMMAND_SUBSTITUTION_TICK BLANK LETTER BLANK LETTER BLANK LETTER RPAREN EOL
42 BLANK NAME LSQUARE NAME RSQUARE EQUALS DIGIT EOL
43 BLANK NAME EQUALS LPAREN LETTER BLANK LETTER BLANK LSQUARE DIGIT RSQUARE EQUALS LETTER RPAREN SEMIC EOL
44 RPAREN EOL
@@ -48,10 +48,10 @@
48 NAME BLANK LBRACE LBRACE LETTER COMMA LETTER RBRACE COMMA LETTER COMMA LETTER RBRACE EOL
49 NAME BLANK LETTER LBRACE LETTER COMMA LETTER RBRACE EOL
50
-51 DOLLAR LPAREN NAME BLANK NAME RPAREN EOL
+51 COMMAND_SUBSTITUTION_PAREN EOL
52 NAME BLANK PIPE NAME BLANK NAME BLANK RSHIFT BLANK NAME EOL
53
-54 CASE BLANK TICK NAME BLANK NAME TICK BLANK IN EOL
+54 CASE BLANK COMMAND_SUBSTITUTION_TICK BLANK IN EOL
55 NAME RPAREN EOL
56 NAME BLANK NAME EOL
57 DOUBLE_SEMIC EOL
@@ -62,14 +62,14 @@
62 DOUBLE_SEMIC EOL
63 ESAC EOL
64
-65 FOR BLANK NAME BLANK IN BLANK TICK NAME BLANK PIPE NAME BLANK NAME TICK SEMIC BLANK DO EOL
+65 FOR BLANK NAME BLANK IN BLANK COMMAND_SUBSTITUTION_TICK SEMIC BLANK DO EOL
66 BLANK NAME BLANK DOLLAR NAME EOL
67 BLANK NAME BLANK NAME EOL
68 DONE EOL
69
70 FOR BLANK LLPAREN DIGIT PLUS DIGIT SEMIC DIGIT PLUS DIGIT SEMIC DIGIT PLUS DIGIT RPAREN RPAREN SEMIC BLANK DO BLANK NAME BLANK NAME SEMIC BLANK DONE EOL
71
-72 SELECT BLANK NAME BLANK IN BLANK TICK NAME BLANK PIPE NAME BLANK NAME TICK SEMIC BLANK DO EOL
+72 SELECT BLANK NAME BLANK IN BLANK COMMAND_SUBSTITUTION_TICK SEMIC BLANK DO EOL
73 BLANK NAME BLANK NAME BLANK DIGIT GREATER_THAN BLANK SLASH NAME SLASH NAME EOL
74 DONE EOL
75
diff --git a/bashast/features_script/features.sh.walker.tokens b/bashast/features_script/features.sh.walker.tokens
index 14b0536..ba1a405 100644
--- a/bashast/features_script/features.sh.walker.tokens
+++ b/bashast/features_script/features.sh.walker.tokens
@@ -1,2 +1,2 @@
-LIST DOWN COMMAND DOWN FUNCTION DOWN STRING DOWN NAME UP CURRENT_SHELL DOWN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN DOUBLE_QUOTED_STRING DOWN NAME BLANK NAME BLANK NAME BLANK NAME BLANK NAME BLANK NAME BLANK NAME COLON BLANK VAR_REF DOWN NAME UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN SINGLE_QUOTED_STRING DOWN SINGLE_QUOTED_STRING_TOKEN UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN VAR_REF DOWN NAME UP UP UP UP UP UP UP COMMAND DOWN FUNCTION DOWN STRING DOWN NAME UP CURRENT_SHELL DOWN LIST DOWN COMMAND DOWN ARITHMETIC_EXPRESSION DOWN TIMES DOWN DIGIT DIGIT UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN EXP DOWN DIGIT DIGIT UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN PLUS DOWN VAR_REF DOWN NAME UP SLASH DOWN DIGIT DIGIT UP UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN PLUS DOWN VAR_REF DOWN LETTER UP MINUS_SIGN DOWN DIGIT UP UP UP UP UP UP UP UP COMMAND DOWN FUNCTION DOWN STRING DOWN NAME UP SUBSHELL DOWN LIST DOWN COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME ARRAY DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN VAR_REF DOWN NAME DOWN DIGIT UP UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME ARRAY DOWN STRING DOWN COMMAND_SUB DOWN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN DIGIT UP UP UP UP UP STRING DOWN LETTER UP STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME DOWN VAR_REF DOWN NAME UP UP STRING DOWN DIGIT UP UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME ARRAY DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP EQUALS DOWN DIGIT STRING DOWN LETTER UP UP UP UP UP UP UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN BRACE_EXP DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN BRACE_EXP DOWN DOTDOT DOWN LETTER LETTER UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN BRACE_EXP DOWN STRING DOWN BRACE_EXP DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN LETTER BRACE_EXP DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP COMMAND DOWN STRING DOWN COMMAND_SUB DOWN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP UP PIPE DOWN COMMAND DOWN STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP REDIR DOWN OP STRING DOWN NAME UP UP UP UP COMMAND DOWN CASE DOWN STRING DOWN COMMAND_SUB DOWN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP CASE_PATTERN DOWN STRING DOWN NAME UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP CASE_PATTERN DOWN STRING DOWN NAME UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP CASE_PATTERN DOWN STRING DOWN MATCH_ALL UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP UP COMMAND DOWN FOR DOWN NAME STRING DOWN COMMAND_SUB DOWN LIST DOWN PIPE DOWN COMMAND DOWN STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN VAR_REF DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP COMMAND DOWN CFOR DOWN FOR_INIT DOWN PLUS DOWN DIGIT DIGIT UP UP FOR_COND DOWN PLUS DOWN DIGIT DIGIT UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP FOR_MOD DOWN PLUS DOWN DIGIT DIGIT UP UP UP UP COMMAND DOWN SELECT DOWN NAME STRING DOWN COMMAND_SUB DOWN LIST DOWN PIPE DOWN COMMAND DOWN STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN DIGIT UP REDIR DOWN GREATER_THAN STRING DOWN SLASH NAME SLASH NAME UP UP UP UP UP UP COMMAND DOWN IF_STATEMENT DOWN IF DOWN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP UP COMMAND DOWN UNTIL DOWN LIST DOWN COMMAND DOWN COMPOUND_COND DOWN KEYWORD_TEST DOWN LETTER DOWN STRING DOWN NAME SLASH NAME DOT NAME UP UP UP UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME SLASH NAME DOT NAME UP UP UP UP UP COMMAND DOWN WHILE DOWN LIST DOWN COMMAND DOWN COMPOUND_COND DOWN BUILTIN_TEST DOWN LETTER DOWN STRING DOWN NAME UP UP UP UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN DOUBLE_QUOTED_STRING DOWN NAME BLANK NAME UP UP UP UP UP UP COMMAND DOWN IF_STATEMENT DOWN IF DOWN LIST DOWN COMMAND DOWN COMPOUND_COND DOWN BUILTIN_TEST DOWN NAME DOWN STRING DOWN DIGIT UP STRING DOWN DIGIT UP UP UP UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN DOUBLE_QUOTED_STRING DOWN NAME SQUOTE LETTER BLANK NAME UP UP UP UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN NAME UP PROCESS_SUBSTITUTION DOWN LESS_THAN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN SLASH NAME SLASH NAME SLASH NAME SLASH NAME DOT NAME UP UP UP UP UP LOGICOR DOWN LOGICAND DOWN LOGICAND DOWN LOGICAND DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN DOT SLASH NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN SLASH NAME SLASH NAME UP UP PIPE DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN MINUS NAME UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME STRING DOWN NAME UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN USE_DEFAULT_WHEN_UNSET_OR_NULL DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN OFFSET DOWN NAME DIGIT UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN BANG DOWN NAME TIMES UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN BANG DOWN NAME AT UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN POUND DOWN NAME UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_FIRST DOWN NAME STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN LAZY_REMOVE_AT_START DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_AT_START DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN LAZY_REMOVE_AT_END DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN LAZY_REMOVE_AT_END DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN DIGIT UP UP STRING DOWN VAR_REF DOWN AT UP UP STRING DOWN VAR_REF DOWN TIMES UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN QMARK UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_ALL DOWN NAME STRING DOWN DOT UP STRING DOWN UNDERSCORE UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_AT_START DOWN NAME STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_AT_END DOWN NAME STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME STRING DOWN VAR_REF DOWN REPLACE_FIRST DOWN NAME STRING DOWN NAME MINUS UP UP UP UP UP UP UP PIPE DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN DIGIT UP REDIR DOWN OP FILE_DESCRIPTOR DOWN DIGIT UP UP REDIR DOWN GREATER_THAN STRING DOWN SLASH NAME SLASH NAME UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP REDIR DOWN OP STRING DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP HERE_STRING_OP DOWN STRING DOWN NAME UP UP UP UP
+LIST DOWN COMMAND DOWN FUNCTION DOWN STRING DOWN NAME UP CURRENT_SHELL DOWN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN DOUBLE_QUOTED_STRING DOWN NAME BLANK NAME BLANK NAME BLANK NAME BLANK NAME BLANK NAME BLANK NAME COLON BLANK VAR_REF DOWN NAME UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN SINGLE_QUOTED_STRING DOWN SINGLE_QUOTED_STRING_TOKEN UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN VAR_REF DOWN NAME UP UP UP UP UP UP UP COMMAND DOWN FUNCTION DOWN STRING DOWN NAME UP CURRENT_SHELL DOWN LIST DOWN COMMAND DOWN ARITHMETIC_EXPRESSION DOWN TIMES DOWN DIGIT DIGIT UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN EXP DOWN DIGIT DIGIT UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN PLUS DOWN VAR_REF DOWN NAME UP SLASH DOWN DIGIT DIGIT UP UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN PLUS DOWN VAR_REF DOWN LETTER UP MINUS_SIGN DOWN DIGIT UP UP UP UP UP UP UP UP COMMAND DOWN FUNCTION DOWN STRING DOWN NAME UP SUBSHELL DOWN LIST DOWN COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME ARRAY DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN VAR_REF DOWN NAME DOWN DIGIT UP UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME ARRAY DOWN STRING DOWN COMMAND_SUB DOWN COMMAND_SUBSTITUTION_TICK UP UP STRING DOWN LETTER UP STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME DOWN VAR_REF DOWN NAME UP UP STRING DOWN DIGIT UP UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME ARRAY DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP EQUALS DOWN DIGIT STRING DOWN LETTER UP UP UP UP UP UP UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN BRACE_EXP DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN BRACE_EXP DOWN DOTDOT DOWN LETTER LETTER UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN BRACE_EXP DOWN STRING DOWN BRACE_EXP DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN LETTER BRACE_EXP DOWN STRING DOWN LETTER UP STRING DOWN LETTER UP UP UP UP COMMAND DOWN STRING DOWN COMMAND_SUB DOWN COMMAND_SUBSTITUTION_PAREN UP UP UP PIPE DOWN COMMAND DOWN STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP REDIR DOWN OP STRING DOWN NAME UP UP UP UP COMMAND DOWN CASE DOWN STRING DOWN COMMAND_SUB DOWN COMMAND_SUBSTITUTION_TICK UP UP CASE_PATTERN DOWN STRING DOWN NAME UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP CASE_PATTERN DOWN STRING DOWN NAME UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP CASE_PATTERN DOWN STRING DOWN MATCH_ALL UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP UP COMMAND DOWN FOR DOWN NAME STRING DOWN COMMAND_SUB DOWN COMMAND_SUBSTITUTION_TICK UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN VAR_REF DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP COMMAND DOWN CFOR DOWN FOR_INIT DOWN PLUS DOWN DIGIT DIGIT UP UP FOR_COND DOWN PLUS DOWN DIGIT DIGIT UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP FOR_MOD DOWN PLUS DOWN DIGIT DIGIT UP UP UP UP COMMAND DOWN SELECT DOWN NAME STRING DOWN COMMAND_SUB DOWN COMMAND_SUBSTITUTION_TICK UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN DIGIT UP REDIR DOWN GREATER_THAN STRING DOWN SLASH NAME SLASH NAME UP UP UP UP UP UP COMMAND DOWN IF_STATEMENT DOWN IF DOWN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP UP COMMAND DOWN UNTIL DOWN LIST DOWN COMMAND DOWN COMPOUND_COND DOWN KEYWORD_TEST DOWN LETTER DOWN STRING DOWN NAME SLASH NAME DOT NAME UP UP UP UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME SLASH NAME DOT NAME UP UP UP UP UP COMMAND DOWN WHILE DOWN LIST DOWN COMMAND DOWN COMPOUND_COND DOWN BUILTIN_TEST DOWN LETTER DOWN STRING DOWN NAME UP UP UP UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN DOUBLE_QUOTED_STRING DOWN NAME BLANK NAME UP UP UP UP UP UP COMMAND DOWN IF_STATEMENT DOWN IF DOWN LIST DOWN COMMAND DOWN COMPOUND_COND DOWN BUILTIN_TEST DOWN NAME DOWN STRING DOWN DIGIT UP STRING DOWN DIGIT UP UP UP UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN DOUBLE_QUOTED_STRING DOWN NAME SQUOTE LETTER BLANK NAME UP UP UP UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN NAME UP PROCESS_SUBSTITUTION DOWN LESS_THAN LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN SLASH NAME SLASH NAME SLASH NAME SLASH NAME DOT NAME UP UP UP UP UP LOGICOR DOWN LOGICAND DOWN LOGICAND DOWN LOGICAND DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN DOT SLASH NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN SLASH NAME SLASH NAME UP UP PIPE DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN MINUS NAME UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME STRING DOWN NAME UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN USE_DEFAULT_WHEN_UNSET_OR_NULL DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN OFFSET DOWN NAME DIGIT UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN BANG DOWN NAME TIMES UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN BANG DOWN NAME AT UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN POUND DOWN NAME UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_FIRST DOWN NAME STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN LAZY_REMOVE_AT_START DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_AT_START DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN LAZY_REMOVE_AT_END DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN LAZY_REMOVE_AT_END DOWN NAME STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN DIGIT UP UP STRING DOWN VAR_REF DOWN AT UP UP STRING DOWN VAR_REF DOWN TIMES UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN QMARK UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_ALL DOWN NAME STRING DOWN DOT UP STRING DOWN UNDERSCORE UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_AT_START DOWN NAME STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP COMMAND DOWN STRING DOWN VAR_REF DOWN REPLACE_AT_END DOWN NAME STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP UP COMMAND DOWN VARIABLE_DEFINITIONS DOWN EQUALS DOWN NAME STRING DOWN VAR_REF DOWN REPLACE_FIRST DOWN NAME STRING DOWN NAME MINUS UP UP UP UP UP UP UP PIPE DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP STRING DOWN DIGIT UP REDIR DOWN OP FILE_DESCRIPTOR DOWN DIGIT UP UP REDIR DOWN GREATER_THAN STRING DOWN SLASH NAME SLASH NAME UP UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP REDIR DOWN OP STRING DOWN NAME UP UP UP COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP HERE_STRING_OP DOWN STRING DOWN NAME UP UP UP UP
diff --git a/bashast/gunit/array.gunit b/bashast/gunit/array.gunit
index ce0b344..0a176eb 100644
--- a/bashast/gunit/array.gunit
+++ b/bashast/gunit/array.gunit
@@ -20,9 +20,9 @@ gunit java_libbash;
var_def:
"asdf=(a b c d)"->(= asdf (ARRAY (STRING a) (STRING b) (STRING c) (STRING d)))
-"asdf=(`echo 6` b c d)"-> (= asdf (ARRAY (STRING (COMMAND_SUB (LIST (COMMAND (STRING echo) (STRING 6))))) (STRING b) (STRING c) (STRING d)))
+"asdf=(`echo 6` b c d)"-> (= asdf (ARRAY (STRING (COMMAND_SUB `echo 6`)) (STRING b) (STRING c) (STRING d)))
"asdf=(${P} b c d)"->(= asdf (ARRAY (STRING (VAR_REF P)) (STRING b) (STRING c) (STRING d)))
-"asdf=($(echo a))" -> (= asdf (ARRAY (STRING (COMMAND_SUB (LIST (COMMAND (STRING echo) (STRING a)))))))
+"asdf=($(echo a))" -> (= asdf (ARRAY (STRING (COMMAND_SUB $(echo a)))))
"asdf=(
--disable-dependency-tracking
${VAR}
diff --git a/bashast/gunit/command_sub.gunit b/bashast/gunit/command_sub.gunit
index e2d0021..49c5844 100644
--- a/bashast/gunit/command_sub.gunit
+++ b/bashast/gunit/command_sub.gunit
@@ -19,8 +19,8 @@
gunit java_libbash;
command_sub:
-"$(echo \"foo\")" -> (COMMAND_SUB (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING foo)))))
-"$(ls |grep file)" -> (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING file)))))
-"$(CONTROL= command arg )" -> (COMMAND_SUB (LIST (COMMAND (STRING command) (STRING arg) (= CONTROL))))
-"`cat output.log |grep error|cut`" -> (COMMAND_SUB (LIST (| (| (COMMAND (STRING cat) (STRING output . log)) (COMMAND (STRING grep) (STRING error))) (COMMAND (STRING cut)))))
-"$(function foo() { echo 'hello'; }; foo)" -> (COMMAND_SUB (LIST (COMMAND (function (STRING foo) (CURRENT_SHELL (LIST (COMMAND (STRING echo) (STRING (SINGLE_QUOTED_STRING 'hello'))))))) (COMMAND (STRING foo))))
+"$(echo \"foo\")" -> (COMMAND_SUB $(echo "foo"))
+"$(ls |grep file)" -> (COMMAND_SUB $(ls |grep file))
+"$(CONTROL= command arg )" -> (COMMAND_SUB $(CONTROL= command arg ))
+"`cat output.log |grep error|cut`" -> (COMMAND_SUB `cat output.log |grep error|cut`)
+"$(function foo() { echo 'hello'; }; foo)" -> (COMMAND_SUB $(function foo() { echo 'hello'; }; foo))
diff --git a/bashast/gunit/compound.gunit b/bashast/gunit/compound.gunit
index 5e2a098..bf98197 100644
--- a/bashast/gunit/compound.gunit
+++ b/bashast/gunit/compound.gunit
@@ -54,7 +54,7 @@ subshell:
case_expr:
"case a in esac" -> (case (STRING a))
"case `echo asdf` in
-esac" -> (case (STRING (COMMAND_SUB (LIST (COMMAND (STRING echo) (STRING asdf))))))
+esac" -> (case (STRING (COMMAND_SUB `echo asdf`)))
"case `echo asdf` in
gz)
@@ -65,7 +65,7 @@ echo three
;;
*) echo woo
;;
-esac" -> (case (STRING (COMMAND_SUB (LIST (COMMAND (STRING echo) (STRING asdf))))) (CASE_PATTERN (STRING gz) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING yay)))) (CASE_PATTERN (STRING bzip) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING three)))) (CASE_PATTERN (STRING MATCH_ALL) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING woo)))))
+esac" -> (case (STRING (COMMAND_SUB `echo asdf`)) (CASE_PATTERN (STRING gz) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING yay)))) (CASE_PATTERN (STRING bzip) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING three)))) (CASE_PATTERN (STRING MATCH_ALL) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING woo)))))
"case asdf in
gz)
@@ -83,8 +83,8 @@ esac" -> (case (STRING asdf) (CASE_PATTERN (STRING gz) CASE_COMMAND (LIST (COMMA
for_expr:
"for each in `ls |grep log`; do
echo \"file found\"
-done" -> (for each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING log)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))
-"for each in `ls |grep log`; do echo \"file found\"; done" -> (for each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING log)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))
+done" -> (for each (STRING (COMMAND_SUB `ls |grep log`)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))
+"for each in `ls |grep log`; do echo \"file found\"; done" -> (for each (STRING (COMMAND_SUB `ls |grep log`)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))
"for i in 'foo' 'bar'; do echo $i; done" -> (for i (STRING (SINGLE_QUOTED_STRING 'foo')) (STRING (SINGLE_QUOTED_STRING 'bar')) (LIST (COMMAND (STRING echo) (STRING (VAR_REF i)))))
"for i in foo$var bar; do echo $i; done" -> (for i (STRING foo (VAR_REF var)) (STRING bar) (LIST (COMMAND (STRING echo) (STRING (VAR_REF i)))))
"for each in `ls |grep log`; do echo file done" FAIL
@@ -97,8 +97,8 @@ done" -> (for each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND
sel_expr:
"select each in `ls |grep log`; do
echo \"file found\"
- done" -> (select each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING log)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))
-"select each in `ls |grep log`; do echo \"file found\"; done" -> (select each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING log)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))
+ done" -> (select each (STRING (COMMAND_SUB `ls |grep log`)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))
+"select each in `ls |grep log`; do echo \"file found\"; done" -> (select each (STRING (COMMAND_SUB `ls |grep log`)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found)))))
"select each in `ls |grep log`; do echo file done" FAIL
if_expr:
@@ -185,7 +185,7 @@ command:
"case a in esac >/dev/null" -> (COMMAND (case (STRING a)) (REDIR > (STRING / dev / null)))
"for i in foo$var bar; do echo $i; done >/dev/null" -> (COMMAND (for i (STRING foo (VAR_REF var)) (STRING bar) (LIST (COMMAND (STRING echo) (STRING (VAR_REF i))))) (REDIR > (STRING / dev / null)))
"for ((5+3;;5+3)); do echo yay; done >/dev/null" -> (COMMAND (CFOR (FOR_INIT (+ 5 3)) (LIST (COMMAND (STRING echo) (STRING yay))) (FOR_MOD (+ 5 3))) (REDIR > (STRING / dev / null)))
-"select each in `ls |grep log`; do echo \"file found\"; done >/dev/null" -> (COMMAND (select each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING log)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found))))) (REDIR > (STRING / dev / null)))
+"select each in `ls |grep log`; do echo \"file found\"; done >/dev/null" -> (COMMAND (select each (STRING (COMMAND_SUB `ls |grep log`)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found))))) (REDIR > (STRING / dev / null)))
"if echo yay2;
then
diff --git a/bashast/gunit/expansions.gunit b/bashast/gunit/expansions.gunit
index a36d4da..b10931d 100644
--- a/bashast/gunit/expansions.gunit
+++ b/bashast/gunit/expansions.gunit
@@ -26,5 +26,5 @@ clist:
"[[ while = while ]] && echo true" -> (LIST (&& (COMMAND (COMPOUND_COND (KEYWORD_TEST (= (STRING while) (STRING while))))) (COMMAND (STRING echo) (STRING true))))
"for each in `ls |grep output`; do
echo $each
-done" -> (LIST (COMMAND (for each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING output)))))) (LIST (COMMAND (STRING echo) (STRING (VAR_REF each)))))))
+done" -> (LIST (COMMAND (for each (STRING (COMMAND_SUB `ls |grep output`)) (LIST (COMMAND (STRING echo) (STRING (VAR_REF each)))))))
"wc <(cat /usr/share/dict/linux.words)" -> (LIST (COMMAND (STRING wc) (PROCESS_SUBSTITUTION < (LIST (COMMAND (STRING cat) (STRING / usr / share / dict / linux . words))))))
diff --git a/bashast/gunit/fname.gunit b/bashast/gunit/fname.gunit
index eb13235..882afd1 100644
--- a/bashast/gunit/fname.gunit
+++ b/bashast/gunit/fname.gunit
@@ -25,8 +25,8 @@ fname:
"\"\"" -> (STRING DOUBLE_QUOTED_STRING)
"\"For more info on this patchset, and how to report problems, see:\"" -> (STRING (DOUBLE_QUOTED_STRING For more info on this patchset , and how to report problems , see :))
"\"asdf;!\"" -> (STRING (DOUBLE_QUOTED_STRING asdf ; !))
-"\"$(whoami)\"" -> (STRING (DOUBLE_QUOTED_STRING (COMMAND_SUB (LIST (COMMAND (STRING whoami))))))
-"\"`whoami`\"" -> (STRING (DOUBLE_QUOTED_STRING (COMMAND_SUB (LIST (COMMAND (STRING whoami))))))
+"\"$(whoami)\"" -> (STRING (DOUBLE_QUOTED_STRING (COMMAND_SUB $(whoami))))
+"\"`whoami`\"" -> (STRING (DOUBLE_QUOTED_STRING (COMMAND_SUB `whoami`)))
"'`whoami`'" -> (STRING (SINGLE_QUOTED_STRING '`whoami`'))
"'$(whoami)'" -> (STRING (SINGLE_QUOTED_STRING '$(whoami)'))
"\"${P}\"" -> (STRING (DOUBLE_QUOTED_STRING (VAR_REF P)))
@@ -72,4 +72,4 @@ fname:
"\"abc#$/\"" -> (STRING (DOUBLE_QUOTED_STRING abc # $ /))
dqstr:
-"\"\\\\\"\$\`\"" -> (DOUBLE_QUOTED_STRING \ " $ `)
+"\"\\\\\"\$\`\"" -> (DOUBLE_QUOTED_STRING \ " \$ \`)
diff --git a/bashast/gunit/simp_prog.gunit b/bashast/gunit/simp_prog.gunit
index 64aa001..d36c5f6 100644
--- a/bashast/gunit/simp_prog.gunit
+++ b/bashast/gunit/simp_prog.gunit
@@ -25,7 +25,7 @@ echo \"I found a file\"
done
echo \"finding complete\"
-"-> (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING finding file))) (COMMAND (for each (STRING (COMMAND_SUB (LIST (| (COMMAND (STRING ls)) (COMMAND (STRING grep) (STRING output)))))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING I found a file)))))) (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING finding complete))))
+"-> (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING finding file))) (COMMAND (for each (STRING (COMMAND_SUB `ls | grep output`)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING I found a file)))))) (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING finding complete))))
"function quit {
exit
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 1edf10d..76c62d6 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -48,6 +48,7 @@ options
#include <boost/algorithm/string/join.hpp>
#include "builtins/builtin_exceptions.h"
+ #include "core/bash_ast.h"
#include "core/bash_condition.h"
#include "core/interpreter.h"
#include "cppbash_builtin.h"
@@ -285,7 +286,7 @@ string_part returns[std::string libbash_value, bool quoted, bool is_raw_string]
$libbash_value = libbash_string;
$is_raw_string = false;
}
- |libbash_string=command_substitution {
+ |(COMMAND_SUB) => libbash_string=command_substitution {
$libbash_value = libbash_string;
$is_raw_string = false;
}
@@ -409,7 +410,7 @@ double_quoted_string returns[std::string libbash_value]
|(ARITHMETIC_EXPRESSION) => ^(ARITHMETIC_EXPRESSION value=arithmetics) {
$libbash_value = boost::lexical_cast<std::string>(value);
}
- |libbash_string=command_substitution {
+ |(COMMAND_SUB) => libbash_string=command_substitution {
$libbash_value = libbash_string;
}
|libbash_string=any_string { $libbash_value = libbash_string; };
@@ -994,9 +995,14 @@ case_clause[const std::string& target] returns[bool matched]
command_substitution returns[std::string libbash_value]
@declarations {
+ std::string subscript;
std::stringstream out;
}
- :^(COMMAND_SUB{ walker->set_output_stream(&out); } command_list) {
+ :^(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);
+ 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);