Be more permissive around indentation between infix operators

This commit is contained in:
Bruce Hill 2024-11-17 15:10:02 -05:00
parent 14ebadbbfd
commit af5b5a90d6

30
parse.c
View File

@ -244,24 +244,21 @@ static const char *unescape(parse_ctx_t *ctx, const char **out) {
}
#pragma GCC diagnostic pop
// Indent is in number of spaces (assuming that \t is 4 spaces)
PUREFUNC static INLINE int64_t get_indent(parse_ctx_t *ctx, const char *pos)
{
int64_t line_num = get_line_number(ctx->file, pos);
const char *line = get_line(ctx->file, line_num);
if (*line == ' ') {
int64_t spaces = (int64_t)strspn(line, " ");
if (spaces % SPACES_PER_INDENT != 0)
parser_err(ctx, line + spaces - (spaces % SPACES_PER_INDENT), line + spaces,
"Indentation must be a multiple of 4 spaces, not %ld", spaces);
int64_t indent = spaces / SPACES_PER_INDENT;
if (line[indent] == '\t')
parser_err(ctx, line + indent, line + indent + 1, "This is a tab following spaces, and you can't mix tabs and spaces");
return indent;
if (line[spaces] == '\t')
parser_err(ctx, line + spaces, line + spaces + 1, "This is a tab following spaces, and you can't mix tabs and spaces");
return spaces;
} else if (*line == '\t') {
int64_t indent = (int64_t)strspn(line, "\t");
if (line[indent] == ' ')
parser_err(ctx, line + indent, line + indent + 1, "This is a space following tabs, and you can't mix tabs and spaces");
return indent;
return indent * SPACES_PER_INDENT;
} else {
return 0;
}
@ -426,7 +423,7 @@ bool indent(parse_ctx_t *ctx, const char **out) {
if (next_line <= *out)
return false;
if (get_indent(ctx, next_line) != starting_indent + 1)
if (get_indent(ctx, next_line) != starting_indent + SPACES_PER_INDENT)
return false;
*out = next_line + strspn(next_line, " \t");
@ -445,12 +442,12 @@ bool newline_with_indentation(const char **out, int64_t target) {
}
if (*pos == ' ') {
if ((int64_t)strspn(pos, " ") >= SPACES_PER_INDENT * target) {
*out = pos + SPACES_PER_INDENT * target;
if ((int64_t)strspn(pos, " ") >= target) {
*out = pos + target;
return true;
}
} else if ((int64_t)strspn(pos, "\t") >= target) {
*out = pos + target;
} else if ((int64_t)strspn(pos, "\t") * SPACES_PER_INDENT >= target) {
*out = pos + target / SPACES_PER_INDENT;
return true;
}
return false;
@ -1330,7 +1327,7 @@ PARSER(parse_text) {
}
int64_t starting_indent = get_indent(ctx, pos);
int64_t string_indent = starting_indent + 1;
int64_t string_indent = starting_indent + SPACES_PER_INDENT;
ast_list_t *chunks = NULL;
CORD chunk = CORD_EMPTY;
@ -1739,6 +1736,8 @@ static ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightn
ast_t *lhs = optional(ctx, &pos, parse_term);
if (!lhs) return NULL;
int64_t starting_line = get_line_number(ctx->file, pos);
int64_t starting_indent = get_indent(ctx, pos);
spaces(&pos);
for (binop_e op; (op=match_binary_operator(&pos)) != BINOP_UNKNOWN && op_tightness[op] >= min_tightness; spaces(&pos)) {
ast_t *key = NULL;
@ -1761,6 +1760,9 @@ static ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightn
}
whitespace(&pos);
if (get_line_number(ctx->file, pos) != starting_line && get_indent(ctx, pos) <= starting_indent)
parser_err(ctx, pos, strchrnul(pos, '\n'), "I expected this line to be more indented than the line above it");
ast_t *rhs = parse_infix_expr(ctx, pos, op_tightness[op] + 1);
if (!rhs) break;
pos = rhs->end;