diff --git a/CMakeLists.txt b/CMakeLists.txt index 55d2127..b5f3a75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,13 +89,24 @@ RAGEL_TARGET(value value.rl value.cpp COMPILE_FLAGS "-p -G2") # need to copy all OUTPUT file to the build dir -add_custom_command( - OUTPUT phase3.cpp phase3.h phase3.out - COMMAND lemon++ phase3.lemon - COMMAND mv -f phase3.cpp phase3.h phase3.out ${CMAKE_CURRENT_BINARY_DIR}/ - MAIN_DEPENDENCY phase3.lemon - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) +# add_custom_command( +# OUTPUT phase3.cpp phase3.h phase3.out +# COMMAND lemon++ phase3.lemon +# COMMAND mv -f phase3.cpp phase3.h phase3.out ${CMAKE_CURRENT_BINARY_DIR}/ +# MAIN_DEPENDENCY phase3.lemon +# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +# ) + +find_program(LEMON_PLUSPLUS NAMES lemon++) +if (LEMON_PLUSPLUS) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/phase3.cpp ${CMAKE_CURRENT_SOURCE_DIR}/phase3.h + #COMMAND cp -f "${CMAKE_CURRENT_SOURCE_DIR}/parser.lemon" "parser.lemon" + COMMAND lemon++ phase3.lemon + MAIN_DEPENDENCY phase3.lemon + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + ) +endif() add_executable(mpw-shell mpw-shell.cpp mpw-shell-token.cpp mpw-shell-expand.cpp diff --git a/lemon_base.h b/lemon_base.h new file mode 100644 index 0000000..caad319 --- /dev/null +++ b/lemon_base.h @@ -0,0 +1,34 @@ +#ifndef __lemon_base_h__ +#define __lemon_base_h__ +#include + +template +class lemon_base { +public: + typedef TokenType token_type; + + virtual ~lemon_base() = default; + + //virtual typename std::enable_if::value, void>::type + virtual void parse(int yymajor, TokenType &&yyminor) = 0; + + virtual void trace(FILE *, const char *) {} + + virtual bool will_accept() const = 0; + virtual void reset() {} + +protected: + virtual void parse_accept() {} + virtual void parse_failure() {} + virtual void stack_overflow() {} + virtual void syntax_error(int yymajor, TokenType &yyminor) {} + lemon_base() {} + +private: + lemon_base(const lemon_base &) = delete; + lemon_base(lemon_base &&) = delete; + lemon_base &operator=(const lemon_base &) = delete; + lemon_base &operator=(lemon_base &&) = delete; +}; + +#endif \ No newline at end of file diff --git a/phase3.cpp b/phase3.cpp new file mode 100644 index 0000000..12cc214 --- /dev/null +++ b/phase3.cpp @@ -0,0 +1,1862 @@ +/* + +January, 2016. Sample class-based version. +#define LEMON_SUPER as the name of a class which overrides lemon_base. +The parser will be implemented in terms of that. +add a %code section to instantiate it. + */ + +/* +** 2000-05-29 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Driver template for the LEMON parser generator. +** +** The "lemon" program processes an LALR(1) input grammar file, then uses +** this template to construct a parser. The "lemon" program inserts text +** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the +** interstitial "-" characters) contained in this template is changed into +** the value of the %name directive from the grammar. Otherwise, the content +** of this template is copied straight through into the generate parser +** source file. +** +** The following is the concatenation of all %include directives from the +** input grammar file: +*/ +#include +#include +#include +#include +#include +#include +#include + +namespace { + + // use std::allocator etc? + + + // this is here so you can do something like Parse(void *, int, my_token &&) or (... const my_token &) + template struct yy_fix_type { + typedef typename std::remove_const::type>::type type; + }; + + template<> + struct yy_fix_type { + typedef struct {} type; + }; + + template + typename yy_fix_type::type &yy_constructor(void *vp, Args&&... args ) { + typedef typename yy_fix_type::type TT; + TT *tmp = ::new(vp) TT(std::forward(args)...); + return *tmp; + } + + + template + typename yy_fix_type::type &yy_cast(void *vp) { + typedef typename yy_fix_type::type TT; + return *(TT *)vp; + } + + + template + void yy_destructor(void *vp) { + typedef typename yy_fix_type::type TT; + ((TT *)vp)->~TT(); + } + + + template + void yy_destructor(T &t) { + t.~T(); + } + + + + template + void yy_move(void *dest, void *src) { + typedef typename yy_fix_type::type TT; + + TT &tmp = yy_cast(src); + yy_constructor(dest, std::move(tmp)); + yy_destructor(tmp); + } + + + // this is to destruct references in the event of an exception. + // only the LHS needs to be deleted -- other items remain on the + // shift/reduce stack in a valid state + // (as long as the destructor) doesn't throw! + template + struct yy_auto_deleter { + + yy_auto_deleter(T &t) : ref(t), enaged(true) + {} + yy_auto_deleter(const yy_auto_deleter &) = delete; + yy_auto_deleter(yy_auto_deleter &&) = delete; + yy_auto_deleter &operator=(const yy_auto_deleter &) = delete; + yy_auto_deleter &operator=(yy_auto_deleter &&) = delete; + + ~yy_auto_deleter() { + if (enaged) yy_destructor(ref); + } + void cancel() { enaged = false; } + + private: + T& ref; + bool enaged=false; + }; + + template + class yy_storage { + private: + typedef typename yy_fix_type::type TT; + + public: + typedef typename std::conditional< + std::is_trivial::value, + TT, + typename std::aligned_storage::type + >::type type; + }; + +} + +/************ Begin %include sections from the grammar ************************/ +#line 7 "phase3.lemon" + + +#include "phase3_parser.h" +#include "command.h" +#define LEMON_SUPER phase3 +#line 142 "phase3.cpp" +/**************** End of %include directives **********************************/ +/* These constants specify the various numeric values for terminal symbols +** in a format understandable to "makeheaders". This section is blank unless +** "lemon" is run with the "-m" command-line option. +***************** Begin makeheaders token definitions *************************/ +/**************** End makeheaders token definitions ***************************/ + +/* The next sections is a series of control #defines. +** various aspects of the generated parser. +** YYCODETYPE is the data type used to store the integer codes +** that represent terminal and non-terminal symbols. +** "unsigned char" is used if there are fewer than +** 256 symbols. Larger types otherwise. +** YYNOCODE is a number of type YYCODETYPE that is not used for +** any terminal or nonterminal symbol. +** YYFALLBACK If defined, this indicates that one or more tokens +** (also known as: "terminal symbols") have fall-back +** values which should be used if the original symbol +** would not parse. This permits keywords to sometimes +** be used as identifiers, for example. +** YYACTIONTYPE is the data type used for "action codes" - numbers +** that indicate what to do in response to the next +** token. +** ParseTOKENTYPE is the data type used for minor type for terminal +** symbols. Background: A "minor type" is a semantic +** value associated with a terminal or non-terminal +** symbols. For example, for an "ID" terminal symbol, +** the minor type might be the name of the identifier. +** Each non-terminal can have a different minor type. +** Terminal symbols all have the same minor type, though. +** This macros defines the minor type for terminal +** symbols. +** YYMINORTYPE is the data type used for all minor types. +** This is typically a union of many types, one of +** which is ParseTOKENTYPE. The entry in the union +** for terminal symbols is called "yy0". +** YYSTACKDEPTH is the maximum depth of the parser's stack. If +** zero the stack is dynamically sized using realloc() +** YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. +** YYNSTATE the combined number of states. +** YYNRULE the number of rules in the grammar +** YY_MAX_SHIFT Maximum value for shift actions +** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions +** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions +** YY_MIN_REDUCE Maximum value for reduce actions +** YY_ERROR_ACTION The yy_action[] code for syntax error +** YY_ACCEPT_ACTION The yy_action[] code for accept +** YY_NO_ACTION The yy_action[] code for no-op +*/ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/************* Begin control #defines *****************************************/ +#define YYCODETYPE unsigned char +#define YYNOCODE 37 +#define YYACTIONTYPE unsigned char +#define ParseTOKENTYPE std::string +typedef union { + int yyinit; + yy_storage::type yy0; + yy_storage::type yy7; + yy_storage::type yy17; + yy_storage::type yy35; + yy_storage::type yy62; +} YYMINORTYPE; +#ifndef YYSTACKDEPTH +#define YYSTACKDEPTH 100 +#endif +#define ParseARG_SDECL +#define ParseARG_PDECL +#define ParseARG_FETCH +#define ParseARG_STORE +#define YYNSTATE 35 +#define YYNRULE 36 +#define YY_MAX_SHIFT 34 +#define YY_MIN_SHIFTREDUCE 61 +#define YY_MAX_SHIFTREDUCE 96 +#define YY_MIN_REDUCE 97 +#define YY_MAX_REDUCE 132 +#define YY_ERROR_ACTION 133 +#define YY_ACCEPT_ACTION 134 +#define YY_NO_ACTION 135 +/************* End control #defines *******************************************/ +namespace { + +/* Define the yytestcase() macro to be a no-op if is not already defined +** otherwise. +** +** Applications can choose to define yytestcase() in the %include section +** to a macro that can assist in verifying code coverage. For production +** code the yytestcase() macro should be turned off. But it is useful +** for testing. +*/ +#ifndef yytestcase +# define yytestcase(X) +#endif + + +/* Next are the tables used to determine what action to take based on the +** current state and lookahead token. These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer. +** +** Suppose the action integer is N. Then the action is determined as +** follows +** +** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead +** token onto the stack and goto state N. +** +** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then +** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. +** +** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE +** and YY_MAX_REDUCE +** +** N == YY_ERROR_ACTION A syntax error has occurred. +** +** N == YY_ACCEPT_ACTION The parser accepts its input. +** +** N == YY_NO_ACTION No such action. Denotes unused +** slots in the yy_action[] table. +** +** The action table is constructed as a single large table named yy_action[]. +** Given state S and lookahead X, the action is computed as either: +** +** (A) N = yy_action[ yy_shift_ofst[S] + X ] +** (B) N = yy_default[S] +** +** The (A) formula is preferred. The B formula is used instead if: +** (1) The yy_shift_ofst[S]+X value is out of range, or +** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or +** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. +** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that +** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) +** +** The formulas above are for computing the action when the lookahead is +** a terminal symbol. If the lookahead is a non-terminal (as occurs after +** a reduce action) then the yy_reduce_ofst[] array is used in place of +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of +** YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +** yy_action[] A single table containing all actions. +** yy_lookahead[] A table containing the lookahead for each entry in +** yy_action. Used to detect hash collisions. +** yy_shift_ofst[] For each state, the offset into yy_action for +** shifting terminals. +** yy_reduce_ofst[] For each state, the offset into yy_action for +** shifting non-terminals after a reduce. +** yy_default[] Default action for each state. +** +*********** Begin parsing tables **********************************************/ +#define YY_ACTTAB_COUNT (193) +static const YYACTIONTYPE yy_action[] = { + /* 0 */ 86, 87, 66, 67, 68, 69, 70, 71, 12, 98, + /* 10 */ 21, 77, 20, 19, 18, 16, 16, 86, 87, 66, + /* 20 */ 67, 68, 69, 70, 71, 12, 97, 21, 76, 20, + /* 30 */ 19, 18, 86, 87, 66, 67, 68, 69, 70, 71, + /* 40 */ 12, 22, 21, 75, 20, 19, 18, 86, 87, 66, + /* 50 */ 67, 68, 69, 70, 71, 12, 23, 21, 74, 20, + /* 60 */ 19, 18, 117, 134, 5, 6, 86, 87, 66, 67, + /* 70 */ 68, 69, 70, 71, 12, 24, 21, 25, 20, 19, + /* 80 */ 18, 86, 87, 66, 67, 68, 69, 70, 71, 12, + /* 90 */ 7, 21, 26, 20, 19, 18, 27, 96, 66, 67, + /* 100 */ 68, 69, 70, 71, 12, 8, 21, 1, 20, 19, + /* 110 */ 18, 121, 13, 32, 2, 13, 13, 13, 13, 13, + /* 120 */ 13, 3, 31, 121, 13, 86, 87, 13, 13, 13, + /* 130 */ 13, 13, 13, 119, 15, 9, 4, 15, 15, 15, + /* 140 */ 15, 15, 15, 121, 14, 10, 73, 14, 14, 14, + /* 150 */ 14, 14, 14, 101, 11, 28, 101, 101, 101, 101, + /* 160 */ 101, 101, 99, 33, 99, 99, 33, 33, 33, 33, + /* 170 */ 33, 33, 99, 34, 99, 99, 34, 34, 34, 34, + /* 180 */ 34, 34, 30, 29, 28, 86, 87, 78, 99, 99, + /* 190 */ 99, 17, 17, +}; +static const YYCODETYPE yy_lookahead[] = { + /* 0 */ 4, 5, 6, 7, 8, 9, 10, 11, 12, 24, + /* 10 */ 14, 15, 16, 17, 18, 19, 20, 4, 5, 6, + /* 20 */ 7, 8, 9, 10, 11, 12, 24, 14, 15, 16, + /* 30 */ 17, 18, 4, 5, 6, 7, 8, 9, 10, 11, + /* 40 */ 12, 24, 14, 15, 16, 17, 18, 4, 5, 6, + /* 50 */ 7, 8, 9, 10, 11, 12, 24, 14, 15, 16, + /* 60 */ 17, 18, 0, 22, 23, 26, 4, 5, 6, 7, + /* 70 */ 8, 9, 10, 11, 12, 24, 14, 24, 16, 17, + /* 80 */ 18, 4, 5, 6, 7, 8, 9, 10, 11, 12, + /* 90 */ 26, 14, 24, 16, 17, 18, 24, 5, 6, 7, + /* 100 */ 8, 9, 10, 11, 12, 26, 14, 26, 16, 17, + /* 110 */ 18, 24, 25, 34, 26, 28, 29, 30, 31, 32, + /* 120 */ 33, 26, 35, 24, 25, 4, 5, 28, 29, 30, + /* 130 */ 31, 32, 33, 24, 25, 27, 26, 28, 29, 30, + /* 140 */ 31, 32, 33, 24, 25, 27, 13, 28, 29, 30, + /* 150 */ 31, 32, 33, 25, 27, 3, 28, 29, 30, 31, + /* 160 */ 32, 33, 36, 25, 36, 36, 28, 29, 30, 31, + /* 170 */ 32, 33, 36, 25, 36, 36, 28, 29, 30, 31, + /* 180 */ 32, 33, 1, 2, 3, 4, 5, 15, 36, 36, + /* 190 */ 36, 19, 20, +}; +#define YY_SHIFT_USE_DFLT (193) +#define YY_SHIFT_COUNT (34) +#define YY_SHIFT_MIN (-4) +#define YY_SHIFT_MAX (181) +static const short yy_shift_ofst[] = { + /* 0 */ 193, -4, 13, 28, 43, 62, 77, 77, 77, 92, + /* 10 */ 92, 92, 193, 181, 181, 181, 121, 121, 121, 121, + /* 20 */ 121, 121, 193, 193, 193, 193, 193, 193, 193, 193, + /* 30 */ 193, 172, 133, 152, 152, +}; +#define YY_REDUCE_USE_DFLT (-16) +#define YY_REDUCE_COUNT (30) +#define YY_REDUCE_MIN (-15) +#define YY_REDUCE_MAX (148) +static const short yy_reduce_ofst[] = { + /* 0 */ 41, 87, 99, 99, 99, 109, 99, 99, 119, 128, + /* 10 */ 138, 148, 79, -15, -15, 2, 17, 32, 51, 53, + /* 20 */ 68, 72, 39, 64, 81, 88, 95, 110, 108, 118, + /* 30 */ 127, +}; +static const YYACTIONTYPE yy_default[] = { + /* 0 */ 118, 133, 133, 133, 133, 133, 115, 116, 130, 133, + /* 10 */ 133, 133, 120, 133, 108, 133, 133, 133, 133, 133, + /* 20 */ 133, 133, 120, 120, 120, 120, 120, 120, 131, 131, + /* 30 */ 131, 133, 133, 100, 99, +}; +/********** End of lemon-generated parsing tables *****************************/ + +/* The next table maps tokens (terminal symbols) into fallback tokens. +** If a construct like the following: +** +** %fallback ID X Y Z. +** +** appears in the grammar, then ID becomes a fallback token for X, Y, +** and Z. Whenever one of the tokens X, Y, or Z is input to the parser +** but it does not parse, the type of the token is changed to ID and +** the parse is retried before an error is thrown. +** +** This feature can be used, for example, to cause some keywords in a language +** to revert to identifiers if they keyword does not apply in the context where +** it appears. +*/ +#ifdef YYFALLBACK +const YYCODETYPE yyFallback[] = { +}; +#endif /* YYFALLBACK */ + +/* The following structure represents a single element of the +** parser's stack. Information stored includes: +** +** + The state number for the parser at this level of the stack. +** +** + The value of the token stored at this level of the stack. +** (In other words, the "major" token.) +** +** + The semantic value stored at this level of the stack. This is +** the information used by the action routines in the grammar. +** It is sometimes called the "minor" token. +** +** After the "shift" half of a SHIFTREDUCE action, the stateno field +** actually contains the reduce action for the second half of the +** SHIFTREDUCE. +*/ +struct yyStackEntry { + YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */ + YYCODETYPE major; /* The major token value. This is the code + ** number for the token at this stack level */ + YYMINORTYPE minor; /* The user-supplied minor token value. This + ** is the value of the token */ +}; + +/* The state of the parser is completely contained in an instance of +** the following structure */ + +#ifndef LEMON_SUPER +#error "LEMON_SUPER must be defined." +#endif + +/* outside the class so the templates above are still accessible */ +void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor); +void yy_move(YYCODETYPE yymajor, YYMINORTYPE *yyDest, YYMINORTYPE *yySource); + +class yypParser : public LEMON_SUPER { + public: + //using LEMON_SUPER::LEMON_SUPER; + + template + yypParser(Args&&... args); + + virtual ~yypParser() override final; + virtual void parse(int, ParseTOKENTYPE &&) override final; + +#ifndef NDEBUG + virtual void trace(FILE *, const char *) final override; +#endif + + virtual void reset() final override; + virtual bool will_accept() const final override; + + /* + ** Return the peak depth of the stack for a parser. + */ + #ifdef YYTRACKMAXSTACKDEPTH + int yypParser::stack_peak(){ + return yyhwm; + } + #endif + + const yyStackEntry *begin() const { return yystack; } + const yyStackEntry *end() const { return yytos + 1; } + + protected: + private: + yyStackEntry *yytos; /* Pointer to top element of the stack */ +#ifdef YYTRACKMAXSTACKDEPTH + int yyhwm = 0; /* Maximum value of yyidx */ +#endif +#ifndef YYNOERRORRECOVERY + int yyerrcnt = -1; /* Shifts left before out of the error */ +#endif +#if YYSTACKDEPTH<=0 + int yystksz = 0; /* Current side of the stack */ + yyStackEntry *yystack = nullptr; /* The parser's stack */ + yyStackEntry yystk0; /* First stack entry */ + int yyGrowStack(); +#else + yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ + yyStackEntry *yystackEnd; /* Last entry in the stack */ +#endif + + + + void yy_accept(); + void yy_parse_failed(); + void yy_syntax_error(int yymajor, ParseTOKENTYPE &yyminor); + + void yy_transfer(yyStackEntry *yySource, yyStackEntry *yyDest); + + void yy_pop_parser_stack(); + unsigned yy_find_shift_action(int stateno, YYCODETYPE iLookAhead) const; + int yy_find_reduce_action(int stateno, YYCODETYPE iLookAhead) const; + + void yy_shift(int yyNewState, int yyMajor, ParseTOKENTYPE &&yypMinor); + void yy_reduce(unsigned int yyruleno); + void yyStackOverflow(); + +#ifndef NDEBUG + void yyTraceShift(int yyNewState) const; +#else +# define yyTraceShift(X) +#endif + + +#ifndef NDEBUG + FILE *yyTraceFILE = 0; + const char *yyTracePrompt = 0; +#endif /* NDEBUG */ + + int yyidx() const { + return (int)(yytos - yystack); + } + +}; + + + + +#ifndef NDEBUG +/* +** Turn parser tracing on by giving a stream to which to write the trace +** and a prompt to preface each trace message. Tracing is turned off +** by making either argument NULL +** +** Inputs: +**
    +**
  • A FILE* to which trace output should be written. +** If NULL, then tracing is turned off. +**
  • A prefix string written at the beginning of every +** line of trace output. If NULL, then tracing is +** turned off. +**
