/* >, < redirection is handled later, after environment expansion. (also, redirection can be in the middle of a command.) */ %include { #include "phase2.h" #include "command.h" #define LEMON_SUPER phase2_parser #include "phase2-parser.h" } %code { std::unique_ptr phase2_parser::make() { return std::make_unique(); } bool phase2_parser::continuation() const { yypParser *self = (yypParser *)this; for (const auto &e : *self) { if (e.major == BEGIN) return true; if (e.major == LPAREN) return true; if (e.major == IF) return true; 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; if (e.major == PIPE) return true; if (e.major == PIPE_PIPE) return true; if (e.major == AMP_AMP) return true; } return false; } } %left PIPE_PIPE AMP_AMP. %left PIPE. %token_type {std::string} %default_type {command_ptr} %type start {void} %type command_list {void} /* these are put into a queue for immmediate execution */ start ::= command_list. command_list ::= . command_list ::= command_list sep . command_list ::= command_list command(C) sep . { if (C) command_queue.emplace_back(std::move(C)); } /* compound_list is identical to command_list, but it is not executed immediately. */ %type compound_list { command_ptr_vector } compound_list ::= . compound_list(RV) ::= compound_list(L) sep. { RV = std::move(L); } compound_list(RV) ::= compound_list(L) command(C) sep . { RV = std::move(L); if (C) RV.emplace_back(std::move(C)); } sep ::= SEMI. sep ::= NL. %type command { command_ptr } /* nb -- ||, &&, | -- both sides are optional. This does not. */ command(RV) ::= command(L) PIPE_PIPE opt_nl command(R). { RV = std::make_unique(std::move(L), std::move(R)); } command(RV) ::= command(L) AMP_AMP opt_nl command(R). { RV = std::make_unique(std::move(L), std::move(R)); } command(RV) ::= command(L) PIPE opt_nl command(R). { RV = std::make_unique(std::move(L), std::move(R)); } command(RV) ::= term(T). { RV = std::move(T); } term(RV) ::= COMMAND(C). { RV = std::make_unique(std::move(C)); } term(RV) ::= EVALUATE(C). { RV = std::make_unique(std::move(C)); } term(RV) ::= BREAK(C). { RV = std::make_unique(std::move(C)); } term(RV) ::= CONTINUE(C). { RV = std::make_unique(std::move(C)); } 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); } /* lexer error (mismatched quotes, etc) */ term(RV) ::= ERROR(C). { RV = std::make_unique(@C, std::move(C)); } /* * fall back to an end error. w/o fallback, it will cause a parse conflict. */ /* %fallback ERROR END RPAREN ELSE ELSE_IF. */ /* term(RV) ::= error RPAREN. term(RV) ::= error END. term(RV) ::= LPAREN error RPAREN. term(RV) ::= BEGIN error END. term(RV) ::= IF error END. term(RV) ::= LOOP error END. term(RV) ::= FOR error END. */ /* compound list ends with a separator. paren command does not need the final separator */ %type paren_list { command_ptr_vector } paren_list(RV) ::= compound_list(L) . { RV = std::move(L); } paren_list(RV) ::= compound_list(L) command(C) . { RV = std::move(L); RV.emplace_back(std::move(C)); } paren_command(RV) ::= LPAREN(T) paren_list(L) RPAREN(E). { RV = std::make_unique(@T, std::move(L), std::move(T), std::move(E)); } begin_command(RV) ::= BEGIN(T) sep compound_list(L) END(E). { RV = std::make_unique(@T, std::move(L), std::move(T), std::move(E)); } loop_command(RV) ::= LOOP(T) sep compound_list(L) END(E). { RV = std::make_unique(@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(@T, std::move(L), std::move(T), std::move(E)); } if_command(RV) ::= IF(I) sep compound_list(L) END(E). { if_command::clause_vector_type v; v.emplace_back(std::make_unique(IF, std::move(L), std::move(I))); RV = std::make_unique( std::move(v), std::move(E) ); } if_command(RV) ::= IF(I) sep compound_list(L) else_command(EC) END(E). { if_command::clause_vector_type v; v.emplace_back(std::make_unique(IF, std::move(L), std::move(I))); for(auto &c : EC) { v.emplace_back(std::move(c)); } RV = std::make_unique( std::move(v), std::move(E)); } %token_class else ELSE_IF ELSE. %type else_command { if_command::clause_vector_type } else_command(RV) ::= else(E) sep compound_list(L). { RV.emplace_back(std::make_unique(@E, std::move(L), std::move(E))); } else_command(RV) ::= else_command(EC) else(E) sep compound_list(L). { RV = std::move(EC); RV.emplace_back(std::make_unique(@E, std::move(L), std::move(E))); } opt_nl ::= . opt_nl ::= opt_nl NL .