Parse_stat MCRepeat::parse(MCScriptPoint &sp) { Parse_stat stat; Symbol_type type; const LT *te; initpoint(sp); if ((stat = sp.next(type)) != PS_NORMAL) { if (stat == PS_EOL) { if (sp.skip_eol() != PS_NORMAL) { MCperror->add (PE_REPEAT_BADCONDEOL, sp); return PS_ERROR; } } else { MCperror->add (PE_REPEAT_BADCONDTYPE, sp); return PS_ERROR; } } else switch (stat) { case PS_NORMAL: if (sp.lookup(SP_REPEAT, te) != PS_NORMAL) { sp.backup(); form = RF_FOR; if (sp.parseexp(False, True, &endcond) != PS_NORMAL) { MCperror->add (PE_REPEAT_BADCOND, sp); return PS_ERROR; } } else { MCExpression *newfact = NULL; switch (form = (Repeat_form)te->which) { case RF_FOREVER: break; case RF_FOR: if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_EACH) == PS_NORMAL) { if (sp.next(type) != PS_NORMAL || sp.lookup(SP_UNIT, te) != PS_NORMAL || sp.next(type) != PS_NORMAL) { MCperror->add(PE_REPEAT_BADCOND, sp); return PS_ERROR; } each = (File_unit)te->which; if (sp.lookupconstant(&newfact) == PS_NORMAL || sp . findnewvar(sp.gettoken_nameref(), kMCEmptyName, &loopvar) != PS_NORMAL) { delete newfact; MCperror->add(PE_REPEAT_BADWITHVAR, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_IN) != PS_NORMAL) { MCperror->add(PE_REPEAT_NOOF, sp); return PS_ERROR; } } case RF_UNTIL: case RF_WHILE: if (sp.parseexp(False, True, &endcond) != PS_NORMAL) { MCperror->add (PE_REPEAT_BADCOND, sp); return PS_ERROR; } break; case RF_WITH: if ((stat = sp.next(type)) != PS_NORMAL) { MCperror->add (PE_REPEAT_NOWITHVAR, sp); return PS_ERROR; } if (sp.lookupconstant(&newfact) == PS_NORMAL || sp.findnewvar(sp.gettoken_nameref(), kMCEmptyName, &loopvar) != PS_NORMAL) { delete newfact; MCperror->add (PE_REPEAT_BADWITHVAR, sp); return PS_ERROR; } if ((stat = sp.next(type)) != PS_NORMAL) { MCperror->add (PE_REPEAT_NOEQUALS, sp); return PS_ERROR; } if (sp.lookup(SP_FACTOR, te) != PS_NORMAL || te->type != TT_BINOP || te->which != O_EQ) { MCperror->add (PE_REPEAT_NOTEQUALS, sp); return PS_ERROR; } if (sp.parseexp(False, True, &startcond) != PS_NORMAL) { MCperror->add (PE_REPEAT_BADWITHSTARTEXP, sp); return PS_ERROR; } if ((stat = sp.next(type)) != PS_NORMAL) { MCperror->add (PE_REPEAT_NOWITHTO, sp); return PS_ERROR; } if (sp.lookup(SP_FACTOR, te) != PS_NORMAL) { if (sp.gettoken() != "down") { MCperror->add (PE_REPEAT_NOWITHTO, sp); return PS_ERROR; } stepval = -1.0; if (sp.skip_token(SP_FACTOR, TT_TO) != PS_NORMAL) { MCperror->add (PE_REPEAT_NODOWNTO, sp); return PS_ERROR; } } else if (te->type != TT_TO) { MCperror->add (PE_REPEAT_NOTWITHTO, sp); return PS_ERROR; } else stepval = 1.0; if (sp.parseexp(False, True, &endcond) != PS_NORMAL) { MCperror->add (PE_REPEAT_BADWITHENDEXP, sp); return PS_ERROR; } if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_STEP) == PS_NORMAL) if (sp.parseexp(False, True, &step) != PS_NORMAL) { MCperror->add (PE_REPEAT_BADWITHSTARTEXP, sp); return PS_ERROR; } break; default: /* repeat form */ fprintf(stderr, "Repeat: ERROR bad control form\n"); return PS_ERROR; } } if (sp.skip_eol() != PS_NORMAL) { MCperror->add (PE_REPEAT_BADFORMEOL, sp); return PS_ERROR; } break; case PS_EOL: break; default: /* token type */ MCperror->add (PE_REPEAT_BADFORMTYPE, sp); return PS_ERROR; } MCStatement *curstatement = NULL; MCStatement *newstatement = NULL; while (True) { switch (sp.next(type)) { case PS_NORMAL: if (type == ST_DATA) newstatement = new MCEcho; else if (sp.lookup(SP_COMMAND, te) != PS_NORMAL) { if (type == ST_ID) newstatement = new MCComref(sp.gettoken_nameref()); else { MCperror->add (PE_REPEAT_NOTCOMMAND, sp); return PS_ERROR; } } else { switch (te->type) { case TT_STATEMENT: newstatement = MCN_new_statement(te->which); break; case TT_END: if (sp.skip_token(SP_COMMAND, TT_STATEMENT, S_REPEAT) != PS_NORMAL) { MCperror->add (PE_REPEAT_WANTEDENDREPEAT, sp); return PS_ERROR; } return PS_NORMAL; default: MCperror->add (PE_REPEAT_BADSTATEMENT, sp); return PS_ERROR; } } break; case PS_EOL: if (sp.skip_eol() != PS_NORMAL) { MCperror->add (PE_REPEAT_WANTEDENDREPEAT, sp); return PS_ERROR; } continue; default: MCperror->add (PE_REPEAT_BADTOKEN, sp); return PS_ERROR; } if (newstatement->parse(sp) != PS_NORMAL) { MCperror->add (PE_REPEAT_BADCOMMAND, sp); delete newstatement; return PS_ERROR; } if (statements == NULL) statements = curstatement = newstatement; else { curstatement->setnext(newstatement); curstatement = newstatement; } } return PS_NORMAL; }
Parse_stat MCTry::parse(MCScriptPoint &sp) { initpoint(sp); Try_state state = TS_TRY; if (sp.skip_eol() != PS_NORMAL) { MCperror->add (PE_TRY_WANTEDENDTRY, sp); return PS_ERROR; } MCStatement *curstatement = NULL; MCStatement *newstatement = NULL; while (True) { Symbol_type type; const LT *te; switch (sp.next(type)) { case PS_NORMAL: if (type == ST_DATA) newstatement = new MCEcho; else if (sp.lookup(SP_COMMAND, te) != PS_NORMAL) { if (type == ST_ID) newstatement = new MCComref(sp.gettoken_nameref()); else { MCperror->add (PE_TRY_NOTCOMMAND, sp); return PS_ERROR; } } else { Parse_stat stat; MCExpression *newfact = NULL; switch (te->type) { case TT_STATEMENT: newstatement = MCN_new_statement(te->which); break; case TT_CATCH: state = TS_CATCH; curstatement = NULL; stat = sp.next(type); if (errorvar != NULL || stat != PS_NORMAL || type != ST_ID || sp.lookup(SP_FACTOR, te) != PS_NO_MATCH || sp.lookupconstant(&newfact) == PS_NORMAL || sp . findnewvar(sp.gettoken_nameref(), kMCEmptyName, &errorvar) != PS_NORMAL) { delete newfact; MCperror->add(PE_LOCAL_BADNAME, sp); return PS_ERROR; } continue; break; case TT_FINALLY: state = TS_FINALLY; curstatement = NULL; continue; break; case TT_END: if (sp.skip_token(SP_COMMAND, TT_STATEMENT, S_TRY) != PS_NORMAL) { MCperror->add (PE_TRY_WANTEDENDTRY, sp); return PS_ERROR; } return PS_NORMAL; default: /* token type */ MCperror->add (PE_TRY_BADSTATEMENT, sp); return PS_ERROR; } } break; case PS_EOL: if (sp.skip_eol() != PS_NORMAL) { MCperror->add (PE_TRY_WANTEDENDTRY, sp); return PS_ERROR; } continue; case PS_EOF: return PS_NORMAL; default: MCperror->add (PE_TRY_BADTYPE, sp); return PS_ERROR; } if (newstatement->parse(sp) != PS_NORMAL) { MCperror->add (PE_TRY_BADSTATEMENT, sp); delete newstatement; return PS_ERROR; } if (curstatement != NULL) { curstatement->setnext(newstatement); curstatement = newstatement; } else switch (state) { case TS_TRY: trystatements = curstatement = newstatement; break; case TS_CATCH: catchstatements = curstatement = newstatement; break; case TS_FINALLY: finallystatements = curstatement = newstatement; break; } } return PS_NORMAL; }
Parse_stat MCIf::parse(MCScriptPoint &sp) { initpoint(sp); if (sp.parseexp(False, True, &cond) != PS_NORMAL) { MCperror->add (PE_IF_BADCONDITION, sp); return PS_ERROR; } Symbol_type type; const LT *te; MCStatement *curstatement = NULL; MCStatement *newstatement = NULL; If_state state = IS_UNDEFINED; If_format format = IF_UNDEFINED; Boolean needstatement = False; while (True) { switch (sp.next(type)) { case PS_NORMAL: if (type == ST_DATA || sp.lookup(SP_COMMAND, te) != PS_NORMAL) { if (needstatement) { if (type == ST_ID) newstatement = new MCComref(sp.gettoken_nameref()); else if (type == ST_DATA) newstatement = new MCEcho; else { MCperror->add(PE_IF_NOTCOMMAND, sp); return PS_ERROR; } } else { if (state == IS_UNDEFINED) { MCperror->add(PE_IF_NOTHEN, sp); return PS_ERROR; } sp.backup(); return PS_NORMAL; } } else { switch (te->type) { case TT_STATEMENT: if (needstatement) newstatement = MCN_new_statement(te->which); else { if (state == IS_UNDEFINED) { MCperror->add(PE_IF_NOTHEN, sp); return PS_ERROR; } sp.backup(); return PS_NORMAL; } break; case TT_THEN: state = IS_THEN; needstatement = True; continue; case TT_ELSE: state = IS_ELSE; needstatement = True; continue; case TT_END: if (needstatement) { if (sp.skip_token(SP_COMMAND, TT_STATEMENT, S_IF) != PS_NORMAL) { MCperror->add(PE_IF_WANTEDENDIF, sp); return PS_ERROR; } } else sp.backup(); return PS_NORMAL; default: /* token type */ if (needstatement) { MCperror->add(PE_IF_WANTEDENDIF, sp); return PS_ERROR; } sp.backup(); return PS_NORMAL; } } break; case PS_EOL: switch (format) { case IF_UNDEFINED: if (state == IS_THEN) format = IF_MULTIPLE; else format = IF_SINGLE; break; case IF_ONELINE: if (state == IS_ELSE) return PS_NORMAL; format = IF_SINGLE; needstatement = False; break; case IF_SINGLE: if (state == IS_ELSE) format = IF_ELSEMULTIPLE; else format = IF_MULTIPLE; break; case IF_MULTIPLE: if (state == IS_ELSE) format = IF_ELSEMULTIPLE; break; case IF_ELSEMULTIPLE: break; } if (sp.skip_eol() != PS_NORMAL) { MCperror->add(PE_IF_BADEOL, sp); return PS_ERROR; } continue; case PS_EOF: return PS_NORMAL; default: MCperror->add(PE_IF_BADTYPE, sp); return PS_ERROR; } if (newstatement->parse(sp) != PS_NORMAL) { MCperror->add(PE_IF_BADSTATEMENT, sp); delete newstatement; return PS_ERROR; } switch (state) { case IS_THEN: if (thenstatements == NULL) thenstatements = curstatement = newstatement; else { curstatement->setnext(newstatement); curstatement = newstatement; } switch (format) { case IF_UNDEFINED: format = IF_ONELINE; needstatement = False; break; case IF_SINGLE: needstatement = False; break; case IF_MULTIPLE: break; default: // may be unreachable return PS_ERROR; } break; case IS_ELSE: if (elsestatements == NULL) elsestatements = curstatement = newstatement; else { curstatement->setnext(newstatement); curstatement = newstatement; } if (format != IF_ELSEMULTIPLE) return PS_NORMAL; break; case IS_UNDEFINED: MCperror->add(PE_IF_NOTHEN, sp); delete newstatement; return PS_ERROR; } } return PS_NORMAL; }
Parse_stat MCSwitch::parse(MCScriptPoint &sp) { Symbol_type type; const LT *te; initpoint(sp); if (sp.next(type) == PS_NORMAL) { sp.backup(); if (sp.parseexp(False, True, &cond) != PS_NORMAL) { MCperror->add (PE_SWITCH_BADCONDITION, sp); return PS_ERROR; } } else if (sp.skip_eol() != PS_NORMAL) { MCperror->add (PE_SWITCH_WANTEDENDSWITCH, sp); return PS_ERROR; } uint2 snum = 0; MCStatement *curstatement = NULL; MCStatement *newstatement = NULL; while (True) { switch (sp.next(type)) { case PS_NORMAL: if (type == ST_DATA) newstatement = new MCEcho; else if (sp.lookup(SP_COMMAND, te) != PS_NORMAL) { if (type == ST_ID) newstatement = new MCComref(sp.gettoken_nameref()); else { MCperror->add (PE_SWITCH_NOTCOMMAND, sp); return PS_ERROR; } } else { switch (te->type) { case TT_STATEMENT: newstatement = MCN_new_statement(te->which); break; case TT_CASE: MCU_realloc((char **)&cases, ncases, ncases + 1, sizeof(MCExpression *)); if (sp.parseexp(False, True, &cases[ncases]) != PS_NORMAL) { MCperror->add (PE_SWITCH_BADCASECONDITION, sp); return PS_ERROR; } MCU_realloc((char **)&caseoffsets, ncases, ncases + 1, sizeof(uint2)); caseoffsets[ncases++] = snum; continue; case TT_DEFAULT: defaultcase = snum; continue; case TT_END: if (sp.skip_token(SP_COMMAND, TT_STATEMENT, S_SWITCH) != PS_NORMAL) { MCperror->add (PE_SWITCH_WANTEDENDSWITCH, sp); return PS_ERROR; } return PS_NORMAL; default: /* token type */ MCperror->add (PE_SWITCH_BADCASECONDITION, sp); return PS_ERROR; } } break; case PS_EOL: if (sp.skip_eol() != PS_NORMAL) { MCperror->add (PE_SWITCH_WANTEDENDSWITCH, sp); return PS_ERROR; } continue; case PS_EOF: return PS_NORMAL; default: MCperror->add (PE_SWITCH_BADTYPE, sp); return PS_ERROR; } if (newstatement->parse(sp) != PS_NORMAL) { MCperror->add (PE_SWITCH_BADSTATEMENT, sp); delete newstatement; return PS_ERROR; } if (statements == NULL) statements = curstatement = newstatement; else { curstatement->setnext(newstatement); curstatement = newstatement; } snum++; } return PS_NORMAL; }