FOR var IN ... ; END support.
This commit is contained in:
parent
701786277b
commit
92ddf18766
60
command.cpp
60
command.cpp
|
@ -487,7 +487,6 @@ int begin_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
|||
|
||||
|
||||
int loop_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
||||
// todo -- parse end for redirection.
|
||||
|
||||
std::string b = expand_vars(begin, env);
|
||||
std::string e = expand_vars(end, env);
|
||||
|
@ -515,7 +514,7 @@ int loop_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
|||
if (status) return env.status(status);
|
||||
|
||||
int rv = 0;
|
||||
for(;; env.echo("end") ) {
|
||||
for(;;) {
|
||||
|
||||
if (control_c) throw execution_of_input_terminated();
|
||||
|
||||
|
@ -525,17 +524,64 @@ int loop_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
|||
});
|
||||
}
|
||||
catch (break_command_t &ex) {
|
||||
env.echo("end");
|
||||
break;
|
||||
}
|
||||
catch (continue_command_t &ex) {
|
||||
continue;
|
||||
}
|
||||
catch (continue_command_t &ex) {}
|
||||
env.echo("end");
|
||||
}
|
||||
env.echo("end");
|
||||
|
||||
return env.status(rv);
|
||||
}
|
||||
|
||||
int for_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
||||
|
||||
std::string b = expand_vars(begin, env);
|
||||
std::string e = expand_vars(end, env);
|
||||
|
||||
|
||||
env.set("command", "end");
|
||||
|
||||
// echo!
|
||||
env.echo("%s ... %s",
|
||||
b.c_str(),
|
||||
e.c_str()
|
||||
);
|
||||
|
||||
// check for extra tokens...
|
||||
auto bt = tokenize(b, true);
|
||||
if (bt.size() < 3 || strcasecmp(bt[2].string.c_str(), "in")) {
|
||||
fprintf(stderr, "### For - Missing in keyword.\n");
|
||||
fprintf(stderr, "Usage - For name in [word...]\n");
|
||||
return env.status(-3);
|
||||
}
|
||||
|
||||
fdmask newfds;
|
||||
int status = check_ends(e, newfds);
|
||||
newfds |= fds;
|
||||
if (status) return env.status(status);
|
||||
|
||||
int rv = 0;
|
||||
for (int i = 3; i < bt.size(); ++i ) {
|
||||
|
||||
if (control_c) throw execution_of_input_terminated();
|
||||
|
||||
env.set(bt[1].string, bt[i].string);
|
||||
|
||||
try {
|
||||
env.loop_indent_and([&]{
|
||||
rv = vector_command::execute(env, newfds);
|
||||
});
|
||||
}
|
||||
catch (break_command_t &ex) {
|
||||
env.echo("end");
|
||||
break;
|
||||
}
|
||||
catch (continue_command_t &ex) {}
|
||||
env.echo("end");
|
||||
}
|
||||
|
||||
return env.status(rv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
14
command.h
14
command.h
|
@ -158,6 +158,20 @@ struct loop_command : public vector_command {
|
|||
virtual int execute(Environment &e, const fdmask &fds, bool throwup) final override;
|
||||
};
|
||||
|
||||
struct for_command : public vector_command {
|
||||
|
||||
template<class S1, class S2>
|
||||
for_command(int t, command_ptr_vector &&v, S1 &&b, S2 &&e) :
|
||||
vector_command(t, std::move(v)), begin(std::forward<S1>(b)), end(std::forward<S2>(e))
|
||||
{}
|
||||
|
||||
std::string begin;
|
||||
std::string end;
|
||||
|
||||
virtual int execute(Environment &e, const fdmask &fds, bool throwup) final override;
|
||||
};
|
||||
|
||||
|
||||
typedef std::unique_ptr<struct if_else_clause> if_else_clause_ptr;
|
||||
struct if_command : public command {
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ bool phase2_parser::continuation() const {
|
|||
if (e.major == AMP_AMP) return true;
|
||||
if (e.major == PIPE_PIPE) return true;
|
||||
if (e.major == LOOP) return true;
|
||||
if (e.major == FOR) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -107,6 +108,7 @@ term(RV) ::= if_command(C). { RV = std::move(C); }
|
|||
term(RV) ::= begin_command(C). { RV = std::move(C); }
|
||||
term(RV) ::= paren_command(C). { RV = std::move(C); }
|
||||
term(RV) ::= loop_command(C). { RV = std::move(C); }
|
||||
term(RV) ::= for_command(C). { RV = std::move(C); }
|
||||
|
||||
/*
|
||||
* fall back to an end error. w/o fallback, it will cause a parse conflict.
|
||||
|
@ -146,6 +148,9 @@ loop_command(RV) ::= LOOP(T) sep compound_list(L) END(E). {
|
|||
RV = std::make_unique<loop_command>(@T, std::move(L), std::move(T), std::move(E));
|
||||
}
|
||||
|
||||
for_command(RV) ::= FOR(T) sep compound_list(L) END(E). {
|
||||
RV = std::make_unique<for_command>(@T, std::move(L), std::move(T), std::move(E));
|
||||
}
|
||||
|
||||
if_command(RV) ::= IF(I) sep compound_list(L) END(E). {
|
||||
|
||||
|
|
|
@ -121,6 +121,7 @@
|
|||
BEGIN = /begin/i;
|
||||
EVALUATE = /evaluate/i;
|
||||
LOOP = /loop/i;
|
||||
FOR = /for/i;
|
||||
BREAK = /break/i;
|
||||
CONTINUE = /continue/i;
|
||||
|
||||
|
@ -147,6 +148,9 @@
|
|||
LOOP %eof{ type = LOOP; return; };
|
||||
LOOP ws => { type = LOOP; return; };
|
||||
|
||||
FOR %eof{ type = FOR; return; };
|
||||
FOR ws => { type = FOR; return; };
|
||||
|
||||
BREAK %eof{ type = BREAK; return; };
|
||||
BREAK ws => { type = BREAK; return; };
|
||||
|
||||
|
|
Loading…
Reference in New Issue