# file      : libbuild2/test/script/parser+command-if.test.testscript
# license   : MIT; see accompanying LICENSE file

: if
:
{{
  test.options += -s

  : true
  :
  $* <<EOI >>EOO
  {
    if true foo
    {
      cmd1
      cmd2
    }
  }
  EOI
  {{
    {
      ? true foo
      cmd1
      cmd2
    }
  }}
  EOO

  : false
  :
  $* <<EOI >>EOO
  {
    if false foo
    {
      cmd1
      cmd2
    }
  }
  EOI
  {{
    {
      ? false foo
    }
  }}
  EOO

  : not-true
  :
  $* <<EOI >>EOO
  {
    if! true foo
    {
      cmd1
      cmd2
    }
  }
  EOI
  {{
    {
      ? true foo
    }
  }}
  EOO

  : not-false
  :
  $* <<EOI >>EOO
  {
    if! false foo
    {
      cmd1
      cmd2
    }
  }
  EOI
  {{
    {
      ? false foo
      cmd1
      cmd2
    }
  }}
  EOO

  : description
  :
  $* <<EOI >>EOO
  : description
  cmd1;
  if true
    cmd2
  else
    cmd3
  EOI
  {{
    : id:description
    {
      cmd1
      ? true
      cmd2
    }
  }}
  EOO

  : both-descriptions
  :
  $* <<EOI 2>>EOE != 0
  : description1
  cmd1;
  if true
    cmd2
  else
    cmd3 : description2
  EOI
  testscript:6:8: error: both leading and trailing descriptions specified
  EOE

  : end
  :
  $* <<EOI 2>>EOE != 0
  if true
    cmd
  end
  EOI
  testscript:3:1: error: flow-control constructs use {} in syntax version 2
  EOE

  : junk-after-semi
  :
  $* <<EOI 2>>EOE != 0
  if true
  {
    cmd
  }; foo
  EOI
  testscript:4:4: error: expected newline after ';'
  EOE

  : junk-after-rbrace
  :
  $* <<EOI 2>>EOE != 0
  cmd1;
  if true
  {
    cmd2
  } +
  EOI
  testscript:5:3: error: expected newline, semicolon, or colon after '}'
  EOE

  : without-command
  :
  $* <<EOI >- 2>>EOE  != 0
  {
    if
      cmd
  }
  EOI
  testscript:2:5: error: missing program
  EOE

  : after-semi
  :
  $* -s <<EOI >>EOO
  cmd1;
  if true
    cmd2
  EOI
  {{
    {
      cmd1
      ? true
      cmd2
    }
  }}
  EOO

  : setup
  :
  $* <<EOI >>EOO
  +if true
    cmd
  EOI
  {{
    ? true
    +cmd
  }}
  EOO

  : tdown
  :
  $* <<EOI >>EOO
  -if true
    cmd
  EOI
  {{
    ? true
    -cmd
  }}
  EOO

  : setup-var-only
  :
  $* <<EOI >>EOO
  if true
    v = foo
  cmd $v
  EOI
  {{
    ? true
    {
      cmd foo
    }
  }}
  EOO

  : tdown-var-only
  :
  $* <<EOI >>EOO
  cmd1
  if true
    v = foo
  -cmd $v
  EOI
  {{
    {
      cmd1
    }
    ? true
    -cmd foo
  }}
  EOO

  : setup-var-only-leading-desc
  :
  $* <<EOI 2>>EOE != 0
  : description
  if true
    v = foo
  cmd $v
  EOI
  testscript:2:1: error: description before/after setup/teardown variable-only 'if'
  EOE

  : setup-var-only-trailing
  :
  $* <<EOI 2>>EOE != 0
  if true
  {
    v = foo
  } : description
  cmd $v
  EOI
  testscript:1:1: error: description before/after setup/teardown variable-only 'if'
  EOE


  : tdown-var-only-leading-desc
  :
  $* <<EOI 2>>EOE != 0
  cmd
  : description
  if true
    v = foo
  EOI
  testscript:3:1: error: description before/after setup/teardown variable-only 'if'
  EOE

  : tdown-var-only-trailing
  :
  $* <<EOI 2>>EOE != 0
  cmd
  if true
  {
    v = foo
  } : description
  EOI
  testscript:2:1: error: description before/after setup/teardown variable-only 'if'
  EOE
}}

