/* =====================================
 * Generated by Mod-c 0.26.5
 * MODULE parser_main
 * ===================================== */

#include "parser_main.h"

void parser_main(void);

/**
 * TMod-c
 * By M. Scott Reynolds
 * Date 28 March 2026
 *
 * Parser.mc - Recursive descent parser for Mod-c source code.
 * 10 August 2026 - Conversion to .mc
 */
#include "Lexer.h"
#include "arena.h"
#include "dynbuf.h"
#include "ttype.h"
#include "parser_common.h"
#include "declaration.h"
#include "expression.h"
#include "statement.h"
#include "utils.h"
#include "node.h"
#include "stddef.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
/**
 * Skip simple type 
 */
static void TParser__skip_simple_type(TParser* p)
{
    if (TParser__match(&(*p), TOK_KEYWORD_CONST))
    {
    }
    if (TParser__match(&(*p), TOK_CARET))
    {
    }
    else if (TParser__match(&(*p), TOK_KEYWORD_POINTER))
    {
        (TParser__match(&(*p), TOK_KEYWORD_TO));
    }
    if (TParser__match(&(*p), TOK_KEYWORD_ARRAY))
    {
        if (TParser__match(&(*p), TOK_LBRACKET))
        {
            if (TParser__check(&(*p), TOK_NUMBER))
            {
                TParser__advance(&(*p));
            }
            (TParser__match(&(*p), TOK_RBRACKET));
        }
        (TParser__match(&(*p), TOK_KEYWORD_OF));
        TParser__skip_simple_type(&(*p));
                return;
    }
    while (TParser__check(&(*p), TOK_IDENT))
    {
        {
            TParser__advance(&(*p));
        }
    }
    if (TParser__match(&(*p), TOK_NUMBER))
    {
    }
    if (TParser__match(&(*p), TOK_LBRACKET))
    {
        if (!TParser__match(&(*p), TOK_RBRACKET))
        {
            if (TParser__check(&(*p), TOK_NUMBER))
            {
                TParser__advance(&(*p));
            }
            (TParser__match(&(*p), TOK_RBRACKET));
        }
    }
}

/**
 * skipped balanced parens
 */
static void TParser__skip_balanced_parens(TParser* p)
{
    integer depth = 0;
    if (!TParser__check(&(*p), TOK_LPAREN))
    {
                return;
    }
    do
    {
        {
            if (TParser__check(&(*p), TOK_LPAREN))
            {
                depth++;
            }
            else if (TParser__check(&(*p), TOK_RPAREN))
            {
                depth--;
            }
            TParser__advance(&(*p));
        }
    }
    while (!(depth <= 0 || TParser__check(&(*p), TOK_EOF)));
}

/**
 * Skip type RHS
 */
static void TParser__skip_type_rhs(TParser* p)
{
    TParser__skip_empty_statements(&(*p));
    if (TParser__match(&(*p), TOK_KEYWORD_PACKED))
    {
    }
    if (TParser__check(&(*p), TOK_KEYWORD_STRUCT))
    {
        TParser__advance(&(*p));
        while (!TParser__check(&(*p), TOK_KEYWORD_END) && !TParser__check(&(*p), TOK_EOF))
        {
            {
                TParser__advance(&(*p));
            }
        }
        if (TParser__check(&(*p), TOK_KEYWORD_END))
        {
            TParser__advance(&(*p));
        }
                return;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_PROCEDURE) || TParser__check(&(*p), TOK_KEYWORD_FUNCTION))
    {
        bool is_function = TParser__check(&(*p), TOK_KEYWORD_FUNCTION);
        TParser__advance(&(*p));
        TParser__skip_balanced_parens(&(*p));
        if (is_function && TParser__match(&(*p), TOK_COLON))
        {
            TParser__skip_simple_type(&(*p));
        }
                return;
    }
    TParser__skip_simple_type(&(*p));
}

/**
 * Skip to EOS
 */
static void TParser__skip_to_eos(TParser* p)
{
    while (!TParser__checkEOS(&(*p)) && !TParser__check(&(*p), TOK_EOF) && !TParser__check(&(*p), TOK_KEYWORD_BEGIN))
    {
        {
            TParser__advance(&(*p));
        }
    }
    (TParser__matchEOS(&(*p)));
}

/**
 * Skip BEGIN END block
 */
static void TParser__skip_begin_end_block(TParser* p)
{
    integer depth = 1;
    if (!TParser__match(&(*p), TOK_KEYWORD_BEGIN))
    {
                return;
    }
    while (depth > 0 && !TParser__check(&(*p), TOK_EOF))
    {
        {
            if (TParser__match(&(*p), TOK_KEYWORD_BEGIN))
            {
                depth++;
            }
            else if (TParser__match(&(*p), TOK_KEYWORD_END))
            {
                depth--;
            }
            else
            {
                TParser__advance(&(*p));
            }
        }
    }
}

/**
 * Skip PROC decl
 */
static void TParser__skip_proc_decl(TParser* p)
{
    bool is_function = false;
    if (TParser__check(&(*p), TOK_KEYWORD_FUNCTION))
    {
        is_function = true;
    }
    if (!TParser__check(&(*p), TOK_KEYWORD_PROCEDURE) && !TParser__check(&(*p), TOK_KEYWORD_FUNCTION))
    {
                return;
    }
    TParser__advance(&(*p));
    if (TParser__check(&(*p), TOK_IDENT))
    {
        TParser__advance(&(*p));
        if (TParser__check(&(*p), TOK_COLON_COLON))
        {
            TParser__advance(&(*p));
            if (TParser__check(&(*p), TOK_IDENT))
            {
                TParser__advance(&(*p));
            }
        }
    }
    TParser__skip_balanced_parens(&(*p));
    if (is_function && TParser__match(&(*p), TOK_COLON))
    {
        TParser__skip_simple_type(&(*p));
    }
    TParser__skip_empty_statements(&(*p));
    if (TParser__check(&(*p), TOK_KEYWORD_BEGIN))
    {
        TParser__skip_begin_end_block(&(*p));
    }
}

/**
 * Prescan type names
 */
