diff --git a/cig.h b/cig.h index 306086b..073e45c 100644 --- a/cig.h +++ b/cig.h @@ -293,15 +293,8 @@ typedef union scan_value { char *string_literal; } scan_value_t; -typedef enum scan_result_type { - scan_result_type_value, - scan_result_type_error, - scan_result_type_none, - count_scan_result_type -} scan_result_type_t; - typedef struct scan_result { - scan_result_type_t type; + bool ok; union { scan_value_t value; scan_error_t error; @@ -317,8 +310,12 @@ typedef struct scanner { scanner_t make_scanner(char const *name, char const *buffer, allocator_t allocator); void scanner_recover(scanner_t *s); -scan_result_t scanner_error(scanner_t *s, char const *message); -void scanner_error_and_recover(scanner_t *s, char const *message); +scan_result_t scan_error(scanner_t *s, char const *message); + +scan_result_t scan_value_func(scan_value_t value); +#define scan_value(arg) scan_value_func((scan_value_t){arg}) + +scan_result_t scan_error_and_recover(scanner_t *s, char const *message); bool scan_eof(scanner_t *s); bool scan_literal(scanner_t *s, char const *lit); int scan_repeat_literal(scanner_t *s, char const *lit); diff --git a/scanner.c b/scanner.c index 953202f..a9b4f95 100644 --- a/scanner.c +++ b/scanner.c @@ -22,7 +22,7 @@ void scanner_recover(scanner_t *s) { s->cur++; // move *past* the newline } -scan_result_t scanner_error(scanner_t *s, char const * message) { +scan_result_t scan_error(scanner_t *s, char const * message) { char const *error_pos = s->cur; // use current scanner position // Compute line + column (1-based) int line = 1, column = 1; @@ -32,7 +32,7 @@ scan_result_t scanner_error(scanner_t *s, char const * message) { } return (scan_result_t) { - .type=scan_result_type_error, + .ok=false, .error=(scan_error_t) { .message=message, .buffer_name=s->name, @@ -43,9 +43,17 @@ scan_result_t scanner_error(scanner_t *s, char const * message) { } -void scanner_error_and_recover(scanner_t *s, char const *message) { - scanner_error(s, message); +scan_result_t scan_value_func(scan_value_t value) { + return (scan_result_t) { + .ok=true, + .value=value, + }; +} + +scan_result_t scan_error_and_recover(scanner_t *s, char const *message) { + scan_result_t result = scan_error(s, message); scanner_recover(s); + return result; } bool scan_eof(scanner_t *s) { @@ -81,16 +89,9 @@ bool scan_whitespace(scanner_t *s) { scan_result_t scan_digit(scanner_t *s) { if (!isdigit((unsigned char)*s->cur)) { - return (scan_result_t){ - .type=scan_result_type_none, - }; + return scan_error(s, "not a digit"); } - scan_result_t ret = (scan_result_t){ - .type=scan_result_type_value, - .value=(scan_value_t){ - .digit=(*s->cur) - '0' - } - }; + scan_result_t ret = scan_value(.digit=(*s->cur) - '0'); s->cur++; return ret; } @@ -100,10 +101,7 @@ scan_result_t scan_i64(scanner_t *s) { if (*s->cur == '-' || *s->cur == '+') s->cur++; if (!isdigit((unsigned char)*s->cur)) { s->cur = save; - return (scan_result_t) { - .type=scan_result_type_none, - }; - // TODO: make macros for each of the scan_result_t types. + return scan_error(s, "not an i64"); } s->cur = save; char *end; @@ -111,58 +109,52 @@ scan_result_t scan_i64(scanner_t *s) { int64_t val = strtoll(s->cur, &end, 10); if (end == s->cur) { s->cur = save; - return (scan_result_t){ - .type=scan_result_type_none, - }; + return scan_error(s, "not an i64"); } if (errno == ERANGE) { - return scanner_error(s, "integer does not fit in i64 value"); + return scan_error(s, "integer does not fit in i64 value"); } s->cur = end; - s->value.i64 = val; - return true; + return scan_value(.i64=val); } -bool scan_i32(scanner_t *s) { - if (!scan_i64(s)) { - return false; +scan_result_t scan_i32(scanner_t *s) { + scan_result_t result = scan_i64(s); + if (!result.ok) { + return result; } - int32_t val = (int32_t)s->value.i64; + int32_t val = (int32_t)result.value.i64; int64_t back = (int64_t)val; - if (back != s->value.i64) { - scanner_error(s, "int does not fit in i32 value"); - return false; + if (back != result.value.i64) { + return scan_error(s, "int does not fit in i32 value"); } - s->value.i32 = val; - return true; + return scan_value(val); } -bool scan_i16(scanner_t *s) { - if (!scan_i64(s)) { - return false; +scan_result_t scan_i16(scanner_t *s) { + scan_result_t result = scan_i64(s); + if (!result.ok) { + return result; } - int16_t val = (int16_t)s->value.i64; + int16_t val = (int16_t)result.value.i64; int64_t back = (int64_t)val; - if (back != s->value.i64) { - scanner_error(s, "int does not fit in i16 value"); - return false; + if (back != result.value.i64) { + return scan_error(s, "int does not fit in i16 value"); } - s->value.i16 = val; - return true; + return scan_value(val); } -bool scan_i8(scanner_t *s) { - if (!scan_i64(s)) { - return false; +scan_result_t scan_i8(scanner_t *s) { + scan_result_t result = scan_i64(s); + if (!result.ok) { + return result; } - int8_t val = (int8_t)s->value.i64; + int8_t val = (int8_t)result.value.i64; int64_t back = (int64_t)val; - if (back != s->value.i64) { - scanner_error(s, "int does not fit in i8 value"); - return false; + if (back != result.value.i64) { + return scan_error(s, "int does not fit in i8 value"); } - s->value.i8 = val; - return true; + return scan_value(val); } bool scan_u64(scanner_t *s) {