: elif
:
{{
  test.options += -s

  : true
  :
  $* <<EOI >>EOO
  {
    if false
    {
      cmd1
      cmd2
    }
    elif true
    {
      cmd3
      cmd4
    }
  }
  EOI
  {{
    {
      ? false
      ? true
      cmd3
      cmd4
    }
  }}
  EOO

  : false
  :
  $* <<EOI >>EOO
  {
    if false
    {
      cmd1
      cmd2
    }
    elif false
    {
      cmd3
      cmd4
    }
  }
  EOI
  {{
    {
      ? false
      ? false
    }
  }}
  EOO

  : not-true
  :
  $* <<EOI >>EOO
  {
    if false
    {
      cmd1
      cmd2
    }
    elif! true
    {
      cmd3
      cmd4
    }
  }
  EOI
  {{
    {
      ? false
      ? true
    }
  }}
  EOO

  : not-false
  :
  $* <<EOI >>EOO
  {
    if false
    {
      cmd1
      cmd2
    }
    elif! false
    {
      cmd3
      cmd4
    }
  }
  EOI
  {{
    {
      ? false
      ? false
      cmd3
      cmd4
    }
  }}
  EOO

  : without-if
  :
  $* <<EOI 2>>EOE != 0
  {
    cmd
    elif true
      cmd
    end
  }
  EOI
  testscript:3:3: error: 'elif' without preceding 'if'
  EOE

  : not-without-if
  :
  $* <<EOI 2>>EOE != 0
  {
    cmd
    elif! true
      cmd
  }
  EOI
  testscript:3:3: error: 'elif!' without preceding 'if'
  EOE

  : after-else
  :
  $* <<EOI 2>>EOE != 0
  {
    if false
      cmd
    else
      cmd
    elif true
      cmd
  }
  EOI
  testscript:6:3: error: 'elif' after 'else'
  EOE
}}

: else
:
{{
  test.options += -s

  : true
  :
  $* <<EOI >>EOO
  {
    if false
    {
      cmd1
      cmd2
    }
    else
    {
      cmd3
      cmd4
    }
  }
  EOI
  {{
    {
      ? false
      cmd3
      cmd4
    }
  }}
  EOO

  : false
  :
  $* <<EOI >>EOO
  {
    if true
    {
      cmd1
      cmd2
    }
    else
    {
      cmd3
      cmd4
    }
  }
  EOI
  {{
    {
      ? true
      cmd1
      cmd2
    }
  }}
  EOO

  : chain
  :
  $* <<EOI >>EOO
  {
    if false
    {
      cmd
      cmd
    }
    elif false
    {
      cmd
      cmd
    }
    elif false
    {
      cmd
      cmd
    }
    elif true
    {
      cmd1
      cmd2
    }
    elif false
    {
      cmd
      cmd
    }
    else
    {
      cmd
      cmd
    }
  }
  EOI
  {{
    {
      ? false
      ? false
      ? false
      ? true
      cmd1
      cmd2
    }
  }}
  EOO

  : command-after
  :
  $* <<EOI 2>>EOE != 0
  {
    if true
      cmd
    else cmd
      cmd
  }
  EOI
  testscript:4:8: error: expected newline instead of 'cmd'
  EOE

  : without-if
  :
  $* <<EOI 2>>EOE != 0
  {
    cmd
    else
      cmd
  }
  EOI
  testscript:3:3: error: 'else' without preceding 'if'
  EOE

  : after-else
  :
  $* <<EOI 2>>EOE != 0
  {
    if false
      cmd
    else
      cmd
    else
      cmd
  }
  EOI
  testscript:6:3: error: 'else' after 'else'
  EOE
}}

