parser_utils.c (11246B)
#include "../parser.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
/* basic range to str */
const char*
range_str(const char* src, size_t start, size_t end, char* stack_alloc_chptr)
{
const size_t len = end - start;
if (!src || !stack_alloc_chptr) return NULL;
if (!strchr(src, '\0')) return NULL; // src has no '\0'
if (len <= 0) return NULL;
memcpy(stack_alloc_chptr, src + start, len);
stack_alloc_chptr[len] = '\0';
return stack_alloc_chptr;
}
const char*
span_str(const char* src, Span s, char* stack_alloc_chptr)
{
return range_str(src, s.start, s.end, stack_alloc_chptr);
}
bool
span_ident_same(Span a, Span b, const char* src)
{
const char* a_name = span_str(src, a, (char[IDENTSZ]) { 0 });
const char* b_name = span_str(src, b, (char[IDENTSZ]) { 0 });
return strcmp(a_name, b_name) == 0;
}
// int span_to_str(const char* src, size_t start, size_t end, char* out_buf) {
// if (!src || !out_buf) return -1; /* Null pointer passed */
// if (start >= end) return -2; /* Empty or inverted span */
// const size_t len = end - start;
// if (len >= IDENTSZ) return -4; /* Identifier too long */
// const char* src_end = strchr(src, '\0');
// if (!src_end) return -5; /* src not NUL‑terminated */
// const size_t src_len = (size_t)(src_end - src);
// if (end > src_len) return -6; /* Span overruns source */
// if (memchr(src + start, '\0', len))
// return -7; /* span crosses a NUL byte */
// memcpy(out_buf, src + start, len);
// out_buf[len] = '\0';
// return 0;
// }
// char* span_to_str_alloc(const char* src, size_t start, size_t end) {
// if (!src || start >= end) return NULL;
// const char* src_end = strchr(src, '\0');
// if (!src_end) return NULL;
// size_t src_len = (size_t)(src_end - src);
// if (end > src_len) return NULL;
// size_t n = end - start;
// if (memchr(src + start, '\0', n)) return NULL;
// char* s = calloc(1, n + 1);
// if (!s) return NULL;
// memcpy(s, src + start, n);
// s[n] = '\0';
// return s;
// }
static void
print_node(const char* source, Node* node, int level)
{
assert(node != NULL);
assert(level < 192);
const char* name;
switch (node->type) {
case NODE_FUNCTION_DECL:
name = range_str(
source, node->data.function_decl.name.start, node->data.function_decl.name.end, (char[IDENTSZ]) { 0 });
printf("%*s FUNC DECL: name='%s'\n", level, "", name);
if (node->data.function_decl.return_type) {
printf("%*s ↳ return type:\n", level * 2, "");
print_node(source, node->data.function_decl.return_type, level + 1);
}
if (node->data.function_decl.params) {
printf("%*s ↳ params:\n", level * 2, "");
for (size_t i = 0; i < node->data.function_decl.p_len; i++) {
Node* param = node->data.function_decl.params[i];
print_node(source, param, level + 1);
}
} else {
printf("%*s ↳ params: N/A\n", level * 2, "");
}
if (node->data.function_decl.body) {
printf("%*s ↳ body:\n", level * 2, "");
print_node(source, node->data.function_decl.body, level + 1);
}
break;
case NODE_PARAM:
name = range_str(source, node->data.param.name.start, node->data.param.name.end, (char[IDENTSZ]) { 0 });
printf("%*s ↳ param: name='%s'\n", level * 2, "", name);
if (node->data.param.type) { print_node(source, node->data.param.type, level + 1); }
break;
case NODE_VAR_DECL:
name = range_str(source, node->data.var_decl.name.start, node->data.var_decl.name.end, (char[IDENTSZ]) { 0 });
printf("%*s VAR DECL: name='%s'\n", level, "", name);
if (node->data.var_decl.type) {
printf("%*s ↳ type:\n", level * 2, "");
print_node(source, node->data.var_decl.type, level + 1);
}
if (node->data.var_decl.init) {
printf("%*s ↳ init:\n", level * 2, "");
print_node(source, node->data.var_decl.init, level + 1);
}
break;
case NODE_PROGRAM:
printf("%*s PROGRAM:\n", level, "");
if (node->data.program.decl) {
for (size_t i = 0; i < node->data.program.len; i++) {
print_node(source, node->data.program.decl[i], level + 1);
}
}
break;
case NODE_BLOCK:
printf("%*s BLOCK:\n", level, "");
if (node->data.block.stmts) {
for (size_t i = 0; i < node->data.block.len; i++) {
print_node(source, node->data.block.stmts[i], level + 1);
}
}
break;
case NODE_CALL_EXPR:
printf("%*s ↳ FUNC CALL:\n", level, "");
if (node->data.call_expr.callee) {
printf("%*s ↳ callee:\n", level * 2, "");
print_node(source, node->data.call_expr.callee, level + 1);
}
if (node->data.call_expr.args) {
printf("%*s ↳ args:\n", level * 2, "");
for (size_t i = 0; i < node->data.call_expr.len; i++) {
Node* arg = node->data.call_expr.args[i];
print_node(source, arg, level + 1);
}
}
break;
case NODE_RETURN:
printf("%*s RETURN statement:\n", level, "");
if (node->data.ret.expr) { print_node(source, node->data.ret.expr, level + 1); }
break;
case NODE_CONTINUE:
printf("%*s CONTINUE statement\n", level, "");
if (node->data.cont.expr) { print_node(source, node->data.cont.expr, level + 1); }
break;
case NODE_INT_LITERAL:
printf("%*s ↳ LITERAL INT NUMBER value=%f\n", level * 2, "", node->data.number.value);
break;
case NODE_FLOAT_LITERAL:
printf("%*s ↳ LITERAL FLOAT NUMBER value=%f\n", level * 2, "", node->data.number.value);
break;
case NODE_BOOL_LITERAL:
if (node->data.boolean.value)
printf("%*s LITERAL BOOL TRUE\n", level * 2, "");
else
printf("%*s LITERAL BOOL FALSE\n", level * 2, "");
break;
case NODE_STRING_LITERAL: {
const char* lit = span_str(source, node->data.string.value, (char[IDENTSZ]) { 0 });
printf("%*s ↳ LITERAL STRING value=\"%s\"\n", level * 2, "", lit);
break;
}
case NODE_TYPE:
name = range_str(source, node->data.ident.name.start, node->data.ident.name.end, (char[IDENTSZ]) { 0 });
printf("%*s ↳ TYPE name='%s'\n", level * 2, "", name);
break;
case NODE_IDENT:
name = range_str(source, node->data.ident.name.start, node->data.ident.name.end, (char[IDENTSZ]) { 0 });
printf("%*s ↳ IDENT name='%s'\n", level * 2, "", name);
break;
// case NODE_VOID:
// printf("%*s <VOID>\n", level * 2, "");
// break;
// case NODE_FLOAT:
// printf("%*s <FLOAT>\n", level * 2, "");
// break;
// case NODE_INT:
// printf("%*s <INT>\n", level * 2, "");
// break;
// case NODE_STRING:
// printf("%*s <STRING>\n", level * 2, "");
// break;
case NODE_UNKNOWN:
break;
case NODE_VAR_ASSIGN: {
const Span name_s = node->data.var_assign.lhs->data.ident.name;
name = range_str(source, name_s.start, name_s.end, (char[IDENTSZ]) { 0 });
printf("%*s VAR ASSIGN: name='%s'\n", level, "", name);
break;
}
case NODE_BREAK:
printf("%*s BREAK statement\n", level, "");
break;
case NODE_BINARY_EXPR:
printf("%*s BINARY EXPR op='%c'\n", level, "", node->data.binary_expr.op);
if (node->data.binary_expr.lhs) {
printf("%*s ↳ lhs:\n", level * 2, "");
print_node(source, node->data.binary_expr.lhs, level + 1);
}
if (node->data.binary_expr.rhs) {
printf("%*s ↳ rhs:\n", level * 2, "");
print_node(source, node->data.binary_expr.rhs, level + 1);
}
break;
case NODE_UNARY_EXPR:
printf("%*s UNARY EXPR: op='%d' is_postfix='%s'\n",
level,
"",
node->data.unary_expr.op,
node->data.unary_expr.is_postfix ? "true" : "false");
if (node->data.unary_expr.operand) {
printf("%*s ↳ operand:\n", level * 2, "");
print_node(source, node->data.unary_expr.operand, level + 1);
}
break;
case NODE_EXPR_STATEMENT:
printf("%*s EXPR STMT:\n", level, "");
if (node->data.expr_statement.expr) { print_node(source, node->data.expr_statement.expr, level + 1); }
break;
case NODE_SUBSCRIPT_EXPR:
printf("%*s SUBSCRIPT expr:\n", level, "");
if (node->data.subscript_expr.array) {
printf("%*s ↳ array:\n", level * 2, "");
print_node(source, node->data.subscript_expr.array, level + 1);
}
if (node->data.subscript_expr.index) {
printf("%*s ↳ index:\n", level * 2, "");
print_node(source, node->data.subscript_expr.index, level + 1);
}
break;
case NODE_IF:
printf("%*s IF Statement:\n", level, "");
if (node->data.if_statement.cond) {
printf("%*s ↳ cond:\n", level * 2, "");
print_node(source, node->data.if_statement.cond, level + 1);
}
if (node->data.if_statement.then_body) {
printf("%*s ↳ then body:\n", level * 2, "");
print_node(source, node->data.if_statement.then_body, level + 1);
}
if (node->data.if_statement.else_body) {
printf("%*s ↳ else body:\n", level * 2, "");
print_node(source, node->data.if_statement.else_body, level + 1);
}
break;
case NODE_WHILE:
printf("%*s WHILE Statement:\n", level, "");
if (node->data.while_statement.cond) {
printf("%*s ↳ cond:\n", level * 2, "");
print_node(source, node->data.while_statement.cond, level + 1);
}
if (node->data.while_statement.body) {
printf("%*s ↳ body:\n", level * 2, "");
print_node(source, node->data.while_statement.body, level + 1);
}
break;
case NODE_FOR:
printf("%*s FOR Statement:\n", level, "");
if (node->data.for_statement.init) {
printf("%*s ↳ init:\n", level * 2, "");
print_node(source, node->data.for_statement.init, level + 1);
}
if (node->data.for_statement.cond) {
printf("%*s ↳ cond:\n", level * 2, "");
print_node(source, node->data.for_statement.cond, level + 1);
}
if (node->data.for_statement.increment) {
printf("%*s ↳ increment:\n", level * 2, "");
print_node(source, node->data.for_statement.increment, level + 1);
}
if (node->data.for_statement.body) {
printf("%*s ↳ body:\n", level * 2, "");
print_node(source, node->data.for_statement.body, level + 1);
}
break;
case NODE_EMPTY_STATEMENT:
printf("%*s EMPTY Statement\n", level, "");
break;
}
while (node->next) {
print_node(source, node->next, level);
node = node->next;
}
}
void
ast_print(Ast* ast)
{
print_node(ast->src, ast->node, 0);
}
void
print_node_type_str(NodeType t)
{
printf("print_node_type_str: %s\n", node_type_str(t));
}
const char*
node_type_str(NodeType t)
{
static const char* type_strings[] = { [NODE_PROGRAM] = "NODE_PROGRAM",
[NODE_FUNCTION_DECL] = "NODE_FUNCTION_DECL",
[NODE_PARAM] = "NODE_PARAM",
[NODE_VAR_DECL] = "NODE_VAR_DECL",
[NODE_BLOCK] = "NODE_BLOCK",
[NODE_CALL_EXPR] = "NODE_CALL_EXPR",
[NODE_RETURN] = "NODE_RETURN",
[NODE_CONTINUE] = "NODE_CONTINUE",
[NODE_INT_LITERAL] = "NODE_INT_LITERAL",
[NODE_FLOAT_LITERAL] = "NODE_FLOAT_LITERAL",
[NODE_STRING_LITERAL] = "NODE_STRING_LITERAL",
[NODE_TYPE] = "NODE_TYPE",
[NODE_IDENT] = "NODE_IDENT",
[NODE_UNKNOWN] = "NODE_UNKNOWN",
[NODE_VAR_ASSIGN] = "NODE_VAR_ASSIGN",
[NODE_BREAK] = "NODE_BREAK",
[NODE_BINARY_EXPR] = "NODE_BINARY_EXPR",
[NODE_UNARY_EXPR] = "NODE_UNARY_EXPR",
[NODE_EXPR_STATEMENT] = "NODE_EXPR_STATEMENT",
[NODE_SUBSCRIPT_EXPR] = "NODE_SUBSCRIPT_EXPR",
[NODE_IF] = "NODE_IF",
[NODE_WHILE] = "NODE_WHILE",
[NODE_FOR] = "NODE_FOR",
[NODE_EMPTY_STATEMENT] = "NODE_EMPTY_STATEMENT" };
if (t >= NODE_PROGRAM && t <= NODE_EMPTY_STATEMENT) {
return type_strings[t];
} else {
return "UNKNOWN_NODE_TYPE";
}
}