+** +** Outputs: +** None. +*/ +void yypParser::trace(FILE *TraceFILE, const char *zTracePrompt){ + yyTraceFILE = TraceFILE; + yyTracePrompt = zTracePrompt; + if( yyTraceFILE==0 ) yyTracePrompt = 0; + else if( yyTracePrompt==0 ) yyTraceFILE = 0; +} +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing shifts, the names of all terminals and nonterminals +** are required. The following table supplies these names */ +const char *const yyTokenName[] = { + "$", "PIPE_PIPE", "AMP_AMP", "PIPE", + "SEMI", "NL", "COMMAND", "EVALUATE", + "BREAK", "CONTINUE", "EXIT", "ERROR", + "LPAREN", "RPAREN", "BEGIN", "END", + "LOOP", "FOR", "IF", "ELSE_IF", + "ELSE", "error", "start", "command_list", + "sep", "command", "compound_list", "opt_nl", + "term", "if_command", "begin_command", "paren_command", + "loop_command", "for_command", "paren_list", "else_command", +}; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing reduce actions, the names of all rules are required. +*/ +const char *const yyRuleName[] = { + /* 0 */ "command_list ::= command_list command sep", + /* 1 */ "compound_list ::= compound_list command sep", + /* 2 */ "command ::= command PIPE_PIPE opt_nl command", + /* 3 */ "command ::= command AMP_AMP opt_nl command", + /* 4 */ "command ::= command PIPE opt_nl command", + /* 5 */ "term ::= COMMAND", + /* 6 */ "term ::= EVALUATE", + /* 7 */ "term ::= BREAK", + /* 8 */ "term ::= CONTINUE", + /* 9 */ "term ::= EXIT", + /* 10 */ "term ::= ERROR", + /* 11 */ "paren_list ::= compound_list command", + /* 12 */ "paren_command ::= LPAREN paren_list RPAREN", + /* 13 */ "begin_command ::= BEGIN sep compound_list END", + /* 14 */ "loop_command ::= LOOP sep compound_list END", + /* 15 */ "for_command ::= FOR sep compound_list END", + /* 16 */ "if_command ::= IF sep compound_list END", + /* 17 */ "if_command ::= IF sep compound_list else_command END", + /* 18 */ "else_command ::= ELSE_IF|ELSE sep compound_list", + /* 19 */ "else_command ::= else_command ELSE_IF|ELSE sep compound_list", + /* 20 */ "start ::= command_list", + /* 21 */ "command_list ::=", + /* 22 */ "command_list ::= command_list sep", + /* 23 */ "compound_list ::=", + /* 24 */ "compound_list ::= compound_list sep", + /* 25 */ "sep ::= SEMI", + /* 26 */ "sep ::= NL", + /* 27 */ "command ::= term", + /* 28 */ "term ::= if_command", + /* 29 */ "term ::= begin_command", + /* 30 */ "term ::= paren_command", + /* 31 */ "term ::= loop_command", + /* 32 */ "term ::= for_command", + /* 33 */ "paren_list ::= compound_list", + /* 34 */ "opt_nl ::=", + /* 35 */ "opt_nl ::= opt_nl NL", +}; +#endif /* NDEBUG */ + + +#if YYSTACKDEPTH<=0 +/* +** Try to increase the size of the parser stack. Return the number +** of errors. Return 0 on success. +*/ +int yypParser::yyGrowStack(){ + int newSize; + yyStackEntry *pNew; + yyStackEntry *pOld = yystack; + int oldSize = yystksz; + + newSize = oldSize*2 + 100; + pNew = (yyStackEntry *)calloc(newSize, sizeof(pNew[0])); + if( pNew ){ + yystack = pNew; + for (int i = 0; i < oldSize; ++i) { + pNew[i].stateno = pOld[i].stateno; + pNew[i].major = pOld[i].major; + yy_move(pOld[i].major, &pNew[i].minor, &pOld[i].minor); + } + if (pOld != &yystk0) free(pOld); +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", + yyTracePrompt, yystksz, newSize); + } +#endif + yystksz = newSize; + } + return pNew==0; +} +#endif + + +/* The following function deletes the "minor type" or semantic value +** associated with a symbol. The symbol can be either a terminal +** or nonterminal. "yymajor" is the symbol code, and "yypminor" is +** a pointer to the value to be deleted. The code used to do the +** deletions is derived from the %destructor and/or %token_destructor +** directives of the input grammar. +*/ +void yy_destructor( + YYCODETYPE yymajor, /* Type code for object to destroy */ + YYMINORTYPE *yypminor /* The object to be destroyed */ +){ + switch( yymajor ){ + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen + ** when the symbol is popped from the stack during a + ** reduce or during error processing or when a parser is + ** being destroyed before it is finished parsing. + ** + ** Note: during a reduce, the only symbols destroyed are those + ** which appear on the RHS of the rule, but which are *not* used + ** inside the C code. + */ +/********* Begin destructor definitions ***************************************/ + case 1: /* PIPE_PIPE */ + case 2: /* AMP_AMP */ + case 3: /* PIPE */ + case 4: /* SEMI */ + case 5: /* NL */ + case 6: /* COMMAND */ + case 7: /* EVALUATE */ + case 8: /* BREAK */ + case 9: /* CONTINUE */ + case 10: /* EXIT */ + case 11: /* ERROR */ + case 12: /* LPAREN */ + case 13: /* RPAREN */ + case 14: /* BEGIN */ + case 15: /* END */ + case 16: /* LOOP */ + case 17: /* FOR */ + case 18: /* IF */ + case 19: /* ELSE_IF */ + case 20: /* ELSE */ + yy_destructor(std::addressof(yypminor->yy0)); + break; + case 0: /* $ */ + case 22: /* start */ + case 23: /* command_list */ + yy_destructor(std::addressof(yypminor->yy7)); + break; + case 24: /* sep */ + case 25: /* command */ + case 27: /* opt_nl */ + case 28: /* term */ + case 29: /* if_command */ + case 30: /* begin_command */ + case 31: /* paren_command */ + case 32: /* loop_command */ + case 33: /* for_command */ + yy_destructor(std::addressof(yypminor->yy17)); + break; + case 26: /* compound_list */ + case 34: /* paren_list */ + yy_destructor< command_ptr_vector >(std::addressof(yypminor->yy35)); + break; + case 35: /* else_command */ + yy_destructor< if_command::clause_vector_type >(std::addressof(yypminor->yy62)); + break; +/********* End destructor definitions *****************************************/ + default: break; /* If no destructor action specified: do nothing */ + } +} + + +/* + * moves an object (such as when growing the stack). + * Source is constructed. + * Destination is also destructed. + * + */ +void yy_move( + YYCODETYPE yymajor, /* Type code for object to move */ + YYMINORTYPE *yyDest, /* */ + YYMINORTYPE *yySource /* */ +){ + switch( yymajor ){ + +/********* Begin move definitions ***************************************/ + case 1: /* PIPE_PIPE */ + case 2: /* AMP_AMP */ + case 3: /* PIPE */ + case 4: /* SEMI */ + case 5: /* NL */ + case 6: /* COMMAND */ + case 7: /* EVALUATE */ + case 8: /* BREAK */ + case 9: /* CONTINUE */ + case 10: /* EXIT */ + case 11: /* ERROR */ + case 12: /* LPAREN */ + case 13: /* RPAREN */ + case 14: /* BEGIN */ + case 15: /* END */ + case 16: /* LOOP */ + case 17: /* FOR */ + case 18: /* IF */ + case 19: /* ELSE_IF */ + case 20: /* ELSE */ + yy_move(std::addressof(yyDest->yy0), std::addressof(yySource->yy0)); + break; + case 0: /* $ */ + case 22: /* start */ + case 23: /* command_list */ + yy_move(std::addressof(yyDest->yy7), std::addressof(yySource->yy7)); + break; + case 24: /* sep */ + case 25: /* command */ + case 27: /* opt_nl */ + case 28: /* term */ + case 29: /* if_command */ + case 30: /* begin_command */ + case 31: /* paren_command */ + case 32: /* loop_command */ + case 33: /* for_command */ + yy_move(std::addressof(yyDest->yy17), std::addressof(yySource->yy17)); + break; + case 26: /* compound_list */ + case 34: /* paren_list */ + yy_move< command_ptr_vector >(std::addressof(yyDest->yy35), std::addressof(yySource->yy35)); + break; + case 35: /* else_command */ + yy_move< if_command::clause_vector_type >(std::addressof(yyDest->yy62), std::addressof(yySource->yy62)); + break; +/********* End move definitions *****************************************/ + default: break; /* If no move action specified: do nothing */ + //yyDest.minor = yySource.minor; + } +} + + +/* +** Pop the parser's stack once. +** +** If there is a destructor routine associated with the token which +** is popped from the stack, then call it. +*/ +void yypParser::yy_pop_parser_stack(){ + yyStackEntry *yymsp; + assert( yytos!=0 ); + assert( yytos > yystack ); + yymsp = yytos--; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sPopping %s\n", + yyTracePrompt, + yyTokenName[yymsp->major]); + } +#endif + yy_destructor(yymsp->major, &yymsp->minor); +} + + +template +yypParser::yypParser(Args&&... args) : LEMON_SUPER(std::forward(args)...) +{ +#if YYSTACKDEPTH<=0 + if( yyGrowStack() ){ + yystack = &yystk0; + yystksz = 1; + } +#else + std::memset(yystack, 0, sizeof(yystack)); +#endif + + yytos = yystack; + yystack[0].stateno = 0; + yystack[0].major = 0; +#if YYSTACKDEPTH>0 + yystackEnd = &yystack[YYSTACKDEPTH-1]; +#endif +} + +void yypParser::reset() { + + while( yytos>yystack ) yy_pop_parser_stack(); + +#ifndef YYNOERRORRECOVERY + yyerrcnt = -1; +#endif + + yytos = yystack; + yystack[0].stateno = 0; + yystack[0].major = 0; + + LEMON_SUPER::reset(); +} + + +/* +** Deallocate and destroy a parser. Destructors are called for +** all stack elements before shutting the parser down. +** +** If the YYPARSEFREENEVERNULL macro exists (for example because it +** is defined in a %include section of the input grammar) then it is +** assumed that the input pointer is never NULL. +*/ + +yypParser::~yypParser() { + while( yytos>yystack ) yy_pop_parser_stack(); +#if YYSTACKDEPTH<=0 + if( yystack!=&yystk0 ) free(yystack); +#endif +} + +/* +** Find the appropriate action for a parser given the terminal +** look-ahead token iLookAhead. +*/ +unsigned yypParser::yy_find_shift_action( + int stateno, /* Current state number */ + YYCODETYPE iLookAhead /* The look-ahead token */ +) const { + int i; + + if( stateno>=YY_MIN_REDUCE ) return stateno; + assert( stateno <= YY_SHIFT_COUNT ); + do{ + i = yy_shift_ofst[stateno]; + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ +#ifdef YYFALLBACK + YYCODETYPE iFallback; /* Fallback token */ + if( iLookAhead %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + } +#endif + assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } +#endif +#ifdef YYWILDCARD + { + int j = i - iLookAhead + YYWILDCARD; + if( +#if YY_SHIFT_MIN+YYWILDCARD<0 + j>=0 && +#endif +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j0 + ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], + yyTokenName[YYWILDCARD]); + } +#endif /* NDEBUG */ + return yy_action[j]; + } + } +#endif /* YYWILDCARD */ + return yy_default[stateno]; + }else{ + return yy_action[i]; + } + }while(1); +} + +/* +** Find the appropriate action for a parser given the non-terminal +** look-ahead token iLookAhead. +*/ +int yypParser::yy_find_reduce_action( + int stateno, /* Current state number */ + YYCODETYPE iLookAhead /* The look-ahead token */ +) const { + int i; +#ifdef YYERRORSYMBOL + if( stateno>YY_REDUCE_COUNT ){ + return yy_default[stateno]; + } +#else + assert( stateno<=YY_REDUCE_COUNT ); +#endif + i = yy_reduce_ofst[stateno]; + assert( i!=YY_REDUCE_USE_DFLT ); + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; +#ifdef YYERRORSYMBOL + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + return yy_default[stateno]; + } +#else + assert( i>=0 && iyystack ) yy_pop_parser_stack(); + /* Here code is inserted which will execute if the parser + ** stack every overflows */ +/******** Begin %stack_overflow code ******************************************/ +/******** End %stack_overflow code ********************************************/ + LEMON_SUPER::stack_overflow(); +} + +/* +** Print tracing information for a SHIFT action +*/ +#ifndef NDEBUG +void yypParser::yyTraceShift(int yyNewState) const { + if( yyTraceFILE ){ + if( yyNewStatemajor], + yyNewState); + }else{ + fprintf(yyTraceFILE,"%sShift '%s'\n", + yyTracePrompt,yyTokenName[yytos->major]); + } + } +} +#endif + +/* +** Perform a shift action. +*/ +void yypParser::yy_shift( + int yyNewState, /* The new state to shift in */ + int yyMajor, /* The major token to shift in */ + ParseTOKENTYPE &&yyMinor /* The minor token to shift in */ +){ + yytos++; +#ifdef YYTRACKMAXSTACKDEPTH + if( yyidx()>yyhwm ){ + yyhwm++; + assert(yyhwm == yyidx()); + } +#endif +#if YYSTACKDEPTH>0 + if( yytos>yystackEnd ){ + yytos--; + yyStackOverflow(); + return; + } +#else + if( yytos>=&yystack[yystksz] ){ + if( yyGrowStack() ){ + yytos--; + yyStackOverflow(); + return; + } + } +#endif + if( yyNewState > YY_MAX_SHIFT ){ + yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } + yytos->stateno = (YYACTIONTYPE)yyNewState; + yytos->major = (YYCODETYPE)yyMajor; + //yytos->minor.yy0 = yyMinor; + //yy_move also calls the destructor... + //yy_move(std::addressof(yytos->minor.yy0), std::addressof(yyMinor)); + yy_constructor(std::addressof(yytos->minor.yy0), std::move(yyMinor)); + yyTraceShift(yyNewState); +} + +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ +} yyRuleInfo[] = { + { 23, -3 }, + { 26, -3 }, + { 25, -4 }, + { 25, -4 }, + { 25, -4 }, + { 28, -1 }, + { 28, -1 }, + { 28, -1 }, + { 28, -1 }, + { 28, -1 }, + { 28, -1 }, + { 34, -2 }, + { 31, -3 }, + { 30, -4 }, + { 32, -4 }, + { 33, -4 }, + { 29, -4 }, + { 29, -5 }, + { 35, -3 }, + { 35, -4 }, + { 22, -1 }, + { 23, 0 }, + { 23, -2 }, + { 26, 0 }, + { 26, -2 }, + { 24, -1 }, + { 24, -1 }, + { 25, -1 }, + { 28, -1 }, + { 28, -1 }, + { 28, -1 }, + { 28, -1 }, + { 28, -1 }, + { 34, -1 }, + { 27, 0 }, + { 27, -2 }, +}; + +/* +** Perform a reduce action and the shift that must immediately +** follow the reduce. +*/ +void yypParser::yy_reduce( + unsigned int yyruleno /* Number of the rule by which to reduce */ +){ + int yygoto; /* The next state */ + int yyact; /* The next action */ + yyStackEntry *yymsp; /* The top of the parser's stack */ + int yysize; /* Amount to pop the stack */ + yymsp = yytos; +#ifndef NDEBUG + if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ + yysize = yyRuleInfo[yyruleno].nrhs; + fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, + yyRuleName[yyruleno], yymsp[yysize].stateno); + } +#endif /* NDEBUG */ + + /* Check that the stack is large enough to grow by a single entry + ** if the RHS of the rule is empty. This ensures that there is room + ** enough on the stack to push the LHS value */ + if( yyRuleInfo[yyruleno].nrhs==0 ){ +#ifdef YYTRACKMAXSTACKDEPTH + if( yyidx()>yyhwm ){ + yyhwm++; + assert(yyhwm == yyidx()); + } +#endif +#if YYSTACKDEPTH>0 + if( yytos>=yystackEnd ){ + yyStackOverflow(); + return; + } +#else + if( yytos>=&yystack[yystksz-1] ){ + if( yyGrowStack() ){ + yyStackOverflow(); + return; + } + yymsp = yytos; + } +#endif + } + + switch( yyruleno ){ + /* Beginning here are the reduction cases. A typical example + ** follows: + ** case 0: + ** #line + ** { ... } // User supplied code + ** #line + ** break; + */ +/********** Begin reduce actions **********************************************/ + case 0: /* command_list ::= command_list command sep */ +{ + yy_destructor(std::addressof(yymsp[-2].minor.yy7)); + yy_destructor(std::addressof(yymsp[0].minor.yy17)); + auto &C=yy_cast< command_ptr >(std::addressof(yymsp[-1].minor.yy17)); +#line 95 "phase3.lemon" +{ + if (C) command_queue.emplace_back(std::move(C)); +} +#line 1124 "phase3.cpp" + yy_destructor(C); + yy_constructor(std::addressof(yymsp[-2].minor.yy7)); +} + break; + case 1: /* compound_list ::= compound_list command sep */ +{ + yy_destructor(std::addressof(yymsp[0].minor.yy17)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[-2].minor.yy35)); + auto &C=yy_cast< command_ptr >(std::addressof(yymsp[-1].minor.yy17)); +#line 111 "phase3.lemon" +{ + if (C) L.emplace_back(std::move(C)); +} +#line 1138 "phase3.cpp" + yy_destructor(C); +} + break; + case 2: /* command ::= command PIPE_PIPE opt_nl command */ +{ + yy_destructor(std::addressof(yymsp[-2].minor.yy0)); + yy_destructor(std::addressof(yymsp[-1].minor.yy17)); + command_ptr RV; + auto &L=yy_cast< command_ptr >(std::addressof(yymsp[-3].minor.yy17)); + auto &R=yy_cast< command_ptr >(std::addressof(yymsp[0].minor.yy17)); +#line 124 "phase3.lemon" +{ + RV = std::make_unique(std::move(L), std::move(R)); +} +#line 1153 "phase3.cpp" + yy_destructor(L); + yy_destructor(R); + yy_constructor< command_ptr >(std::addressof(yymsp[-3].minor.yy17), std::move(RV)); +} + break; + case 3: /* command ::= command AMP_AMP opt_nl command */ +{ + yy_destructor(std::addressof(yymsp[-2].minor.yy0)); + yy_destructor(std::addressof(yymsp[-1].minor.yy17)); + command_ptr RV; + auto &L=yy_cast< command_ptr >(std::addressof(yymsp[-3].minor.yy17)); + auto &R=yy_cast< command_ptr >(std::addressof(yymsp[0].minor.yy17)); +#line 128 "phase3.lemon" +{ + RV = std::make_unique(std::move(L), std::move(R)); +} +#line 1170 "phase3.cpp" + yy_destructor(L); + yy_destructor(R); + yy_constructor< command_ptr >(std::addressof(yymsp[-3].minor.yy17), std::move(RV)); +} + break; + case 4: /* command ::= command PIPE opt_nl command */ +{ + yy_destructor(std::addressof(yymsp[-2].minor.yy0)); + yy_destructor(std::addressof(yymsp[-1].minor.yy17)); + command_ptr RV; + auto &L=yy_cast< command_ptr >(std::addressof(yymsp[-3].minor.yy17)); + auto &R=yy_cast< command_ptr >(std::addressof(yymsp[0].minor.yy17)); +#line 132 "phase3.lemon" +{ + RV = std::make_unique(std::move(L), std::move(R)); +} +#line 1187 "phase3.cpp" + yy_destructor(L); + yy_destructor(R); + yy_constructor< command_ptr >(std::addressof(yymsp[-3].minor.yy17), std::move(RV)); +} + break; + case 5: /* term ::= COMMAND */ +{ + command_ptr RV; + auto &C=yy_cast(std::addressof(yymsp[0].minor.yy0)); +#line 138 "phase3.lemon" +{ RV = std::make_unique(std::move(C)); } +#line 1199 "phase3.cpp" + yy_destructor(C); + yy_constructor(std::addressof(yymsp[0].minor.yy17), std::move(RV)); +} + break; + case 6: /* term ::= EVALUATE */ +{ + command_ptr RV; + auto &C=yy_cast(std::addressof(yymsp[0].minor.yy0)); +#line 139 "phase3.lemon" +{ RV = std::make_unique(std::move(C)); } +#line 1210 "phase3.cpp" + yy_destructor(C); + yy_constructor(std::addressof(yymsp[0].minor.yy17), std::move(RV)); +} + break; + case 7: /* term ::= BREAK */ +{ + command_ptr RV; + auto &C=yy_cast(std::addressof(yymsp[0].minor.yy0)); +#line 140 "phase3.lemon" +{ RV = std::make_unique(std::move(C)); } +#line 1221 "phase3.cpp" + yy_destructor(C); + yy_constructor(std::addressof(yymsp[0].minor.yy17), std::move(RV)); +} + break; + case 8: /* term ::= CONTINUE */ +{ + command_ptr RV; + auto &C=yy_cast(std::addressof(yymsp[0].minor.yy0)); +#line 141 "phase3.lemon" +{ RV = std::make_unique(std::move(C)); } +#line 1232 "phase3.cpp" + yy_destructor(C); + yy_constructor(std::addressof(yymsp[0].minor.yy17), std::move(RV)); +} + break; + case 9: /* term ::= EXIT */ +{ + command_ptr RV; + auto &C=yy_cast(std::addressof(yymsp[0].minor.yy0)); +#line 142 "phase3.lemon" +{ RV = std::make_unique(std::move(C)); } +#line 1243 "phase3.cpp" + yy_destructor(C); + yy_constructor(std::addressof(yymsp[0].minor.yy17), std::move(RV)); +} + break; + case 10: /* term ::= ERROR */ +{ + command_ptr RV; + auto &C=yy_cast(std::addressof(yymsp[0].minor.yy0)); + const int yymsp_1_major = yymsp[0].major; /* @C */ +#line 151 "phase3.lemon" +{ + RV = std::make_unique(yymsp_1_major, std::move(C)); +} +#line 1257 "phase3.cpp" + yy_destructor(C); + yy_constructor(std::addressof(yymsp[0].minor.yy17), std::move(RV)); +} + break; + case 11: /* paren_list ::= compound_list command */ +{ + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[-1].minor.yy35)); + auto &C=yy_cast< command_ptr >(std::addressof(yymsp[0].minor.yy17)); +#line 180 "phase3.lemon" +{ + L.emplace_back(std::move(C)); +} +#line 1270 "phase3.cpp" + yy_destructor(C); +} + break; + case 12: /* paren_command ::= LPAREN paren_list RPAREN */ +{ + command_ptr RV; + auto &T=yy_cast(std::addressof(yymsp[-2].minor.yy0)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[-1].minor.yy35)); + auto &E=yy_cast(std::addressof(yymsp[0].minor.yy0)); + const int yymsp_1_major = yymsp[-2].major; /* @T */ +#line 184 "phase3.lemon" +{ + RV = std::make_unique(yymsp_1_major, std::move(L), std::move(T), std::move(E)); +} +#line 1285 "phase3.cpp" + yy_destructor(T); + yy_destructor(L); + yy_destructor(E); + yy_constructor(std::addressof(yymsp[-2].minor.yy17), std::move(RV)); +} + break; + case 13: /* begin_command ::= BEGIN sep compound_list END */ +{ + yy_destructor(std::addressof(yymsp[-2].minor.yy17)); + command_ptr RV; + auto &T=yy_cast(std::addressof(yymsp[-3].minor.yy0)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[-1].minor.yy35)); + auto &E=yy_cast(std::addressof(yymsp[0].minor.yy0)); + const int yymsp_1_major = yymsp[-3].major; /* @T */ +#line 189 "phase3.lemon" +{ + RV = std::make_unique(yymsp_1_major, std::move(L), std::move(T), std::move(E)); +} +#line 1304 "phase3.cpp" + yy_destructor(T); + yy_destructor(L); + yy_destructor(E); + yy_constructor(std::addressof(yymsp[-3].minor.yy17), std::move(RV)); +} + break; + case 14: /* loop_command ::= LOOP sep compound_list END */ +{ + yy_destructor(std::addressof(yymsp[-2].minor.yy17)); + command_ptr RV; + auto &T=yy_cast(std::addressof(yymsp[-3].minor.yy0)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[-1].minor.yy35)); + auto &E=yy_cast(std::addressof(yymsp[0].minor.yy0)); + const int yymsp_1_major = yymsp[-3].major; /* @T */ +#line 194 "phase3.lemon" +{ + RV = std::make_unique(yymsp_1_major, std::move(L), std::move(T), std::move(E)); +} +#line 1323 "phase3.cpp" + yy_destructor(T); + yy_destructor(L); + yy_destructor(E); + yy_constructor(std::addressof(yymsp[-3].minor.yy17), std::move(RV)); +} + break; + case 15: /* for_command ::= FOR sep compound_list END */ +{ + yy_destructor(std::addressof(yymsp[-2].minor.yy17)); + command_ptr RV; + auto &T=yy_cast(std::addressof(yymsp[-3].minor.yy0)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[-1].minor.yy35)); + auto &E=yy_cast(std::addressof(yymsp[0].minor.yy0)); + const int yymsp_1_major = yymsp[-3].major; /* @T */ +#line 198 "phase3.lemon" +{ + RV = std::make_unique(yymsp_1_major, std::move(L), std::move(T), std::move(E)); +} +#line 1342 "phase3.cpp" + yy_destructor(T); + yy_destructor(L); + yy_destructor(E); + yy_constructor(std::addressof(yymsp[-3].minor.yy17), std::move(RV)); +} + break; + case 16: /* if_command ::= IF sep compound_list END */ +{ + yy_destructor(std::addressof(yymsp[-2].minor.yy17)); + command_ptr RV; + auto &I=yy_cast(std::addressof(yymsp[-3].minor.yy0)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[-1].minor.yy35)); + auto &E=yy_cast(std::addressof(yymsp[0].minor.yy0)); +#line 202 "phase3.lemon" +{ + + 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) + ); + +} +#line 1368 "phase3.cpp" + yy_destructor(I); + yy_destructor(L); + yy_destructor(E); + yy_constructor(std::addressof(yymsp[-3].minor.yy17), std::move(RV)); +} + break; + case 17: /* if_command ::= IF sep compound_list else_command END */ +{ + yy_destructor(std::addressof(yymsp[-3].minor.yy17)); + command_ptr RV; + auto &I=yy_cast(std::addressof(yymsp[-4].minor.yy0)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[-2].minor.yy35)); + auto &EC=yy_cast< if_command::clause_vector_type >(std::addressof(yymsp[-1].minor.yy62)); + auto &E=yy_cast(std::addressof(yymsp[0].minor.yy0)); +#line 214 "phase3.lemon" +{ + + 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)); +} +#line 1393 "phase3.cpp" + yy_destructor(I); + yy_destructor(L); + yy_destructor(EC); + yy_destructor(E); + yy_constructor(std::addressof(yymsp[-4].minor.yy17), std::move(RV)); +} + break; + case 18: /* else_command ::= ELSE_IF|ELSE sep compound_list */ +{ + yy_destructor(std::addressof(yymsp[-1].minor.yy17)); + if_command::clause_vector_type RV; + auto &E=yy_cast(std::addressof(yymsp[-2].minor.yy0)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[0].minor.yy35)); + const int yymsp_1_major = yymsp[-2].major; /* @E */ +#line 227 "phase3.lemon" +{ + RV.emplace_back(std::make_unique(yymsp_1_major, std::move(L), std::move(E))); +} +#line 1412 "phase3.cpp" + yy_destructor(E); + yy_destructor(L); + yy_constructor< if_command::clause_vector_type >(std::addressof(yymsp[-2].minor.yy62), std::move(RV)); +} + break; + case 19: /* else_command ::= else_command ELSE_IF|ELSE sep compound_list */ +{ + yy_destructor(std::addressof(yymsp[-1].minor.yy17)); + auto &EC=yy_cast< if_command::clause_vector_type >(std::addressof(yymsp[-3].minor.yy62)); + auto &E=yy_cast(std::addressof(yymsp[-2].minor.yy0)); + auto &L=yy_cast< command_ptr_vector >(std::addressof(yymsp[0].minor.yy35)); + const int yymsp_2_major = yymsp[-2].major; /* @E */ +#line 232 "phase3.lemon" +{ + EC.emplace_back(std::make_unique(yymsp_2_major, std::move(L), std::move(E))); +} +#line 1429 "phase3.cpp" + yy_destructor(E); + yy_destructor(L); +} + break; + case 20: /* start ::= command_list */ +{ + yy_destructor(std::addressof(yymsp[0].minor.yy7)); + yy_constructor(std::addressof(yymsp[0].minor.yy7)); +} + break; + case 21: /* command_list ::= */ + yy_constructor(std::addressof(yymsp[1].minor.yy7)); + break; + case 22: /* command_list ::= command_list sep */ +{ + yy_destructor(std::addressof(yymsp[-1].minor.yy7)); + yy_destructor(std::addressof(yymsp[0].minor.yy17)); + yy_constructor(std::addressof(yymsp[-1].minor.yy7)); +} + break; + case 23: /* compound_list ::= */ + yy_constructor< command_ptr_vector >(std::addressof(yymsp[1].minor.yy35)); + break; + case 24: /* compound_list ::= compound_list sep */ +{ + yy_destructor(std::addressof(yymsp[0].minor.yy17)); +} + break; + case 25: /* sep ::= SEMI */ + case 26: /* sep ::= NL */ yytestcase(yyruleno==26); +{ + yy_destructor(std::addressof(yymsp[0].minor.yy0)); + yy_constructor(std::addressof(yymsp[0].minor.yy17)); +} + break; + case 34: /* opt_nl ::= */ + yy_constructor(std::addressof(yymsp[1].minor.yy17)); + break; + case 35: /* opt_nl ::= opt_nl NL */ +{ + yy_destructor(std::addressof(yymsp[-1].minor.yy17)); + yy_destructor(std::addressof(yymsp[0].minor.yy0)); + yy_constructor(std::addressof(yymsp[-1].minor.yy17)); +} + break; + default: + /* (27) command ::= term (OPTIMIZED OUT) */ assert(yyruleno!=27); + /* (28) term ::= if_command (OPTIMIZED OUT) */ assert(yyruleno!=28); + /* (29) term ::= begin_command (OPTIMIZED OUT) */ assert(yyruleno!=29); + /* (30) term ::= paren_command (OPTIMIZED OUT) */ assert(yyruleno!=30); + /* (31) term ::= loop_command (OPTIMIZED OUT) */ assert(yyruleno!=31); + /* (32) term ::= for_command (OPTIMIZED OUT) */ assert(yyruleno!=32); + /* (33) paren_list ::= compound_list */ yytestcase(yyruleno==33); + break; +/********** End reduce actions ************************************************/ + }; + assert( yyrulenoYY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) ); + + /* It is not possible for a REDUCE to be followed by an error */ + assert( yyact!=YY_ERROR_ACTION ); + + if( yyact==YY_ACCEPT_ACTION ){ + yytos += yysize; + yy_accept(); + }else{ + yymsp += yysize+1; + yytos = yymsp; + yymsp->stateno = (YYACTIONTYPE)yyact; + yymsp->major = (YYCODETYPE)yygoto; + yyTraceShift(yyact); + } +} + +/* +** The following code executes when the parse fails +*/ +#ifndef YYNOERRORRECOVERY +void yypParser::yy_parse_failed(){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); + } +#endif + while( yytos>yystack ) yy_pop_parser_stack(); + /* Here code is inserted which will be executed whenever the + ** parser fails */ +/************ Begin %parse_failure code ***************************************/ +/************ End %parse_failure code *****************************************/ + LEMON_SUPER::parse_failure(); +} +#endif /* YYNOERRORRECOVERY */ + +/* +** The following code executes when a syntax error first occurs. +*/ +void yypParser::yy_syntax_error( + int yymajor, /* The major type of the error token */ + ParseTOKENTYPE &yyminor /* The minor type of the error token */ +){ +//#define TOKEN yyminor + auto &TOKEN = yyminor; +/************ Begin %syntax_error code ****************************************/ +/************ End %syntax_error code ******************************************/ + LEMON_SUPER::syntax_error(yymajor, TOKEN); +} + +/* +** The following is executed when the parser accepts +*/ +void yypParser::yy_accept(){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); + } +#endif +#ifndef YYNOERRORRECOVERY + yyerrcnt = -1; +#endif + assert( yytos==yystack ); + /* Here code is inserted which will be executed whenever the + ** parser accepts */ +/*********** Begin %parse_accept code *****************************************/ +/*********** End %parse_accept code *******************************************/ + LEMON_SUPER::parse_accept(); +} + +/* The main parser program. +** The first argument is a pointer to a structure obtained from +** "ParseAlloc" which describes the current state of the parser. +** The second argument is the major token number. The third is +** the minor token. The fourth optional argument is whatever the +** user wants (and specified in the grammar) and is available for +** use by the action routines. +** +** Inputs: +**
    +**
  • A pointer to the parser (an opaque structure.) +**
  • The major token number. +**
  • The minor token number. +**
  • An option argument of a grammar-specified type. +**