: if-predicate
:
{{
  test.options += -s

  : ifn
  :
  {{
    : null
    :
    $* <<EOI >>EOO
    {
      ifn $foo
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd1
        cmd2
      }
    }}
    EOO

    : not-null
    :
    $* <<EOI >>EOO
    {
      foo =
      ifn $foo
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd3
        cmd4
      }
    }}
    EOO

    : end
    :
    $* <<EOI 2>>EOE != 0
    {
      ifn foo
        cmd
      end
    }
    EOI
    testscript:4:3: error: flow-control constructs use {} in syntax version 2
    EOE

    : without-value
    :
    $* <<EOI 2>>EOE != 0
    {
      ifn
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    testscript:2:6: error: expected value after 'ifn'
    EOE
  }}

  : elifn
  :
  {{
    : null
    :
    $* <<EOI >>EOO
    {
      ifn foo
      {
        cmd1
        cmd2
      }
      elifn $foo
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd3
        cmd4
      }
    }}
    EOO

    : not-null
    :
    $* <<EOI >>EOO
    {
      foo =
      ifn foo
      {
        cmd1
        cmd2
      }
      elifn $foo
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
      }
    }}
    EOO

    : without-if
    :
    $* <<EOI 2>>EOE != 0
    {
      cmd
      elifn foo
        cmd
    }
    EOI
    testscript:3:3: error: 'elifn' without preceding 'if'
    EOE

    : after-else
    :
    $* <<EOI 2>>EOE != 0
    {
      ifn foo
        cmd
      else
        cmd
      elifn bar
        cmd
    }
    EOI
    testscript:6:3: error: 'elifn' after 'else'
    EOE
  }}

  : ifnn
  :
  {{
    : null
    :
    $* <<EOI >>EOO
    {
      ifn! $foo
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd3
        cmd4
      }
    }}
    EOO

    : not-null
    :
    $* <<EOI >>EOO
    {
      foo =
      ifn! $foo
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd1
        cmd2
      }
    }}
    EOO
  }}

  : elifnn
  :
  {{
    : null
    :
    $* <<EOI >>EOO
    {
      ifn foo
      {
        cmd1
        cmd2
      }
      elifn! $foo
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
      }
    }}
    EOO

    : not-null
    :
    $* <<EOI >>EOO
    {
      foo =
      ifn foo
      {
        cmd1
        cmd2
      }
      elifn! $foo
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd3
        cmd4
      }
    }}
    EOO
  }}

  : ife
  :
  {{
    : empty
    :
    $* <<EOI >>EOO
    {
      foo =
      ife $foo
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd1
        cmd2
      }
    }}
    EOO

    : not-empty
    :
    $* <<EOI >>EOO
    {
      foo = 'abc'
      ife $foo
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd3
        cmd4
      }
    }}
    EOO

    : end
    :
    $* <<EOI 2>>EOE != 0
    {
      ife foo
        cmd
      end
    }
    EOI
    testscript:4:3: error: flow-control constructs use {} in syntax version 2
    EOE

    : without-value
    :
    $* <<EOI 2>>EOE != 0
    {
      ife
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    testscript:2:6: error: expected value after 'ife'
    EOE
  }}

  : elife
  :
  {{
    : empty
    :
    $* <<EOI >>EOO
    {
      foo =
      ife foo
      {
        cmd1
        cmd2
      }
      elife $foo
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd3
        cmd4
      }
    }}
    EOO

    : not-empty
    :
    $* <<EOI >>EOO
    {
      foo = 'abc'
      ife foo
      {
        cmd1
        cmd2
      }
      elife $foo
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
      }
    }}
    EOO

    : without-if
    :
    $* <<EOI 2>>EOE != 0
    {
      cmd
      elife foo
        cmd
    }
    EOI
    testscript:3:3: error: 'elife' without preceding 'if'
    EOE

    : after-else
    :
    $* <<EOI 2>>EOE != 0
    {
      ife foo
        cmd
      else
        cmd
      elife bar
        cmd
    }
    EOI
    testscript:6:3: error: 'elife' after 'else'
    EOE
  }}

  : ifen
  :
  {{
    : empty
    :
    $* <<EOI >>EOO
    {
      foo =
      ife! $foo
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd3
        cmd4
      }
    }}
    EOO

    : not-empty
    :
    $* <<EOI >>EOO
    {
      foo = 'abc'
      ife! $foo
      {
        cmd1
        cmd2
      }
      else
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd1
        cmd2
      }
    }}
    EOO
  }}

  : elifen
  :
  {{
    : empty
    :
    $* <<EOI >>EOO
    {
      foo =
      ife foo
      {
        cmd1
        cmd2
      }
      elife! $foo
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
      }
    }}
    EOO

    : not-empty
    :
    $* <<EOI >>EOO
    {
      foo = 'abc'
      ife foo
      {
        cmd1
        cmd2
      }
      elife! $foo
      {
        cmd3
        cmd4
      }
    }
    EOI
    {{
      {
        cmd3
        cmd4
      }
    }}
    EOO
  }}
}}

