diff options
| -rw-r--r-- | engines/glk/adrift/scexpr.cpp | 272 | 
1 files changed, 135 insertions, 137 deletions
| diff --git a/engines/glk/adrift/scexpr.cpp b/engines/glk/adrift/scexpr.cpp index 2375b5e5a7..0f4c2be4ce 100644 --- a/engines/glk/adrift/scexpr.cpp +++ b/engines/glk/adrift/scexpr.cpp @@ -22,6 +22,7 @@  #include "glk/adrift/scare.h"  #include "glk/adrift/scprotos.h" +#include "glk/jumps.h"  namespace Glk {  namespace Adrift { @@ -545,16 +546,12 @@ static sc_int expr_eval_abs(sc_int value) {  	return value < 0 ? -value : value;  } - -/* Parse error jump buffer. */ -static jmp_buf expr_parse_error; -  /* - * expr_eval_action() + * expr_eval_action   *   * Evaluate the effect of a token into the values stack.   */ -static void expr_eval_action(sc_int token) { +static void expr_eval_action(CONTEXT, sc_int token) {  	sc_vartype_t token_value;  	switch (token) { @@ -577,7 +574,7 @@ static void expr_eval_action(sc_int token) {  		if (!var_get(expr_varset, token_value.string, &type, &vt_rvalue)) {  			sc_error("expr_eval_action:"  			         " undefined variable, %s\n", token_value.string); -			longjmp(expr_parse_error, 1); +			LONG_JUMP;  		}  		switch (type) {  		case VAR_INTEGER: @@ -1044,23 +1041,23 @@ static void expr_eval_action(sc_int token) {  static sc_int expr_parse_lookahead = TOK_NONE;  /* Forward declaration of factor parsers and string expression parser. */ -static void expr_parse_numeric_factor(void); -static void expr_parse_string_factor(void); -static void expr_parse_string_expr(void); +static void expr_parse_numeric_factor(CONTEXT); +static void expr_parse_string_factor(CONTEXT); +static void expr_parse_string_expr(CONTEXT);  /* - * expr_parse_match() + * expr_parse_match   *   * Match a token to the lookahead, then advance lookahead.   */ -static void expr_parse_match(sc_int token) { +static void expr_parse_match(CONTEXT, sc_int token) {  	if (expr_parse_lookahead == token)  		expr_parse_lookahead = expr_next_token();  	else {  		/* Syntax error. */  		sc_error("expr_parse_match: syntax error,"  		         " expected %ld, got %ld\n", expr_parse_lookahead, token); -		longjmp(expr_parse_error, 1); +		LONG_JUMP;  	}  } @@ -1143,14 +1140,14 @@ static int expr_parse_contains_token(const sc_precedence_entry_t *entry, sc_int   * to match tokens, then decide whether, and how, to recurse into itself, or   * whether to parse a highest-precedence factor.   */ -static void expr_parse_numeric_element(sc_int precedence) { +static void expr_parse_numeric_element(CONTEXT, sc_int precedence) {  	const sc_precedence_entry_t *entry;  	/* See if the level passed in has listed tokens. */  	entry = PRECEDENCE_TABLE + precedence;  	if (entry->token_count == 0) {  		/* Precedence levels that hit the table end are factors. */ -		expr_parse_numeric_factor(); +		CALL0(expr_parse_numeric_factor);  		return;  	} @@ -1158,27 +1155,27 @@ static void expr_parse_numeric_element(sc_int precedence) {  	 * Parse initial higher-precedence factor, then others that associate  	 * with the given level.  	 */ -	expr_parse_numeric_element(precedence + 1); +	CALL1(expr_parse_numeric_element, precedence + 1);  	while (expr_parse_contains_token(entry, expr_parse_lookahead)) {  		sc_int token;  		/* Note token and match, parse next level, then action this token. */  		token = expr_parse_lookahead; -		expr_parse_match(token); -		expr_parse_numeric_element(precedence + 1); -		expr_eval_action(token); +		CALL1(expr_parse_match, token); +		CALL1(expr_parse_numeric_element, precedence + 1); +		CALL1(expr_eval_action, token);  	}  }  /* - * expr_parse_numeric_expr() + * expr_parse_numeric_expr   *   * Parse a complete numeric (sub-)expression.   */ -static void expr_parse_numeric_expr(void) { +static void expr_parse_numeric_expr(CONTEXT) {  	/* Call the parser of the lowest precedence operators. */ -	expr_parse_numeric_element(0); +	CALL1(expr_parse_numeric_element, 0);  } @@ -1187,30 +1184,30 @@ static void expr_parse_numeric_expr(void) {   *   * Parse a numeric expression factor.   */ -static void expr_parse_numeric_factor(void) { +static void expr_parse_numeric_factor(CONTEXT) {  	/* Handle factors based on lookahead token. */  	switch (expr_parse_lookahead) {  	/* Handle straightforward factors first. */  	case TOK_LPAREN: -		expr_parse_match(TOK_LPAREN); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_RPAREN); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_RPAREN);  		break;  	case TOK_UMINUS: -		expr_parse_match(TOK_UMINUS); -		expr_parse_numeric_factor(); -		expr_eval_action(TOK_UMINUS); +		CALL1(expr_parse_match, TOK_UMINUS); +		CALL0(expr_parse_numeric_factor); +		CALL1(expr_eval_action, TOK_UMINUS);  		break;  	case TOK_UPLUS: -		expr_parse_match(TOK_UPLUS); -		expr_parse_numeric_factor(); +		CALL1(expr_parse_match, TOK_UPLUS); +		CALL0(expr_parse_numeric_factor);  		break;  	case TOK_INTEGER: -		expr_eval_action(TOK_INTEGER); -		expr_parse_match(TOK_INTEGER); +		CALL1(expr_eval_action, TOK_INTEGER); +		CALL1(expr_parse_match, TOK_INTEGER);  		break;  	case TOK_VARIABLE: { @@ -1221,51 +1218,51 @@ static void expr_parse_numeric_factor(void) {  		if (!var_get(expr_varset, token_value.string, &type, &vt_rvalue)) {  			sc_error("expr_parse_numeric_factor:"  			         " undefined variable, %s\n", token_value.string); -			longjmp(expr_parse_error, 1); +			LONG_JUMP;  		}  		if (type != VAR_INTEGER) {  			sc_error("expr_parse_numeric_factor:"  			         " string variable in numeric context, %s\n",  			         token_value.string); -			longjmp(expr_parse_error, 1); +			LONG_JUMP;  		} -		expr_eval_action(TOK_VARIABLE); -		expr_parse_match(TOK_VARIABLE); +		CALL1(expr_eval_action, TOK_VARIABLE); +		CALL1(expr_parse_match, TOK_VARIABLE);  		break;  	}  	/* Handle functions as factors. */  	case TOK_ABS:  		/* Parse as "abs (val)". */ -		expr_parse_match(TOK_ABS); -		expr_parse_match(TOK_LPAREN); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(TOK_ABS); +		CALL1(expr_parse_match, TOK_ABS); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, TOK_ABS);  		break;  	case TOK_IF:  		/* Parse as "if (boolean, val1, val2)". */ -		expr_parse_match(TOK_IF); -		expr_parse_match(TOK_LPAREN); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_COMMA); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_COMMA); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(TOK_IF); +		CALL1(expr_parse_match, TOK_IF); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_COMMA); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_COMMA); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, TOK_IF);  		break;  	case TOK_RANDOM:  		/* Parse as "random (low, high)". */ -		expr_parse_match(TOK_RANDOM); -		expr_parse_match(TOK_LPAREN); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_COMMA); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(TOK_RANDOM); +		CALL1(expr_parse_match, TOK_RANDOM); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_COMMA); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, TOK_RANDOM);  		break;  	case TOK_MAX: @@ -1277,64 +1274,64 @@ static void expr_parse_numeric_factor(void) {  		/* Match up the function name and opening parenthesis. */  		token = expr_parse_lookahead; -		expr_parse_match(token); -		expr_parse_match(TOK_LPAREN); +		CALL1(expr_parse_match, token); +		CALL1(expr_parse_match, TOK_LPAREN);  		/* Count variable number of arguments as they are stacked. */ -		expr_parse_numeric_expr(); +		CALL0(expr_parse_numeric_expr);  		argument_count = 1;  		while (expr_parse_lookahead == TOK_COMMA) { -			expr_parse_match(TOK_COMMA); -			expr_parse_numeric_expr(); +			CALL1(expr_parse_match, TOK_COMMA); +			CALL0(expr_parse_numeric_expr);  			argument_count++;  		} -		expr_parse_match(TOK_RPAREN); +		CALL1(expr_parse_match, TOK_RPAREN);  		/* Push additional value -- the count of arguments. */  		expr_eval_push_integer(argument_count); -		expr_eval_action(token); +		CALL1(expr_eval_action, token);  		break;  	}  	case TOK_INSTR:  		/* Parse as "instr (val1, val2)". */ -		expr_parse_match(TOK_INSTR); -		expr_parse_match(TOK_LPAREN); -		expr_parse_string_expr(); -		expr_parse_match(TOK_COMMA); -		expr_parse_string_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(TOK_INSTR); +		CALL1(expr_parse_match, TOK_INSTR); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_string_expr); +		CALL1(expr_parse_match, TOK_COMMA); +		CALL0(expr_parse_string_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, TOK_INSTR);  		break;  	case TOK_LEN:  		/* Parse as "len (val)". */ -		expr_parse_match(TOK_LEN); -		expr_parse_match(TOK_LPAREN); -		expr_parse_string_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(TOK_LEN); +		CALL1(expr_parse_match, TOK_LEN); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_string_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, TOK_LEN);  		break;  	case TOK_VAL:  		/* Parse as "val (val)". */ -		expr_parse_match(TOK_VAL); -		expr_parse_match(TOK_LPAREN); -		expr_parse_string_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(TOK_VAL); +		CALL1(expr_parse_match, TOK_VAL); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_string_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, TOK_VAL);  		break;  	case TOK_IDENT:  		/* Unrecognized function-type token. */  		sc_error("expr_parse_numeric_factor: syntax error, unknown ident\n"); -		longjmp(expr_parse_error, 1); +		LONG_JUMP;  	default:  		/* Syntax error. */  		sc_error("expr_parse_numeric_factor:"  		         " syntax error, unexpected token, %ld\n", expr_parse_lookahead); -		longjmp(expr_parse_error, 1); +		LONG_JUMP;  	}  } @@ -1344,17 +1341,17 @@ static void expr_parse_numeric_factor(void) {   *   * Parse a complete string (sub-)expression.   */ -static void expr_parse_string_expr(void) { +static void expr_parse_string_expr(CONTEXT) {  	/*  	 * Parse a string factor, then all repeated concatenations.  Because the '+'  	 * and '&' are context sensitive, we have to invent/translate them into the  	 * otherwise unused TOK_CONCATENATE for evaluation.  	 */ -	expr_parse_string_factor(); +	CALL0(expr_parse_string_factor);  	while (expr_parse_lookahead == TOK_AND || expr_parse_lookahead == TOK_ADD) { -		expr_parse_match(expr_parse_lookahead); -		expr_parse_string_factor(); -		expr_eval_action(TOK_CONCATENATE); +		CALL1(expr_parse_match, expr_parse_lookahead); +		CALL0(expr_parse_string_factor); +		CALL1(expr_eval_action, TOK_CONCATENATE);  	}  } @@ -1364,19 +1361,19 @@ static void expr_parse_string_expr(void) {   *   * Parse a string expression factor.   */ -static void expr_parse_string_factor(void) { +static void expr_parse_string_factor(CONTEXT) {  	/* Handle factors based on lookahead token. */  	switch (expr_parse_lookahead) {  	/* Handle straightforward factors first. */  	case TOK_LPAREN: -		expr_parse_match(TOK_LPAREN); -		expr_parse_string_expr(); -		expr_parse_match(TOK_RPAREN); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_string_expr); +		CALL1(expr_parse_match, TOK_RPAREN);  		break;  	case TOK_STRING: -		expr_eval_action(TOK_STRING); -		expr_parse_match(TOK_STRING); +		CALL1(expr_eval_action, TOK_STRING); +		CALL1(expr_parse_match, TOK_STRING);  		break;  	case TOK_VARIABLE: { @@ -1387,16 +1384,16 @@ static void expr_parse_string_factor(void) {  		if (!var_get(expr_varset, token_value.string, &type, &vt_rvalue)) {  			sc_error("expr_parse_string_factor:"  			         " undefined variable, %s\n", token_value.string); -			longjmp(expr_parse_error, 1); +			LONG_JUMP;  		}  		if (type != VAR_STRING) {  			sc_error("expr_parse_string_factor:"  			         " numeric variable in string context, %s\n",  			         token_value.string); -			longjmp(expr_parse_error, 1); +			LONG_JUMP;  		} -		expr_eval_action(TOK_VARIABLE); -		expr_parse_match(TOK_VARIABLE); +		CALL1(expr_eval_action, TOK_VARIABLE); +		CALL1(expr_parse_match, TOK_VARIABLE);  		break;  	} @@ -1409,11 +1406,11 @@ static void expr_parse_string_factor(void) {  		sc_int token;  		token = expr_parse_lookahead; -		expr_parse_match(token); -		expr_parse_match(TOK_LPAREN); -		expr_parse_string_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(token); +		CALL1(expr_parse_match, token); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_string_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, token);  		break;  	} @@ -1424,48 +1421,48 @@ static void expr_parse_string_factor(void) {  		sc_int token;  		token = expr_parse_lookahead; -		expr_parse_match(token); -		expr_parse_match(TOK_LPAREN); -		expr_parse_string_expr(); -		expr_parse_match(TOK_COMMA); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(token); +		CALL1(expr_parse_match, token); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_string_expr); +		CALL1(expr_parse_match, TOK_COMMA); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, token);  		break;  	}  	case TOK_MID:  		/* Parse as "mid (text,start,length)". */ -		expr_parse_match(TOK_MID); -		expr_parse_match(TOK_LPAREN); -		expr_parse_string_expr(); -		expr_parse_match(TOK_COMMA); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_COMMA); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(TOK_MID); +		CALL1(expr_parse_match, TOK_MID); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_string_expr); +		CALL1(expr_parse_match, TOK_COMMA); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_COMMA); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, TOK_MID);  		break;  	case TOK_STR:  		/* Parse as "str (val)". */ -		expr_parse_match(TOK_STR); -		expr_parse_match(TOK_LPAREN); -		expr_parse_numeric_expr(); -		expr_parse_match(TOK_RPAREN); -		expr_eval_action(TOK_STR); +		CALL1(expr_parse_match, TOK_STR); +		CALL1(expr_parse_match, TOK_LPAREN); +		CALL0(expr_parse_numeric_expr); +		CALL1(expr_parse_match, TOK_RPAREN); +		CALL1(expr_eval_action, TOK_STR);  		break;  	case TOK_IDENT:  		/* Unrecognized function-type token. */  		sc_error("expr_parse_string_factor: syntax error, unknown ident\n"); -		longjmp(expr_parse_error, 1); +		LONG_JUMP;  	default:  		/* Syntax error. */  		sc_error("expr_parse_string_factor:"  		         " syntax error, unexpected token, %ld\n", expr_parse_lookahead); -		longjmp(expr_parse_error, 1); +		LONG_JUMP;  	}  } @@ -1479,21 +1476,22 @@ static void expr_parse_string_factor(void) {  static sc_bool expr_evaluate_expression(const sc_char *expression, sc_var_setref_t vars,  		sc_int assign_type, sc_vartype_t *vt_rvalue) {  	assert(assign_type == VAR_INTEGER || assign_type == VAR_STRING); +	Context context;  	/* Reset values stack and start tokenizer. */  	expr_eval_start(vars);  	expr_tokenize_start(expression); -	/* Try parsing an expression, and catch errors. */ -	if (setjmp(expr_parse_error) == 0) { -		/* Parse an expression, and ensure it ends at string end. */ -		expr_parse_lookahead = expr_next_token(); -		if (assign_type == VAR_STRING) -			expr_parse_string_expr(); -		else -			expr_parse_numeric_expr(); -		expr_parse_match(TOK_EOS); -	} else { +	// Try parsing an expression, and ensure it ends at string end. */ +	expr_parse_lookahead = expr_next_token(); +	if (assign_type == VAR_STRING) +		expr_parse_string_expr(context); +	else +		expr_parse_numeric_expr(context); +	if (!context._break) +		expr_parse_match(context, TOK_EOS); + +	if (context._break) {  		/* Parse error -- clean up tokenizer, collect garbage, and fail. */  		expr_tokenize_end();  		expr_eval_garbage_collect(); | 