static void TParser__prescan_type_names(TParser* p)
{
    TLexer saved_lexer = ((*p)).lexer;
    TToken saved_current = ((*p)).current;
    while (!TParser__check(&(*p), TOK_KEYWORD_BEGIN) && !TParser__check(&(*p), TOK_KEYWORD_END) && !TParser__check(&(*p), TOK_EOF))
    {
        {
            TParser__skip_empty_statements(&(*p));
            if (TParser__check(&(*p), TOK_KEYWORD_BEGIN) || TParser__check(&(*p), TOK_KEYWORD_END) || TParser__check(&(*p), TOK_EOF))
            {
                                /* INVARIANT (on loop exit) */
                break;
            }
            (TParser__match(&(*p), TOK_KEYWORD_EXPORT));
            if (TParser__check(&(*p), TOK_KEYWORD_EXTERN))
            {
                (TParser__match(&(*p), TOK_KEYWORD_EXTERN));
            }
            else if (TParser__check(&(*p), TOK_KEYWORD_STATIC))
            {
                (TParser__match(&(*p), TOK_KEYWORD_STATIC));
            }
            (TParser__match(&(*p), TOK_KEYWORD_RECURSIVE));
            if (TParser__check(&(*p), TOK_KEYWORD_EXTERN))
            {
                TParser__advance(&(*p));
                (TParser__match(&(*p), TOK_KEYWORD_EXPORT));
                if (TParser__check(&(*p), TOK_KEYWORD_TYPE))
                {
                    TParser__advance(&(*p));
                    if (TParser__check(&(*p), TOK_IDENT))
                    {
                        TParser__register_type_name(&(*p), (((*p)).current).start, (((*p)).current).length);
                    }
                    TParser__skip_to_eos(&(*p));
                                        /* INVARIANT (on loop exit) */
                    continue;
                }
            }
            if (TParser__check(&(*p), TOK_KEYWORD_TYPE))
            {
                TParser__advance(&(*p));
                do
                {
                    {
                        if (TParser__check(&(*p), TOK_IDENT))
                        {
                            TParser__register_type_name(&(*p), (((*p)).current).start, (((*p)).current).length);
                            TParser__advance(&(*p));
                        }
                        if (!TParser__match(&(*p), TOK_EQ))
                        {
                                                        /* INVARIANT (on loop exit) */
                            break;
                        }
                        TParser__skip_type_rhs(&(*p));
                    }
                }
                while (!(!TParser__match(&(*p), TOK_COMMA)));
                TParser__skip_to_eos(&(*p));
            }
            else if (TParser__check(&(*p), TOK_KEYWORD_PROCEDURE) || TParser__check(&(*p), TOK_KEYWORD_FUNCTION))
            {
                TParser__skip_proc_decl(&(*p));
                TParser__skip_to_eos(&(*p));
            }
            else if (TParser__check(&(*p), TOK_KEYWORD_IMPORT))
            {
                TParser__advance(&(*p));
                TParser__skip_to_eos(&(*p));
            }
            else if (TParser__check(&(*p), TOK_KEYWORD_VAR) || TParser__check(&(*p), TOK_KEYWORD_CONST) || TParser__check(&(*p), TOK_KEYWORD_LET))
            {
                TParser__advance(&(*p));
                TParser__skip_to_eos(&(*p));
            }
            else
            {
                TParser__advance(&(*p));
            }
        }
    }
    ((*p)).lexer = saved_lexer;
    ((*p)).current = saved_current;
}

/**
 * Parse doc comments
 */
static pNode TParser__parse_doc_comment(TParser* p)
{
    pNode n = nil;
    if (!TParser__check(&(*p), TOK_DOC_COMMENT))
    {
        /* return value captured before defers */
        pNode __ret_l340 = nil;
        return __ret_l340;
    }
    n = node_create(((*p)).arena, NODE_DOC_COMMENT, ((*p)).current);
    (((*n)).doc_comment).text = (((*p)).current).start;
    (((*n)).doc_comment).text_len = (((*p)).current).length;
    TParser__advance(&(*p));
    /* return value captured before defers */
    pNode __ret_l351 = n;
    return __ret_l351;
}

static pNode TParser__parse_preprocessor(TParser* p)
{
    pNode n = nil;
    n = node_create(((*p)).arena, NODE_PREPROCESSOR, ((*p)).current);
    (((*n)).preprocessor).text = (((*p)).current).start;
    (((*n)).preprocessor).length = (((*p)).current).length;
    TParser__advance(&(*p));
    /* return value captured before defers */
    pNode __ret_l369 = n;
    return __ret_l369;
}

static pTType TParser__parse_array_type_after_lbracket(TParser* p, pTType element)
{
    pNode bound = nil;
    size_t fixed_size = 0;
    if (TParser__match(&(*p), TOK_RBRACKET))
    {
        /* return value captured before defers */
        pTType __ret_l385 = type_create_array(((*p)).arena, element, 0);
        return __ret_l385;
    }
    bound = TParser__parse_const_expression(&(*p));
    if (bound == nil)
    {
        TParser__error_at(&(*p), "TParser::parse_array_type_after_lbracket: expected const-expression array size", true);
    }
    TParser__consume(&(*p), TOK_RBRACKET, "TParser::parse_array_type_after_lbracket: expected ']' after array size");
    if (((*bound)).kind == NODE_LITERAL && (((*bound)).token).kind == TOK_NUMBER)
    {
        fixed_size = (size_t)utils_parse_integer_literal((((*bound)).token).start, (((*bound)).token).length);
        /* return value captured before defers */
        pTType __ret_l397 = type_create_array(((*p)).arena, element, fixed_size);
        return __ret_l397;
    }
    /* return value captured before defers */
    pTType __ret_l400 = type_create_array_expr(((*p)).arena, element, bound);
    return __ret_l400;
}

/**
 * Parse a return type.
 * 
 * This is the most restricted of the parsing functions. It only accepts 
 * syntax that is valid (or can be reasonably lowered) as a C return type.
 *
 * In particular:
 *  - Direct array types (T[], T[N], array[...] of T) are accepted syntactically,
 *    but are expected to be lowered to pointer types during code generation.
 *  - Method types (PROCEDURE / FUNCTION signatures) are NOT accepted here.
 *
 * Intended usage:
 *  - Return types of FUNCTION declarations
 *  - Return type of PROGRAM/MODULE.
 *
 * For parameter types, use parse_parameter_type().
 * For general type expressions (including method types, struct types, etc.),
 * use parse_type_expression().
 *
 * Allow opaque: true only for TYPE RHS (parse_type_expression)
 *
 * Exits on fatal parse error. 
 */
