....(CompoundWord
  parts: [
    (Token
      id: Id.Lit_Chars
      length: 2
      col: 0
      line: (SourceLine line_num:1 content:"hi'\n" src:(source.MainFile path:hi))
    )
    (SingleQuoted
      left: (Token id:Id.Left_SingleQuote length:1 col:2 line:...0x7f21739c7db8)
      sval: "\nsingle quoted"
      right: 
        (Token
          id: Id.Right_SingleQuote
          length: 1
          col: 13
          line: (SourceLine line_num:2 content:"single quoted'\"double\n" src:...0x7f21739da710)
        )
    )
    (DoubleQuoted
      left: (Token id:Id.Left_DoubleQuote length:1 col:14 line:...0x7f21739c7e10)
      parts: [
        (Token id:Id.Lit_Chars length:7 col:15 line:...0x7f21739c7e10)
        (Token
          id: Id.Lit_Chars
          length: 7
          col: 0
          line: (SourceLine line_num:3 content:"quoted\n" src:...0x7f21739da710)
        )
      ]
      right: 
        (Token
          id: Id.Right_DoubleQuote
          length: 1
          col: 0
          line: (SourceLine line_num:4 content:"\"there\n" src:...0x7f21739da710)
        )
    )
    (Token id:Id.Lit_Chars length:5 col:1 line:...0x7f21739c7f18)
  ]
)
s = '\'\nsingle quoted\'"double\nquoted\n"'
s = "'\nsingle quoted'"
s = 'hi'
(CompoundWord
  parts: [
    (Token
      id: Id.Lit_VarLike
      length: 4
      col: 4
      line: (SourceLine line_num:1 content:"ls; foo=42" src:(source.MainFile path:""))
    )
    (Token id:Id.Lit_Chars length:2 col:8 line:...0x7f21739c7f18)
  ]
)
(CompoundWord
  parts: [
    (Token
      id: Id.Lit_VarLike
      length: 5
      col: 4
      line: (SourceLine line_num:1 content:"ls; foo+=X" src:(source.MainFile path:""))
    )
    (Token id:Id.Lit_Chars length:1 col:9 line:...0x7f21739c7ec0)
  ]
)

