aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2019-09-22 22:37:10 -0700
committerPaul Gilbert2019-09-25 20:13:27 -0700
commit1e483ec0f50a430598f5f76f59338d74f67b20f5 (patch)
tree174f9dcb52bf50c47860e9b9336a71a283cec0c7
parenta401ccc61e5f70350152bccc05e45c68520d845d (diff)
downloadscummvm-rg350-1e483ec0f50a430598f5f76f59338d74f67b20f5.tar.gz
scummvm-rg350-1e483ec0f50a430598f5f76f59338d74f67b20f5.tar.bz2
scummvm-rg350-1e483ec0f50a430598f5f76f59338d74f67b20f5.zip
GLK: ADRIFT: Refactor tokenizer to not use longjmp
-rw-r--r--engines/glk/adrift/scexpr.cpp272
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();