static pTType TParser__parse_return_type_ex(TParser* p, bool allow_opaque)
{
    bool is_const = false;
    bool is_pointer = false;
    bool is_array_keyword = false;
    pTType element = nil;
    if (TParser__match(&(*p), TOK_KEYWORD_CONST))
    {
        is_const = true;
    }
    if (TParser__match(&(*p), TOK_CARET))
    {
        is_pointer = true;
    }
    else if (TParser__match(&(*p), TOK_KEYWORD_POINTER))
    {
        TParser__consume(&(*p), TOK_KEYWORD_TO, "TParser::parse_return_type_ex: expected 'TO' after POINTER");
        is_pointer = true;
    }
    is_array_keyword = TParser__match(&(*p), TOK_KEYWORD_ARRAY);
    if (is_array_keyword)
    {
        pTType arr = nil;
        pNode bound = nil;
        bool had_brackets = false;
        bool open_brackets = false;
        if (TParser__match(&(*p), TOK_LBRACKET))
        {
            had_brackets = true;
            if (TParser__match(&(*p), TOK_RBRACKET))
            {
                open_brackets = true;
            }
            else
            {
                bound = TParser__parse_const_expression(&(*p));
                if (bound == nil)
                {
                    TParser__error_at(&(*p), "TParser::parse_return_type_ex: expected const-expression array size", true);
                }
                TParser__consume(&(*p), TOK_RBRACKET, "TParser::parse_return_type_ex: expected ']' after array size");
            }
        }
        TParser__consume(&(*p), TOK_KEYWORD_OF, "TParser::parse_return_type_ex: expected 'OF' after array[...]");
        element = TParser__parse_return_type_ex(&(*p), false);
        if (!had_brackets || open_brackets)
        {
            arr = type_create_array(((*p)).arena, element, 0);
        }
        else if (((*bound)).kind == NODE_LITERAL && (((*bound)).token).kind == TOK_NUMBER)
        {
            arr = type_create_array(((*p)).arena, element, (size_t)utils_parse_integer_literal((((*bound)).token).start, (((*bound)).token).length));
        }
        else
        {
            arr = type_create_array_expr(((*p)).arena, element, bound);
        }
        ((*arr)).is_const = is_const;
        ((*arr)).is_pointer = is_pointer;
        /* return value captured before defers */
        pTType __ret_l480 = arr;
        return __ret_l480;
    }
    if (allow_opaque && TParser__match(&(*p), TOK_KEYWORD_OPAQUE))
    {
        pTType t = type_create_opaque(((*p)).arena);
        ((*t)).is_pointer = is_pointer;
        ((*t)).is_const = is_const;
        /* return value captured before defers */
        pTType __ret_l487 = t;
        return __ret_l487;
    }
    if ((((*p)).current).kind != TOK_IDENT)
    {
        TParser__error_at(&(*p), "TParser::parse_return_type_ex: expected type identifier", true);
    }
    {
        const char* start = (((*p)).current).start;
        size_t length = (((*p)).current).length;
        TParser__advance(&(*p));
        if (type_is_width_base(start, length) && TParser__check(&(*p), TOK_NUMBER))
        {
            size_t i = 0;
            integer w = 0;
            while (i < (((*p)).current).length)
            {
                {
                    char ch = (((*p)).current).start[i];
                    if (ch < '0' || ch > '9')
                    {
                        TParser__error_at(&(*p), "TParser::parse_return_type_ex: width must be a decimal integer", true);
                    }
                    i++;
                }
            }
            if ((((*p)).current).length > 1 && (((*p)).current).start[0] == '0')
            {
                TParser__error_at(&(*p), "TParser::parse_return_type_ex: widht must be a decimal integer", true);
            }
            w = (integer)utils_parse_integer_literal((((*p)).current).start, (((*p)).current).length);
            if (!type_width_allowed(start, length, w))
            {
                TParser__error_at(&(*p), "TParser::parse_return_type_ex: unsupported width for this type", true);
            }
            TParser__advance(&(*p));
            element = type_create_named(((*p)).arena, start, length);
            ((*element)).width = w;
        }
        else
        {
            while ((((*p)).current).kind == TOK_IDENT)
            {
                {
                    length = (size_t)((((*p)).current).start + (((*p)).current).length - start);
                    TParser__advance(&(*p));
                }
            }
            element = type_create_named(((*p)).arena, start, length);
        }
        ((*element)).is_pointer = is_pointer;
        ((*element)).is_const = is_const;
    }
    if (TParser__match(&(*p), TOK_LBRACKET))
    {
        element = TParser__parse_array_type_after_lbracket(&(*p), element);
    }
    /* return value captured before defers */
    pTType __ret_l539 = element;
    return __ret_l539;
}

static void TParser__parse_optional_end_tag(TParser* p)
{
    if (!TParser__check(&(*p), TOK_IDENT))
    {
                return;
    }
    TParser__advance(&(*p));
    if (TParser__match(&(*p), TOK_COLON_COLON))
    {
        if ((((*p)).current).kind != TOK_IDENT)
        {
            TParser__error_at(&(*p), "TParser::parse_optional_end_tag: expected identifer after '::'", true);
        }
        TParser__advance(&(*p));
    }
}

