Small refactor of indentation lexer.

master
James T. Martin 2022-10-17 10:02:43 -07:00
parent 8808c41250
commit f951e8ce08
Signed by: james
GPG Key ID: D6FB2F9892F9B225
2 changed files with 31 additions and 36 deletions

View File

@ -108,58 +108,53 @@ static uint32_t count_indents(enum indent_type type) {
return counter; return counter;
} }
static void new_indent(void) { // Returns `true` if a new indentation level was introduced.
static _Bool new_indent(void) {
struct indent indent = { 0, 0 }; struct indent indent = { 0, 0 };
indent.tabs = count_indents(INDENT_TABS); indent.tabs = count_indents(INDENT_TABS);
indent.spaces = count_indents(INDENT_SPACES); indent.spaces = count_indents(INDENT_SPACES);
char c = peekc(); char c = peekc();
if (c == '\t' && (indent.spaces > 0 || !tabs_allowed())) { if ((indent.tabs > 0 && !tabs_allowed()) || (c == '\t' && indent.spaces > 0)) {
fprintf(stderr, "lexical error: all tabs on a line must precede all spaces\n"); fprintf(stderr, "lexical error: all tabs on a line must precede all spaces\n");
exit(1); exit(1);
} }
if (is_newline(c)) { if (indent_levels == MAX_INDENTS && !is_newline(c)) {
return;
}
if (indent_levels == MAX_INDENTS) {
fprintf(stderr, "lexical error: too many indentation levels! factor your code!\n"); fprintf(stderr, "lexical error: too many indentation levels! factor your code!\n");
exit(1); exit(1);
} }
indents[indent_levels] = indent; indents[indent_levels] = indent;
indent_levels++; return indent.tabs > 0 || indent.spaces > 0;
} }
int32_t lex_indentation(void) { uint32_t lex_line_indentation(void) {
uint32_t indent_level = 0; uint32_t indent_level = 0;
char c = peekc(); while (indent_level < indent_levels) {
while (true) { if (!is_indent(peekc())) {
while (is_newline(c)) {
nextc();
c = peekc();
}
if (c == 0) {
indent_levels = 0;
return indent_level; return indent_level;
} }
if (!is_indent(c)) { struct indent expected_indent = indents[indent_level];
break; expect_indent(INDENT_TABS, expected_indent.tabs);
} expect_indent(INDENT_SPACES, expected_indent.spaces);
indent_level++;
}
if (new_indent()) {
return indent_level + 1;
}
return indent_level;
}
uint32_t lex_indentation(void) {
uint32_t indent_level;
while (true) {
indent_level = lex_line_indentation();
// We ignore trailing whitespace on empty lines,
// but don't know that a line will be empty until we've reached the end.
if (!is_newline(peekc())) { break; }
nextc();
}
if (peekc() == 0) {
// EOF closes all indentation-based blocks.
indent_level = 0; indent_level = 0;
while (is_indent(c) && indent_level < indent_levels) {
struct indent indent = indents[indent_level];
expect_indent(INDENT_TABS, indent.tabs);
expect_indent(INDENT_SPACES, indent.spaces);
indent_level++;
c = peekc();
}
if (is_indent(c)) {
new_indent();
c = peekc();
if (!is_newline(c)) {
indent_levels++;
return indent_levels;
}
}
c = peekc();
} }
indent_levels = indent_level; indent_levels = indent_level;
return indent_levels; return indent_levels;

View File

@ -9,6 +9,6 @@
_Bool is_newline(char c); _Bool is_newline(char c);
_Bool is_indent(char c); _Bool is_indent(char c);
int32_t lex_indentation(void); uint32_t lex_indentation(void);
#endif #endif