<commit_before>#include "parse.h"
#include "error.h"
#include "util.h"
#include "operator.h"
#include "color.h"
#include "module.h"

#include <stdbool.h>
#include <assert.h>

#define NEXT if (ps->tok->type != TOK_END) ps->tok = ps->tok->next;

struct parser *
new_parser()
{
	struct parser *ps = oak_malloc(sizeof *ps);
	ps->r = new_reporter();
	return ps;
}

void
free_parser(struct parser *ps)
{
	error_clear(ps->r);
	/* the parser is not responsible for the token stream, so we
	 * don't have to free it here. */
	free(ps);
}

static void
expect_symbol(struct parser *ps, char *sym)
{
//	DOUT("expecting %s, looking at %s\n", sym, ps->tok->value);

	if (strcmp(ps->tok->value, sym)) {
		if (ps->tok->type == TOK_END) {
			struct token *tok = ps->tok->prev;

			error_push(ps->r, tok->loc, ERR_FATAL,
				   "unexpected end-of-file; expected '" ERROR_LOCATION_COLOR "%s" RESET_COLOR "'",
				   sym);
		} else {
			error_push(ps->r, ps->tok->loc, ERR_FATAL,
				   "unexpected token '"
				   ERROR_LOCATION_COLOR "%s" RESET_COLOR
				   "'; expected '"
				   ERROR_LOCATION_COLOR "%s" RESET_COLOR "'",
				   ps->tok->value, sym);
		}
	}

	NEXT;
}

static void
expect_terminator(struct parser *ps)
{
	if (strcmp(ps->tok->value, ";") && !ps->tok->prev->is_line_end) {
		if (ps->tok->type == TOK_END) {
			struct token *tok = ps->tok->prev;

			error_push(ps->r, tok->loc, ERR_FATAL,
				   "unexpected end-of-file; expected a statement terminator");
		} else {
			error_push(ps->r, ps->tok->loc, ERR_FATAL,
				   "unexpected token '"
				   ERROR_LOCATION_COLOR "%s" RESET_COLOR
				   "'; expected a statement terminator",
				   ps->tok->value);
		}
	}<commit_msg>allow } to function as an expression terminator<commit_after>#include "parse.h"
#include "error.h"
#include "util.h"
#include "operator.h"
#include "color.h"
#include "module.h"

#include <stdbool.h>
#include <assert.h>

#define NEXT if (ps->tok->type != TOK_END) ps->tok = ps->tok->next;

struct parser *
new_parser()
{
	struct parser *ps = oak_malloc(sizeof *ps);
	ps->r = new_reporter();
	return ps;
}

void
free_parser(struct parser *ps)
{
	error_clear(ps->r);
	/* the parser is not responsible for the token stream, so we
	 * don't have to free it here. */
	free(ps);
}

static void
expect_symbol(struct parser *ps, char *sym)
{
//	DOUT("expecting %s, looking at %s\n", sym, ps->tok->value);

	if (strcmp(ps->tok->value, sym)) {
		if (ps->tok->type == TOK_END) {
			struct token *tok = ps->tok->prev;

			error_push(ps->r, tok->loc, ERR_FATAL,
				   "unexpected end-of-file; expected '" ERROR_LOCATION_COLOR "%s" RESET_COLOR "'",
				   sym);
		} else {
			error_push(ps->r, ps->tok->loc, ERR_FATAL,
				   "unexpected token '"
				   ERROR_LOCATION_COLOR "%s" RESET_COLOR
				   "'; expected '"
				   ERROR_LOCATION_COLOR "%s" RESET_COLOR "'",
				   ps->tok->value, sym);
		}
	}

	NEXT;
}

static void
expect_terminator(struct parser *ps)
{
	if (strcmp(ps->tok->value, ";") && strcmp(ps->tok->value, "}") && !ps->tok->prev->is_line_end) {
		if (ps->tok->type == TOK_END) {
			struct token *tok = ps->tok->prev;

			error_push(ps->r, tok->loc, ERR_FATAL,
				   "unexpected end-of-file; expected a statement terminator");
		} else {
			error_push(ps->r, ps->tok->loc, ERR_FATAL,
				   "unexpected token '"
				   ERROR_LOCATION_COLOR "%s" RESET_COLOR
				   "'; expected a statement terminator",
				   ps->tok->value);
		}
	}
{'fraction_non_alphanumeric': 0.17533039647577092, 'fraction_numerical': 0.0, 'mean_word_length': 3.40620957309185, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2517768', 'n_tokens_mistral': 1421, 'n_tokens_neox': 1280, 'n_words': 299}