...('\n---', '${array[0]}') { (braced_var_sub token: bracket_op: (bracket_op.ArrayIndex expr:(arith_expr.ArithWord w:{})) ) }('\n---', '${array[5+5]}') { (braced_var_sub token: bracket_op: (bracket_op.ArrayIndex expr: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) ) }('\n---', '${array[@]}') {(braced_var_sub token: bracket_op:(bracket_op.WholeArray op_id:Id.Lit_At))}('\n---', '${array[*]}') {(braced_var_sub token: bracket_op:(bracket_op.WholeArray op_id:Id.Arith_Star))}('\n---', '${#}') {(${ Id.VSub_Pound '#')}('\n---', '${!}') {(${ Id.VSub_Bang '!')}('\n---', '${?}') {(${ Id.VSub_QMark '?')}('\n---', '${var}') {(${ Id.VSub_Name var)}('\n---', '${15}') {(${ Id.VSub_Number 15)}('\n---', '${#var}') {(braced_var_sub token: prefix_op:(Id.VSub_Pound))}('\n---', '${!ref}') {(braced_var_sub token: prefix_op:(Id.VSub_Bang))}('\n---', '${##}') {(braced_var_sub token: prefix_op:(Id.VSub_Pound))}('\n---', '${array[0]}') { (braced_var_sub token: bracket_op: (bracket_op.ArrayIndex expr:(arith_expr.ArithWord w:{})) ) }('\n---', '${array[@]}') {(braced_var_sub token: bracket_op:(bracket_op.WholeArray op_id:Id.Lit_At))}('\n---', '${#array[0]}') { (braced_var_sub token: prefix_op: (Id.VSub_Pound) bracket_op: (bracket_op.ArrayIndex expr:(arith_expr.ArithWord w:{})) ) }('\n---', '${!array[0]}') { (braced_var_sub token: prefix_op: (Id.VSub_Bang) bracket_op: (bracket_op.ArrayIndex expr:(arith_expr.ArithWord w:{})) ) }('\n---', '${var#prefix}') { (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_Pound arg_word:{}) ) }('\n---', '${!var#prefix}') { (braced_var_sub token: prefix_op: (Id.VSub_Bang) suffix_op: (suffix_op.Unary op_id:Id.VOp1_Pound arg_word:{}) ) }('\n---', '${#var#prefix}') Got expected ParseError: ('\n---', '${##2}') Got expected ParseError: ('\n---', '${undef:-') Got expected ParseError: ('\n---', '${undef:-$') Got expected ParseError: ('\n---', '${undef:-$F') Got expected ParseError: ('\n---', '${x@') Got expected ParseError: ('\n---', '${x@Q') Got expected ParseError: ('\n---', '${x%') Got expected ParseError: ('\n---', '${x/') Got expected ParseError: ('\n---', '${x/a/') Got expected ParseError: ('\n---', '${x/a/b') Got expected ParseError: ('\n---', '${x:') Got expected ParseError: ('\n---', '--foo=$func()') {<--foo> args:(arg_list))}('\n---', '$func()trailer') {(word_part.FuncCall name.....: args:(arg_list)) }('\n---', '--foo=$func()trailer') {<--foo> args:(arg_list)) }('\n---', '${#@}') {(braced_var_sub token: prefix_op:(Id.VSub_Pound))}('\n---', '${#11}') {(braced_var_sub token: prefix_op:(Id.VSub_Pound))}('\n---', '${#str}') {(braced_var_sub token: prefix_op:(Id.VSub_Pound))}('\n---', '${#array[0]}') { (braced_var_sub token: prefix_op: (Id.VSub_Pound) bracket_op: (bracket_op.ArrayIndex expr:(arith_expr.ArithWord w:{})) ) }('\n---', '${#array["key"]}') { (braced_var_sub token: prefix_op: (Id.VSub_Pound) bracket_op: (bracket_op.ArrayIndex expr:(arith_expr.ArithWord w:{(DQ )})) ) }--MULTI ('\n---', '@words') {(word_part.Splice name:)}('\n---', '.@words') {<.> }('\n---', '.@words.') {<.> <.>}('\n---', '@words[') Got expected ParseError: ('\n---', '@words.') Got expected ParseError: ('\n---', '@func()') {(word_part.FuncCall name: args:(arg_list))}('\n---', '$(echo @func())') { (command_sub left_token: command_list: (command.CommandList children: [(C {} {(word_part.FuncCall name: args:(arg_list))})] ) ) }('\n---', '$(($(echo @func())))') { (word_part.ArithSub anode: (arith_expr.ArithWord w: { (command_sub left_token: command_list: (command.CommandList children: [(C {} {(word_part.FuncCall name: args:(arg_list))})] ) ) } ) ) }('\n---', '@func().') Got expected ParseError: {)}\$ 0 (line_span line_id:0 col:0 length:2) {(SQ )}'' 0 (line_span line_id:0 col:0 length:1) {(SQ )}'sq' 0 (line_span line_id:0 col:0 length:1) {(DQ )}"" 0 (line_span line_id:0 col:0 length:1) {(DQ )}"dq" 0 (line_span line_id:0 col:0 length:1) { (command_sub left_token: command_list: (command.CommandList children:[(C {} {} {})]) ) }$(echo command sub) 0 (line_span line_id:0 col:0 length:2) { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) }$(( 1 + 2 )) 0 (line_span line_id:0 col:0 length:3) {}~user 0 (line_span line_id:0 col:0 length:5) {(braced_var_sub token: suffix_op:(suffix_op.Unary op_id:Id.VOp1_Pound arg_word:{}))}${var#} 0 (line_span line_id:0 col:0 length:2) ('\n---', '${var/pat/replace}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat:{} replace:{} replace_mode:Id.Undefined_Tok) ) }('\n---', '${var//pat/replace}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat:{} replace:{} replace_mode:Id.Lit_Slash) ) }('\n---', '${var/%pat/replace}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat:{} replace:{} replace_mode:Id.Lit_Percent) ) }('\n---', '${var/#pat/replace}') { (braced_var_sub token: suffix_op:.. (suffix_op.PatSub pat:{} replace:{} replace_mode:Id.Lit_Pound) ) }('\n---', '${var/pat}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat:{} replace_mode:Id.Undefined_Tok) ) }('\n---', '${var//pat}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat:{} replace_mode:Id.Lit_Slash) ) }('\n---', '${var/pat//}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat:{} replace:{} replace_mode:Id.Undefined_Tok) ) }('\n---', '${var/pat///}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat: {} replace: { } replace_mode: Id.Undefined_Tok ) ) }('\n---', '${var/pat/"//"}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat:{} replace:{(DQ )} replace_mode:Id.Undefined_Tok) ) }('\n---', '${var////\\\\/}') { (braced_var_sub token: suffix_op: (suffix_op.PatSub pat: {} replace: {(word_part.EscapedLiteral token:) } replace_mode: Id.Lit_Slash ) ) }--- ls "foo" () {}{(DQ )}--- $(( 1 + 2 )) () { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) }--- $(echo $(( 1 )) ) () { (command_sub left_token: command_list: (command.CommandList children: [(C {} {(word_part.ArithSub anode:(arith_expr.ArithWord w:{}))})] ) ) }--- echo ${#array[@]} b () {}{ (braced_var_sub token: prefix_op: (Id.VSub_Pound) bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At) ) }{}--- echo $(( ${#array[@]} )) () {}{ (word_part.ArithSub anode: (arith_expr.ArithWord w: { (braced_var_sub token: prefix_op: (Id.VSub_Pound) bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At) ) } ) ) }--- echo ${@%suffix} () {}{ (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_Percent arg_word:{}) ) }--- ${@} () {(${ Id.VSub_At '@')}--- echo ${var,,} () {}{(braced_var_sub token: suffix_op:(suffix_op.Unary op_id:Id.VOp1_DComma arg_word:{}))}--- echo ${var,,?} () {}{ (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_DComma arg_word:{<'?'>}) ) }--- ${\ foo} () {(${ Id.VSub_Name foo)}--- ${foo\ } () {(${ Id.VSub_Name foo)}--- ${foo#\ yo} () { (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_Pound arg_word:{}) ) }--- "${foo#\ yo}" () { (DQ (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_Pound arg_word:{}) ) ) }--- 1 + 2 () {}{}--- a + b () {}{}--- $a * $b () {($ Id.VSub_DollarName '$a')}{($ Id.VSub_DollarName '$b')}--- ${a} * ${b} () {(${ Id.VSub_Name a)}{(${ Id.VSub_Name b)}--- $(echo 1) * $(echo 2) () { (command_sub left_token: command_list: (command.CommandList children:[(C {} {<1>})]) ) }{ (command_sub left_token: command_list: (command.CommandList childr....en:[(C {} {<2>})]) ) }--- `echo 1` + 2 () { (command_sub left_token: command_list: (command.CommandList children:[(C {} {<1>})]) ) }{}--- $((1 + 2)) * $((3 + 4)) () { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) }{ (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) }--- 'single quoted' () {(SQ <'single quoted'>)}--- "${a}" + "${b}" () {(DQ (${ Id.VSub_Name a))}{(DQ (${ Id.VSub_Name b))}--- $# + $$ () {($ Id.VSub_Pound '$#')}{($ Id.VSub_Dollar '$$')}--- $(( x[0] < 5 )) () { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Less left: (arith_expr.Binary op_id: Id.Arith_LBracket left: (arith_expr.VarRef token:) right: (arith_expr.ArithWord w:{}) ) right: (arith_expr.ArithWord w:{}) ) ) }--- $(( ++i )) () { (word_part.ArithSub anode: (arith_expr.UnaryAssign op_id:Id.Arith_DPlus child:(sh_lhs_expr.Name name:i)) ) }--- $(( i++ )) () { (word_part.ArithSub anode: (arith_expr.UnaryAssign op_id:Id.Node_PostDPlus child:(sh_lhs_expr.Name name:i)) ) }--- $(( x -= 1)) () { (word_part.ArithSub anode: (arith_expr.BinaryAssign op_id: Id.Arith_MinusEqual left: (sh_lhs_expr.Name name:x) right: (arith_expr.ArithWord w:{}) ) ) }--- $(( x |= 1)) () { (word_part.ArithSub anode: (arith_expr.BinaryAssign op_id: Id.Arith_PipeEqual left: (sh_lhs_expr.Name name:x) right: (arith_expr.ArithWord w:{}) ) ) }--- $(( x[0] = 1 )) () { (word_part.ArithSub anode: (arith_expr.BinaryAssign op_id: Id.Arith_Equal left: (sh_lhs_expr.IndexedName name:x index:(arith_expr.ArithWord w:{})) right: (arith_expr.ArithWord w:{}) ) ) }--- $(( 1 | 0 )) () { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Pipe left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) }--- $((0x$size)) () { (word_part.ArithSub anode: (arith_expr.ArithWord w: { ($ Id.VSub_DollarName '$size')} ) ) }('\n---', '$(( (1+2) ))') { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) }('\n---', '$(( (1+2) ))') { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) }('\n---', '${foo:0}') { (braced_var_sub token: suffix_op: (suffix_op.Slice begin:(arith_expr.ArithWord w:{})) ) }('\n---', '${foo:0:1}') { (braced_var_sub token: suffix_op: (suffix_op.Slice begin: (arith_expr.ArithWord w:{}) length: (arith_expr.ArithWord w:{}) ) ) }('\n---', '${foo:1+2:2+3}') { (braced_var_sub token: suffix_op: (suffix_op.Slice begin: (arith_expr.Binary ...... ---------------------------------------------------------------------- Ran 20 tests in 0.076s OK op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) length: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{}) right: (arith_expr.ArithWord w:{}) ) ) ) }('\n---', '${foo::1}') { (braced_var_sub token: suffix_op: (suffix_op.Slice length:(arith_expr.ArithWord w:{})) ) }('\n---', '${var:-default]}') { (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VTest_ColonHyphen arg_word:{<'default]'>}) ) }('\n---', '~/git/oilshell/oil') { }('\n---', '~andy/git/oilshell/oil') { }('\n---', '~andy_c/git/oilshell/oil') { }('\n---', '~andy.c/git/oilshell/oil') { }('\n---', '~andy-c/git/oilshell/oil') { }('\n---', '~andy-c:git/oilshell/oil') { }('\n---', '${var#}') {(braced_var_sub token: suffix_op:(suffix_op.Unary op_id:Id.VOp1_Pound arg_word:{}))}('\n---', '${var#prefix}') { (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_Pound arg_word:{}) ) }('\n---', '${var##}') {(braced_var_sub token: suffix_op:(suffix_op.Unary op_id:Id.VOp1_DPound arg_word:{}))}('\n---', '${var##prefix}') { (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_DPound arg_word:{}) ) }('\n---', '${var%suffix}') { (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_Percent arg_word:{}) ) }('\n---', '${var%%suffix}') { (braced_var_sub token: suffix_op: (suffix_op.Unary op_id:Id.VOp1_DPercent arg_word:{}) ) }('\n---', '${name}') {(${ Id.VSub_Name name)}('\n---', '${name[0]}') { (braced_var_sub token: bracket_op: (bracket_op.ArrayIndex expr:(arith_expr.ArithWord w:{})) ) }('\n---', '${array[@]}') {(braced_var_sub token: bracket_op:(bracket_op.WholeArray op_id:Id.Lit_At))}