static pNode TParser__parse_decl(TParser* p)
{
    bool exported = false;
    bool is_extern = false;
    bool is_static = false;
    bool is_recursive = false;
    if (TParser__check(&(*p), TOK_DOC_COMMENT))
    {
        /* return value captured before defers */
        pNode __ret_l580 = TParser__parse_doc_comment(&(*p));
        return __ret_l580;
    }
    if (TParser__check(&(*p), TOK_PREPROCESSOR))
    {
        /* return value captured before defers */
        pNode __ret_l585 = TParser__parse_preprocessor(&(*p));
        return __ret_l585;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_IMPORT))
    {
        /* return value captured before defers */
        pNode __ret_l590 = parse_import_stmt(&(*p));
        return __ret_l590;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_EXTERN))
    {
        bool ext_exported = false;
        TParser__advance(&(*p));
        ext_exported = TParser__match(&(*p), TOK_KEYWORD_EXPORT);
        if (TParser__check(&(*p), TOK_KEYWORD_TYPE))
        {
            /* return value captured before defers */
            pNode __ret_l601 = parse_extern_type_decl(&(*p), ext_exported);
            return __ret_l601;
        }
        if (TParser__check(&(*p), TOK_KEYWORD_VAR))
        {
            /* return value captured before defers */
            pNode __ret_l604 = parse_var_decl(&(*p), ext_exported, true, false);
            return __ret_l604;
        }
        if (TParser__check(&(*p), TOK_KEYWORD_PROCEDURE) || TParser__check(&(*p), TOK_KEYWORD_FUNCTION))
        {
            /* return value captured before defers */
            pNode __ret_l607 = parse_proc_or_func_decl(&(*p), ext_exported, false, true);
            return __ret_l607;
        }
        TParser__error_at(&(*p), "TParser::parse_decl: EXTERN requires TYPE, VAR, PROCEDURE or FUNCTION", true);
    }
    exported = TParser__match(&(*p), TOK_KEYWORD_EXPORT);
    if (TParser__check(&(*p), TOK_KEYWORD_EXTERN))
    {
        is_extern = TParser__match(&(*p), TOK_KEYWORD_EXTERN);
    }
    else if (TParser__check(&(*p), TOK_KEYWORD_STATIC))
    {
        is_static = TParser__match(&(*p), TOK_KEYWORD_STATIC);
    }
    is_recursive = TParser__match(&(*p), TOK_KEYWORD_RECURSIVE);
    if (TParser__check(&(*p), TOK_KEYWORD_VAR))
    {
        /* return value captured before defers */
        pNode __ret_l627 = parse_var_decl(&(*p), exported, is_extern, is_static);
        return __ret_l627;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_CONST))
    {
        /* return value captured before defers */
        pNode __ret_l630 = parse_const_decl(&(*p), exported);
        return __ret_l630;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_LET))
    {
        /* return value captured before defers */
        pNode __ret_l633 = parse_let_decl(&(*p), exported);
        return __ret_l633;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_TYPE))
    {
        /* return value captured before defers */
        pNode __ret_l636 = parse_type_decl(&(*p), exported);
        return __ret_l636;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_PROCEDURE) || TParser__check(&(*p), TOK_KEYWORD_FUNCTION))
    {
        /* return value captured before defers */
        pNode __ret_l640 = parse_proc_or_func_decl(&(*p), exported, is_recursive, is_extern);
        return __ret_l640;
    }
    TParser__error_at(&(*p), "TParser::parse_decl: unexpected token at top level (expected declaration)", true);
    /* return value captured before defers */
    pNode __ret_l645 = nil;
    return __ret_l645;
}

static pNode TParser__parse_decl_sequence(TParser* p)
{
    /* return value captured before defers */
    pNode __ret_l654 = TParser__parse_decl(&(*p));
    return __ret_l654;
}

static pNode TParser__parse_program(TParser* p)
{
    pNode prog = node_create(((*p)).arena, NODE_PROGRAM, ((*p)).current);
    pNode param_list = nil;
    TParser__skip_empty_statements(&(*p));
    if (!TParser__match(&(*p), TOK_KEYWORD_PROGRAM) && !TParser__match(&(*p), TOK_KEYWORD_MODULE))
    {
        TParser__error_at(&(*p), "TParser::parse_program: expected PROGRAM or MODULE at top level", true);
    }
    (((*prog)).program_decl).unit_kind = (((*prog)).token).kind;
    if ((((*p)).current).kind == TOK_IDENT)
    {
        (((*prog)).program_decl).name = (((*p)).current).start;
        (((*prog)).program_decl).name_len = (((*p)).current).length;
        TParser__advance(&(*p));
    }
    else
    {
        TParser__error_at(&(*p), "TParser::parse_program: expected PROGRAM/MODULE name", true);
    }
    param_list = parse_param_list(&(*p));
    if (param_list != nil)
    {
        (((*prog)).program_decl).params = (((*param_list)).param_list).params;
        (((*prog)).program_decl).param_count = (((*param_list)).param_list).count;
        (((*prog)).program_decl).param_capacity = (((*param_list)).param_list).capacity;
    }
    else
    {
        TParser__error_at(&(*p), "TParser::parse_program: formal parameters expected", false);
        (((*prog)).program_decl).params = nil;
        (((*prog)).program_decl).param_count = 0;
        (((*prog)).program_decl).param_capacity = 0;
    }
    if (TParser__match(&(*p), TOK_COLON))
    {
        (((*prog)).program_decl).return_type = TParser__parse_return_type_ex(&(*p), false);
        TParser__advance(&(*p));
    }
    TParser__skip_empty_statements(&(*p));
    TParser__prescan_type_names(&(*p));
    while (!TParser__check(&(*p), TOK_KEYWORD_BEGIN) && !TParser__check(&(*p), TOK_KEYWORD_END) && !TParser__check(&(*p), TOK_EOF))
    {
        {
            pNode decl = TParser__parse_decl_sequence(&(*p));
            if (decl == nil)
            {
                                /* INVARIANT (on loop exit) */
                break;
            }
            arena_append_ptr(((*p)).arena, (ppvoid)(&(((*prog)).program_decl).decls), &(((*prog)).program_decl).count, &(((*prog)).program_decl).capacity, decl);
            TParser__skip_empty_statements(&(*p));
        }
    }
    if (TParser__check(&(*p), TOK_KEYWORD_BEGIN))
    {
        (((*prog)).program_decl).block = TParser__parse_block(&(*p));
    }
    else if ((((*prog)).program_decl).unit_kind == TOK_KEYWORD_PROGRAM)
    {
        TParser__error_at(&(*p), "TParser::parse_program: PROGRAM requires a BEGIN ... END block", true);
    }
    else if ((((*prog)).program_decl).unit_kind == TOK_KEYWORD_MODULE)
    {
        if (!TParser__check(&(*p), TOK_KEYWORD_END))
        {
            TParser__error_at(&(*p), "TParser::parse_program: expected END at end of MODULE", true);
        }
        else
        {
            TParser__error_at(&(*p), "TParser::parse_program: MODULE expects a BEGIN ... END block", false);
        }
    }
    else
    {
        TParser__advance(&(*p));
    }
    /* return value captured before defers */
    pNode __ret_l742 = prog;
    return __ret_l742;
}