+** +** Outputs: +** None. +*/ + + + +void yypParser::parse( + int yymajor, /* The major token code number */ + ParseTOKENTYPE &&yyminor /* The value for the token */ +){ + //YYMINORTYPE yyminorunion; + unsigned int yyact; /* The parser action. */ +#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) + int yyendofinput; /* True if we are at the end of input */ +#endif +#ifdef YYERRORSYMBOL + int yyerrorhit = 0; /* True if yymajor has invoked an error */ +#endif + + assert( yytos!=0 ); + +#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) + yyendofinput = (yymajor==0); +#endif + +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + } +#endif + + do{ + yyact = yy_find_shift_action(yytos->stateno, (YYCODETYPE)yymajor); + if( yyact <= YY_MAX_SHIFTREDUCE ){ + yy_shift(yyact,yymajor,std::move(yyminor)); +#ifndef YYNOERRORRECOVERY + yyerrcnt--; +#endif + yymajor = YYNOCODE; + }else if( yyact <= YY_MAX_REDUCE ){ + yy_reduce(yyact-YY_MIN_REDUCE); + }else{ + assert( yyact == YY_ERROR_ACTION ); +#ifdef YYERRORSYMBOL + int yymx; +#endif +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); + } +#endif +#ifdef YYERRORSYMBOL + /* A syntax error has occurred. + ** The response to an error depends upon whether or not the + ** grammar defines an error token "ERROR". + ** + ** This is what we do if the grammar does define ERROR: + ** + ** * Call the %syntax_error function. + ** + ** * Begin popping the stack until we enter a state where + ** it is legal to shift the error symbol, then shift + ** the error symbol. + ** + ** * Set the error count to three. + ** + ** * Begin accepting and shifting new tokens. No new error + ** processing will occur until three tokens have been + ** shifted successfully. + ** + */ + if( yyerrcnt<0 ){ + yy_syntax_error(yymajor,yyminor); + } + yymx = yytos->major; + if( yymx==YYERRORSYMBOL || yyerrorhit ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sDiscard input token %s\n", + yyTracePrompt,yyTokenName[yymajor]); + } +#endif + //yy_destructor(yyminor); + yymajor = YYNOCODE; + }else{ + while( yytos >= yystack + && yymx != YYERRORSYMBOL + && (yyact = yy_find_reduce_action( + yytos->stateno, + YYERRORSYMBOL)) >= YY_MIN_REDUCE + ){ + yy_pop_parser_stack(); + } + if( yytos < yystack || yymajor==0 ){ + //yy_destructor(yyminor); + yy_parse_failed(); +#ifndef YYNOERRORRECOVERY + yyerrcnt = -1; +#endif + yymajor = YYNOCODE; + }else if( yymx!=YYERRORSYMBOL ){ + yy_shift(yyact,YYERRORSYMBOL,std::move(yyminor)); + } + } + yyerrcnt = 3; + yyerrorhit = 1; +#elif defined(YYNOERRORRECOVERY) + /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to + ** do any kind of error recovery. Instead, simply invoke the syntax + ** error routine and continue going as if nothing had happened. + ** + ** Applications can set this macro (for example inside %include) if + ** they intend to abandon the parse upon the first syntax error seen. + */ + yy_syntax_error(yymajor,yyminor); + //yy_destructor(yyminor); + yymajor = YYNOCODE; + +#else /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** + ** * Report an error message, and throw away the input token. + ** + ** * If the input token is $, then fail the parse. + ** + ** As before, subsequent error messages are suppressed until + ** three input tokens have been successfully shifted. + */ + if( yyerrcnt<=0 ){ + yy_syntax_error(yymajor,yyminor); + } + yyerrcnt = 3; + //yy_destructor(yyminor); + if( yyendofinput ){ + yy_parse_failed(); +#ifndef YYNOERRORRECOVERY + yyerrcnt = -1; +#endif + } + yymajor = YYNOCODE; +#endif + } + }while( yymajor!=YYNOCODE && yytos>yystack ); +#ifndef NDEBUG + if( yyTraceFILE ){ + yyStackEntry *i; + char cDiv = '['; + fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); + for(i=&yystack[1]; i<=yytos; i++){ + fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]); + cDiv = ' '; + } + if (cDiv == '[') fprintf(yyTraceFILE,"["); + fprintf(yyTraceFILE,"]\n"); + } +#endif + return; +} + + +bool yypParser::will_accept() const { + + + struct stack_entry { + int stateno; + int major; + }; + + int yyact; + const int yymajor = 0; + std::vector stack; + + + // copy stack to stack. + stack.reserve(yyidx()+1); + std::transform(begin(), end(), std::back_inserter(stack), [](const yyStackEntry &e){ + return stack_entry({e.stateno, e.major}); + }); + + do { + yyact = yy_find_shift_action(stack.back().stateno, yymajor); + if (yyact <= YY_MAX_SHIFTREDUCE) { + // shift + return false; + //stack.push_back({yyact, yymajor}); + //yymajor = YYNOCODE; + } + else if (yyact <= YY_MAX_REDUCE) { + // reduce... + unsigned yyruleno = yyact - YY_MIN_REDUCE; + + int yygoto = yyRuleInfo[yyruleno].lhs; + int yysize = -yyRuleInfo[yyruleno].nrhs; /* stored as negative value */ + + while (yysize--) stack.pop_back(); + + yyact = yy_find_reduce_action(stack.back().stateno,(YYCODETYPE)yygoto); + + + if (yyact == YY_ACCEPT_ACTION) return true; + + if( yyact>YY_MAX_SHIFT ){ + yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } + + stack.push_back({yyact, yygoto}); + } + else { + return false; + } + + } while (!stack.empty()); + + return false; + + +} + + + + +} // namespace +#line 15 "phase3.lemon" + + +std::unique_ptr phase3::make() { + return std::make_unique(); +} + +bool phase3::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; +} + + +void phase3::parse_accept() { + error = false; +} + +void phase3::parse_failure() { + error = false; +} + +void phase3::syntax_error(int yymajor, std::string &yyminor) { +/* + switch (yymajor) { + case END: + fprintf(stderr, "### MPW Shell - Extra END command.\n"); + break; + + case RPAREN: + fprintf(stderr, "### MPW Shell - Extra ) command.\n"); + break; + + case ELSE: + case ELSE_IF: + fprintf(stderr, "### MPW Shell - ELSE must be within IF ... END.\n"); + break; + + default: + fprintf(stderr, "### Parse error near %s\n", yyminor.c_str()); + break; + } +*/ + + + fprintf(stderr, "### MPW Shell - Parse error near %s\n", yymajor ? yyminor.c_str() : "EOF"); + error = true; +} + + +#line 1863 "phase3.cpp" diff --git a/phase3.h b/phase3.h new file mode 100644 index 0000000..372f54a --- /dev/null +++ b/phase3.h @@ -0,0 +1,20 @@ +#define PIPE_PIPE 1 +#define AMP_AMP 2 +#define PIPE 3 +#define SEMI 4 +#define NL 5 +#define COMMAND 6 +#define EVALUATE 7 +#define BREAK 8 +#define CONTINUE 9 +#define EXIT 10 +#define ERROR 11 +#define LPAREN 12 +#define RPAREN 13 +#define BEGIN 14 +#define END 15 +#define LOOP 16 +#define FOR 17 +#define IF 18 +#define ELSE_IF 19 +#define ELSE 20 diff --git a/phase3.out b/phase3.out new file mode 100644 index 0000000..049f778 --- /dev/null +++ b/phase3.out @@ -0,0 +1,822 @@ +State 0: + start ::= * command_list + (21) command_list ::= * + command_list ::= * command_list sep + command_list ::= * command_list command sep + + start accept + command_list shift 5 + {default} reduce 21 command_list ::= + +State 1: + compound_list ::= compound_list * sep + compound_list ::= compound_list * command sep + sep ::= * SEMI + sep ::= * NL + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= IF sep compound_list * END + if_command ::= * IF sep compound_list else_command END + if_command ::= IF sep compound_list * else_command END + else_command ::= * ELSE_IF|ELSE sep compound_list + else_command ::= * else_command ELSE_IF|ELSE sep compound_list + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + END shift-reduce 16 if_command ::= IF sep compound_list END + LOOP shift 20 + FOR shift 19 + IF shift 18 + ELSE_IF shift 16 + ELSE shift 16 + sep shift-reduce 24 compound_list ::= compound_list sep + command shift 13 + term shift 13 /* because term==command */ + if_command shift 13 /* because if_command==term */ + begin_command shift 13 /* because begin_command==term */ + paren_command shift 13 /* because paren_command==term */ + loop_command shift 13 /* because loop_command==term */ + for_command shift 13 /* because for_command==term */ + else_command shift 31 + +State 2: + compound_list ::= compound_list * sep + compound_list ::= compound_list * command sep + sep ::= * SEMI + sep ::= * NL + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + for_command ::= FOR sep compound_list * END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + END shift-reduce 15 for_command ::= FOR sep compound_list END + LOOP shift 20 + FOR shift 19 + IF shift 18 + sep shift-reduce 24 compound_list ::= compound_list sep + command shift 13 + term shift 13 /* because term==command */ + if_command shift 13 /* because if_command==term */ + begin_command shift 13 /* because begin_command==term */ + paren_command shift 13 /* because paren_command==term */ + loop_command shift 13 /* because loop_command==term */ + for_command shift 13 /* because for_command==term */ + +State 3: + compound_list ::= compound_list * sep + compound_list ::= compound_list * command sep + sep ::= * SEMI + sep ::= * NL + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + loop_command ::= LOOP sep compound_list * END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + END shift-reduce 14 loop_command ::= LOOP sep compound_list END + LOOP shift 20 + FOR shift 19 + IF shift 18 + sep shift-reduce 24 compound_list ::= compound_list sep + command shift 13 + term shift 13 /* because term==command */ + if_command shift 13 /* because if_command==term */ + begin_command shift 13 /* because begin_command==term */ + paren_command shift 13 /* because paren_command==term */ + loop_command shift 13 /* because loop_command==term */ + for_command shift 13 /* because for_command==term */ + +State 4: + compound_list ::= compound_list * sep + compound_list ::= compound_list * command sep + sep ::= * SEMI + sep ::= * NL + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + begin_command ::= BEGIN sep compound_list * END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + END shift-reduce 13 begin_command ::= BEGIN sep compound_list END + LOOP shift 20 + FOR shift 19 + IF shift 18 + sep shift-reduce 24 compound_list ::= compound_list sep + command shift 13 + term shift 13 /* because term==command */ + if_command shift 13 /* because if_command==term */ + begin_command shift 13 /* because begin_command==term */ + paren_command shift 13 /* because paren_command==term */ + loop_command shift 13 /* because loop_command==term */ + for_command shift 13 /* because for_command==term */ + +State 5: + (20) start ::= command_list * + command_list ::= command_list * sep + command_list ::= command_list * command sep + sep ::= * SEMI + sep ::= * NL + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + + $ reduce 20 start ::= command_list + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + LOOP shift 20 + FOR shift 19 + IF shift 18 + sep shift-reduce 22 command_list ::= command_list sep + command shift 15 + term shift 15 /* because term==command */ + if_command shift 15 /* because if_command==term */ + begin_command shift 15 /* because begin_command==term */ + paren_command shift 15 /* because paren_command==term */ + loop_command shift 15 /* because loop_command==term */ + for_command shift 15 /* because for_command==term */ + +State 6: + compound_list ::= compound_list * sep + compound_list ::= compound_list * command sep + sep ::= * SEMI + sep ::= * NL + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + (18) else_command ::= ELSE_IF|ELSE sep compound_list * + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + LOOP shift 20 + FOR shift 19 + IF shift 18 + sep shift-reduce 24 compound_list ::= compound_list sep + command shift 13 + term shift 13 /* because term==command */ + if_command shift 13 /* because if_command==term */ + begin_command shift 13 /* because begin_command==term */ + paren_command shift 13 /* because paren_command==term */ + loop_command shift 13 /* because loop_command==term */ + for_command shift 13 /* because for_command==term */ + {default} reduce 18 else_command ::= ELSE_IF|ELSE sep compound_list + +State 7: + compound_list ::= compound_list * sep + compound_list ::= compound_list * command sep + sep ::= * SEMI + sep ::= * NL + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + (19) else_command ::= else_command ELSE_IF|ELSE sep compound_list * + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + LOOP shift 20 + FOR shift 19 + IF shift 18 + sep shift-reduce 24 compound_list ::= compound_list sep + command shift 13 + term shift 13 /* because term==command */ + if_command shift 13 /* because if_command==term */ + begin_command shift 13 /* because begin_command==term */ + paren_command shift 13 /* because paren_command==term */ + loop_command shift 13 /* because loop_command==term */ + for_command shift 13 /* because for_command==term */ + {default} reduce 19 else_command ::= else_command ELSE_IF|ELSE sep compound_list + +State 8: + compound_list ::= compound_list * sep + compound_list ::= compound_list * command sep + sep ::= * SEMI + sep ::= * NL + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + (33) paren_list ::= compound_list * + paren_list ::= compound_list * command + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + LOOP shift 20 + FOR shift 19 + IF shift 18 + sep shift-reduce 24 compound_list ::= compound_list sep + command shift 14 + term shift 14 /* because term==command */ + if_command shift 14 /* because if_command==term */ + begin_command shift 14 /* because begin_command==term */ + paren_command shift 14 /* because paren_command==term */ + loop_command shift 14 /* because loop_command==term */ + for_command shift 14 /* because for_command==term */ + {default} reduce 33 paren_list ::= compound_list + +State 9: + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= command PIPE opt_nl * command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + opt_nl ::= opt_nl * NL + + NL shift-reduce 35 opt_nl ::= opt_nl NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + LOOP shift 20 + FOR shift 19 + IF shift 18 + command shift-reduce 4 command ::= command PIPE opt_nl command + term shift-reduce 4 command ::= command PIPE opt_nl command /* because term==command */ + if_command shift-reduce 4 command ::= command PIPE opt_nl command /* because if_command==term */ + begin_command shift-reduce 4 command ::= command PIPE opt_nl command /* because begin_command==term */ + paren_command shift-reduce 4 command ::= command PIPE opt_nl command /* because paren_command==term */ + loop_command shift-reduce 4 command ::= command PIPE opt_nl command /* because loop_command==term */ + for_command shift-reduce 4 command ::= command PIPE opt_nl command /* because for_command==term */ + +State 10: + command ::= * command PIPE_PIPE opt_nl command + command ::= * command AMP_AMP opt_nl command + command ::= command AMP_AMP opt_nl * command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + opt_nl ::= opt_nl * NL + + NL shift-reduce 35 opt_nl ::= opt_nl NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + LOOP shift 20 + FOR shift 19 + IF shift 18 + command shift 33 + term shift 33 /* because term==command */ + if_command shift 33 /* because if_command==term */ + begin_command shift 33 /* because begin_command==term */ + paren_command shift 33 /* because paren_command==term */ + loop_command shift 33 /* because loop_command==term */ + for_command shift 33 /* because for_command==term */ + +State 11: + command ::= * command PIPE_PIPE opt_nl command + command ::= command PIPE_PIPE opt_nl * command + command ::= * command AMP_AMP opt_nl command + command ::= * command PIPE opt_nl command + command ::= * term + term ::= * COMMAND + term ::= * EVALUATE + term ::= * BREAK + term ::= * CONTINUE + term ::= * EXIT + term ::= * if_command + term ::= * begin_command + term ::= * paren_command + term ::= * loop_command + term ::= * for_command + term ::= * ERROR + paren_command ::= * LPAREN paren_list RPAREN + begin_command ::= * BEGIN sep compound_list END + loop_command ::= * LOOP sep compound_list END + for_command ::= * FOR sep compound_list END + if_command ::= * IF sep compound_list END + if_command ::= * IF sep compound_list else_command END + opt_nl ::= opt_nl * NL + + NL shift-reduce 35 opt_nl ::= opt_nl NL + COMMAND shift-reduce 5 term ::= COMMAND + EVALUATE shift-reduce 6 term ::= EVALUATE + BREAK shift-reduce 7 term ::= BREAK + CONTINUE shift-reduce 8 term ::= CONTINUE + EXIT shift-reduce 9 term ::= EXIT + ERROR shift-reduce 10 term ::= ERROR + LPAREN shift 12 + BEGIN shift 21 + LOOP shift 20 + FOR shift 19 + IF shift 18 + command shift 34 + term shift 34 /* because term==command */ + if_command shift 34 /* because if_command==term */ + begin_command shift 34 /* because begin_command==term */ + paren_command shift 34 /* because paren_command==term */ + loop_command shift 34 /* because loop_command==term */ + for_command shift 34 /* because for_command==term */ + +State 12: + (23) compound_list ::= * + compound_list ::= * compound_list sep + compound_list ::= * compound_list command sep + paren_list ::= * compound_list + paren_list ::= * compound_list command + paren_command ::= LPAREN * paren_list RPAREN + + compound_list shift 8 + paren_list shift 32 + {default} reduce 23 compound_list ::= + +State 13: + compound_list ::= compound_list command * sep + sep ::= * SEMI + sep ::= * NL + command ::= command * PIPE_PIPE opt_nl command + command ::= command * AMP_AMP opt_nl command + command ::= command * PIPE opt_nl command + + PIPE_PIPE shift 30 + AMP_AMP shift 29 + PIPE shift 28 + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift-reduce 1 compound_list ::= compound_list command sep + +State 14: + compound_list ::= compound_list command * sep + sep ::= * SEMI + sep ::= * NL + command ::= command * PIPE_PIPE opt_nl command + command ::= command * AMP_AMP opt_nl command + command ::= command * PIPE opt_nl command + (11) paren_list ::= compound_list command * + + PIPE_PIPE shift 30 + AMP_AMP shift 29 + PIPE shift 28 + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift-reduce 1 compound_list ::= compound_list command sep + {default} reduce 11 paren_list ::= compound_list command + +State 15: + command_list ::= command_list command * sep + sep ::= * SEMI + sep ::= * NL + command ::= command * PIPE_PIPE opt_nl command + command ::= command * AMP_AMP opt_nl command + command ::= command * PIPE opt_nl command + + PIPE_PIPE shift 30 + AMP_AMP shift 29 + PIPE shift 28 + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift-reduce 0 command_list ::= command_list command sep + +State 16: + sep ::= * SEMI + sep ::= * NL + else_command ::= ELSE_IF|ELSE * sep compound_list + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift 22 + +State 17: + sep ::= * SEMI + sep ::= * NL + else_command ::= else_command ELSE_IF|ELSE * sep compound_list + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift 23 + +State 18: + sep ::= * SEMI + sep ::= * NL + if_command ::= IF * sep compound_list END + if_command ::= IF * sep compound_list else_command END + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift 24 + +State 19: + sep ::= * SEMI + sep ::= * NL + for_command ::= FOR * sep compound_list END + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift 25 + +State 20: + sep ::= * SEMI + sep ::= * NL + loop_command ::= LOOP * sep compound_list END + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift 26 + +State 21: + sep ::= * SEMI + sep ::= * NL + begin_command ::= BEGIN * sep compound_list END + + SEMI shift-reduce 25 sep ::= SEMI + NL shift-reduce 26 sep ::= NL + sep shift 27 + +State 22: + (23) compound_list ::= * + compound_list ::= * compound_list sep + compound_list ::= * compound_list command sep + else_command ::= ELSE_IF|ELSE sep * compound_list + + compound_list shift 6 + {default} reduce 23 compound_list ::= + +State 23: + (23) compound_list ::= * + compound_list ::= * compound_list sep + compound_list ::= * compound_list command sep + else_command ::= else_command ELSE_IF|ELSE sep * compound_list + + compound_list shift 7 + {default} reduce 23 compound_list ::= + +State 24: + (23) compound_list ::= * + compound_list ::= * compound_list sep + compound_list ::= * compound_list command sep + if_command ::= IF sep * compound_list END + if_command ::= IF sep * compound_list else_command END + + compound_list shift 1 + {default} reduce 23 compound_list ::= + +State 25: + (23) compound_list ::= * + compound_list ::= * compound_list sep + compound_list ::= * compound_list command sep + for_command ::= FOR sep * compound_list END + + compound_list shift 2 + {default} reduce 23 compound_list ::= + +State 26: + (23) compound_list ::= * + compound_list ::= * compound_list sep + compound_list ::= * compound_list command sep + loop_command ::= LOOP sep * compound_list END + + compound_list shift 3 + {default} reduce 23 compound_list ::= + +State 27: + (23) compound_list ::= * + compound_list ::= * compound_list sep + compound_list ::= * compound_list command sep + begin_command ::= BEGIN sep * compound_list END + + compound_list shift 4 + {default} reduce 23 compound_list ::= + +State 28: + command ::= command PIPE * opt_nl command + (34) opt_nl ::= * + opt_nl ::= * opt_nl NL + + opt_nl shift 9 + {default} reduce 34 opt_nl ::= + +State 29: + command ::= command AMP_AMP * opt_nl command + (34) opt_nl ::= * + opt_nl ::= * opt_nl NL + + opt_nl shift 10 + {default} reduce 34 opt_nl ::= + +State 30: + command ::= command PIPE_PIPE * opt_nl command + (34) opt_nl ::= * + opt_nl ::= * opt_nl NL + + opt_nl shift 11 + {default} reduce 34 opt_nl ::= + +State 31: + if_command ::= IF sep compound_list else_command * END + else_command ::= else_command * ELSE_IF|ELSE sep compound_list + + END shift-reduce 17 if_command ::= IF sep compound_list else_command END + ELSE_IF shift 17 + ELSE shift 17 + +State 32: + paren_command ::= LPAREN paren_list * RPAREN + + RPAREN shift-reduce 12 paren_command ::= LPAREN paren_list RPAREN + +State 33: + command ::= command * PIPE_PIPE opt_nl command + command ::= command * AMP_AMP opt_nl command + (3) command ::= command AMP_AMP opt_nl command * + command ::= command * PIPE opt_nl command + + PIPE shift 28 + {default} reduce 3 command ::= command AMP_AMP opt_nl command + +State 34: + command ::= command * PIPE_PIPE opt_nl command + (2) command ::= command PIPE_PIPE opt_nl command * + command ::= command * AMP_AMP opt_nl command + command ::= command * PIPE opt_nl command + + PIPE shift 28 + {default} reduce 2 command ::= command PIPE_PIPE opt_nl command + +---------------------------------------------------- +Symbols: + 0: $: + 1: PIPE_PIPE + 2: AMP_AMP + 3: PIPE + 4: SEMI + 5: NL + 6: COMMAND + 7: EVALUATE + 8: BREAK + 9: CONTINUE + 10: EXIT + 11: ERROR + 12: LPAREN + 13: RPAREN + 14: BEGIN + 15: END + 16: LOOP + 17: FOR + 18: IF + 19: ELSE_IF + 20: ELSE + 21: error: + 22: start: SEMI NL COMMAND EVALUATE BREAK CONTINUE EXIT ERROR LPAREN BEGIN LOOP FOR IF + 23: command_list: SEMI NL COMMAND EVALUATE BREAK CONTINUE EXIT ERROR LPAREN BEGIN LOOP FOR IF + 24: sep: SEMI NL + 25: command: COMMAND EVALUATE BREAK CONTINUE EXIT ERROR LPAREN BEGIN LOOP FOR IF + 26: compound_list: SEMI NL COMMAND EVALUATE BREAK CONTINUE EXIT ERROR LPAREN BEGIN LOOP FOR IF + 27: opt_nl: NL + 28: term: COMMAND EVALUATE BREAK CONTINUE EXIT ERROR LPAREN BEGIN LOOP FOR IF + 29: if_command: IF + 30: begin_command: BEGIN + 31: paren_command: LPAREN + 32: loop_command: LOOP + 33: for_command: FOR + 34: paren_list: SEMI NL COMMAND EVALUATE BREAK CONTINUE EXIT ERROR LPAREN BEGIN LOOP FOR IF + 35: else_command: ELSE_IF ELSE