some progress
some progress
This commit is contained in:
@@ -293,15 +293,8 @@ typedef union scan_value {
|
|||||||
char *string_literal;
|
char *string_literal;
|
||||||
} scan_value_t;
|
} 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 {
|
typedef struct scan_result {
|
||||||
scan_result_type_t type;
|
bool ok;
|
||||||
union {
|
union {
|
||||||
scan_value_t value;
|
scan_value_t value;
|
||||||
scan_error_t error;
|
scan_error_t error;
|
||||||
@@ -317,8 +310,12 @@ typedef struct scanner {
|
|||||||
|
|
||||||
scanner_t make_scanner(char const *name, char const *buffer, allocator_t allocator);
|
scanner_t make_scanner(char const *name, char const *buffer, allocator_t allocator);
|
||||||
void scanner_recover(scanner_t *s);
|
void scanner_recover(scanner_t *s);
|
||||||
scan_result_t scanner_error(scanner_t *s, char const *message);
|
scan_result_t scan_error(scanner_t *s, char const *message);
|
||||||
void scanner_error_and_recover(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_eof(scanner_t *s);
|
||||||
bool scan_literal(scanner_t *s, char const *lit);
|
bool scan_literal(scanner_t *s, char const *lit);
|
||||||
int scan_repeat_literal(scanner_t *s, char const *lit);
|
int scan_repeat_literal(scanner_t *s, char const *lit);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ void scanner_recover(scanner_t *s) {
|
|||||||
s->cur++; // move *past* the newline
|
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
|
char const *error_pos = s->cur; // use current scanner position
|
||||||
// Compute line + column (1-based)
|
// Compute line + column (1-based)
|
||||||
int line = 1, column = 1;
|
int line = 1, column = 1;
|
||||||
@@ -32,7 +32,7 @@ scan_result_t scanner_error(scanner_t *s, char const * message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (scan_result_t) {
|
return (scan_result_t) {
|
||||||
.type=scan_result_type_error,
|
.ok=false,
|
||||||
.error=(scan_error_t) {
|
.error=(scan_error_t) {
|
||||||
.message=message,
|
.message=message,
|
||||||
.buffer_name=s->name,
|
.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) {
|
scan_result_t scan_value_func(scan_value_t value) {
|
||||||
scanner_error(s, message);
|
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);
|
scanner_recover(s);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_eof(scanner_t *s) {
|
bool scan_eof(scanner_t *s) {
|
||||||
@@ -81,16 +89,9 @@ bool scan_whitespace(scanner_t *s) {
|
|||||||
|
|
||||||
scan_result_t scan_digit(scanner_t *s) {
|
scan_result_t scan_digit(scanner_t *s) {
|
||||||
if (!isdigit((unsigned char)*s->cur)) {
|
if (!isdigit((unsigned char)*s->cur)) {
|
||||||
return (scan_result_t){
|
return scan_error(s, "not a digit");
|
||||||
.type=scan_result_type_none,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
scan_result_t ret = (scan_result_t){
|
scan_result_t ret = scan_value(.digit=(*s->cur) - '0');
|
||||||
.type=scan_result_type_value,
|
|
||||||
.value=(scan_value_t){
|
|
||||||
.digit=(*s->cur) - '0'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
s->cur++;
|
s->cur++;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -100,10 +101,7 @@ scan_result_t scan_i64(scanner_t *s) {
|
|||||||
if (*s->cur == '-' || *s->cur == '+') s->cur++;
|
if (*s->cur == '-' || *s->cur == '+') s->cur++;
|
||||||
if (!isdigit((unsigned char)*s->cur)) {
|
if (!isdigit((unsigned char)*s->cur)) {
|
||||||
s->cur = save;
|
s->cur = save;
|
||||||
return (scan_result_t) {
|
return scan_error(s, "not an i64");
|
||||||
.type=scan_result_type_none,
|
|
||||||
};
|
|
||||||
// TODO: make macros for each of the scan_result_t types.
|
|
||||||
}
|
}
|
||||||
s->cur = save;
|
s->cur = save;
|
||||||
char *end;
|
char *end;
|
||||||
@@ -111,70 +109,63 @@ scan_result_t scan_i64(scanner_t *s) {
|
|||||||
int64_t val = strtoll(s->cur, &end, 10);
|
int64_t val = strtoll(s->cur, &end, 10);
|
||||||
if (end == s->cur) {
|
if (end == s->cur) {
|
||||||
s->cur = save;
|
s->cur = save;
|
||||||
return (scan_result_t){
|
return scan_error(s, "not an i64");
|
||||||
.type=scan_result_type_none,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if (errno == ERANGE) {
|
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->cur = end;
|
||||||
s->value.i64 = val;
|
return scan_value(.i64=val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_i32(scanner_t *s) {
|
scan_result_t scan_i32(scanner_t *s) {
|
||||||
if (!scan_i64(s)) {
|
scan_result_t result = scan_i64(s);
|
||||||
return false;
|
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;
|
int64_t back = (int64_t)val;
|
||||||
if (back != s->value.i64) {
|
if (back != result.value.i64) {
|
||||||
scanner_error(s, "int does not fit in i32 value");
|
return scan_error(s, "int does not fit in i32 value");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
s->value.i32 = val;
|
return scan_value(val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_i16(scanner_t *s) {
|
scan_result_t scan_i16(scanner_t *s) {
|
||||||
if (!scan_i64(s)) {
|
scan_result_t result = scan_i64(s);
|
||||||
return false;
|
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;
|
int64_t back = (int64_t)val;
|
||||||
if (back != s->value.i64) {
|
if (back != result.value.i64) {
|
||||||
scanner_error(s, "int does not fit in i16 value");
|
return scan_error(s, "int does not fit in i16 value");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
s->value.i16 = val;
|
return scan_value(val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_i8(scanner_t *s) {
|
scan_result_t scan_i8(scanner_t *s) {
|
||||||
if (!scan_i64(s)) {
|
scan_result_t result = scan_i64(s);
|
||||||
return false;
|
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;
|
int64_t back = (int64_t)val;
|
||||||
if (back != s->value.i64) {
|
if (back != result.value.i64) {
|
||||||
scanner_error(s, "int does not fit in i8 value");
|
return scan_error(s, "int does not fit in i8 value");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
s->value.i8 = val;
|
return scan_value(val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_u64(scanner_t *s) {
|
scan_result_t scan_u64(scanner_t *s) {
|
||||||
char const *save = s->cur;
|
char const *save = s->cur;
|
||||||
if (*s->cur == '-') {
|
if (*s->cur == '-') {
|
||||||
scanner_error(s, "- is not allowed for unsigned integers");
|
return scan_error(s, "- is not allowed for unsigned integers");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (*s->cur == '+') s->cur++;
|
if (*s->cur == '+') s->cur++;
|
||||||
if (!isdigit((unsigned char)*s->cur)) {
|
if (!isdigit((unsigned char)*s->cur)) {
|
||||||
s->cur = save;
|
s->cur = save;
|
||||||
return false;
|
return scan_error(s, "is not number");
|
||||||
}
|
}
|
||||||
s->cur = save;
|
s->cur = save;
|
||||||
char *end;
|
char *end;
|
||||||
@@ -182,57 +173,53 @@ bool scan_u64(scanner_t *s) {
|
|||||||
uint64_t val = strtoull(s->cur, &end, 10);
|
uint64_t val = strtoull(s->cur, &end, 10);
|
||||||
if (end == s->cur) {
|
if (end == s->cur) {
|
||||||
s->cur = save;
|
s->cur = save;
|
||||||
return false;
|
return scan_error(s, "is not number");
|
||||||
|
// TODO: standardize error messages
|
||||||
}
|
}
|
||||||
if (errno == ERANGE) {
|
if (errno == ERANGE) {
|
||||||
scanner_error(s, "integer does not fit in u64 value");
|
return scan_error(s, "integer does not fit in u64 value");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
s->cur = end;
|
s->cur = end;
|
||||||
s->value.u64 = val;
|
return scan_value(.u64=val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_u32(scanner_t *s) {
|
scan_result_t scan_u32(scanner_t *s) {
|
||||||
if (!scan_u64(s)) {
|
scan_result_t result = scan_u64(s);
|
||||||
return false;
|
if (!result.ok) {
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
uint32_t val = (uint32_t)s->value.u64;
|
uint32_t val = (uint32_t)result.value.u64;
|
||||||
uint64_t back = (uint64_t)val;
|
uint64_t back = (uint64_t)val;
|
||||||
if (back != s->value.u64) {
|
if (back != result.value.u64) {
|
||||||
scanner_error(s, "int does not fit in u32 value");
|
return scan_error(s, "int does not fit in u32 value");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
s->value.u32 = val;
|
return scan_value(val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_u16(scanner_t *s) {
|
scan_result_t scan_u16(scanner_t *s) {
|
||||||
if (!scan_u64(s)) {
|
scan_result_t result = scan_u64(s);
|
||||||
return false;
|
if (!result.ok) {
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
uint16_t val = (uint16_t)s->value.u64;
|
uint16_t val = (uint16_t)result.value.u64;
|
||||||
uint64_t back = (uint64_t)val;
|
uint64_t back = (uint64_t)val;
|
||||||
if (back != s->value.u64) {
|
if (back != result.value.u64) {
|
||||||
scanner_error(s, "int does not fit in u16 value");
|
return scan_error(s, "int does not fit in u16 value");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
s->value.u16 = val;
|
return scan_value(val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_u8(scanner_t *s) {
|
scan_result_t scan_u8(scanner_t *s) {
|
||||||
if (!scan_u64(s)) {
|
scan_result_t result = scan_u64(s);
|
||||||
return false;
|
if (!result.ok) {
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
uint8_t val = (uint8_t)s->value.u64;
|
uint8_t val = (uint8_t)result.value.u64;
|
||||||
uint64_t back = (uint64_t)val;
|
uint64_t back = (uint64_t)val;
|
||||||
if (back != s->value.u64) {
|
if (back != result.value.u64) {
|
||||||
scanner_error(s, "int does not fit in u8 value");
|
return scan_error(s, "int does not fit in u8 value");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
s->value.u8 = val;
|
return scan_value(val);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_f64(scanner_t *s) {
|
bool scan_f64(scanner_t *s) {
|
||||||
|
|||||||
Reference in New Issue
Block a user