/**
 * Initialize parser state.
 * Primes the lexer and advances to the first token.
 * Does NOT take ownership of source or out - they must remain valid.
 *
 * @param p         Parser to initialize
 * @param arena     Arena for all AST node allocations (must be initialized)
 * @param source    Null-terminated source code buffer (must remain valid)
 * @param out       Optional output buffer for debug/codegen (may be NULL)
 */
void TParser__init(TParser* p, pArena arena, const char* source, pDynBuf out)
{
    if (arena == nil || source == nil)
    {
        fprintf(stderr, "TParser::init: ERROR: NULL pointer argument\n");
        exit(1);
    }
    TLexer__init(&((*p)).lexer, source);
    ((*p)).arena = arena;
    ((*p)).out = out;
    ((*p)).show_tokens = true;
    ((*p)).type_names = nil;
    ((*p)).type_name_count = 0;
    ((*p)).type_name_capacity = 0;
}

/**
 * Register a user TYPE spelling for sizeof() operand disambiguation.
 * Case-sensitive; duplicates are ignored.
 */
void TParser__register_type_name(TParser* p, const char* start, size_t length)
{
    size_t i = 0;
    if (start == nil || length == 0)
    {
                return;
    }
    {
        const long long __for_end_l784 = (long long)(((*p)).type_name_count);
        for (i = 1; (long long)(i) <= __for_end_l784; i++)
        {
            {
                if ((((*p)).type_names[i - 1]).length == length && memcmp((((*p)).type_names[i - 1]).start, start, length) == 0)
                {
                                        return;
                }
            }
        }
    }
    if (((*p)).type_name_count >= ((*p)).type_name_capacity)
    {
        size_t new_capacity = (((*p)).type_name_capacity ? ((*p)).type_name_capacity * 2u : 8u);
        pParserTypeName new_names = (pParserTypeName)arena_alloc(((*p)).arena, new_capacity * SIZE_PARSER_TYPE_NAME());
        if (((*p)).type_names != nil && ((*p)).type_name_count > 0)
        {
            memcpy(new_names, ((*p)).type_names, ((*p)).type_name_count * SIZE_PARSER_TYPE_NAME());
        }
        ((*p)).type_names = new_names;
        ((*p)).type_name_capacity = new_capacity;
    }
    (((*p)).type_names[((*p)).type_name_count]).start = start;
    (((*p)).type_names[((*p)).type_name_count]).length = length;
    ((*p)).type_name_count++;
}

/**
 * Is user type name?
 * True when start/len is a registered user TYPE name (not a builtin).
 */
bool TParser__is_user_type_name(TParser* p, const char* start, size_t length)
{
    size_t i = 0;
    if (start == nil || length == 0)
    {
        /* return value captured before defers */
        bool __ret_l819 = false;
        return __ret_l819;
    }
    {
        const long long __for_end_l822 = (long long)(((*p)).type_name_count);
        for (i = 1; (long long)(i) <= __for_end_l822; i++)
        {
            {
                if ((((*p)).type_names[i - 1]).length == length && memcmp((((*p)).type_names[i - 1]).start, start, length) == 0)
                {
                    /* return value captured before defers */
                    bool __ret_l824 = true;
                    return __ret_l824;
                }
            }
        }
    }
    /* return value captured before defers */
    bool __ret_l828 = false;
    return __ret_l828;
}

/**
 * Parse expression
 */
pNode TParser__parse_expr(TParser* p)
{
    /* return value captured before defers */
    pNode __ret_l842 = parse_conditional(&(*p));
    return __ret_l842;
}

/**
 * Parse a return type
 *
 * Narrow parser used only where a C return type is expected.
 * See the header declaration for full rationale and restrictions.
 */
pTType TParser__parse_return_type(TParser* p)
{
    /* return value captured before defers */
    pTType __ret_l854 = TParser__parse_return_type_ex(&(*p), false);
    return __ret_l854;
}

/**
 * Parse parameter types: Type specified in formal parameters, grammar may
 * allow more than just parse_return_type. Returns fully constructed ^TType
 * Exits on fatal parse error.
 */
pTType TParser__parse_parameter_type(TParser* p)
{
    /* return value captured before defers */
    pTType __ret_l865 = TParser__parse_return_type_ex(&(*p), false);
    return __ret_l865;
}

/**
 * Parse full type expression. Used for full type declarations.
 * Returns fully constructed ^TType.
 * Exits on fatal parse error.
 */
pTType TParser__parse_type_expression(TParser* p)
{
    /* return value captured before defers */
    pTType __ret_l876 = TParser__parse_return_type_ex(&(*p), true);
    return __ret_l876;
}

/**
 * Parse a const expression.
 * Same as normal expression for now. Semantics will enforce later.
 */
pNode TParser__parse_const_expression(TParser* p)
{
    /* return value captured before defers */
    pNode __ret_l886 = TParser__parse_expr(&(*p));
    return __ret_l886;
}

/**
 * Parse a designator (for left-hand side of assignment, etc.)
 * Supports: ident, ident.field, ident[index], ^designator
 */
pNode TParser__parse_designator(TParser* p)
{
    pNode d = parse_primary(&(*p));
    while (1)
    {
        {
            if (TParser__match(&(*p), TOK_DOT))
            {
                pNode fa = nil;
                if ((((*p)).current).kind != TOK_IDENT)
                {
                    TParser__error_at(&(*p), "TParser::parse_designator: expected identifer after '.'", true);
                }
                const TToken field_tok_l907_c26 = ((*p)).current;
                TParser__advance(&(*p));
                fa = node_create(((*p)).arena, NODE_FIELD_ACCESS, field_tok_l907_c26);
                (((*fa)).field_access).record_ = d;
                (((*fa)).field_access).field_name = (field_tok_l907_c26).start;
                (((*fa)).field_access).field_len = (field_tok_l907_c26).length;
                d = fa;
            }
            else if (TParser__check(&(*p), TOK_LBRACKET))
            {
                d = parse_array_index(&(*p), d);
            }
            else if (TParser__check(&(*p), TOK_CARET))
            {
                pNode unary = nil;
                unary = node_create(((*p)).arena, NODE_UNARY, ((*p)).current);
                (((*unary)).unary).op = TOK_CARET;
                (((*unary)).unary).operand = d;
                d = unary;
                TParser__advance(&(*p));
            }
            else
            {
                                /* INVARIANT (on loop exit) */
                break;
            }
        }
    }
    /* return value captured before defers */
    pNode __ret_l928 = d;
    return __ret_l928;
}

