working my way through unfucking the fuckery

This commit is contained in:
2026-03-26 19:01:56 +01:00
parent 9e99293c56
commit f0d7f0ecb6
+49 -15
View File
@@ -22,50 +22,84 @@ void scan_next_line(scan_t *s) {
s->cur++; // move *past* the newline s->cur++; // move *past* the newline
} }
scan_error_t scan_error(const scan_t *s, const char *message) {
const char *error_pos = s->cur; // use current scanner position
// Compute line + column (1-based)
int line = 1, col = 1;
for (const char *p = s->start; p < error_pos; p++) {
if (*p == '\n') { line++; col = 1; }
else col++;
}
return (scan_error_t) {
.filename = s->name,
.line = line,
.column = col,
.error_message = message
};
// TODO: probably do not need an allocator for a scanner?
}
scan_result_t scan_eof(scan_t *s) { scan_result_t scan_eof(scan_t *s) {
return (scan_result_t) { return (scan_result_t) {
.ok=*s->cur == '\0', .ok=*s->cur == '\0',
.error=(scan_error_t){ .error=scan_error(s, "null character not found"),
// TODO: make reusable error value maker. kind of what we had earlier, but with no allocation };
},
}
} }
bool scan_literal(scan_t *s, const char *lit) { scan_result_t scan_literal(scan_t *s, const char *lit) {
const char *save = s->cur; const char *save = s->cur;
while (*lit && *lit == *s->cur) { while (*lit && *lit == *s->cur) {
lit++; lit++;
s->cur++; s->cur++;
} }
if (*lit == '\0') { if (*lit == '\0') {
return true; return (scan_result_t) {
.ok=true,
};
} }
s->cur = save; s->cur = save;
return false; return (scan_result_t) {
.ok=false,
.error=scan_error(s, "invalid literal"),
};
// TODO: add another optional string field to specify what literal is
// missing
} }
int scan_repeat_literal(scan_t *s, const char *lit) { int scan_repeat_literal(scan_t *s, const char *lit) {
int n_repeats = 0; int n_repeats = 0;
while (scan_literal(s, lit)) { while (scan_literal(s, lit).ok) {
n_repeats++; n_repeats++;
} }
return n_repeats; return n_repeats;
} }
bool scan_whitespace(scan_t *s) { scan_result_t scan_whitespace(scan_t *s) {
const char *save = s->cur; const char *save = s->cur;
while (isspace((unsigned char)*s->cur)) s->cur++; while (isspace((unsigned char)*s->cur)) s->cur++;
return save != s->cur; return (scan_result_t) {
.ok=save != s->cur,
.error=scan_error(s, "expected whitespace"),
};
} }
bool scan_digit(scan_t *s) { scan_result_t scan_digit(scan_t *s) {
if (!isdigit((unsigned char)*s->cur)) { if (!isdigit((unsigned char)*s->cur)) {
return false; return (scan_result_t){
.ok=false,
.error=scan_error(s, "expected digit"),
};
} }
s->value.digit = (*s->cur) - '0';
s->cur++; s->cur++;
return true; return (scan_result_t){
.ok=true,
.value=(scan_value_t){
.digit=(*s->cur) - '0',
},
};
} }
bool scan_i64(scan_t *s) { bool scan_i64(scan_t *s) {