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;
}
static void new_indent(void) {
// Returns `true` if a new indentation level was introduced.
static _Bool new_indent(void) {
struct indent indent = { 0, 0 };
indent.tabs = count_indents(INDENT_TABS);
indent.spaces = count_indents(INDENT_SPACES);
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");
exit(1);
}
if (is_newline(c)) {
return;
}
if (indent_levels == MAX_INDENTS) {
if (indent_levels == MAX_INDENTS && !is_newline(c)) {
fprintf(stderr, "lexical error: too many indentation levels! factor your code!\n");
exit(1);
}
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;
char c = peekc();
while (true) {
while (is_newline(c)) {
nextc();
c = peekc();
}
if (c == 0) {
indent_levels = 0;
while (indent_level < indent_levels) {
if (!is_indent(peekc())) {
return indent_level;
}
if (!is_indent(c)) {
break;
}
struct indent expected_indent = indents[indent_level];
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;
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;
return indent_levels;

View File

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