/**
 * Parse block: BEGIN statement-list END
 * 
 * Allocates and grows stmts array dynamically.
 * Exits on fatal parse errors.
 *
 * @param p     Parser state (current token should be BEGIN)
 * @return      BLOCK node with parsed statements.
 */
pNode TParser__parse_block(TParser* p)
{
    TToken begin_token = ((*p)).current;
    pNode block = nil;
    pNode saw_early_exit = nil;
    TParser__consume(&(*p), TOK_KEYWORD_BEGIN, "TParser::parse_block: expected BEGIN");
    block = node_create(((*p)).arena, NODE_BLOCK, begin_token);
    (((*block)).block).stmts = nil;
    (((*block)).block).count = 0;
    (((*block)).block).capacity = 0;
    (((*block)).block).defers = nil;
    (((*block)).block).defer_count = 0;
    (((*block)).block).defer_capacity = 0;
    (((*block)).block).requires = nil;
    (((*block)).block).require_count = 0;
    (((*block)).block).require_capacity = 0;
    (((*block)).block).ensures = nil;
    (((*block)).block).ensure_count = 0;
    (((*block)).block).ensure_capacity = 0;
    TParser__skip_empty_statements(&(*p));
    while (TParser__check(&(*p), TOK_KEYWORD_REQUIRE))
    {
        {
            pNode expr = nil;
            TParser__consume(&(*p), TOK_KEYWORD_REQUIRE, "TParser::parse_block: expected REQUIRE");
            expr = TParser__parse_expr(&(*p));
            if (expr == nil)
            {
                TParser__error_at(&(*p), "TParser::parse_block: expected expression after REQUIRE ...", true);
            }
            if (!TParser__matchEOS(&(*p)))
            {
                TParser__error_at(&(*p), "TParser::parse_block: expected end-of-statement after REQUIRE", true);
            }
            arena_append_ptr(((*p)).arena, (ppvoid)(&(((*block)).block).requires), &(((*block)).block).require_count, &(((*block)).block).require_capacity, expr);
            TParser__skip_empty_statements(&(*p));
        }
    }
    while (1)
    {
        {
            bool is_static = TParser__match(&(*p), TOK_KEYWORD_STATIC);
            bool exported = false;
            bool is_extern = false;
            pNode decl = nil;
            if (TParser__check(&(*p), TOK_KEYWORD_VAR))
            {
                decl = parse_var_decl(&(*p), exported, is_extern, is_static);
            }
            else if (is_static)
            {
                TParser__error_at(&(*p), "TParser::parse_block: STATIC can only be used with VAR here", true);
            }
            else if (TParser__check(&(*p), TOK_KEYWORD_CONST))
            {
                decl = parse_const_decl(&(*p), exported);
            }
            else if (TParser__check(&(*p), TOK_KEYWORD_LET))
            {
                decl = parse_let_decl(&(*p), exported);
            }
            else if (TParser__check(&(*p), TOK_PREPROCESSOR))
            {
                decl = TParser__parse_preprocessor(&(*p));
            }
            else
            {
                                /* INVARIANT (on loop exit) */
                break;
            }
            if (decl != nil)
            {
                arena_append_ptr(((*p)).arena, (ppvoid)(&(((*block)).block).stmts), &(((*block)).block).count, &(((*block)).block).capacity, decl);
            }
            TParser__skip_empty_statements(&(*p));
        }
    }
    while (!TParser__check(&(*p), TOK_KEYWORD_END) && !TParser__check(&(*p), TOK_EOF) && !TParser__check(&(*p), TOK_KEYWORD_ENSURE))
    {
        {
            pNode stmt = TParser__parse_stmt(&(*p));
            if (stmt != nil)
            {
                if (((*stmt)).kind == NODE_DEFER)
                {
                    arena_append_ptr(((*p)).arena, (ppvoid)(&(((*block)).block).defers), &(((*block)).block).defer_count, &(((*block)).block).defer_capacity, stmt);
                }
                if (saw_early_exit != nil)
                {
                    TParser__error_at(&(*p), "TParser::parse_block: unreachable statment after RETURN/BREAK/CONTINUE", true);
                }
                else
                {
                    arena_append_ptr(((*p)).arena, (ppvoid)(&(((*block)).block).stmts), &(((*block)).block).count, &(((*block)).block).capacity, stmt);
                }
                if (saw_early_exit == nil && (((*stmt)).kind == NODE_RETURN || ((*stmt)).kind == NODE_BREAK || ((*stmt)).kind == NODE_CONTINUE))
                {
                    saw_early_exit = stmt;
                }
            }
            else
            {
                fprintf(stderr, "WARNING: TParser::parse_block: unrecognized statement %.*s\n", (int)(((*p)).current).length, (((*p)).current).start);
                TParser__advance(&(*p));
            }
            TParser__skip_empty_statements(&(*p));
        }
    }
    while (TParser__check(&(*p), TOK_KEYWORD_ENSURE))
    {
        {
            pNode expr = nil;
            TParser__consume(&(*p), TOK_KEYWORD_ENSURE, "TParser::parse_block: expected ENSURE");
            expr = TParser__parse_expr(&(*p));
            if (expr == nil)
            {
                TParser__error_at(&(*p), "TParser::parse_block: expected expression after ENSURE ...", true);
            }
            if (!TParser__matchEOS(&(*p)))
            {
                TParser__error_at(&(*p), "TParser::parse_block: expected end-of-statement after ENSURE", true);
            }
            arena_append_ptr(((*p)).arena, (ppvoid)(&(((*block)).block).ensures), &(((*block)).block).ensure_count, &(((*block)).block).ensure_capacity, expr);
            TParser__skip_empty_statements(&(*p));
        }
    }
    TParser__consume(&(*p), TOK_KEYWORD_END, "TParser::parse_block: expected END");
    TParser__parse_optional_end_tag(&(*p));
    if (!TParser__matchEOS(&(*p)))
    {
    }
    /* return value captured before defers */
    pNode __ret_l1094 = block;
    return __ret_l1094;
}

