Parse_stat MCReturn::parse(MCScriptPoint &sp) { initpoint(sp); if (sp.parseexp(False, True, &source) != PS_NORMAL) { MCperror->add (PE_RETURN_BADEXP, sp); return PS_ERROR; } if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL) { if (sp.skip_token(SP_FACTOR, TT_CHUNK, CT_URL)) { // MW-2011-06-22: [[ SERVER ]] Update to use SP findvar method to take into account // execution outwith a handler. Symbol_type type; if (sp.next(type) != PS_NORMAL || sp.findvar(sp.gettoken_nameref(), &var) != PS_NORMAL) sp.backup(); else var->parsearray(sp); } if (var == NULL) { sp.skip_token(SP_FACTOR, TT_FUNCTION, F_CACHED_URLS); if (sp.parseexp(False, True, &url) != PS_NORMAL) { MCperror->add (PE_RETURN_BADEXP, sp); return PS_ERROR; } } } return PS_NORMAL; }
Parse_stat MCStatement::gettime(MCScriptPoint &sp, MCExpression **in, Functions &units) { if (sp.skip_token(SP_FACTOR, TT_IN) == PS_NORMAL) { if (sp.parseexp(False, True, in) != PS_NORMAL) { MCperror->add (PE_STATEMENT_BADINEXP, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_FUNCTION, F_MILLISECS) == PS_NORMAL) units = F_MILLISECS; else if (sp.skip_token(SP_FACTOR, TT_FUNCTION, F_SECONDS) == PS_NORMAL || sp.skip_token(SP_FACTOR, TT_CHUNK, CT_SECOND) == PS_NORMAL) units = F_SECONDS; else if (sp.skip_token(SP_FACTOR, TT_FUNCTION, F_TICKS) == PS_NORMAL) units = F_TICKS; else units = F_TICKS; } return PS_NORMAL; }
Parse_stat MCDo::parse(MCScriptPoint &sp) { initpoint(sp); h = sp.gethandler(); if (sp.parseexp(False, True, &source) != PS_NORMAL) { MCperror->add(PE_DO_BADEXP, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_IN, PT_IN) == PS_NORMAL) { if (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_BROWSER) == PS_NORMAL) browser = True; else if (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_CALLER) == PS_NORMAL) caller = true; else { MCperror->add(PE_DO_BADENV, sp); return PS_ERROR; } return PS_NORMAL; } if (sp.skip_token(SP_FACTOR, TT_PREP, PT_AS) == PS_NORMAL) { if (sp.parseexp(False, True, &alternatelang) != PS_NORMAL) { MCperror->add(PE_DO_BADLANG, sp); return PS_ERROR; } } return PS_NORMAL; }
Parse_stat MCSet::parse(MCScriptPoint &sp) { initpoint(sp); if (sp.skip_token(SP_FACTOR, TT_THE) == PS_ERROR) { MCperror->add(PE_SET_NOTHE, sp); return PS_ERROR; } target = new MCProperty; if (target->parse(sp, True) != PS_NORMAL) { MCperror->add(PE_SET_NOPROP, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_TO) != PS_NORMAL) { MCperror->add(PE_SET_NOTO, sp); return PS_ERROR; } if (sp.parseexp(False, True, &value) != PS_NORMAL) { MCperror->add(PE_SET_BADEXP, sp); return PS_ERROR; } return PS_NORMAL; }
Parse_stat MCChoose::parse(MCScriptPoint &sp) { Symbol_type type; const LT *te; initpoint(sp); sp.skip_token(SP_FACTOR, TT_THE); if (sp.next(type) != PS_NORMAL) { MCperror->add(PE_CHOOSE_NOTOKEN, sp); return PS_ERROR; } if (sp.lookup(SP_TOOL, te) != PS_NORMAL) { sp.backup(); if (sp.parseexp(False, True, &etool) != PS_NORMAL) { MCperror->add(PE_CHOOSE_BADEXP, sp); return PS_ERROR; } sp.skip_token(SP_TOOL, TT_END); return PS_NORMAL; } else { littool = (Tool)te->which; while (sp.skip_token(SP_TOOL, TT_TOOL) == PS_NORMAL) ; sp.skip_token(SP_TOOL, TT_END); } return PS_NORMAL; }
Parse_stat MCFind::parse(MCScriptPoint &sp) { Symbol_type type; const LT *te; initpoint(sp); if (sp.next(type) != PS_NORMAL) { MCperror->add (PE_FIND_NOSTRING, sp); return PS_ERROR; } if (sp.lookup(SP_FIND, te) == PS_NORMAL) mode = (Find_mode)te->which; else sp.backup(); if (sp.parseexp(False, True, &tofind) != PS_NORMAL) { MCperror->add (PE_FIND_BADSTRING, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_IN) == PS_NORMAL) { field = new MCChunk(False); if (field->parse(sp, False) != PS_NORMAL) { MCperror->add (PE_FIND_BADFIELD, sp); return PS_ERROR; } } return PS_NORMAL; }
Parse_stat MCAdd::parse(MCScriptPoint &sp) { initpoint(sp); if (sp.parseexp(False, True, &source) != PS_NORMAL) { MCperror->add(PE_ADD_BADEXP, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_TO) == PS_ERROR) { MCperror->add(PE_ADD_NOTO, sp); return PS_ERROR; } Symbol_type type; // MW-2011-06-22: [[ SERVER ]] Update to use SP findvar method to take into account // execution outwith a handler. if (sp.next(type) != PS_NORMAL || type != ST_ID || sp.findvar(sp.gettoken_nameref(), &destvar) != PS_NORMAL) { sp.backup(); dest = new (nothrow) MCChunk(True); if (dest->parse(sp, False) != PS_NORMAL) { MCperror->add(PE_ADD_BADDEST, sp); return PS_ERROR; } } else destvar->parsearray(sp); // MW-2013-08-01: [[ Bug 10925 ]] If the dest chunk is just a var, extract the varref. if (dest != NULL && dest -> isvarchunk()) destvar = dest -> getrootvarref(); return PS_NORMAL; }
Parse_stat MCPass::parse(MCScriptPoint &sp) { Symbol_type type; initpoint(sp); if (sp.next(type) != PS_NORMAL || !sp.gethandler()->hasname(sp.gettoken_nameref())) { MCperror->add(PE_PASS_NOMESSAGE, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_TO) == PS_NORMAL) { if (sp.next(type) != PS_NORMAL) { MCperror->add(PE_PASS_NOMESSAGE, sp); return PS_ERROR; } all = True; } if (sp.gethandler() -> isprivate()) { MCperror -> add(PE_PRIVATE_BADPASS, sp); return PS_ERROR; } return PS_NORMAL; }
Parse_stat MCEdit::parse(MCScriptPoint &sp) { initpoint(sp); sp.skip_token(SP_FACTOR, TT_THE); if (sp.skip_token(SP_FACTOR, TT_PROPERTY) != PS_NORMAL) { MCperror->add(PE_EDIT_NOSCRIPT, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_OF) != PS_NORMAL) { MCperror->add(PE_EDIT_NOOF, sp); return PS_ERROR; } target = new MCChunk(False); if (target->parse(sp, False) != PS_NORMAL) { MCperror->add(PE_EDIT_NOTARGET, sp); return PS_ERROR; } return PS_NORMAL; }
Parse_stat MCSetOp::parse(MCScriptPoint &sp) { initpoint(sp); // MW-2011-06-22: [[ SERVER ]] Update to use SP findvar method to take into account // execution outwith a handler. Symbol_type type; if (sp.next(type) != PS_NORMAL || type != ST_ID || sp.findvar(sp.gettoken_nameref(), &destvar) != PS_NORMAL || destvar -> parsearray(sp) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_BADARRAY, sp); return PS_ERROR; } if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_ERROR && sp.skip_token(SP_FACTOR, TT_PREP, PT_BY) == PS_ERROR) { MCperror->add(PE_ARRAYOP_NOWITH, sp); return PS_ERROR; } if (sp.parseexp(True, False, &source) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_BADEXP, sp); return PS_ERROR; } // MERG-2013-08-26: [[ RecursiveArrayOp ]] Support nested arrays in union and intersect recursive = sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_RECURSIVELY) == PS_NORMAL; MCVarref *t_src_ref, *t_dst_ref; t_src_ref = source -> getrootvarref(); t_dst_ref = destvar -> getrootvarref(); overlap = t_src_ref != NULL && t_dst_ref != NULL && t_src_ref -> rootmatches(t_dst_ref); return PS_NORMAL; }
Parse_stat MCConvert::parse(MCScriptPoint &sp) { initpoint(sp); MCerrorlock++; container = new MCChunk(True); MCScriptPoint tsp(sp); if (container->parse(sp, False) != PS_NORMAL) { sp = tsp; MCerrorlock--; delete container; container = NULL; if (sp.parseexp(False, True, &source) != PS_NORMAL) { MCperror->add (PE_CONVERT_NOCONTAINER, sp); return PS_ERROR; } getit(sp, it); } else MCerrorlock--; if (sp.skip_token(SP_FACTOR, TT_FROM) == PS_NORMAL) { if (parsedtformat(sp, fform, fsform) != PS_NORMAL) return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_TO) != PS_NORMAL) { MCperror->add (PE_CONVERT_NOTO, sp); return PS_ERROR; } if (parsedtformat(sp, pform, sform) != PS_NORMAL) return PS_ERROR; return PS_NORMAL; }
Parse_stat MCWait::parse(MCScriptPoint &sp) { Symbol_type type; const LT *te; initpoint(sp); if (sp.next(type) != PS_NORMAL) { MCperror->add (PE_WAIT_NODURATION, sp); return PS_ERROR; } if (sp.lookup(SP_REPEAT, te) == PS_NORMAL) condition = (Repeat_form)te->which; else { condition = RF_FOR; sp.backup(); } if (sp.skip_token(SP_MOVE, TT_UNDEFINED, MM_MESSAGES) == PS_NORMAL) messages = True; else { if (sp.parseexp(False, True, &duration) != PS_NORMAL) { MCperror->add (PE_WAIT_BADCOND, sp); return PS_ERROR; } if (condition == RF_FOR) if (sp.skip_token(SP_FACTOR, TT_FUNCTION, F_MILLISECS) == PS_NORMAL) units = F_MILLISECS; else if (sp.skip_token(SP_FACTOR, TT_FUNCTION, F_SECONDS) == PS_NORMAL || sp.skip_token(SP_FACTOR, TT_CHUNK, CT_SECOND) == PS_NORMAL) units = F_SECONDS; else if (sp.skip_token(SP_FACTOR, TT_FUNCTION, F_TICKS) == PS_NORMAL) units = F_TICKS; else units = F_TICKS; if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_NORMAL) { sp.skip_token(SP_MOVE, TT_UNDEFINED, MM_MESSAGES); messages = True; } } return PS_NORMAL; }
Parse_stat MCReset::parse(MCScriptPoint &sp) { Symbol_type type; const LT *te; initpoint(sp); sp.skip_token(SP_FACTOR, TT_THE); if (sp.next(type) != PS_NORMAL) { MCperror->add (PE_CHOOSE_NOTOKEN, sp); return PS_ERROR; } if (sp.lookup(SP_RESET, te) != PS_NORMAL) { MCperror->add (PE_RESET_NOTYPE, sp); return PS_ERROR; } which = (Reset_type)te->which; return PS_NORMAL; }
// put [ unicode | binary ] <expr> // put [ unicode ] ( content | markup ) <expr> // put [ new ] header <expr> // put [ secure ] [ httponly ] cookie <name> [ for <path> ] [ on <domain> ] to <value> [ until <expiry> ] // put <expr> ( into | after | before ) message [ box ] // put <expr> ( into | after | before ) <chunk> // Parse_stat MCPut::parse(MCScriptPoint &sp) { Symbol_type type; const LT *te; initpoint(sp); // IM-2011-08-22: [[ SERVER ]] Add support for new put variant. // Parse: put [ secure ] [ httponly ] cookie <name> [ for path ] [ on domain ] with <value> [ until expires ] if (sp . skip_token(SP_SERVER, TT_SERVER, SK_SECURE) == PS_NORMAL) is_secure = true; if (sp . skip_token(SP_SERVER, TT_SERVER, SK_HTTPONLY) == PS_NORMAL) is_httponly = true; if (sp . skip_token(SP_SERVER, TT_PREP, PT_COOKIE) == PS_NORMAL) { prep = PT_COOKIE; if (sp . parseexp(True, False, &name) != PS_NORMAL) { MCperror->add(PE_PUT_BADEXP, sp); return PS_ERROR; } if (sp . skip_token(SP_REPEAT, TT_UNDEFINED, RF_FOR) == PS_NORMAL) { if (sp . parseexp(True, False, &path) != PS_NORMAL) { MCperror->add(PE_PUT_BADEXP, sp); return PS_ERROR; } } if (sp . skip_token(SP_FACTOR, TT_OF, PT_ON) == PS_NORMAL) { if (sp . parseexp(True, False, &domain) != PS_NORMAL) { MCperror->add(PE_PUT_BADEXP, sp); return PS_ERROR; } } sp . skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH); if (sp . parseexp(True, False, &source) != PS_NORMAL) { MCperror->add(PE_PUT_BADEXP, sp); return PS_ERROR; } if (sp . skip_token(SP_REPEAT, TT_UNDEFINED, RF_UNTIL) == PS_NORMAL) { if (sp . parseexp(True, False, &expires) != PS_NORMAL) { MCperror->add(PE_PUT_BADEXP, sp); return PS_ERROR; } } return PS_NORMAL; } if (is_secure || is_httponly) { MCperror->add(PE_PUT_BADPREP, sp); return PS_ERROR; } // MW-2011-06-22: [[ SERVER ]] Add support for new put variant. // Parse: put new header <expr> if (sp.skip_token(SP_SERVER, TT_SERVER, SK_NEW) == PS_NORMAL) { if (sp.skip_token(SP_SERVER, TT_PREP, PT_HEADER) == PS_NORMAL) { prep = PT_NEW_HEADER; if (sp . parseexp(False, True, &source) != PS_NORMAL) { MCperror->add(PE_PUT_BADEXP, sp); return PS_ERROR; } return PS_NORMAL; } else sp.backup(); } // MW-2012-02-23: [[ UnicodePut ]] Store whether 'unicode' was present // in the ast. if (sp . skip_token(SP_SERVER, TT_SERVER, SK_UNICODE) == PS_NORMAL) is_unicode = true; // MW-2011-06-22: [[ SERVER ]] Add support for new put variant. // Parse: put [ unicode ] ( header | content | markup ) <expr> if (sp.next(type) == PS_NORMAL) { if (sp.lookup(SP_SERVER, te) == PS_NORMAL && te -> type == TT_PREP) { prep = (Preposition_type)te -> which; if (is_unicode && (prep == PT_HEADER || prep == PT_BINARY)) { MCperror->add(PE_PUT_BADPREP, sp); return PS_ERROR; } if (sp . parseexp(False, True, &source) != PS_NORMAL) { MCperror->add(PE_PUT_BADEXP, sp); return PS_ERROR; } return PS_NORMAL; } else sp.backup(); } if (sp.parseexp(False, True, &source) != PS_NORMAL) { MCperror->add(PE_PUT_BADEXP, sp); return PS_ERROR; } if (sp.next(type) != PS_NORMAL) return PS_NORMAL; if (sp.lookup(SP_FACTOR, te) != PS_NORMAL || te->type != TT_PREP) { sp.backup(); return PS_NORMAL; } prep = (Preposition_type)te->which; if (prep != PT_BEFORE && prep != PT_INTO && prep != PT_AFTER) { MCperror->add(PE_PUT_BADPREP, sp); return PS_ERROR; } if (sp.skip_token(SP_SHOW, TT_UNDEFINED, SO_MESSAGE) == PS_NORMAL) { sp.skip_token(SP_SHOW, TT_UNDEFINED, SO_MESSAGE); // "box" return PS_NORMAL; } dest = new MCChunk(True); if (dest->parse(sp, False) != PS_NORMAL) { MCperror->add(PE_PUT_BADCHUNK, sp); return PS_ERROR; } MCVarref *t_src_ref, *t_dst_ref; t_src_ref = source -> getrootvarref(); t_dst_ref = dest -> getrootvarref(); overlap = t_src_ref != NULL && t_dst_ref != NULL && t_src_ref -> rootmatches(t_dst_ref); 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 MCMarking::parse(MCScriptPoint &sp) { Symbol_type type; const LT *te; initpoint(sp); if (sp.next(type) != PS_NORMAL) { MCperror->add (PE_MARK_NOCARDS, sp); return PS_ERROR; } if (sp.lookup(SP_MARK, te) != PS_NORMAL) { sp.backup(); card = new MCChunk(False); if (card->parse(sp, False) != PS_NORMAL) { MCperror->add (PE_MARK_NOTCARDS, sp); return PS_ERROR; } return PS_NORMAL; } if (te->which == MC_ALL) { if (sp.skip_token(SP_MARK, TT_UNDEFINED, MC_CARDS) != PS_NORMAL) { MCperror->add (PE_MARK_NOCARDS, sp); return PS_ERROR; } return PS_NORMAL; } if (te->which != MC_CARDS) { MCperror->add (PE_MARK_NOCARDS, sp); return PS_ERROR; } if (sp.next(type) != PS_NORMAL) { MCperror->add (PE_MARK_NOBYORWHERE, sp); return PS_ERROR; } if (sp.lookup(SP_MARK,te) != PS_NORMAL || te->which != MC_BY && te->which != MC_WHERE) { MCperror->add (PE_MARK_NOTBYORWHERE, sp); return PS_ERROR; } if (te->which == MC_WHERE) { if (sp.parseexp(False, True, &where) != PS_NORMAL) { MCperror->add (PE_MARK_BADWHEREEXP, sp); return PS_ERROR; } return PS_NORMAL; } if (sp.skip_token(SP_MARK, TT_UNDEFINED, MC_FINDING) != PS_NORMAL) { MCperror->add (PE_MARK_NOFINDING, sp); return PS_ERROR; } if (sp.next(type) != PS_NORMAL) { MCperror->add (PE_MARK_NOSTRING, sp); return PS_ERROR; } if (sp.lookup(SP_FIND, te) == PS_NORMAL) mode = (Find_mode)te->which; else sp.backup(); if (sp.parseexp(False, True, &tofind) != PS_NORMAL) { MCperror->add (PE_MARK_BADSTRING, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_IN) == PS_NORMAL) { field = new MCChunk(False); if (field->parse(sp, False) != PS_NORMAL) { MCperror->add (PE_MARK_BADFIELD, sp); return PS_ERROR; } } 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 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 MCLocaltoken::parse(MCScriptPoint &sp) { initpoint(sp); while (True) { Symbol_type type; Parse_stat stat = sp.next(type); if (stat == PS_EOL) return PS_NORMAL; const LT *te; MCExpression *newfact = NULL; if (stat != PS_NORMAL || type != ST_ID || sp.lookup(SP_FACTOR, te) != PS_NO_MATCH || sp.lookupconstant(&newfact) == PS_NORMAL) { delete newfact; MCperror->add(PE_LOCAL_BADNAME, sp); return PS_ERROR; } MCAutoNameRef t_token_name; /* UNCHECKED */ t_token_name . Clone(sp . gettoken_nameref()); MCExpression *e = NULL; MCVarref *v = NULL; if (sp.gethandler() == NULL) if (constant) sp.gethlist()->findconstant(t_token_name, &e); else sp.gethlist()->findvar(t_token_name, false, &v); else if (constant) sp.gethandler()->findconstant(t_token_name, &e); else sp.gethandler()->findvar(t_token_name, &v); if (e != NULL || v != NULL) { MCperror->add(PE_LOCAL_SHADOW, sp); delete v; delete e; return PS_ERROR; } MCVariable *tmp; for (tmp = MCglobals ; tmp != NULL ; tmp = tmp->getnext()) if (tmp -> hasname(t_token_name)) if (MCexplicitvariables) { MCperror->add(PE_LOCAL_SHADOW, sp); return PS_ERROR; } MCVarref *tvar = NULL; MCString init; bool initialised = false; if (sp.skip_token(SP_FACTOR, TT_BINOP, O_EQ) == PS_NORMAL) { if (sp.next(type) != PS_NORMAL || MCexplicitvariables && type != ST_LIT && type != ST_NUM) { if (constant) MCperror->add(PE_CONSTANT_BADINIT, sp); else MCperror->add(PE_LOCAL_BADINIT, sp); return PS_ERROR; } if (type == ST_MIN) { // negative initializer const char *sptr = sp.gettoken().getstring(); if (sp.next(type) != PS_NORMAL || type != ST_NUM) { if (constant) MCperror->add(PE_CONSTANT_BADINIT, sp); else MCperror->add(PE_LOCAL_BADINIT, sp); return PS_ERROR; } uint4 l = sp.gettoken().getstring() + sp.gettoken().getlength() - sptr; init.set(sptr, l); } else init = sp.gettoken(); initialised = true; } else if (constant) { MCperror->add(PE_CONSTANT_NOINIT, sp); return PS_ERROR; } else init = NULL; MCAutoNameRef t_init_name; if (initialised) /* UNCHECKED */ t_init_name . CreateWithOldString(init); else t_init_name . Clone(kMCEmptyName); if (sp.gethandler() == NULL) { if (constant) sp.gethlist()->newconstant(t_token_name, t_init_name); else if (sp.gethlist()->newvar(t_token_name, t_init_name, &tvar, initialised) != PS_NORMAL) { MCperror->add(PE_LOCAL_BADNAME, sp); return PS_ERROR; } } else if (constant) sp.gethandler()->newconstant(t_token_name, t_init_name); else if (sp.gethandler()->newvar(t_token_name, t_init_name, &tvar) != PS_NORMAL) { MCperror->add(PE_LOCAL_BADNAME, sp); return PS_ERROR; } delete tvar; switch (sp.next(type)) { case PS_NORMAL: if (type != ST_SEP) { MCperror->add(PE_STATEMENT_NOTSEP, sp); return PS_ERROR; } break; case PS_EOL: case PS_EOF: return PS_NORMAL; default: MCperror->add(PE_STATEMENT_NOTSEP, sp); return PS_ERROR; } } return PS_NORMAL; }
Parse_stat MCConvert::parsedtformat(MCScriptPoint &sp, Convert_form &firstform, Convert_form &secondform) { const LT *te; Symbol_type type; Boolean needformat = True; Convert_form localeform = CF_UNDEFINED; while (True) { if (sp.next(type) != PS_NORMAL) { if (needformat) { MCperror->add (PE_CONVERT_NOFORMAT, sp); return PS_ERROR; } else return PS_NORMAL; } if (sp.lookup(SP_CONVERT, te) != PS_NORMAL) { if (needformat) { MCperror->add (PE_CONVERT_NOTFORMAT, sp); return PS_ERROR; } else { sp.backup(); break; } } switch (te->which) { case CF_ABBREVIATED: case CF_SHORT: case CF_LONG: case CF_INTERNET: if (firstform == CF_UNDEFINED) firstform = (Convert_form)te->which; else secondform = (Convert_form)te->which; break; case CF_SYSTEM: case CF_ENGLISH: localeform = (Convert_form)te->which; break; case CF_DATE: case CF_TIME: if (firstform == CF_UNDEFINED) firstform = (Convert_form)(te->which + 1 + localeform); else if (firstform > CF_INTERNET) { if (secondform == CF_UNDEFINED) secondform = (Convert_form)(te->which + 1 + localeform); else { uint2 dummy = secondform; dummy += te->which + localeform; secondform = (Convert_form)dummy; } } else { uint2 dummy = firstform; dummy += te->which + localeform; firstform = (Convert_form)dummy; } needformat = False; break; default: firstform = (Convert_form)te->which; return PS_NORMAL; } if (sp.skip_token(SP_FACTOR, TT_BINOP, O_AND) == PS_NORMAL) { if (needformat) { MCperror->add (PE_CONVERT_BADAND, sp); return PS_ERROR; } else needformat = True; } else if (!needformat) break; } return PS_NORMAL; }
Parse_stat MCStatement::getparams(MCScriptPoint &sp, MCParameter **params) { Boolean needparam = False; MCParameter *pptr = NULL; while (True) { if (sp.skip_token(SP_COMMAND, TT_ELSE, S_UNDEFINED) == PS_NORMAL) { sp.backup(); return PS_NORMAL; } Symbol_type type; switch (sp.next(type)) { case PS_NORMAL: sp.backup(); break; case PS_ERROR: return PS_ERROR; case PS_EOL: case PS_EOF: if (needparam) { MCperror->add (PE_STATEMENT_BADPARAM, sp); return PS_ERROR; } return PS_NORMAL; default: sp.backup(); return PS_NORMAL; } MCParameter *newptr = new MCParameter; if (newptr->parse(sp) != PS_NORMAL) { delete newptr; MCperror->add (PE_STATEMENT_BADPARAM, sp); return PS_ERROR; } if (pptr == NULL) *params = pptr = newptr; else { pptr->setnext(newptr); pptr = newptr; } if (sp.skip_token(SP_COMMAND, TT_ELSE, S_UNDEFINED) == PS_NORMAL) { sp.backup(); return PS_NORMAL; } switch (sp.next(type)) { case PS_NORMAL: break; case PS_EOL: case PS_EOF: return PS_NORMAL; default: MCperror->add (PE_STATEMENT_NOTSEP, sp); return PS_ERROR; } if (type != ST_SEP) { MCperror->add (PE_STATEMENT_BADSEP, sp); return PS_ERROR; } needparam = True; } return PS_NORMAL; }
Parse_stat MCStatement::getmods(MCScriptPoint &sp, uint2 &mstate) { Symbol_type type; const LT *te; while (True) { if (sp.next(type) != PS_NORMAL) { MCperror->add (PE_STATEMENT_NOKEY, sp); return PS_ERROR; } if (sp.lookup(SP_FACTOR, te) != PS_NORMAL || te->type != TT_FUNCTION) { MCperror->add (PE_STATEMENT_BADKEY, sp); return PS_ERROR; } switch (te->which) { case F_COMMAND_KEY: mstate |= MS_CONTROL; break; case F_CONTROL_KEY: mstate |= MS_MAC_CONTROL; break; case F_OPTION_KEY: mstate |= MS_MOD1; break; case F_SHIFT_KEY: mstate |= MS_SHIFT; break; default: MCperror->add (PE_STATEMENT_BADKEY, sp); return PS_ERROR; } if (sp.skip_token(SP_COMMAND, TT_ELSE, S_UNDEFINED) == PS_NORMAL) { sp.backup(); return PS_NORMAL; } switch (sp.next(type)) { case PS_NORMAL: break; case PS_EOL: case PS_EOF: return PS_NORMAL; default: MCperror->add (PE_STATEMENT_BADSEP, sp); return PS_ERROR; } if (type != ST_SEP) { MCperror->add (PE_STATEMENT_BADSEP, sp); 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; }
Parse_stat MCArrayOp::parse(MCScriptPoint &sp) { initpoint(sp); Symbol_type type; // MW-2008-08-20: [[ Bug 6954 ]] Split/Combine don't work on array keys // MW-2011-06-22: [[ SERVER ]] Update to use SP findvar method to take into account // execution outwith a handler. if (sp.next(type) != PS_NORMAL || type != ST_ID || sp.findvar(sp.gettoken_nameref(), &destvar) != PS_NORMAL || destvar -> parsearray(sp) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_BADARRAY, sp); return PS_ERROR; } if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) != PS_NORMAL && sp.skip_token(SP_FACTOR, TT_PREP, PT_BY) != PS_NORMAL && sp.skip_token(SP_START, TT_UNDEFINED, SC_USING) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_NOWITH, sp); return PS_ERROR; } if (sp . next(type) == PS_NORMAL && type == ST_ID && (sp . gettoken() == "column" || sp . gettoken() == "row")) { if (sp . gettoken() == "column") mode = TYPE_COLUMN; else mode = TYPE_ROW; } else { sp.backup(); if (sp.parseexp(True, False, &element) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_BADEXP, sp); return PS_ERROR; } if (sp.skip_token(SP_FACTOR, TT_BINOP, O_AND) == PS_NORMAL) if (sp.parseexp(True, False, &key) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_BADEXP, sp); return PS_ERROR; } } if (sp . skip_token(SP_FACTOR, TT_PREP, PT_AS) == PS_NORMAL) { if (sp . skip_token(SP_COMMAND, TT_STATEMENT, S_SET) != PS_NORMAL || key != nil) { MCperror -> add(PE_ARRAYOP_BADFORM, sp); return PS_ERROR; } form = FORM_SET; } return PS_NORMAL; }
Parse_stat MCSetOp::parse(MCScriptPoint &sp) { initpoint(sp); if (op == kOpSymmetricDifference) { if (sp.skip_token(SP_COMMAND, TT_STATEMENT, S_DIFFERENCE) == PS_ERROR) { MCperror->add(PE_ARRAYOP_NODIFFERENCE, sp); return PS_ERROR; } } // MW-2011-06-22: [[ SERVER ]] Update to use SP findvar method to take into account // execution outwith a handler. MCerrorlock++; Symbol_type type; MCScriptPoint tsp(sp); if (sp.next(type) != PS_NORMAL || type != ST_ID || sp.findvar(sp.gettoken_nameref(), &(&destvar)) != PS_NORMAL || destvar -> parsearray(sp) != PS_NORMAL) { sp = tsp; MCerrorlock--; destvar.Reset(); if (sp.parseexp(False, True, &(&destexpr)) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_BADARRAY, sp); return PS_ERROR; } } else MCerrorlock--; if (sp.skip_token(SP_REPEAT, TT_UNDEFINED, RF_WITH) == PS_ERROR && sp.skip_token(SP_FACTOR, TT_PREP, PT_BY) == PS_ERROR) { MCperror->add(PE_ARRAYOP_NOWITH, sp); return PS_ERROR; } if (sp.parseexp(True, False, &(&source)) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_BADEXP, sp); return PS_ERROR; } // MERG-2013-08-26: [[ RecursiveArrayOp ]] Support nested arrays in union and intersect if (sp.skip_token(SP_SUGAR, TT_UNDEFINED, SG_RECURSIVELY) == PS_NORMAL) { if (op == kOpIntersect) op = kOpIntersectRecursively; else if (op == kOpUnion) op = kOpUnionRecursively; else { MCperror->add(PE_ARRAYOP_BADRECURSIVE, sp); return PS_ERROR; } } if (sp.skip_token(SP_FACTOR, TT_PREP, PT_INTO) == PS_NORMAL) { if (!destexpr) { destexpr.Reset(destvar.Release()); } Symbol_type ttype; if (sp.next(ttype) != PS_NORMAL || ttype != ST_ID || sp.findvar(sp.gettoken_nameref(), &(&destvar)) != PS_NORMAL || destvar -> parsearray(sp) != PS_NORMAL) { MCperror->add(PE_ARRAYOP_BADARRAY, sp); return PS_ERROR; } is_into = true; } if (!destvar && is_into) { MCperror->add(PE_ARRAYOP_DSTNOTCONTAINER, sp); return PS_ERROR; } return PS_NORMAL; }
Parse_stat MCStatement::gettargets(MCScriptPoint &sp, MCChunk **targets, Boolean forset) { Boolean needchunk = False; MCChunk *pptr = NULL; while (True) { if (sp.skip_token(SP_COMMAND, TT_ELSE, S_UNDEFINED) == PS_NORMAL) { sp.backup(); return PS_NORMAL; } Symbol_type type; switch (sp.next(type)) { case PS_NORMAL: sp.backup(); break; case PS_ERROR: return PS_ERROR; case PS_EOL: case PS_EOF: if (needchunk) { MCperror->add (PE_STATEMENT_BADCHUNK, sp); return PS_ERROR; } return PS_NORMAL; default: sp.backup(); return PS_NORMAL; } MCChunk *newptr = new MCChunk(forset); if (newptr->parse(sp, False) != PS_NORMAL) { delete newptr; MCperror->add (PE_STATEMENT_BADCHUNK, sp); return PS_ERROR; } if (pptr == NULL) *targets = pptr = newptr; else { pptr->next = newptr; pptr = pptr->next; } if (sp.skip_token(SP_COMMAND, TT_ELSE, S_UNDEFINED) == PS_NORMAL || sp.skip_token(SP_FACTOR, TT_TO, PT_TO) == PS_NORMAL) { sp.backup(); return PS_NORMAL; } switch (sp.skip_token(SP_FACTOR, TT_BINOP, O_AND)) { case PS_NORMAL: break; case PS_EOL: case PS_EOF: return PS_NORMAL; default: MCperror->add (PE_STATEMENT_NOTAND, sp); return PS_ERROR; } needchunk = True; } return PS_NORMAL; }