: nested
:
{{
  test.options += -s

  : take
  :
  $* <<EOI >>EOO
  {
    if true
    {
      cmd1
      if false
        cmd
      elif false
      {
        if true
          cmd
      }
      else
        cmd2
      cmd3
    }
  }
  EOI
  {{
    {
      ? true
      cmd1
      ? false
      ? false
      cmd2
      cmd3
    }
  }}
  EOO

  : skip
  :
  $* <<EOI >>EOO
  {
    if false
    {
      cmd1
      if false
        cmd
      elif false
      {
        if true
          cmd
      }
      else
        cmd2
      cmd3
    }
    else
      cmd
  }
  EOI
  {{
    {
      ? false
      cmd
    }
  }}
  EOO
}}

: contained
:
{{
  : semi
  :
  $* <<EOI 2>>EOE != 0
  {
    if
    {
      cmd;
      cmd
    }
  }
  EOI
  testscript:4:8: error: ';' inside 'if'
  EOE

  : semi-after-block
  :
  $* <<EOI 2>>EOE != 0
  {
    if true
    {
      cmd
    };
    cmd2
  }
  EOI
  testscript:5:4: error: ';' inside test scope
  EOE

  : semi-after-line
  :
  $* <<EOI 2>>EOE != 0
  {
    if true
      cmd;
    cmd2
  }
  EOI
  testscript:3:8: error: ';' inside test scope
  EOE

  : colon-leading
  :
  $* <<EOI 2>>EOE != 0
  {
    if
    {
      : foo
      cmd
    }
  }
  EOI
  testscript:4:5: error: description inside 'if'
  EOE

  : colon-trailing
  :
  $* <<EOI 2>>EOE != 0
  {
    if
    {
      cmd : foo
    }
  }
  EOI
  testscript:4:9: error: description inside 'if'
  EOE

  : colon-after-block
  :
  $* <<EOI 2>>EOE != 0
  {
    if true
    {
      cmd
    } : description
  }
  EOI
  testscript:5:5: error: description inside test scope
  EOE

  : colon-after-line
  :
  $* <<EOI 2>>EOE != 0
  {
    if true
      cmd : description
  }
  EOI
  testscript:3:9: error: description inside test scope
  EOE

  : junk-after-block
  :
  $* <<EOI 2>>EOE != 0
  {
    if true
    {
      cmd
    } +
  }
  EOI
  testscript:5:5: error: expected newline after command in test scope
  EOE

  : duplicate-id-trailing
  :
  $* <<EOI 2>>EOE != 0
  cmd1 : foo

  cmd2;
  if true
  {
    cmd3 : foo
  }
  EOI
  testscript:6:8: error: description inside 'if'
  EOE

  : eos
  :
  $* <<EOI 2>>EOE != 0
  {
    if
  }
  EOI
  testscript:3:1: error: expected command instead of '}' inside 'if'
  EOE

  : scope
  :
  $* <<EOI 2>>EOE != 0
  {
    if
    {
      cmd
      {
      }
    }
  }
  EOI
  testscript:5:5: error: expected command instead of '{' inside 'if'
  EOE

  : setup
  :
  $* <<EOI 2>>EOE != 0
  {
    if
      +cmd
  }
  EOI
  testscript:3:5: error: setup command inside 'if'
  EOE

  : tdown
  :
  $* <<EOI 2>>EOE != 0
  {
    if
      -cmd
  }
  EOI
  testscript:3:5: error: teardown command inside 'if'
  EOE
}}

: line-index
:
$* -l -s <<EOI >>EOO
{
  if false
  {
    cmd
    if true
      cmd
    cmd
  }
  elif false
    cmd
  else
    cmd
}
EOI
{{
  {
    ? false # 1
    ? false # 6
    cmd # 8
  }
}}
EOO

: var
:
$* -s <<EOI >>EOO
if true
  x = foo
else
  x = bar;
cmd $x
EOI
{{
  {
    ? true
    cmd foo
  }
}}
EOO

: leading-and-trailing-description-block
:
$* <<EOI 2>>EOE != 0
: foo
if true
{
  cmd
} : bar
EOI
testscript:5:3: error: both leading and trailing descriptions specified
EOE

: leading-and-trailing-description-cmd
:
$* <<EOI 2>>EOE != 0
: foo
if true
  cmd : bar
