#ifndef PARSER_H #define PARSER_H #include #include typedef struct { size_t index; int line; int col; } Pos; void print_error(const char* message, Pos pos); typedef enum { TokenType_Error, TokenType_EOF, TokenType_Id, TokenType_Int, TokenType_Not, TokenType_And, TokenType_Or, TokenType_If, TokenType_Loop, TokenType_Fn, TokenType_Return, TokenType_Break, TokenType_LParen, TokenType_RParen, TokenType_LBrace, TokenType_RBrace, TokenType_LBracket, TokenType_RBracket, TokenType_Comma, TokenType_Semicolon, TokenType_Plus, TokenType_PlusEqual, TokenType_Minus, TokenType_MinusEqual, TokenType_Asterisk, TokenType_AsteriskEqual, TokenType_Equal, TokenType_EqualEqual, TokenType_Exclamation, TokenType_ExclamationEqual, TokenType_LT, TokenType_LTEqual, TokenType_GT, TokenType_GTEqual, TokenType_Pipe, TokenType_PipeGT, } TokenType; typedef struct { TokenType token_type; Pos pos; size_t length; } Token; typedef struct { const char* text; size_t text_length; size_t index; int line; int col; bool failed; } Lexer; void lexer_construct(Lexer* lexer, const char* text, size_t text_length); Token lexer_next(Lexer* lexer); bool lexer_failed(const Lexer* lexer); Token lexer_token(Lexer* lexer, TokenType token_type, Pos pos); void lexer_step(Lexer* lexer); bool lexer_done(const Lexer* lexer); char lexer_current(const Lexer* lexer); Pos lexer_pos(const Lexer* lexer); typedef enum { ASTNodeType_Error, ASTNodeType_Id, ASTNodeType_Int, ASTNodeType_Block, ASTNodeType_If, ASTNodeType_Loop, ASTNodeType_Call, ASTNodeType_Index, ASTNodeType_Unary, ASTNodeType_Binary, ASTNodeType_Assign, ASTNodeType_Let, ASTNodeType_Break, ASTNodeType_Fn, } ASTNodeType; typedef struct ASTNode ASTNode; typedef struct { ASTNode** data; size_t length; size_t capacity; } ASTNodeVec; int ast_node_vec_construct(ASTNodeVec* vec); void ast_node_vec_destroy(ASTNodeVec* vec); int ast_node_vec_push(ASTNodeVec* vec, ASTNode* item); typedef struct { ASTNode* condition; ASTNode* truthy; ASTNode* falsy; } ASTIfNode; typedef struct { ASTNode* body; } ASTLoopNode; typedef struct { ASTNode* subject; ASTNodeVec args; } ASTCallNode; typedef struct { ASTNode* subject; ASTNode* value; } ASTIndexNode; typedef enum { UnaryType_Not, UnaryType_Negate, } UnaryType; typedef struct { UnaryType unary_type; ASTNode* subject; } ASTUnaryNode; typedef enum { BinaryType_And, BinaryType_Or, BinaryType_Add, BinaryType_Subtract, BinaryType_Multiply, BinaryType_EE, BinaryType_NE, BinaryType_LT, BinaryType_GT, BinaryType_LTE, BinaryType_GTE, } BinaryType; typedef struct { BinaryType binary_type; ASTNode* left; ASTNode* right; } ASTBinaryNode; typedef enum { AssignType_Assign, AssignType_Add, AssignType_Subtract, AssignType_Multiply, } AssignType; typedef struct { AssignType assign_type; ASTNode* subject; ASTNode* value; } ASTAssignNode; typedef struct { char* id; ASTNode* value; } ASTLetNode; typedef struct { char* id; ASTNodeVec params; ASTNode* body; } ASTFnNode; struct ASTNode { ASTNodeType node_type; Pos pos; union { char* id_value; int int_value; ASTNodeVec statements; ASTIfNode if_node; ASTLoopNode loop_node; ASTCallNode call_node; ASTIndexNode index_node; ASTUnaryNode unary_node; ASTBinaryNode binary_node; ASTAssignNode assign_node; ASTLetNode let_node; ASTFnNode fn_node; }; }; ASTNode* ast_node_new(ASTNodeType node_type, Pos pos, ASTNode spec_init); void ast_node_free(ASTNode* node); typedef struct { const char* text; size_t text_length; Lexer lexer; Token current; bool failed; } Parser; void parser_construct(Parser* parser, const char* text, size_t text_length); bool parser_failed(const Parser* parser); void parser_step(Parser* parser); bool parser_done(const Parser* parser); ASTNode* parser_parse(Parser* parser); ASTNode* parser_parse_statement(Parser* parser); ASTNode* parser_parse_expr(Parser* parser); ASTNode* parser_parse_operand(Parser* parser); ASTNode* parser_parse_id(Parser* parser); ASTNode* parser_parse_int(Parser* parser); ASTNode* parser_parse_group(Parser* parser); ASTNode* parser_parse_block(Parser* parser); ASTNode* parser_parse_if(Parser* parser); ASTNode* parser_parse_loop(Parser* parser); #endif