--- ${array[0]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    bracket_op: (bracket_op.ArrayIndex expr:{<Id.Lit_Digits 0>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${array[5+5]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    bracket_op: 
      (bracket_op.ArrayIndex
        expr: 
          (arith_expr.Binary
            op: <Id.Arith_Plus "+">
            left: {<Id.Lit_Digits 5>}
            right: {<Id.Lit_Digits 5>}
          )
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${array[@]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At)
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${array[*]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    bracket_op: (bracket_op.WholeArray op_id:Id.Arith_Star)
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${#}

{(${ Id.VSub_Pound "#")}

--- ${!}

{(${ Id.VSub_Bang "!")}

--- ${?}

{(${ Id.VSub_QMark "?")}

--- ${var}

{(${ Id.VSub_Name var)}

--- ${15}

{(${ Id.VSub_Number 15)}

--- ${#var}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    prefix_op: <Id.VSub_Pound "#">
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${!ref}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name ref>
    var_name: ref
    prefix_op: <Id.VSub_Bang "!">
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${##}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Pound "#">
    var_name: "#"
    prefix_op: <Id.VSub_Pound "#">
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${array[0]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    bracket_op: (bracket_op.ArrayIndex expr:{<Id.Lit_Digits 0>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${array[@]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At)
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${#array[0]}

{
  (BracedVarSub
    left:..... <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    prefix_op: <Id.VSub_Pound "#">
    bracket_op: (bracket_op.ArrayIndex expr:{<Id.Lit_Digits 0>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${!array[0]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    prefix_op: <Id.VSub_Bang "!">
    bracket_op: (bracket_op.ArrayIndex expr:{<Id.Lit_Digits 0>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var#prefix}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_Pound "#"> arg_word:{<Id.Lit_Chars prefix>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${!var#prefix}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    prefix_op: <Id.VSub_Bang "!">
    suffix_op: (suffix_op.Unary op:<Id.VOp1_Pound "#"> arg_word:{<Id.Lit_Chars prefix>})
    right: <Id.Right_DollarBrace "}">
  )
}
('\n---', '${#var#prefix}')
Got expected ParseError: 
('\n---', '${##2}')
Got expected ParseError: 
--MULTI
('\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: 

--- ${#@}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_At "@">
    var_name: "@"
    prefix_op: <Id.VSub_Pound "#">
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${#11}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Number 11>
    var_name: 11
    prefix_op: <Id.VSub_Pound "#">
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${#str}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name str>
    var_name: str
    prefix_op: <Id.VSub_Pound "#">
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${#array[0]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    prefix_op: <Id.VSub_Pound "#">
    bracket_op: (bracket_op.ArrayIndex expr:{<Id.Lit_Digits 0>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${#array["key"]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    prefix_op: <Id.VSub_Pound "#">
    bracket_op: (bracket_op.ArrayIndex expr:{(DQ <Id.Lit_Chars key>)})
    right: <Id.Right_DollarBrace "}">
  )
}

--- @words

{(word_part.Splice blame_tok:<Id.Lit_Splice "@words"> var_name:words)}

--- .@words

{<Id.Lit_Chars .> <Id.Lit_Splice "@words">}

--- .@words.

{<Id.Lit_Chars .> <Id.Lit_Splice "@words"> <Id.Lit_Chars .>}
('\n---', '@words[')
Got expected ParseError: 
('\n---', '@words.')
Got expected ParseError: 
{<Id.Lit_VarLike "a="> 
  (ShArrayLiteral
    left: <Id.Op_LParen "(">
    words: [{<Id.Lit_Chars 1>} {<Id.Lit_Chars 2>} {<Id.Lit_Chars 3>}]
    right: <Id.Right_ShArrayLiteral ")">
  )
}
a=(1 2 3)
(Token
  id: Id.Lit_VarLike
  length: 2
  col: 0
  line: (SourceLine line_num:1 content:"a=(1 2 3)" src:(source.MainFile path:word_parse_test.py))
)
{<Id.Lit_Chars foo>}
foo
(Token
  id: Id.Lit_Chars
  length: 3
  col: 0
  line: (SourceLine line_num:1 content:foo src:(source.MainFile path:word_parse_test.py))
)
{(word_part.EscapedLiteral token:<Id.Lit_EscapedChar "\\$"> ch:"$")}
\$
(Token
  id: Id.Lit_EscapedChar
  length: 2
  col: 0
  line: (SourceLine line_num:1 content:"\\$" src:(source.MainFile path:word_parse_test.py))
)
{(SQ "")}
''
(Token
  id: Id.Left_SingleQuote
  length: 1
  col: 0
  line: (SourceLine line_num:1 content:"''" src:(source.MainFile path:word_parse_test.py))
)
{(SQ sq)}
'sq'
(Token
  id: Id.Left_SingleQuote
  length: 1
  col: 0
  line: (SourceLine line_num:1 content:"'sq'" src:(source.MainFile path:word_par.se_test.py))
)
{(DQ )}
""
(Token
  id: Id.Left_DoubleQuote
  length: 1
  col: 0
  line: (SourceLine line_num:1 content:"\"\"" src:(source.MainFile path:word_parse_test.py))
)
{(DQ <Id.Lit_Chars dq>)}
"dq"
(Token
  id: Id.Left_DoubleQuote
  length: 1
  col: 0
  line: (SourceLine line_num:1 content:"\"dq\"" src:(source.MainFile path:word_parse_test.py))
)
{
  (CommandSub
    left_token: <Id.Left_DollarParen "$(">
    child: 
      (command.Simple
        blame_tok: <Id.Lit_Chars echo>
        more_env: []
        words: [{<Id.Lit_Chars echo>} {<Id.Lit_Chars command>} {<Id.Lit_Chars sub>}]
        is_last_cmd: F
      )
    right: <Id.Eof_RParen ")">
  )
}
$(echo command sub)
(Token
  id: Id.Left_DollarParen
  length: 2
  col: 0
  line: 
    (SourceLine
      line_num: 1
      content: "$(echo command sub)"
      src: (source.MainFile path:word_parse_test.py)
    )
)
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.Binary
        op: <Id.Arith_Plus "+">
        left: {<Id.Lit_Digits 1>}
        right: {<Id.Lit_Digits 2>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}
$(( 1 + 2 ))
(Token
  id: Id.Left_DollarDParen
  length: 3
  col: 0
  line: (SourceLine line_num:1 content:"$(( 1 + 2 ))" src:(source.MainFile path:word_parse_test.py))
)
{<Id.Lit_Tilde "~"> <Id.Lit_Chars user>}
~user
(Token
  id: Id.Lit_Tilde
  length: 1
  col: 0
  line: (SourceLine line_num:1 content:"~user" src:(source.MainFile path:word_parse_test.py))
)
{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_Pound "#"> arg_word:{})
    right: <Id.Right_DollarBrace "}">
  )
}
${var#}
(Token
  id: Id.Left_DollarBrace
  length: 2
  col: 0
  line: (SourceLine line_num:1 content:"${var#}" src:(source.MainFile path:word_parse_test.py))
)

--- ${var/pat/replace}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: {<Id.Lit_Chars replace>}
        replace_mode: Id.Undefined_Tok
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var//pat/replace}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: {<Id.Lit_Chars replace>}
        replace_mode: Id.Lit_Slash
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var/%pat/replace}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: {<Id.Lit_Chars replace>}
        replace_mode: Id.Lit_Percent
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var/#pat/replace}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: {<Id.Lit_Chars replace>}
        replace_mode: Id.Lit_Pound
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var/pat}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: (rhs_word__Empty)
        replace_mode: Id.Undefined_Tok
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var//pat}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: (rhs_word__Empty)
        replace_mode: Id.Lit_Slash
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var/pat//}

{
  (BracedVarSub
.    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: {<Id.Lit_Slash />}
        replace_mode: Id.Undefined_Tok
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var/pat///}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: {<Id.Lit_Slash /> <Id.Lit_Slash />}
        replace_mode: Id.Undefined_Tok
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var/pat/"//"}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Chars pat>}
        replace: {(DQ <Id.Lit_Chars //>)}
        replace_mode: Id.Undefined_Tok
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var////\\/}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: 
      (suffix_op.PatSub
        pat: {<Id.Lit_Slash />}
        replace: 
          {(word_part.EscapedLiteral token:<Id.Lit_EscapedChar "\\\\"> ch:"\\") <Id.Lit_Slash />}
        replace_mode: Id.Lit_Slash
        slash_tok: <Id.VOp2_Slash />
      )
    right: <Id.Right_DollarBrace "}">
  )
}
---
ls "foo"
()
{<Id.Lit_Chars ls>}{(DQ <Id.Lit_Chars foo>)}<Id.Eof_Real "">---
$(( 1 + 2 ))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.Binary
        op: <Id.Arith_Plus "+">
        left: {<Id.Lit_Digits 1>}
        right: {<Id.Lit_Digits 2>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
$(echo $(( 1 )) )
()
{
  (CommandSub
    left_token: <Id.Left_DollarParen "$(">
    child: 
      (command.Simple
        blame_tok: <Id.Lit_Chars echo>
        more_env: []
        words: [
          {<Id.Lit_Chars echo>}
          {
            (word_part.ArithSub
              left: <Id.Left_DollarDParen "$((">
              anode: {<Id.Lit_Digits 1>}
              right: <Id.Right_DollarDParen ")">
            )
          }
        ]
        is_last_cmd: F
      )
    right: <Id.Eof_RParen ")">
  )
}<Id.Eof_Real "">---
echo ${#array[@]} b
()
{<Id.Lit_Chars echo>}{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    prefix_op: <Id.VSub_Pound "#">
    bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At)
    right: <Id.Right_DollarBrace "}">
  )
}{<Id.Lit_Chars b>}<Id.Eof_Real "">---
echo $(( ${#array[@]} ))
()
{<Id.Lit_Chars echo>}{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      {
        (BracedVarSub
          left: <Id.Left_DollarBrace "${">
          token: <Id.VSub_Name array>
          var_name: array
          prefix_op: <Id.VSub_Pound "#">
          bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At)
          right: <Id.Right_DollarBrace "}">
        )
      }
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
echo ${@%suffix}
()
{<Id.Lit_Chars echo>}{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_At "@">
    var_name: "@"
    suffix_op: (suffix_op.Unary op:<Id.VOp1_Percent "%"> arg_word:{<Id.Lit_Chars suffix>})
    right: <Id.Right_DollarBrace "}">
  )
}<Id.Eof_Real "">---
${@}
()
{(${ Id.VSub_At "@")}<Id.Eof_Real "">---
echo ${var,,}
()
{<Id.Lit_Chars echo>}{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_DComma ",,"> arg_word:{})
    right: <Id.Right_DollarBrace "}">
  )
}<Id.Eof_Real "">---
echo ${var,,?}
()
{<Id.Lit_Chars echo>}{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_DComma ",,"> arg_word:{<Id.Lit_Other "?">})
    right: <Id.Right_DollarBrac.e "}">
  )
}<Id.Eof_Real "">---
${\
foo}
()
{(${ Id.VSub_Name foo)}<Id.Eof_Real "">---
${foo\
}
()
{(${ Id.VSub_Name foo)}<Id.Eof_Real "">---
${foo#\
yo}
()
{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name foo>
    var_name: foo
    suffix_op: (suffix_op.Unary op:<Id.VOp1_Pound "#"> arg_word:{<Id.Lit_Chars yo>})
    right: <Id.Right_DollarBrace "}">
  )
}<Id.Eof_Real "">---
"${foo#\
yo}"
()
{
  (DQ 
    (BracedVarSub
      left: <Id.Left_DollarBrace "${">
      token: <Id.VSub_Name foo>
      var_name: foo
      suffix_op: (suffix_op.Unary op:<Id.VOp1_Pound "#"> arg_word:{<Id.Lit_Chars yo>})
      right: <Id.Right_DollarBrace "}">
    )
  )
}<Id.Eof_Real "">---
1 + 2
()
{<Id.Lit_Digits 1>}<Id.Arith_Plus "+">{<Id.Lit_Digits 2>}<Id.Eof_Real "">---
a + b
()
{<Id.Lit_ArithVarLike a>}<Id.Arith_Plus "+">{<Id.Lit_ArithVarLike b>}<Id.Eof_Real "">---
$a * $b
()
{($ a)}<Id.Arith_Star "*">{($ b)}<Id.Eof_Real "">---
${a} * ${b}
()
{(${ Id.VSub_Name a)}<Id.Arith_Star "*">{(${ Id.VSub_Name b)}<Id.Eof_Real "">---
$(echo 1) * $(echo 2)
()
{
  (CommandSub
    left_token: <Id.Left_DollarParen "$(">
    child: 
      (command.Simple
        blame_tok: <Id.Lit_Chars echo>
        more_env: []
        words: [{<Id.Lit_Chars echo>} {<Id.Lit_Chars 1>}]
        is_last_cmd: F
      )
    right: <Id.Eof_RParen ")">
  )
}<Id.Arith_Star "*">{
  (CommandSub
    left_token: <Id.Left_DollarParen "$(">
    child: 
      (command.Simple
        blame_tok: <Id.Lit_Chars echo>
        more_env: []
        words: [{<Id.Lit_Chars echo>} {<Id.Lit_Chars 2>}]
        is_last_cmd: F
      )
    right: <Id.Eof_RParen ")">
  )
}<Id.Eof_Real "">---
`echo 1` + 2
()
{
  (CommandSub
    left_token: <Id.Left_Backtick "`">
    child: 
      (command.Simple
        blame_tok: <Id.Lit_Chars echo>
        more_env: []
        words: [{<Id.Lit_Chars echo>} {<Id.Lit_Chars 1>}]
        is_last_cmd: F
      )
    right: <Id.Backtick_Right "`">
  )
}<Id.Arith_Plus "+">{<Id.Lit_Digits 2>}<Id.Eof_Real "">---
$((1 + 2)) * $((3 + 4))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.Binary
        op: <Id.Arith_Plus "+">
        left: {<Id.Lit_Digits 1>}
        right: {<Id.Lit_Digits 2>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Arith_Star "*">{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.Binary
        op: <Id.Arith_Plus "+">
        left: {<Id.Lit_Digits 3>}
        right: {<Id.Lit_Digits 4>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
'single quoted'
()
{(SQ "single quoted")}<Id.Eof_Real "">---
"${a}" + "${b}"
()
{(DQ (${ Id.VSub_Name a))}<Id.Arith_Plus "+">{(DQ (${ Id.VSub_Name b))}<Id.Eof_Real "">---
$# + $$
()
{($ Id.VSub_Pound)}<Id.Arith_Plus "+">{($ Id.VSub_Dollar)}<Id.Eof_Real "">---
$(( x[0] < 5 ))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.Binary
        op: <Id.Arith_Less "<">
        left: 
          (arith_expr.Binary
            op: <Id.Arith_LBracket "[">
            left: <Id.Lit_ArithVarLike x>
            right: {<Id.Lit_Digits 0>}
          )
        right: {<Id.Lit_Digits 5>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
$(( ++i ))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: (arith_expr.UnaryAssign op_id:Id.Arith_DPlus child:<Id.Lit_ArithVarLike i>)
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
$(( i++ ))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: (arith_expr.UnaryAssign op_id:Id.Node_PostDPlus child:<Id.Lit_ArithVarLike i>)
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
$(( x -= 1))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.BinaryAssign
        op_id: Id.Arith_MinusEqual
        left: <Id.Lit_ArithVarLike x>
        right: {<Id.Lit_Digits 1>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
$(( x |= 1))
()
{
  (word_part.ArithSub
    left: <......Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.BinaryAssign
        op_id: Id.Arith_PipeEqual
        left: <Id.Lit_ArithVarLike x>
        right: {<Id.Lit_Digits 1>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
$(( x[0] = 1 ))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.BinaryAssign
        op_id: Id.Arith_Equal
        left: 
          (arith_expr.Binary
            op: <Id.Arith_LBracket "[">
            left: <Id.Lit_ArithVarLike x>
            right: {<Id.Lit_Digits 0>}
          )
        right: {<Id.Lit_Digits 1>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
$(( 1 | 0 ))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.Binary
        op: <Id.Arith_Pipe "|">
        left: {<Id.Lit_Digits 1>}
        right: {<Id.Lit_Digits 0>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">---
$((0x$size))
()
{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: {<Id.Lit_Digits 0> <Id.Lit_ArithVarLike x> ($ size)}
    right: <Id.Right_DollarDParen ")">
  )
}<Id.Eof_Real "">
--- $(( (1+2) ))

{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.Binary
        op: <Id.Arith_Plus "+">
        left: {<Id.Lit_Digits 1>}
        right: {<Id.Lit_Digits 2>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}

--- $(( (1+2) ))

{
  (word_part.ArithSub
    left: <Id.Left_DollarDParen "$((">
    anode: 
      (arith_expr.Binary
        op: <Id.Arith_Plus "+">
        left: {<Id.Lit_Digits 1>}
        right: {<Id.Lit_Digits 2>}
      )
    right: <Id.Right_DollarDParen ")">
  )
}

--- ${foo:0}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name foo>
    var_name: foo
    suffix_op: (suffix_op.Slice begin:{<Id.Lit_Digits 0>})
    right: <Id.Arith_RBrace "}">
  )
}

--- ${foo:0:1}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name foo>
    var_name: foo
    suffix_op: (suffix_op.Slice begin:{<Id.Lit_Digits 0>} length:{<Id.Lit_Digits 1>})
    right: <Id.Arith_RBrace "}">
  )
}

--- ${foo:1+2:2+3}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name foo>
    var_name: foo
    suffix_op: 
      (suffix_op.Slice
        begin: 
          (arith_expr.Binary
            op: <Id.Arith_Plus "+">
            left: {<Id.Lit_Digits 1>}
            right: {<Id.Lit_Digits 2>}
          )
        length: 
          (arith_expr.Binary
            op: <Id.Arith_Plus "+">
            left: {<Id.Lit_Digits 2>}
            right: {<Id.Lit_Digits 3>}
          )
      )
    right: <Id.Arith_RBrace "}">
  )
}

--- ${foo::1}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name foo>
    var_name: foo
    suffix_op: (suffix_op.Slice begin:(arith_expr__EmptyZero) length:{<Id.Lit_Digits 1>})
    right: <Id.Arith_RBrace "}">
  )
}

--- ${var:-default]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VTest_ColonHyphen ":-"> arg_word:{<Id.Lit_Chars "default]">})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ~/git/oilshell/oil

{<Id.Lit_Tilde "~"> <Id.Lit_Slash /> <Id.Lit_Chars git> <Id.Lit_Slash /> <Id.Lit_Chars oilshell> 
  <Id.Lit_Slash /> <Id.Lit_Chars oil>
}

--- ~andy/git/oilshell/oil

{<Id.Lit_Tilde "~"> <Id.Lit_Chars andy> <Id.Lit_Slash /> <Id.Lit_Chars git> <Id.Lit_Slash /> 
  <Id.Lit_Chars oilshell> <Id.Lit_Slash /> <Id.Lit_Chars oil>
}

--- ~andy_c/git/oilshell/oil

{<Id.Lit_Tilde "~"> <Id.Lit_Chars andy_c> <Id.Lit_Slash /> <Id.Lit_Chars git> <Id.Lit_Slash /> 
  <Id.Lit_Chars oilshell> <Id.Lit_Slash /> <Id.Lit_Chars oil>
}

--- ~andy.c/git/oilshell/oil

{<Id.Lit_Tilde "~"> <Id.Lit_Chars andy.c> <Id.Lit_Slash /> <Id.Lit_Chars git> <Id.Lit_Slash /> 
  <Id.Lit_Chars oilshell> <Id.Lit_Slash /> <Id.Lit_Chars oil>
}

--- ~andy-c/git/oilshell/oil

{<Id.Lit_Tilde "~"> <Id.Lit_Chars andy-c> <Id.Lit_Slash /> <Id.Lit_Chars gi....
----------------------------------------------------------------------
Ran 22 tests in 0.083s

OK
t> <Id.Lit_Slash /> 
  <Id.Lit_Chars oilshell> <Id.Lit_Slash /> <Id.Lit_Chars oil>
}

--- ~andy-c:git/oilshell/oil

{<Id.Lit_Tilde "~"> <Id.Lit_Chars andy-c> <Id.Lit_Colon ":"> <Id.Lit_Chars git> <Id.Lit_Slash /> 
  <Id.Lit_Chars oilshell> <Id.Lit_Slash /> <Id.Lit_Chars oil>
}

--- ${var#}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_Pound "#"> arg_word:{})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var#prefix}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_Pound "#"> arg_word:{<Id.Lit_Chars prefix>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var##}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_DPound "##"> arg_word:{})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var##prefix}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_DPound "##"> arg_word:{<Id.Lit_Chars prefix>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var%suffix}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_Percent "%"> arg_word:{<Id.Lit_Chars suffix>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${var%%suffix}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name var>
    var_name: var
    suffix_op: (suffix_op.Unary op:<Id.VOp1_DPercent "%%"> arg_word:{<Id.Lit_Chars suffix>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${name}

{(${ Id.VSub_Name name)}

--- ${name[0]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name name>
    var_name: name
    bracket_op: (bracket_op.ArrayIndex expr:{<Id.Lit_Digits 0>})
    right: <Id.Right_DollarBrace "}">
  )
}

--- ${array[@]}

{
  (BracedVarSub
    left: <Id.Left_DollarBrace "${">
    token: <Id.VSub_Name array>
    var_name: array
    bracket_op: (bracket_op.WholeArray op_id:Id.Lit_At)
    right: <Id.Right_DollarBrace "}">
  )
}