EOI
testscript:3:7: error: both leading and trailing descriptions specified
EOE

: syntax-1
:
{{
  test.options += -v 1

  : if
  :
  {{
    : true
    :
    $* <<EOI >>EOO
    if true foo
      cmd1
      cmd2
    end
    EOI
    ? true foo
    cmd1
    cmd2
    EOO

    : false
    :
    $* <<EOI >>EOO
    if false foo
      cmd1
      cmd2
    end
    EOI
    ? false foo
    EOO

    : not-true
    :
    $* <<EOI >>EOO
    if! true foo
      cmd1
      cmd2
    end
    EOI
    ? true foo
    EOO

    : not-false
    :
    $* <<EOI >>EOO
    if! false foo
      cmd1
      cmd2
    end
    EOI
    ? false foo
    cmd1
    cmd2
    EOO

    : without-command
    :
    $* <<EOI 2>>EOE != 0
    if
      cmd
    end
    EOI
    testscript:1:3: error: missing program
    EOE

    : after-semi
    :
    $* -s <<EOI >>EOO
    cmd1;
    if true
      cmd2
    end
    EOI
    {
      {
        cmd1
        ? true
        cmd2
      }
    }
    EOO

    : setup
    :
    $* -s <<EOI >>EOO
    +if true
      cmd
    end
    EOI
    {
      ? true
      +cmd
    }
    EOO

    : tdown
    :
    $* -s <<EOI >>EOO
    -if true
      cmd
    end
    EOI
    {
      ? true
      -cmd
    }
    EOO

    : setup-var-only
    :
    $* -s <<EOI >>EOO
    if true
      v = foo
    end
    cmd $v
    EOI
    {
      ? true
      {
        cmd foo
      }
    }
    EOO

    : tdown-var-only
    :
    $* -s <<EOI >>EOO
    cmd1
    if true
      v = foo
    end
    -cmd $v
    EOI
    {
      {
        cmd1
      }
      ? true
      -cmd foo
    }
    EOO
  }}

  : elif
  :
  {{
    : true
    :
    $* <<EOI >>EOO
    if false
      cmd1
      cmd2
    elif true
      cmd3
      cmd4
    end
    EOI
    ? false
    ? true
    cmd3
    cmd4
    EOO

    : false
    :
    $* <<EOI >>EOO
    if false
      cmd1
      cmd2
    elif false
      cmd3
      cmd4
    end
    EOI
    ? false
    ? false
    EOO

    : not-true
    :
    $* <<EOI >>EOO
    if false
      cmd1
      cmd2
    elif! true
      cmd3
      cmd4
    end
    EOI
    ? false
    ? true
    EOO

    : not-false
    :
    $* <<EOI >>EOO
    if false
      cmd1
      cmd2
    elif! false
      cmd3
      cmd4
    end
    EOI
    ? false
    ? false
    cmd3
    cmd4
    EOO

    : without-if
    :
    $* <<EOI 2>>EOE != 0
    cmd
    elif true
      cmd
    end
    EOI
    testscript:2:1: error: 'elif' without preceding 'if'
    EOE

    : not-without-if
    :
    $* <<EOI 2>>EOE != 0
    cmd
    elif! true
      cmd
    end
    EOI
    testscript:2:1: error: 'elif!' without preceding 'if'
    EOE

    : after-else
    :
    $* <<EOI 2>>EOE != 0
    if false
      cmd
    else
      cmd
    elif true
      cmd
    end
    EOI
    testscript:5:1: error: 'elif' after 'else'
    EOE
  }}

  : else
  :
  {{
    : true
    :
    $* <<EOI >>EOO
    if false
      cmd1
      cmd2
    else
      cmd3
      cmd4
    end
    EOI
    ? false
    cmd3
    cmd4
    EOO

    : false
    :
    $* <<EOI >>EOO
    if true
      cmd1
      cmd2
    else
      cmd3
      cmd4
    end
    EOI
    ? true
    cmd1
    cmd2
    EOO

    : chain
    :
    $* <<EOI >>EOO
    if false
      cmd
      cmd
    elif false
      cmd
      cmd
    elif false
      cmd
      cmd
    elif true
      cmd1
      cmd2
    elif false
      cmd
      cmd
    else
      cmd
      cmd
    end
    EOI
    ? false
    ? false
    ? false
    ? true
    cmd1
    cmd2
    EOO

    : command-after
    :
    $* <<EOI 2>>EOE != 0
    if true
      cmd
    else cmd
      cmd
    end
    EOI
    testscript:3:6: error: expected newline instead of 'cmd'
    EOE

    : without-if
    :
    $* <<EOI 2>>EOE != 0
    cmd
    else
      cmd
    end
    EOI
    testscript:2:1: error: 'else' without preceding 'if'
    EOE

    : after-else
    :
    $* <<EOI 2>>EOE != 0
    if false
      cmd
    else
      cmd
    else
      cmd
    end
    EOI
    testscript:5:1: error: 'else' after 'else'
    EOE
  }}

  : end
  :
  {{
    : without-if
    :
    $* <<EOI 2>>EOE != 0
    cmd
    end
    EOI
    testscript:2:1: error: 'end' without preceding 'if', 'for', or 'while'
    EOE

    : without-if-semi
    :
    $* <<EOI 2>>EOE != 0
    cmd;
    end
    EOI
    testscript:2:1: error: 'end' without preceding 'if', 'for', or 'while'
    EOE

    : before
    :
    {{
      : semi
      :
      $* -s <<EOI >>EOO
      if true
        cmd1
      end;
      cmd2
      EOI
      {
        {
          ? true
          cmd1
          cmd2
        }
      }
      EOO

      : command
      :
      $* <<EOI 2>>EOE != 0
      if true
        cmd
      end cmd
      EOI
      testscript:3:5: error: expected newline instead of 'cmd'
      EOE

      : colon
      :
      $* -s <<EOI >>EOO
      if true
        cmd1
        cmd2
      end : test
      EOI
      {
        : id:test
        {
          ? true
          cmd1
          cmd2
        }
      }
      EOO
    }}
  }}

  : nested
  :
  {{
    : take
    :
    $* <<EOI >>EOO
    if true
      cmd1
      if false
        cmd
      elif false
        if true
          cmd
        end
      else
        cmd2
      end
      cmd3
    end
    EOI
    ? true
    cmd1
    ? false
    ? false
    cmd2
    cmd3
    EOO

    : skip
    :
    $* <<EOI >>EOO
    if false
      cmd1
      if false
        cmd
      elif false
        if true
          cmd
        end
      else
        cmd2
      end
      cmd3
    else
      cmd
    end
    EOI
    ? false
    cmd
    EOO
  }}

  : contained
  {{
    : semi
    :
    $* <<EOI 2>>EOE != 0
    if
      cmd;
      cmd
    end
    EOI
    testscript:2:3: error: ';' inside 'if'
    EOE

    : colon-leading
    :
    $* <<EOI 2>>EOE != 0
    if
      : foo
      cmd
    end
    EOI
    testscript:2:3: error: description inside 'if'
    EOE

    : colon-trailing
    :
    $* <<EOI 2>>EOE != 0
    if
      cmd : foo
    end
    EOI
    testscript:2:3: error: description inside 'if'
    EOE

    : eos
    :
    $* <<EOI 2>>EOE != 0
    if
    EOI
    testscript:2:1: error: expected closing 'end'
    EOE

    : scope
    :
    $* <<EOI 2>>EOE != 0
    if
      cmd
      {
      }
    end
    EOI
    testscript:3:3: error: expected closing 'end'
    EOE

    : setup
    :
    $* <<EOI 2>>EOE != 0
    if
      +cmd
    end
    EOI
    testscript:2:3: error: setup command inside 'if'
    EOE

    : tdown
    :
    $* <<EOI 2>>EOE != 0
    if
      -cmd
    end
    EOI
    testscript:2:3: error: teardown command inside 'if'
    EOE
  }}

  : line-index
  :
  $* -l <<EOI >>EOO
  if false
    cmd
    if true
      cmd
    end
    cmd
  elif false
    cmd
  else
    cmd
  end
  EOI
  ? false # 1
  ? false # 6
  cmd # 8
  EOO

  : var
  :
  $* <<EOI >>EOO
  if true
    x = foo
  else
    x = bar
  end;
  cmd $x
  EOI
  ? true
  cmd foo
  EOO

  : leading-and-trailing-description
  :
  $* <<EOI 2>>EOE != 0
  : foo
  if true
    cmd
  end : bar
  EOI
  testscript:4:1: error: both leading and trailing descriptions specified
  EOE
}}
