aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Aparício <aparicio99@gmail.com>2012-06-11 02:45:15 +0100
committerAndré Aparício <aparicio99@gmail.com>2012-08-03 01:03:35 +0100
commit3b61db33dab08044404af5ae9123b9bad85f7b05 (patch)
treef5e22e929c1db8917d9d349a54c8560c5756e618
parentWalker: Support local declaration inside eval (diff)
downloadlibbash-3b61db33dab08044404af5ae9123b9bad85f7b05.tar.gz
libbash-3b61db33dab08044404af5ae9123b9bad85f7b05.tar.bz2
libbash-3b61db33dab08044404af5ae9123b9bad85f7b05.zip
Parser&Walker: Support redirection
The order of the arguments for commands in the AST was changed, it was 'command_atom redirection', and now it's 'redirection command_atom'. This is due to the need of having the redirection set before evaluating the expression.
-rw-r--r--.gitignore1
-rw-r--r--bashast/bashast.g6
-rw-r--r--bashast/features_script/features.sh.ast2
-rw-r--r--bashast/features_script/features.sh.walker.tokens2
-rw-r--r--bashast/gunit/compound.gunit26
-rw-r--r--bashast/gunit/expansions.gunit2
-rw-r--r--bashast/gunit/function.gunit6
-rw-r--r--bashast/gunit/list.gunit4
-rw-r--r--bashast/gunit/pipeline.gunit2
-rw-r--r--bashast/gunit/process_substitution.gunit2
-rw-r--r--bashast/gunit/redir.gunit2
-rw-r--r--bashast/gunit/simp_command.gunit4
-rw-r--r--bashast/libbashWalker.g53
-rw-r--r--scripts/command_execution.bash11
-rw-r--r--scripts/here_document.ast4
-rw-r--r--src/core/interpreter.h35
-rwxr-xr-xtest/bash_compiler.sh1
17 files changed, 113 insertions, 50 deletions
diff --git a/.gitignore b/.gitignore
index f550a92..eb6b0f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,3 +67,4 @@ ltmain.sh
INSTALL
test_coverage/
doxygen-doc/
+scripts/input_output_test
diff --git a/bashast/bashast.g b/bashast/bashast.g
index 0fb8212..3ce2c8e 100644
--- a/bashast/bashast.g
+++ b/bashast/bashast.g
@@ -299,7 +299,7 @@ file_descriptor
| DIGIT MINUS -> ^(FILE_DESCRIPTOR_MOVE DIGIT);
here_string
- : BLANK? HERE_STRING_OP^ BLANK!? (string_expr) => string_expr;
+ : BLANK!? HERE_STRING_OP^ BLANK!? (string_expr) => string_expr;
here_document
#ifdef OUTPUT_C
@@ -372,7 +372,7 @@ redirection_operator
command
: command_atom
(
- redirection here_document? -> ^(COMMAND command_atom redirection here_document?)
+ redirection here_document? -> ^(COMMAND redirection command_atom here_document?)
| here_document -> ^(COMMAND command_atom here_document)
| -> ^(COMMAND command_atom)
);
@@ -421,7 +421,7 @@ command_atom
command_name
: string_expr_no_reserved_word
- | {LA(1) == GREATER_THAN}? => redirection_atom -> ^(STRING NAME) redirection_atom;
+ | {LA(1) == GREATER_THAN}? => redirection_atom -> redirection_atom ^(STRING NAME);
variable_definitions
: variable_definition_atom ((BLANK name (LSQUARE|EQUALS|PLUS EQUALS)) => BLANK! variable_definition_atom)* ;
diff --git a/bashast/features_script/features.sh.ast b/bashast/features_script/features.sh.ast
index 60d71b3..52b5bcf 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 (ARITHMETIC (* 5 4)))) (COMMAND (ARITHMETIC_EXPRESSION (ARITHMETIC (** 5 4)))) (COMMAND (ARITHMETIC_EXPRESSION (ARITHMETIC (+ (VAR_REF failedtests) (/ 5 4))))) (COMMAND (ARITHMETIC_EXPRESSION (ARITHMETIC (+ (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 (ARITHMETIC 3))))) (COMMAND (VARIABLE_DEFINITIONS (= foo (ARRAY (STRING (COMMAND_SUB `echo 6`)) (STRING b) (STRING c) (STRING d))))) (COMMAND (VARIABLE_DEFINITIONS (= (arr (ARITHMETIC (VAR_REF foo))) (STRING 3)))) (COMMAND (VARIABLE_DEFINITIONS (= bar (ARRAY (STRING a) (STRING b) (= (ARITHMETIC 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 (BRANCH gz) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING yay)))) (CASE_PATTERN (BRANCH bzip) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING three)))) (CASE_PATTERN (BRANCH 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 (ARITHMETIC (+ 5 3))) (FOR_COND (ARITHMETIC (+ 6 2))) (LIST (COMMAND (STRING echo) (STRING yay))) (FOR_MOD (ARITHMETIC (+ 3 1))))) (COMMAND (select each (STRING (COMMAND_SUB `ls |grep output`)) (LIST (COMMAND (STRING echo) (STRING asdf) (REDIR 2 > (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 (OFFSET (ARITHMETIC 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) (REDIR 2 >& (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 (ARITHMETIC (* 5 4)))) (COMMAND (ARITHMETIC_EXPRESSION (ARITHMETIC (** 5 4)))) (COMMAND (ARITHMETIC_EXPRESSION (ARITHMETIC (+ (VAR_REF failedtests) (/ 5 4))))) (COMMAND (ARITHMETIC_EXPRESSION (ARITHMETIC (+ (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 (ARITHMETIC 3))))) (COMMAND (VARIABLE_DEFINITIONS (= foo (ARRAY (STRING (COMMAND_SUB `echo 6`)) (STRING b) (STRING c) (STRING d))))) (COMMAND (VARIABLE_DEFINITIONS (= (arr (ARITHMETIC (VAR_REF foo))) (STRING 3)))) (COMMAND (VARIABLE_DEFINITIONS (= bar (ARRAY (STRING a) (STRING b) (= (ARITHMETIC 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 (REDIR >> (STRING filelist)) (STRING grep) (STRING gunit))) (COMMAND (case (STRING (COMMAND_SUB `echo asdf`)) (CASE_PATTERN (BRANCH gz) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING yay)))) (CASE_PATTERN (BRANCH bzip) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING three)))) (CASE_PATTERN (BRANCH 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 (ARITHMETIC (+ 5 3))) (FOR_COND (ARITHMETIC (+ 6 2))) (LIST (COMMAND (STRING echo) (STRING yay))) (FOR_MOD (ARITHMETIC (+ 3 1))))) (COMMAND (select each (STRING (COMMAND_SUB `ls |grep output`)) (LIST (COMMAND (REDIR 2 > (STRING / dev / null)) (STRING echo) (STRING asdf))))) (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 (PROCESS_SUBSTITUTION < (LIST (COMMAND (STRING cat) (STRING / usr / share / dict / linux . words)))) (STRING wc)) (|| (&& (&& (&& (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 (OFFSET (ARITHMETIC 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 (REDIR 2 >& (FILE_DESCRIPTOR 1)) (REDIR > (STRING / dev / null)) (STRING grep) (STRING three))) (COMMAND (REDIR >> (STRING APPEND)) (STRING echo) (STRING asdf)) (COMMAND (<<< (STRING word)) (STRING echo) (STRING cat)))
diff --git a/bashast/features_script/features.sh.walker.tokens b/bashast/features_script/features.sh.walker.tokens
index 8b92d49..bd966a9 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 ARITHMETIC DOWN TIMES DOWN DIGIT DIGIT UP UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN ARITHMETIC DOWN EXP DOWN DIGIT DIGIT UP UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN ARITHMETIC DOWN PLUS DOWN VAR_REF DOWN NAME UP SLASH DOWN DIGIT DIGIT UP UP UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN ARITHMETIC DOWN PLUS DOWN VAR_REF DOWN LETTER UP MINUS_SIGN DOWN DIGIT UP 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 ARITHMETIC DOWN DIGIT UP 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 ARITHMETIC DOWN VAR_REF DOWN NAME UP 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 ARITHMETIC DOWN DIGIT UP 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 BRANCH DOWN NAME UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP CASE_PATTERN DOWN BRANCH DOWN NAME UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP CASE_PATTERN DOWN BRANCH 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 ARITHMETIC DOWN PLUS DOWN DIGIT DIGIT UP UP UP FOR_COND DOWN ARITHMETIC DOWN PLUS DOWN DIGIT DIGIT UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP FOR_MOD DOWN ARITHMETIC DOWN PLUS DOWN DIGIT DIGIT UP 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 REDIR DOWN DIGIT 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 OFFSET DOWN ARITHMETIC DOWN DIGIT UP UP 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 REDIR DOWN DIGIT 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 BLANK 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 ARITHMETIC DOWN TIMES DOWN DIGIT DIGIT UP UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN ARITHMETIC DOWN EXP DOWN DIGIT DIGIT UP UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN ARITHMETIC DOWN PLUS DOWN VAR_REF DOWN NAME UP SLASH DOWN DIGIT DIGIT UP UP UP UP UP COMMAND DOWN ARITHMETIC_EXPRESSION DOWN ARITHMETIC DOWN PLUS DOWN VAR_REF DOWN LETTER UP MINUS_SIGN DOWN DIGIT UP 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 ARITHMETIC DOWN DIGIT UP 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 ARITHMETIC DOWN VAR_REF DOWN NAME UP 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 ARITHMETIC DOWN DIGIT UP 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 REDIR DOWN OP STRING DOWN NAME UP UP STRING DOWN NAME UP STRING DOWN NAME UP UP UP COMMAND DOWN CASE DOWN STRING DOWN COMMAND_SUB DOWN COMMAND_SUBSTITUTION_TICK UP UP CASE_PATTERN DOWN BRANCH DOWN NAME UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP CASE_PATTERN DOWN BRANCH DOWN NAME UP CASE_COMMAND LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP UP CASE_PATTERN DOWN BRANCH 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 ARITHMETIC DOWN PLUS DOWN DIGIT DIGIT UP UP UP FOR_COND DOWN ARITHMETIC DOWN PLUS DOWN DIGIT DIGIT UP UP UP LIST DOWN COMMAND DOWN STRING DOWN NAME UP STRING DOWN NAME UP UP UP FOR_MOD DOWN ARITHMETIC DOWN PLUS DOWN DIGIT DIGIT UP UP UP UP UP COMMAND DOWN SELECT DOWN NAME STRING DOWN COMMAND_SUB DOWN COMMAND_SUBSTITUTION_TICK UP UP LIST DOWN COMMAND DOWN REDIR DOWN DIGIT GREATER_THAN STRING DOWN SLASH NAME SLASH NAME UP UP STRING DOWN NAME UP STRING DOWN NAME 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 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 STRING DOWN NAME 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 OFFSET DOWN ARITHMETIC DOWN DIGIT UP UP 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 REDIR DOWN DIGIT OP FILE_DESCRIPTOR DOWN DIGIT UP UP REDIR DOWN GREATER_THAN STRING DOWN SLASH NAME SLASH NAME UP UP STRING DOWN NAME UP STRING DOWN NAME UP UP UP COMMAND DOWN REDIR DOWN OP STRING DOWN NAME UP UP STRING DOWN NAME UP STRING DOWN NAME UP UP COMMAND DOWN HERE_STRING_OP DOWN STRING DOWN NAME UP UP STRING DOWN NAME UP STRING DOWN NAME UP UP UP
diff --git a/bashast/gunit/compound.gunit b/bashast/gunit/compound.gunit
index f3ec44f..e66b3ba 100644
--- a/bashast/gunit/compound.gunit
+++ b/bashast/gunit/compound.gunit
@@ -162,7 +162,7 @@ case_expr:
echo \"Usage: $0 start|stop\" >&2
exit 3
;;
-esac" -> (case (STRING (DOUBLE_QUOTED_STRING (VAR_REF 1))) (CASE_PATTERN (BRANCH MATCH_ALL) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING Usage : (VAR_REF 0) start | stop)) (REDIR >& (FILE_DESCRIPTOR 2))) (COMMAND (STRING exit) (STRING 3)))))
+esac" -> (case (STRING (DOUBLE_QUOTED_STRING (VAR_REF 1))) (CASE_PATTERN (BRANCH MATCH_ALL) CASE_COMMAND (LIST (COMMAND (REDIR >& (FILE_DESCRIPTOR 2)) (STRING echo) (STRING (DOUBLE_QUOTED_STRING Usage : (VAR_REF 0) start | stop))) (COMMAND (STRING exit) (STRING 3)))))
"case $asdf in
a)
@@ -182,23 +182,23 @@ stop)
echo \"Usage: $0 start|stop\" >&2
exit 3
;;
-esac" -> (case (STRING (DOUBLE_QUOTED_STRING (VAR_REF 1))) (CASE_PATTERN (BRANCH stop)) (CASE_PATTERN (BRANCH MATCH_ALL) CASE_COMMAND (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING Usage : (VAR_REF 0) start | stop)) (REDIR >& (FILE_DESCRIPTOR 2))) (COMMAND (STRING exit) (STRING 3)))))
+esac" -> (case (STRING (DOUBLE_QUOTED_STRING (VAR_REF 1))) (CASE_PATTERN (BRANCH stop)) (CASE_PATTERN (BRANCH MATCH_ALL) CASE_COMMAND (LIST (COMMAND (REDIR >& (FILE_DESCRIPTOR 2)) (STRING echo) (STRING (DOUBLE_QUOTED_STRING Usage : (VAR_REF 0) start | stop))) (COMMAND (STRING exit) (STRING 3)))))
command:
-"[[ asdf > qwert ]] > /dev/null" -> (COMMAND (COMPOUND_COND (KEYWORD_TEST (> (STRING asdf) (STRING qwert)))) (REDIR > (STRING / dev / null)))
-"(( 5+3 )) > /dev/null" -> (COMMAND (ARITHMETIC_EXPRESSION (ARITHMETIC (+ 5 3))) (REDIR > (STRING / dev / null)))
-"{ time cat; } > /dev/null" -> (COMMAND (CURRENT_SHELL (LIST (COMMAND (STRING cat) time))) (REDIR > (STRING / dev / null)))
-"(time cat) > /dev/null" -> (COMMAND (SUBSHELL (LIST (COMMAND (STRING cat) time))) (REDIR > (STRING / dev / null)))
-"case a in esac >/dev/null" -> (COMMAND (case (STRING a) CASE_PATTERN) (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 (ARITHMETIC (+ 5 3))) (LIST (COMMAND (STRING echo) (STRING yay))) (FOR_MOD (ARITHMETIC (+ 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 `ls |grep log`)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found))))) (REDIR > (STRING / dev / null)))
+"[[ asdf > qwert ]] > /dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (COMPOUND_COND (KEYWORD_TEST (> (STRING asdf) (STRING qwert)))))
+"(( 5+3 )) > /dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (ARITHMETIC_EXPRESSION (ARITHMETIC (+ 5 3))))
+"{ time cat; } > /dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (CURRENT_SHELL (LIST (COMMAND (STRING cat) time))))
+"(time cat) > /dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (SUBSHELL (LIST (COMMAND (STRING cat) time))))
+"case a in esac >/dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (case (STRING a) CASE_PATTERN))
+"for i in foo$var bar; do echo $i; done >/dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (for i (STRING foo (VAR_REF var)) (STRING bar) (LIST (COMMAND (STRING echo) (STRING (VAR_REF i))))))
+"for ((5+3;;5+3)); do echo yay; done >/dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (CFOR (FOR_INIT (ARITHMETIC (+ 5 3))) (LIST (COMMAND (STRING echo) (STRING yay))) (FOR_MOD (ARITHMETIC (+ 5 3)))))
+"select each in `ls |grep log`; do echo \"file found\"; done >/dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (select each (STRING (COMMAND_SUB `ls |grep log`)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found))))))
"if echo yay2;
then
echo yay
elif echo yay3; then
echo boo
-fi > /dev/null" -> (COMMAND (IF_STATEMENT (if (LIST (COMMAND (STRING echo) (STRING yay2))) (LIST (COMMAND (STRING echo) (STRING yay)))) (if (LIST (COMMAND (STRING echo) (STRING yay3))) (LIST (COMMAND (STRING echo) (STRING boo))))) (REDIR > (STRING / dev / null)))
-"while echo true; do echo \"file found\"; done > /dev/null" -> (COMMAND (while (LIST (COMMAND (STRING echo) (STRING true))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found))))) (REDIR > (STRING / dev / null)))
-"until echo true; do echo \"file found\"; done >/dev/null" -> (COMMAND (until (LIST (COMMAND (STRING echo) (STRING true))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found))))) (REDIR > (STRING / dev / null)))
+fi > /dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (IF_STATEMENT (if (LIST (COMMAND (STRING echo) (STRING yay2))) (LIST (COMMAND (STRING echo) (STRING yay)))) (if (LIST (COMMAND (STRING echo) (STRING yay3))) (LIST (COMMAND (STRING echo) (STRING boo))))))
+"while echo true; do echo \"file found\"; done > /dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (while (LIST (COMMAND (STRING echo) (STRING true))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found))))))
+"until echo true; do echo \"file found\"; done >/dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (until (LIST (COMMAND (STRING echo) (STRING true))) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING file found))))))
diff --git a/bashast/gunit/expansions.gunit b/bashast/gunit/expansions.gunit
index 39acfa9..86c55ae 100644
--- a/bashast/gunit/expansions.gunit
+++ b/bashast/gunit/expansions.gunit
@@ -27,7 +27,7 @@ command_list:
"for each in `ls |grep output`; do
echo $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))))))
+"wc <(cat /usr/share/dict/linux.words)" -> (LIST (COMMAND (PROCESS_SUBSTITUTION < (LIST (COMMAND (STRING cat) (STRING / usr / share / dict / linux . words)))) (STRING wc)))
all_expansions:
"$'abc' abc $(ab) ${ab} $((ab)) `ab` \"ab\" 'ab'" -> (STRING (ANSI_C_QUOTING 'abc') abc (COMMAND_SUB $(ab)) (VAR_REF ab) (ARITHMETIC_EXPRESSION (ARITHMETIC (VAR_REF ab))) (COMMAND_SUB `ab`) (DOUBLE_QUOTED_STRING ab) 'ab')
diff --git a/bashast/gunit/function.gunit b/bashast/gunit/function.gunit
index e0b23ef..62eb773 100644
--- a/bashast/gunit/function.gunit
+++ b/bashast/gunit/function.gunit
@@ -36,9 +36,9 @@ command_atom:
"function out() { function inner() { :; }; }" -> (FUNCTION (STRING out) (CURRENT_SHELL (LIST (COMMAND (FUNCTION (STRING inner) (CURRENT_SHELL (LIST (COMMAND (STRING :)))))))))
command:
-"function quit { exit; } > /dev/null" -> (COMMAND (FUNCTION (STRING quit) (CURRENT_SHELL (LIST (COMMAND (STRING exit))))) (REDIR > (STRING / dev / null)))
+"function quit { exit; } > /dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (FUNCTION (STRING quit) (CURRENT_SHELL (LIST (COMMAND (STRING exit))))))
"function quit {
# comment
- exit; } > /dev/null" -> (COMMAND (FUNCTION (STRING quit) (CURRENT_SHELL (LIST (COMMAND (STRING exit))))) (REDIR > (STRING / dev / null)))
-"function help { echo hi; } 2> /dev/null" -> (COMMAND (FUNCTION (STRING help) (CURRENT_SHELL (LIST (COMMAND (STRING echo) (STRING hi))))) (REDIR 2 > (STRING / dev / null)))
+ exit; } > /dev/null" -> (COMMAND (REDIR > (STRING / dev / null)) (FUNCTION (STRING quit) (CURRENT_SHELL (LIST (COMMAND (STRING exit))))))
+"function help { echo hi; } 2> /dev/null" -> (COMMAND (REDIR 2 > (STRING / dev / null)) (FUNCTION (STRING help) (CURRENT_SHELL (LIST (COMMAND (STRING echo) (STRING hi))))))
"function help { echo 3; } 2> /dev/null > output" OK
diff --git a/bashast/gunit/list.gunit b/bashast/gunit/list.gunit
index 552788a..acd1728 100644
--- a/bashast/gunit/list.gunit
+++ b/bashast/gunit/list.gunit
@@ -41,6 +41,6 @@ echo \"a b\"" -> (LIST (COMMAND (VARIABLE_DEFINITIONS (= a (STRING asdf)))) (COM
"FOO='bar' ;" -> (LIST (COMMAND (VARIABLE_DEFINITIONS (= FOO (STRING (SINGLE_QUOTED_STRING 'bar'))))))
"true;
true" -> (LIST (COMMAND (STRING true)) (COMMAND (STRING true)))
-"(echo hi > /dev/null) >> 1" -> (LIST (COMMAND (SUBSHELL (LIST (COMMAND (STRING echo) (STRING hi) (REDIR > (STRING / dev / null))))) (REDIR >> (FILE_DESCRIPTOR 1))))
-"{ echo hi > /dev/null; } >> 1" -> (LIST (COMMAND (CURRENT_SHELL (LIST (COMMAND (STRING echo) (STRING hi) (REDIR > (STRING / dev / null))))) (REDIR >> (FILE_DESCRIPTOR 1))))
+"(echo hi > /dev/null) >> 1" -> (LIST (COMMAND (REDIR >> (FILE_DESCRIPTOR 1)) (SUBSHELL (LIST (COMMAND (REDIR > (STRING / dev / null)) (STRING echo) (STRING hi))))))
+"{ echo hi > /dev/null; } >> 1" -> (LIST (COMMAND (REDIR >> (FILE_DESCRIPTOR 1)) (CURRENT_SHELL (LIST (COMMAND (REDIR > (STRING / dev / null)) (STRING echo) (STRING hi))))))
"test 1 -gt 0 || return 0" -> (LIST (|| (COMMAND (COMPOUND_COND (BUILTIN_TEST (gt (STRING 1) (STRING 0))))) (COMMAND (STRING return) (STRING 0))))
diff --git a/bashast/gunit/pipeline.gunit b/bashast/gunit/pipeline.gunit
index aea66f0..b97ec3b 100644
--- a/bashast/gunit/pipeline.gunit
+++ b/bashast/gunit/pipeline.gunit
@@ -25,7 +25,7 @@ pipeline:
"time -p cat file" -> (COMMAND (STRING cat) (STRING file) (time p))
"time cat file | grep search" -> (| (COMMAND (STRING cat) (STRING file) time) (COMMAND (STRING grep) (STRING search)))
"time -p cat | grep asdf | a.out" -> (| (| (COMMAND (STRING cat) (time p)) (COMMAND (STRING grep) (STRING asdf))) (COMMAND (STRING a . out)))
-"time -p cat file |grep search >> log" -> (| (COMMAND (STRING cat) (STRING file) (time p)) (COMMAND (STRING grep) (STRING search) (REDIR >> (STRING log))))
+"time -p cat file |grep search >> log" -> (| (COMMAND (STRING cat) (STRING file) (time p)) (COMMAND (REDIR >> (STRING log)) (STRING grep) (STRING search)))
"if time cat; then
echo \"three\"
fi" -> (COMMAND (IF_STATEMENT (if (LIST (COMMAND (STRING cat) time)) (LIST (COMMAND (STRING echo) (STRING (DOUBLE_QUOTED_STRING three)))))))
diff --git a/bashast/gunit/process_substitution.gunit b/bashast/gunit/process_substitution.gunit
index f7e0ec2..34802f7 100644
--- a/bashast/gunit/process_substitution.gunit
+++ b/bashast/gunit/process_substitution.gunit
@@ -25,5 +25,5 @@ process_substitution:
command:
"while read -d $'\0' -r nspkg_pth_file; do
nspkg_pth_files+=(\"${nspkg_pth_file}\")
-done < <(find \"${ED}\" -name \"*-nspkg.pth\" -type f -print0)" -> (COMMAND (while (LIST (COMMAND (STRING read) (STRING - d) (STRING (ANSI_C_QUOTING '\0')) (STRING - r) (STRING nspkg_pth_file))) (LIST (COMMAND (VARIABLE_DEFINITIONS (PLUS_ASSIGN nspkg_pth_files (ARRAY (STRING (DOUBLE_QUOTED_STRING (VAR_REF nspkg_pth_file))))))))) (REDIR < (PROCESS_SUBSTITUTION < (LIST (COMMAND (STRING find) (STRING (DOUBLE_QUOTED_STRING (VAR_REF ED))) (STRING - name) (STRING (DOUBLE_QUOTED_STRING * - nspkg . pth)) (STRING - type) (STRING f) (STRING - print0))))))
+done < <(find \"${ED}\" -name \"*-nspkg.pth\" -type f -print0)" -> (COMMAND (REDIR < (PROCESS_SUBSTITUTION < (LIST (COMMAND (STRING find) (STRING (DOUBLE_QUOTED_STRING (VAR_REF ED))) (STRING - name) (STRING (DOUBLE_QUOTED_STRING * - nspkg . pth)) (STRING - type) (STRING f) (STRING - print0))))) (while (LIST (COMMAND (STRING read) (STRING - d) (STRING (ANSI_C_QUOTING '\0')) (STRING - r) (STRING nspkg_pth_file))) (LIST (COMMAND (VARIABLE_DEFINITIONS (PLUS_ASSIGN nspkg_pth_files (ARRAY (STRING (DOUBLE_QUOTED_STRING (VAR_REF nspkg_pth_file))))))))))
"echo<(cat)" FAIL
diff --git a/bashast/gunit/redir.gunit b/bashast/gunit/redir.gunit
index d6aa599..bd4cdd9 100644
--- a/bashast/gunit/redir.gunit
+++ b/bashast/gunit/redir.gunit
@@ -50,5 +50,5 @@ _EOF_.abc
) (REDIR > (STRING / dev / null)))))
"cat > /dev/null <<-END_LDSCRIPT
GNU...
-END_LDSCRIPT" -> (LIST (COMMAND (STRING cat) (REDIR > (STRING / dev / null)) (<<- (STRING GNU .. .
+END_LDSCRIPT" -> (LIST (COMMAND (REDIR > (STRING / dev / null)) (STRING cat) (<<- (STRING GNU .. .
))))
diff --git a/bashast/gunit/simp_command.gunit b/bashast/gunit/simp_command.gunit
index e6a8602..2415b5e 100644
--- a/bashast/gunit/simp_command.gunit
+++ b/bashast/gunit/simp_command.gunit
@@ -32,6 +32,6 @@ command_atom:
"echo \"ab#af ###\" #abc" -> (STRING echo) (STRING (DOUBLE_QUOTED_STRING ab # af # # #))
command:
-"asdf=5 cat out.log > result" -> (COMMAND (STRING cat) (STRING out . log) (= asdf (STRING 5)) (REDIR > (STRING result)))
-"cat results.log > asdf 2> /dev/null" -> (COMMAND (STRING cat) (STRING results . log) (REDIR > (STRING asdf)) (REDIR 2 > (STRING / dev / null)))
+"asdf=5 cat out.log > result" -> (COMMAND (REDIR > (STRING result)) (STRING cat) (STRING out . log) (= asdf (STRING 5)))
+"cat results.log > asdf 2> /dev/null" -> (COMMAND (REDIR > (STRING asdf)) (REDIR 2 > (STRING / dev / null)) (STRING cat) (STRING results . log))
"test-parser a b c" -> (COMMAND (STRING test - parser) (STRING a) (STRING b) (STRING c))
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index 44cb4c2..27377de 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -171,6 +171,23 @@ options
{
return isdigit(target[0]);
}
+
+ class current_streams {
+ private:
+ std::ostream* _out;
+ std::ostream* _err;
+ std::istream* _in;
+ public:
+ current_streams(std::ostream* out, std::ostream* err, std::istream* in) :
+ _out(out), _err(err), _in(in) {
+ }
+
+ ~current_streams() {
+ walker->set_output_stream(_out);
+ walker->set_error_stream(_err);
+ walker->set_input_stream(_in);
+ }
+ };
}
}
@@ -624,7 +641,10 @@ var_ref [bool double_quoted] returns[std::string libbash_value]
|^(VAR_REF libbash_string=var_expansion) { $libbash_value = libbash_string; };
command
- :^(COMMAND command_atom);
+@declarations {
+ current_streams streams(walker->get_output_stream(), walker->get_error_stream(), walker->get_input_stream());
+}
+ :^(COMMAND redirect* command_atom);
command_atom
:variable_definitions
@@ -644,24 +664,18 @@ simple_command
execute_command[std::string& name, std::vector<std::string>& libbash_args]
@declarations {
std::unique_ptr<interpreter::local_scope> current_scope;
- std::unique_ptr<std::ostream> out;
- std::unique_ptr<std::ostream> err;
- std::unique_ptr<std::istream> in;
- bool redirection = false;
}
@init {
if(name != "local" && name != "set" && name != "declare" && name != "eval")
current_scope.reset(new interpreter::local_scope(*walker));
}
- :var_def[true]* (redirect[out, err, in]{ redirection = true; })* {
+ :var_def[true]* {
// Empty command, still need to run bash redirection
if(name.empty())
name = ":";
if(walker->has_function(name))
{
- if(redirection)
- std::cerr << "We do not support redirection for function calls." << std::endl;
ANTLR3_MARKER command_index = INDEX();
try
{
@@ -677,7 +691,7 @@ execute_command[std::string& name, std::vector<std::string>& libbash_args]
}
else if(cppbash_builtin::is_builtin(name))
{
- walker->set_status(walker->execute_builtin(name, libbash_args, out.get(), err.get(), in.get()));
+ walker->set_status(walker->execute_builtin(name, libbash_args));
}
else
{
@@ -687,16 +701,17 @@ execute_command[std::string& name, std::vector<std::string>& libbash_args]
}
(BANG { walker->set_status(!walker->get_status()); })?;
-redirect[std::unique_ptr<std::ostream>& out, std::unique_ptr<std::ostream>& err, std::unique_ptr<std::istream>& in]
- :^(REDIR LESS_THAN redirect_destination_input[in]) {
+redirect
+ :^(REDIR LESS_THAN redirect_destination_input)
+ |^(REDIR GREATER_THAN redirect_destination_output)
+ |^(REDIR DIGIT LESS_THAN redirect_destination_input) {
std::cerr << "Redirection is not supported yet" << std::endl;
}
- |^(REDIR GREATER_THAN redirect_destination_output[out])
- |^(REDIR DIGIT LESS_THAN redirect_destination_input[in]) {
+ |^(REDIR DIGIT GREATER_THAN redirect_destination_output) {
std::cerr << "Redirection is not supported yet" << std::endl;
}
- |^(REDIR DIGIT GREATER_THAN redirect_destination_output[out]) {
- std::cerr << "Redirection is not supported yet" << std::endl;
+ |^(HERE_STRING_OP string_expr) {
+ walker->set_input_stream(new std::istringstream($string_expr.libbash_value));
};
redirect_operator
@@ -704,9 +719,9 @@ redirect_operator
|GREATER_THAN
|FILE_DESCRIPTOR DIGIT redirect_operator;
-redirect_destination_output[std::unique_ptr<std::ostream>& out]
+redirect_destination_output
:string_expr {
- out.reset(new std::ofstream($string_expr.libbash_value, std::ofstream::trunc));
+ walker->set_output_stream(new std::ofstream($string_expr.libbash_value, std::ofstream::trunc));
}
|FILE_DESCRIPTOR DIGIT {
std::cerr << "FILE_DESCRIPTOR redirection is not supported yet" << std::endl;
@@ -715,9 +730,9 @@ redirect_destination_output[std::unique_ptr<std::ostream>& out]
std::cerr << "FILE_DESCRIPTOR_MOVE redirection is not supported yet" << std::endl;
};
-redirect_destination_input[std::unique_ptr<std::istream>& in]
+redirect_destination_input
:string_expr {
- std::cerr << "Input redirection for file is not supported yet" << std::endl;
+ walker->set_input_stream(new std::ifstream($string_expr.libbash_value, std::ifstream::in));
}
|FILE_DESCRIPTOR DIGIT {
std::cerr << "FILE_DESCRIPTOR redirection is not supported yet" << std::endl;
diff --git a/scripts/command_execution.bash b/scripts/command_execution.bash
index 901a9bb..3b275ca 100644
--- a/scripts/command_execution.bash
+++ b/scripts/command_execution.bash
@@ -96,3 +96,14 @@ eval abc+=\( \"\$@\" \)
declare MOZILLA_FIVE_HOME="/usr/share/${PN}"
declare foo=23 empty bar=42
echo $MOZILLA_FIVE_HOME $foo $lol $bar
+
+FILE=scripts/input_output_test
+echo foo > $FILE
+read line < scripts/input_output_test
+echo $line
+if [ 1 = 1 ]; then
+ read line
+ echo $line
+fi < $FILE
+read string <<< "a b c d"
+echo $string
diff --git a/scripts/here_document.ast b/scripts/here_document.ast
index 4dadb03..612fa0b 100644
--- a/scripts/here_document.ast
+++ b/scripts/here_document.ast
@@ -1,7 +1,7 @@
(LIST (COMMAND (STRING cat) (<< (STRING blah
blah
-) (REDIR > (STRING / dev / null)))) (COMMAND (STRING echo) (STRING hi)) (COMMAND (STRING cat) (REDIR > (STRING (DOUBLE_QUOTED_STRING / dev / null))) (<<- (STRING
+) (REDIR > (STRING / dev / null)))) (COMMAND (STRING echo) (STRING hi)) (COMMAND (REDIR > (STRING (DOUBLE_QUOTED_STRING / dev / null))) (STRING cat) (<<- (STRING
java - Dtijmp . jar = " $(java-config -p tijmp) " - agentlib : tijmp " $ { @ } "
-))) (COMMAND (STRING cat) (REDIR > (STRING (DOUBLE_QUOTED_STRING / dev / null))) (<<- (STRING
+))) (COMMAND (REDIR > (STRING (DOUBLE_QUOTED_STRING / dev / null))) (STRING cat) (<<- (STRING
java - Dtijmp . jar = " $(java-config -p tijmp) " - agentlib : tijmp " $ { @ } "
))))
diff --git a/src/core/interpreter.h b/src/core/interpreter.h
index 2f6854b..3c6dde6 100644
--- a/src/core/interpreter.h
+++ b/src/core/interpreter.h
@@ -191,12 +191,47 @@ public:
_out = stream;
}
+ /// \brief get current output stream
+ /// \return the pointer to the output stream
+ std::ostream* get_output_stream()
+ {
+ return _out;
+ }
+
/// \brief restore the current output stream to standard output stream
void restore_output_stream()
{
_out = &std::cout;
}
+ /// \brief set current error stream
+ /// \param stream the pointer to the error stream
+ void set_error_stream(std::ostream* stream)
+ {
+ _err = stream;
+ }
+
+ /// \brief get current error stream
+ /// \return the pointer to the error stream
+ std::ostream* get_error_stream()
+ {
+ return _err;
+ }
+
+ /// \brief set current input stream
+ /// \param stream the pointer to the input stream
+ void set_input_stream(std::istream* stream)
+ {
+ _in = stream;
+ }
+
+ /// \brief get current input stream
+ /// \return the pointer to the input stream
+ std::istream* get_input_stream()
+ {
+ return _in;
+ }
+
/// \brief check whether a variable is valid and can be used
/// \param var variable
/// \return whether the variable is valid
diff --git a/test/bash_compiler.sh b/test/bash_compiler.sh
index 54b8178..8f7f80f 100755
--- a/test/bash_compiler.sh
+++ b/test/bash_compiler.sh
@@ -18,4 +18,5 @@ do
done
rm -rf $result
+rm -rf scripts/input_output_test
exit $error