<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

#include "../util/dynarray.h"
#include "../util/util.h"
#include "../util/alloc.h"

#include "cc1_where.h"
#include "cc1.h" /* cc1_std */

#include "tokenise.h"
#include "tokconv.h"

#include "parse_stmt.h"

#include "parse_type.h"
#include "parse_expr.h"

struct stmt_ctx
{
	stmt *continue_target,
	     *break_target,
	     *switch_target;
	symtable *scope;
};

static void parse_test_init_expr(stmt *t, struct stmt_ctx *ctx)
{
	where here;

	where_cc1_current(&here);

	EAT(token_open_paren);

	/* if C99, we create a new scope here, for e.g.
	 * if(5 > (enum { a, b })a){ return a; } return b;
	 * "return b" can't see 'b' since its scope is only the if
	 *
	 * C90 drags the scope of the enum up to the enclosing block
	 */
	if(cc1_std >= STD_C99){
		ctx->scope = t->symtab = symtab_new(t->symtab, &here);
	}

  if(parse_at_decl(ctx->scope)){
		decl *d;

		/* if we are at a type, push a scope for it, for
		 * for(int i ...), if(int i = ...) etc
		 */
		symtable *init_scope = symtab_new(t->symtab, &here);

		d = parse_decl_single(
				DECL_SPEL_NEED, 0,
				ctx->scope, init_scope);

		UCC_ASSERT(d, "at decl, but no decl?");

		t->flow = stmt_flow_new(init_scope);

		UCC_ASSERT(
				t->flow->for_init_symtab == init_scope,
				"wrong scope for stmt-init");

		ctx->scope = t->symtab = t->flow->for_init_symtab;

		/* `d' is added to the scope implicitly */

		if(accept(token_comma)){
			/* if(int i = 5, i > f()){ ... } */
			t->expr = parse_expr_exp(ctx->scope);
		}else{
			/* if(int i = 5) -> if(i) */
			t->expr = expr_new_identifier(d->spel);
		}
	}else{
		t->expr = parse_expr_exp(t->symtab);
	}

	EAT(token_close_paren);
}

static stmt *parse_if(const struct stmt_ctx *const ctx)
{
	stmt *t = stmt_new_wrapper(if, ctx->scope);
	struct stmt_ctx subctx = *ctx;

	EAT(token_if);

	parse_test_init_expr(t, &subctx);

	t->lhs = parse_stmt(&subctx);

	if(accept(token_else))
		t->rhs = parse_stmt(&subctx);

	return t;
}

static stmt *parse_switch(const struct stmt_ctx *const ctx)
{
	stmt *t = stmt_new_wrapper(switch, ctx->scope);
	struct stmt_ctx subctx = *ctx;

	subctx.break_target = t;
	subctx.switch_target = t;

	EAT(token_switch);

	parse_test_init_expr(t, &subctx);

	t->lhs = parse_stmt(&subctx);

	return t;
}

static stmt *parse_do(const struct stmt_ctx *const ctx)
{
	stmt *t = stmt_new_wrapper(do, ctx->scope);
	struct stmt_ctx subctx = *ctx;

	subctx.break_target = t;
	subctx.continue_target = t;

	EAT(token_do);

	t->lhs = parse_stmt(&subctx);

	EAT(token_while);
	EAT(token_open_paren);
	t->expr = parse_expr_exp(subctx.scope);
	EAT(token_close_paren);
	EAT(token_semicolon);

	return t;
}

static stmt *parse_while(const struct stmt_ctx *const ctx)
{
	stmt *t = stmt_new_wrapper(while, ctx->scope);
	struct stmt_ctx subctx = *ctx;

	subctx.continue_target = t;
	subctx.break_target = t;

	EAT(token_while);

	parse_test_init_expr(t, &subctx);

	t->lhs = parse_stmt(&subctx);

	return t;
}

