Small refactor of indentation lexer.
parent
8808c41250
commit
f951e8ce08
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue