# Do not edit this file - Generated by Perlito5 9.025

{
    package main;
    package Perlito5::Grammar::Statement;
    use Perlito5::Macro ;
    my @Statement_chars;
    my %Statement;
    sub Perlito5::Grammar::Statement::add_statement {
        my $name = shift;
        my $param = shift;
        $Statement{$name} = $param;
        unshift(@Statement_chars, scalar(@Statement_chars) + 1)
            while @Statement_chars < length($name)
    }
    sub Perlito5::Grammar::Statement::stmt_yadayada {
        my $str = $_[0];
        my $pos = $_[1];
        my $MATCH = {"str" => $str, "from" => $pos, "to" => $pos, };
        my $tmp = (((("." eq $str->[($MATCH->{"to"}) + 0]) && ("." eq $str->[($MATCH->{"to"}) + 1]) && ("." eq $str->[($MATCH->{"to"}) + 2]) && ($MATCH->{"to"} += 3)) && (do {
            $MATCH->{"capture"} = Perlito5::AST::Apply::->new("code", "die", "namespace", '', "arguments", [Perlito5::AST::Buf::->new("buf", "Unimplemented")]);
            1
        })));
        $tmp ? $MATCH : undef
    }
    sub Perlito5::Grammar::Statement::stmt_format {
        my $str = $_[0];
        my $pos = $_[1];
        my $MATCH = {"str" => $str, "from" => $pos, "to" => $pos, };
        my $tmp = (((("f" eq $str->[($MATCH->{"to"}) + 0]) && ("o" eq $str->[($MATCH->{"to"}) + 1]) && ("r" eq $str->[($MATCH->{"to"}) + 2]) && ("m" eq $str->[($MATCH->{"to"}) + 3]) && ("a" eq $str->[($MATCH->{"to"}) + 4]) && ("t" eq $str->[($MATCH->{"to"}) + 5]) && ($MATCH->{"to"} += 6)) && (do {
            my $m2 = Perlito5::Grammar::Space::ws($str, $MATCH->{"to"});
            if ($m2) {
                $MATCH->{"to"} = $m2->{"to"};
                1
            }
            else {;
                0
            }
        }) && (do {
            my $tmp108 = $MATCH->{"to"};
            ((do {
                my $m2 = Perlito5::Grammar::full_ident($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"Perlito5::Grammar::full_ident"} = $m2;
                    1
                }
                else {;
                    0
                }
            })) || ($MATCH->{"to"} = $tmp108, (do {
                $MATCH->{"Perlito5::Grammar::full_ident"} = "STDOUT";
                1
            }))
        }) && (do {
            my $placeholder = Perlito5::AST::Apply::->new("code", "list:<.>", "namespace", '', "arguments", [Perlito5::AST::Apply::->new("code", "list:<.>", "namespace", '', "arguments", [])]);
            push(@Perlito5::Grammar::String::Here_doc, ["single_quote", $placeholder->{"arguments"}->[0]->{"arguments"}, "."]);
            $MATCH->{"capture"} = Perlito5::AST::Apply::->new("code", "p5:format", "namespace", '', "arguments", [Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::full_ident"}), $placeholder]);
            1
        }) && (do {
            my $m2 = Perlito5::Grammar::Space::opt_ws($str, $MATCH->{"to"});
            if ($m2) {
                $MATCH->{"to"} = $m2->{"to"};
                1
            }
            else {;
                0
            }
        }) && (("=" eq $str->[($MATCH->{"to"}) + 0]) && ($MATCH->{"to"} += 1)) && (do {
            my $m2 = Perlito5::Grammar::Space::ws($str, $MATCH->{"to"});
            if ($m2) {
                $MATCH->{"to"} = $m2->{"to"};
                1
            }
            else {;
                0
            }
        })));
        $tmp ? $MATCH : undef
    }
    sub Perlito5::Grammar::Statement::stmt_package {
        my $str = $_[0];
        my $pos = $_[1];
        my $MATCH = {"str" => $str, "from" => $pos, "to" => $pos, };
        my $tmp = (((("p" eq $str->[($MATCH->{"to"}) + 0]) && ("a" eq $str->[($MATCH->{"to"}) + 1]) && ("c" eq $str->[($MATCH->{"to"}) + 2]) && ("k" eq $str->[($MATCH->{"to"}) + 3]) && ("a" eq $str->[($MATCH->{"to"}) + 4]) && ("g" eq $str->[($MATCH->{"to"}) + 5]) && ("e" eq $str->[($MATCH->{"to"}) + 6]) && ($MATCH->{"to"} += 7)) && (do {
            my $m2 = Perlito5::Grammar::Space::ws($str, $MATCH->{"to"});
            if ($m2) {
                $MATCH->{"to"} = $m2->{"to"};
                1
            }
            else {;
                0
            }
        }) && (do {
            my $m2 = Perlito5::Grammar::full_ident($str, $MATCH->{"to"});
            if ($m2) {
                $MATCH->{"to"} = $m2->{"to"};
                $MATCH->{"Perlito5::Grammar::full_ident"} = $m2;
                1
            }
            else {;
                0
            }
        }) && (do {
            my $tmp119 = $MATCH->{"to"};
            (((do {
                my $m2 = Perlito5::Grammar::Space::ws($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    1
                }
                else {;
                    0
                }
            }) && (do {
                my $m2 = Perlito5::Grammar::Use::version_string($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"Perlito5::Grammar::Use::version_string"} = $m2;
                    1
                }
                else {;
                    0
                }
            }) && (do {
                my $version = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::Use::version_string"});
                $MATCH->{"_version"} = $version;
                1
            }) && (do {
                my $m2 = Perlito5::Grammar::Space::opt_ws($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    1
                }
                else {;
                    0
                }
            }))) || ($MATCH->{"to"} = $tmp119, (do {
                my $m2 = Perlito5::Grammar::Space::opt_ws($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    1
                }
                else {;
                    0
                }
            }))
        }) && (do {
            my $tmp120 = $MATCH->{"to"};
            (((do {
                my $name = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::full_ident"});
                $MATCH->{"_package"} = $Perlito5::PKG_NAME;
                $Perlito5::PACKAGES->{$name} = 1;
                $Perlito5::PKG_NAME = $name;
                1
            }) && (do {
                my $m2 = Perlito5::Grammar::block($str, $MATCH->{"to"});
                if ($m2) {
                    $MATCH->{"to"} = $m2->{"to"};
                    $MATCH->{"Perlito5::Grammar::block"} = $m2;
                    1
                }
                else {;
                    0
                }
            }) && (do {
                my $namespace = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::full_ident"});
                my @statements = @{$MATCH->{"Perlito5::Grammar::block"}->{"capture"}->{"stmts"}};
                if (@statements == 1) {
                    my $stmt = $statements[0];
                    if ($stmt && ref($stmt) eq "Perlito5::AST::Apply" && ($stmt->{"code"} eq "infix:<=>>" || $stmt->{"code"} eq "list:<,>")) {;
                        push(@Perlito::ANNOTATION, [$namespace, Perlito5::AST::Apply::->new("arguments", [$stmt], "code", "circumfix:<{ }>")])
                    }
                }
                if ($MATCH->{"_version"}) {;
                    unshift(@statements, Perlito5::AST::Apply::->new("arguments", [Perlito5::AST::Var::->new("name", "VERSION", "namespace", $namespace, "sigil", "\$"), $MATCH->{"_version"}], "code", "infix:<=>"))
                }
                $MATCH->{"capture"} = Perlito5::AST::Block::->new("stmts", [Perlito5::AST::Apply::->new("code", "package", "arguments", [], "namespace", $namespace), @statements]);
                $Perlito5::PKG_NAME = $MATCH->{"_package"};
                1
            }))) || ($MATCH->{"to"} = $tmp120, (do {
                my $name = Perlito5::Match::flat($MATCH->{"Perlito5::Grammar::full_ident"});
                $Perlito5::PACKAGES->{$name} = 1;
                $Perlito5::PKG_NAME = $name;
                $MATCH->{"capture"} = Perlito5::AST::Apply::->new("code", "package", "arguments", [], "namespace", $name);
                1
            }))
        })));
        $tmp ? $MATCH : undef
    }
    sub Perlito5::Grammar::Statement::exp_stmt {
        my $str = $_[0];
        my $pos = $_[1];
        my $tok = join('', @{$str}[$pos .. $pos + 15]);
        for my $len (@Statement_chars) {
            my $term = substr($tok, 0, $len);
            if (exists($Statement{$term})) {
                my $m = $Statement{$term}->($_[0], $pos);
                $m && return $m
            }
        }
        return 0
    }
    my @Modifier_chars = (7, 6, 5, 4, 3, 2);
    my %Modifier = ("if", 1, "unless", 1, "when", 1, "for", 1, "foreach", 1, "while", 1, "until", 1, "given", 1);
    sub Perlito5::Grammar::Statement::statement_modifier {
        my $str = $_[0];
        my $pos = $_[1];
        my $tok = join('', @{$str}[$pos .. $pos + 15]);
        my $expression = $_[2];
        for my $len (@Modifier_chars) {
            my $term = substr($tok, 0, $len);
            if (exists($Modifier{$term})) {
                my $m = Perlito5::Grammar::Statement::modifier($_[0], $pos + $len, $term, $expression);
                $m && return $m
            }
        }
        return 0
    }
    sub Perlito5::Grammar::Statement::modifier {
        my $str = $_[0];
        my $pos = $_[1];
        my $modifier = $_[2];
        my $expression = $_[3];
        my $modifier_exp = Perlito5::Grammar::Expression::exp_parse($str, $pos);
        if (!$modifier_exp) {;
            Perlito5::Compiler::error("Expected expression after '", Perlito5::Match::flat($modifier), "'")
        }
        if ($modifier eq "if") {;
            return {"str" => $str, "from" => $pos, "to" => $modifier_exp->{"to"}, "capture" => Perlito5::AST::Apply::->new("arguments", [Perlito5::Match::flat($modifier_exp), $expression], "code", "infix:<&&>", "namespace", ''), }
        }
        if ($modifier eq "unless") {;
            return {"str" => $str, "from" => $pos, "to" => $modifier_exp->{"to"}, "capture" => Perlito5::AST::Apply::->new("arguments", [Perlito5::Match::flat($modifier_exp), $expression], "code", "infix:<||>", "namespace", ''), }
        }
        if ($modifier eq "when") {;
            return {"str" => $str, "from" => $pos, "to" => $modifier_exp->{"to"}, "capture" => Perlito5::AST::When::->new("cond", Perlito5::Match::flat($modifier_exp), "body", $expression), }
        }
        if ($modifier eq "while") {
            my $stmt = Perlito5::AST::While::->new("cond", Perlito5::Match::flat($modifier_exp), "body", $expression);
            my $out = Perlito5::Macro::while_file($stmt);
            $out && ($stmt = $out);
            return {"str" => $str, "from" => $pos, "to" => $modifier_exp->{"to"}, "capture" => $stmt, }
        }
        if ($modifier eq "until") {
            my $stmt = Perlito5::AST::While::->new("cond", Perlito5::AST::Apply::->new("arguments", [Perlito5::Match::flat($modifier_exp)], "code", "prefix:<!>", "namespace", ''), "body", $expression);
            return {"str" => $str, "from" => $pos, "to" => $modifier_exp->{"to"}, "capture" => $stmt, }
        }
        if ($modifier eq "for" || $modifier eq "foreach") {;
            return {"str" => $str, "from" => $pos, "to" => $modifier_exp->{"to"}, "capture" => Perlito5::AST::For::->new("cond", Perlito5::Match::flat($modifier_exp), "body", $expression, "topic", Perlito5::AST::Var::SCALAR_ARG()), }
        }
        Perlito5::Compiler::error("Unexpected statement modifier '" . $modifier . "'")
    }
    sub Perlito5::Grammar::Statement::statement_parse {
        my $m = Perlito5::Grammar::Statement::statement_parse_inner(@_);
        !@Perlito5::SCOPE_STMT && return $m;
        Perlito5::Grammar::Scope::check_variable_declarations();
        return $m
    }
    sub Perlito5::Grammar::Statement::statement_parse_inner {
        my $str = $_[0];
        my $pos = $_[1];
        my $res = Perlito5::Grammar::Statement::exp_stmt($str, $pos);
        if ($res) {
            if (ref($res->{"capture"}) eq "Perlito5::AST::Apply" && $res->{"capture"}->{"code"} eq "circumfix:<{ }>") {}
            else {;
                return $res
            }
        }
        $res = Perlito5::Grammar::Expression::exp_parse($str, $pos);
        if (!$res) {;
            return
        }
        if ($str->[$res->{"to"}] eq ":" && ref($res->{"capture"}) eq "Perlito5::AST::Apply" && $res->{"capture"}->{"bareword"}) {
            my $label = $res->{"capture"}->{"code"};
            my $ws = Perlito5::Grammar::Space::opt_ws($str, ($res->{"to"}) + 1);
            my $stmt = Perlito5::Grammar::Statement::statement_parse($str, $ws->{"to"});
            if ($stmt) {
                $stmt->{"capture"}->{"label"} = $label;
                return $stmt
            }
            $res->{"to"} = $ws->{"to"};
            $res->{"capture"} = Perlito5::AST::Apply::->new("arguments", [], "code", "undef", "namespace", '', "label", $label);
            return $res
        }
        my $modifier = Perlito5::Grammar::Statement::statement_modifier($str, $res->{"to"}, Perlito5::Match::flat($res));
        my $p = $modifier ? $modifier->{"to"} : $res->{"to"};
        my $terminator = $str->[$p];
        if ($terminator ne ";" && $terminator ne "}" && $terminator ne '') {
            my $type = "Number or Bareword";
            $terminator ge 0 && $terminator le 9 && ($type = "Number");
            ($terminator eq "\"" || $terminator eq "'") && ($type = "String");
            $terminator eq "\$" && ($type = "Scalar");
            $terminator eq "\@" && ($type = "Array");
            Perlito5::Compiler::error($type . " found where operator expected")
        }
        if (!$modifier) {;
            return $res
        }
        return $modifier
    }
    Perlito5::Grammar::Statement::add_statement("...", \&stmt_yadayada);
    Perlito5::Grammar::Statement::add_statement("package", \&stmt_package);
    Perlito5::Grammar::Statement::add_statement("format", \&stmt_format);
    1
}
;1