static stmt *parse_for(const struct stmt_ctx *const ctx)
{
	stmt *s = stmt_new_wrapper(for, ctx->scope);
	stmt_flow *sf;
	struct stmt_ctx subctx = *ctx;

	subctx.continue_target = s;
	subctx.break_target = s;

	EAT(token_for);
	EAT(token_open_paren);

	sf = s->flow = stmt_flow_new(symtab_new(s->symtab, &s->where));

	subctx.scope = sf->for_init_symtab;

	if(!accept(token_semicolon)){
		decl **c99inits = NULL;

		parse_decls_single_type(
				DECL_MULTI_ALLOW_ALIGNAS,
				/*newdecl context:*/1,
				subctx.scope, subctx.scope,
				&c99inits);

		if(c99inits){
			if(cc1_std < STD_C99)
				warn_at(NULL, "use of C99 for-init");

			dynarray_free(decl **, &c99inits, NULL);
		}else{
			sf->for_init = parse_expr_exp(subctx.scope);
		}

		/* ';' eaten by parse_decls_single_type() */
	}

	if(!accept(token_semicolon)){
		sf->for_while = parse_expr_exp(subctx.scope);
		EAT(token_semicolon);
	}

	if(!accept(token_close_paren)){<commit_msg>Fixed for-loop parsing in the non-decl case<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

#include "../util/dynarray.h"
#include "../util/util.h"
#include "../util/alloc.h"

#include "cc1_where.h"
#include "cc1.h" /* cc1_std */

#include "tokenise.h"
#include "tokconv.h"

#include "parse_stmt.h"

#include "parse_type.h"
#include "parse_expr.h"

struct stmt_ctx
{
	stmt *continue_target,
	     *break_target,
	     *switch_target;
	symtable *scope;
};

static void parse_test_init_expr(stmt *t, struct stmt_ctx *ctx)
{
	where here;

	where_cc1_current(&here);

	EAT(token_open_paren);

	/* if C99, we create a new scope here, for e.g.
	 * if(5 > (enum { a, b })a){ return a; } return b;
	 * "return b" can't see 'b' since its scope is only the if
	 *
	 * C90 drags the scope of the enum up to the enclosing block
	 */
	if(cc1_std >= STD_C99){
		ctx->scope = t->symtab = symtab_new(t->symtab, &here);
	}

  if(parse_at_decl(ctx->scope)){
		decl *d;

		/* if we are at a type, push a scope for it, for
		 * for(int i ...), if(int i = ...) etc
		 */
		symtable *init_scope = symtab_new(t->symtab, &here);

		d = parse_decl_single(
				DECL_SPEL_NEED, 0,
				ctx->scope, init_scope);

		UCC_ASSERT(d, "at decl, but no decl?");

		t->flow = stmt_flow_new(init_scope);

		UCC_ASSERT(
				t->flow->for_init_symtab == init_scope,
				"wrong scope for stmt-init");

		ctx->scope = t->symtab = t->flow->for_init_symtab;

		/* `d' is added to the scope implicitly */

		if(accept(token_comma)){
			/* if(int i = 5, i > f()){ ... } */
			t->expr = parse_expr_exp(ctx->scope);
		}else{
			/* if(int i = 5) -> if(i) */
			t->expr = expr_new_identifier(d->spel);
		}
	}else{
		t->expr = parse_expr_exp(t->symtab);
	}

	EAT(token_close_paren);
}

static stmt *parse_if(const struct stmt_ctx *const ctx)
{
	stmt *t = stmt_new_wrapper(if, ctx->scope);
	struct stmt_ctx subctx = *ctx;

	EAT(token_if);

	parse_test_init_expr(t, &subctx);

	t->lhs = parse_stmt(&subctx);

	if(accept(token_else))
		t->rhs = parse_stmt(&subctx);

	return t;
}

static stmt *parse_switch(const struct stmt_ctx *const ctx)
{
	stmt *t = stmt_new_wrapper(switch, ctx->scope);
	struct stmt_ctx subctx = *ctx;

	subctx.break_target = t;
	subctx.switch_target = t;

	EAT(token_switch);

	parse_test_init_expr(t, &subctx);

	t->lhs = parse_stmt(&subctx);

	return t;
}

static stmt *parse_do(const struct stmt_ctx *const ctx)
{
	stmt *t = stmt_new_wrapper(do, ctx->scope);
	struct stmt_ctx subctx = *ctx;

	subctx.break_target = t;
	subctx.continue_target = t;

	EAT(token_do);

	t->lhs = parse_stmt(&subctx);

	EAT(token_while);
	EAT(token_open_paren);
	t->expr = parse_expr_exp(subctx.scope);
	EAT(token_close_paren);
	EAT(token_semicolon);

	return t;
}

static stmt *parse_while(const struct stmt_ctx *const ctx)
{
	stmt *t = stmt_new_wrapper(while, ctx->scope);
	struct stmt_ctx subctx = *ctx;

	subctx.continue_target = t;
	subctx.break_target = t;

	EAT(token_while);

	parse_test_init_expr(t, &subctx);

	t->lhs = parse_stmt(&subctx);

	return t;
}

static stmt *parse_for(const struct stmt_ctx *const ctx)
{
	stmt *s = stmt_new_wrapper(for, ctx->scope);
	stmt_flow *sf;
	struct stmt_ctx subctx = *ctx;

	subctx.continue_target = s;
	subctx.break_target = s;

	EAT(token_for);
	EAT(token_open_paren);

	sf = s->flow = stmt_flow_new(symtab_new(s->symtab, &s->where));

	subctx.scope = sf->for_init_symtab;

	if(!accept(token_semicolon)){
		int got_decl = parse_decls_single_type(
				DECL_MULTI_ALLOW_ALIGNAS,
				/*newdecl context:*/1,
				subctx.scope, subctx.scope,
				NULL);

		if(got_decl){
			if(cc1_std < STD_C99)
				warn_at(NULL, "use of C99 for-init");
		}else{
			sf->for_init = parse_expr_exp(subctx.scope);
			EAT(token_semicolon);
		}

		/* ';' eaten by parse_decls_single_type() */
	}

	if(!accept(token_semicolon)){
		sf->for_while = parse_expr_exp(subctx.scope);
		EAT(token_semicolon);
	}

	if(!accept(token_close_paren)){
{'fraction_non_alphanumeric': 0.1554318957885418, 'fraction_numerical': 0.006323510813203491, 'mean_word_length': 4.008233058898036, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 91, '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': '2841361', 'n_tokens_mistral': 3515, 'n_tokens_neox': 3266, 'n_words': 682}