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