예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}