/**
 * Parse statement_sequence - statements until a terminating key word (NED, UNTIL, etc.)
 * This is what IF/THEN, FOR/DO, REPEAT, ELSIF, ELSE use.
 * No BEGIN is required.
 * This is similar to TParser::parse_block; any changes there will need to also go here.
 */
pNode TParser__parse_statement_sequence(TParser* p)
{
    pNode block = nil;
    pNode saw_early_exit = nil;
    block = node_create(((*p)).arena, NODE_BLOCK, ((*p)).current);
    (((*block)).block).stmts = nil;
    (((*block)).block).count = 0;
    (((*block)).block).capacity = 0;
    (((*block)).block).defers = nil;
    (((*block)).block).defer_count = 0;
    (((*block)).block).defer_capacity = 0;
    (((*block)).block).requires = nil;
    (((*block)).block).require_count = 0;
    (((*block)).block).require_capacity = 0;
    (((*block)).block).ensures = nil;
    (((*block)).block).ensure_count = 0;
    (((*block)).block).ensure_capacity = 0;
    TParser__skip_empty_statements(&(*p));
    while (1)
    {
        {
            bool is_static = TParser__match(&(*p), TOK_KEYWORD_STATIC);
            bool exported = false;
            bool is_extern = false;
            pNode decl = nil;
            if (TParser__check(&(*p), TOK_KEYWORD_VAR))
            {
                decl = parse_var_decl(&(*p), exported, is_extern, is_static);
            }
            else if (is_static)
            {
                TParser__error_at(&(*p), "TParser::parse_statement_sequence: STATIC can only bu used with VAR here", true);
            }
            else if (TParser__check(&(*p), TOK_KEYWORD_CONST))
            {
                decl = parse_const_decl(&(*p), exported);
            }
            else if (TParser__check(&(*p), TOK_KEYWORD_LET))
            {
                decl = parse_let_decl(&(*p), exported);
            }
            else if (TParser__check(&(*p), TOK_PREPROCESSOR))
            {
                decl = TParser__parse_preprocessor(&(*p));
            }
            else
            {
                                /* INVARIANT (on loop exit) */
                break;
            }
            if (decl != nil)
            {
                arena_append_ptr(((*p)).arena, (ppvoid)(&(((*block)).block).stmts), &(((*block)).block).count, &(((*block)).block).capacity, decl);
            }
            TParser__skip_empty_statements(&(*p));
        }
    }
    while (!TParser__check(&(*p), TOK_KEYWORD_END) && !TParser__check(&(*p), TOK_KEYWORD_UNTIL) && !TParser__check(&(*p), TOK_KEYWORD_ELSIF) && !TParser__check(&(*p), TOK_KEYWORD_ELSE) && !TParser__check(&(*p), TOK_EOF) && !TParser__check(&(*p), TOK_KEYWORD_CASE))
    {
        {
            pNode stmt = TParser__parse_stmt(&(*p));
            if (stmt != nil)
            {
                if (((*stmt)).kind == NODE_DEFER)
                {
                    arena_append_ptr(((*p)).arena, (ppvoid)(&(((*block)).block).defers), &(((*block)).block).defer_count, &(((*block)).block).defer_capacity, stmt);
                }
                if (saw_early_exit != nil)
                {
                    TParser__error_at(&(*p), "TParser::parse_statement_sequence: unreachable statement after RETURN/BREAK/CONTINUE", true);
                }
                else
                {
                    arena_append_ptr(((*p)).arena, (ppvoid)(&(((*block)).block).stmts), &(((*block)).block).count, &(((*block)).block).capacity, stmt);
                }
                if (saw_early_exit == nil && (((*stmt)).kind == NODE_RETURN || ((*stmt)).kind == NODE_BREAK || ((*stmt)).kind == NODE_CONTINUE))
                {
                    saw_early_exit = stmt;
                }
            }
            else
            {
                TParser__advance(&(*p));
            }
            TParser__skip_empty_statements(&(*p));
        }
    }
    /* return value captured before defers */
    pNode __ret_l1205 = block;
    return __ret_l1205;
}

/**
 * Parse a single statement.
 * Recognizes:
 *  - expression / assignment statements / call statements
 *  - contorl structure (if, for, repeat, loop) -- TODO
 *  - empty statements (just ; or newline)
 *
 * Returns statement node or nil for empty / skiped lines.
 */
pNode TParser__parse_stmt(TParser* p)
{
    if (TParser__check(&(*p), TOK_PREPROCESSOR))
    {
        /* return value captured before defers */
        pNode __ret_l1221 = TParser__parse_preprocessor(&(*p));
        return __ret_l1221;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_ASSERT))
    {
        /* return value captured before defers */
        pNode __ret_l1226 = TParser__parse_builtin_stmt(&(*p));
        return __ret_l1226;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_INC) || TParser__check(&(*p), TOK_KEYWORD_DEC))
    {
        /* return value captured before defers */
        pNode __ret_l1230 = parse_inc_dec_stmt(&(*p));
        return __ret_l1230;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_LET))
    {
        /* return value captured before defers */
        pNode __ret_l1234 = parse_let_decl(&(*p), false);
        return __ret_l1234;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_IF))
    {
        /* return value captured before defers */
        pNode __ret_l1238 = parse_if_stmt(&(*p));
        return __ret_l1238;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_WHILE))
    {
        /* return value captured before defers */
        pNode __ret_l1242 = parse_while_stmt(&(*p));
        return __ret_l1242;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_FOR))
    {
        /* return value captured before defers */
        pNode __ret_l1246 = parse_for_stmt(&(*p));
        return __ret_l1246;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_REPEAT))
    {
        /* return value captured before defers */
        pNode __ret_l1250 = parse_repeat_until_stmt(&(*p));
        return __ret_l1250;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_LOOP))
    {
        /* return value captured before defers */
        pNode __ret_l1254 = parse_loop_stmt(&(*p));
        return __ret_l1254;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_SWITCH))
    {
        /* return value captured before defers */
        pNode __ret_l1258 = parse_switch_stmt(&(*p));
        return __ret_l1258;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_BREAK))
    {
        /* return value captured before defers */
        pNode __ret_l1262 = parse_break_stmt(&(*p));
        return __ret_l1262;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_CONTINUE))
    {
        /* return value captured before defers */
        pNode __ret_l1266 = parse_continue_stmt(&(*p));
        return __ret_l1266;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_RETURN))
    {
        /* return value captured before defers */
        pNode __ret_l1270 = parse_return_stmt(&(*p));
        return __ret_l1270;
    }
    if (TParser__check(&(*p), TOK_IDENT) || TParser__check(&(*p), TOK_CARET) || TParser__check(&(*p), TOK_LPAREN))
    {
        pNode left = TParser__parse_designator(&(*p));
        pNode stmt = nil;
        if (TParser__check_assignment(&(*p)))
        {
            TokenKind assign_tok = (((*p)).current).kind;
            pNode right = nil;
            pNode assign = nil;
            TParser__advance(&(*p));
            right = TParser__parse_expr(&(*p));
            if (right == nil)
            {
                TParser__error_at(&(*p), "TParser::parse_stmt: expected expression after assignment", true);
            }
            assign = node_create(((*p)).arena, NODE_ASSIGN, ((*left)).token);
            (((*assign)).binary).left = left;
            (((*assign)).binary).right = right;
            (((*assign)).binary).op = assign_tok;
            if (!TParser__matchEOS(&(*p)))
            {
                TParser__error_at(&(*p), "TParser::parse_stmt expected end-of-statement after assignment", true);
            }
            /* return value captured before defers */
            pNode __ret_l1301 = assign;
            return __ret_l1301;
        }
        while (1)
        {
            {
                if (TParser__check(&(*p), TOK_LPAREN))
                {
                    if (((*left)).kind == NODE_FIELD_ACCESS)
                    {
                        pNode fa = left;
                        pNode call = parse_call(&(*p), ((*left)).token);
                        (((*call)).call).receiver_expr = (((*fa)).field_access).record_;
                        (((*call)).call).callee_expr = fa;
                        left = call;
                    }
                    else if (((*left)).kind == NODE_IDENT)
                    {
                        left = parse_call(&(*p), ((*left)).token);
                    }
                    else if (((*left)).kind == NODE_CALL)
                    {
                        left = parse_call(&(*p), ((*left)).token);
                    }
                    else
                    {
                        TParser__error_at(&(*p), "TParser::parse_stmt: unexpected '(' after expression", true);
                    }
                }
                else if (TParser__check(&(*p), TOK_LBRACKET))
                {
                    left = parse_array_index(&(*p), left);
                }
                else if (TParser__match(&(*p), TOK_DOT))
                {
                    TToken field_tok = {0};
                    pNode field_node = nil;
                    if ((((*p)).current).kind != TOK_IDENT)
                    {
                        TParser__error_at(&(*p), "TParser::parse_stmt: expected identifier after '.'", true);
                    }
                    field_tok = ((*p)).current;
                    TParser__advance(&(*p));
                    field_node = node_create(((*p)).arena, NODE_FIELD_ACCESS, field_tok);
                    (((*field_node)).field_access).record_ = left;
                    (((*field_node)).field_access).field_name = (field_tok).start;
                    (((*field_node)).field_access).field_len = (field_tok).length;
                    (((*field_node)).field_access).base_depth = 0;
                    left = field_node;
                }
                else if (TParser__match(&(*p), TOK_CARET))
                {
                    pNode unary = node_create(((*p)).arena, NODE_UNARY, ((*p)).current);
                    (((*unary)).unary).op = TOK_CARET;
                    (((*unary)).unary).operand = left;
                    left = unary;
                }
                else
                {
                                        /* INVARIANT (on loop exit) */
                    break;
                }
            }
        }
        stmt = node_create(((*p)).arena, NODE_EXPR_STMT, ((*left)).token);
        (((*stmt)).expr_stmt).expr = left;
        if (!TParser__matchEOS(&(*p)))
        {
            TParser__error_at(&(*p), "TParser::parse_stmt: expected end-of-statement after expression", true);
        }
        /* return value captured before defers */
        pNode __ret_l1369 = stmt;
        return __ret_l1369;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_DEFER))
    {
        /* return value captured before defers */
        pNode __ret_l1373 = parse_defer_stmt(&(*p));
        return __ret_l1373;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_DEBUG))
    {
        /* return value captured before defers */
        pNode __ret_l1377 = parse_debug_stmt(&(*p));
        return __ret_l1377;
    }
    if (TParser__check(&(*p), TOK_KEYWORD_BEGIN))
    {
        /* return value captured before defers */
        pNode __ret_l1381 = TParser__parse_block(&(*p));
        return __ret_l1381;
    }
    /* return value captured before defers */
    pNode __ret_l1385 = nil;
    return __ret_l1385;
}

/**
 * Parse built-in statements: ASSERT 
 */
pNode TParser__parse_builtin_stmt(TParser* p)
{
    TToken tok = ((*p)).current;
    if (TParser__match(&(*p), TOK_KEYWORD_ASSERT))
    {
        pNode cond = TParser__parse_expr(&(*p));
        pNode const_expr = nil;
        pNode n = nil;
        if (cond == nil)
        {
            TParser__error_at(&(*p), "TParser::parse_builtin_stmt: expected expression after ASSERT", true);
        }
        if (TParser__match(&(*p), TOK_COMMA))
        {
            const_expr = TParser__parse_const_expression(&(*p));
        }
        if (!TParser__matchEOS(&(*p)))
        {
            TParser__error_at(&(*p), "TParser::parse_builtin_stmt: expected end-of-statement after ASSERT", true);
        }
        n = node_create(((*p)).arena, NODE_ASSERT, tok);
        (((*n)).assert_stmt).condition = cond;
        (((*n)).assert_stmt).const_expr = const_expr;
        /* return value captured before defers */
        pNode __ret_l1416 = n;
        return __ret_l1416;
    }
    /* return value captured before defers */
    pNode __ret_l1418 = nil;
    return __ret_l1418;
}

/**
 * Entry point. Parse the entire source into an AST.
 * Returns the root PROGRAM node (or NULL on fatal error - exits via error handlers).
 * Caller owns the returned node (allocated in p->arena).
 */
pNode TParser__parse(TParser* p)
{
    if ((((*p)).lexer).start == (((*p)).lexer).current)
    {
        TParser__advance(&(*p));
    }
    TParser__skip_empty_statements(&(*p));
    /* return value captured before defers */
    pNode __ret_l1436 = TParser__parse_program(&(*p));
    return __ret_l1436;
}


void parser_main(void)
{
}
