feat: add code style rules
This commit is contained in:
+131
-122
@@ -1,25 +1,27 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char last_err[256];
|
||||
|
||||
fzl_parser_t *fzl_mkparser(fzl_reader_ll_t *first)
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err), "token is null");
|
||||
return NULL;
|
||||
}
|
||||
if (!first)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err), "token is null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_parser_t *parser = malloc(sizeof(fzl_parser_t));
|
||||
if (!parser) return NULL;
|
||||
fzl_parser_t *parser = malloc(sizeof(fzl_parser_t));
|
||||
if (!parser)
|
||||
return NULL;
|
||||
|
||||
parser->root = NULL;
|
||||
parser->cursor = first->next;
|
||||
if (!parser->cursor) return NULL;
|
||||
parser->root = NULL;
|
||||
parser->cursor = first->next;
|
||||
if (!parser->cursor)
|
||||
return NULL;
|
||||
|
||||
return parser;
|
||||
return parser;
|
||||
}
|
||||
|
||||
// --- Parse zone ---
|
||||
@@ -27,56 +29,61 @@ fzl_parser_t *fzl_mkparser(fzl_reader_ll_t *first)
|
||||
// Make a new node
|
||||
fzl_node_t *fzl_mknode(fzl_nodetype_t type, fzl_token_t *token)
|
||||
{
|
||||
fzl_node_t *node = malloc(sizeof(fzl_node_t));
|
||||
fzl_node_t *node = malloc(sizeof(fzl_node_t));
|
||||
|
||||
if (!node) return NULL;
|
||||
node->type = type;
|
||||
node->token = token;
|
||||
node->parent = NULL;
|
||||
node->next = NULL;
|
||||
if (!node)
|
||||
return NULL;
|
||||
node->type = type;
|
||||
node->token = token;
|
||||
node->parent = NULL;
|
||||
node->next = NULL;
|
||||
|
||||
return node;
|
||||
return node;
|
||||
}
|
||||
|
||||
// Get token at cursor
|
||||
static fzl_token_t *peek(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser->cursor) return NULL;
|
||||
return parser->cursor->token;
|
||||
if (!parser->cursor)
|
||||
return NULL;
|
||||
return parser->cursor->token;
|
||||
}
|
||||
|
||||
// Get token at (cursor + 1)
|
||||
static fzl_token_t *next(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser->cursor) return NULL;
|
||||
|
||||
fzl_reader_ll_t *next = parser->cursor->next;
|
||||
if (!next) return NULL;
|
||||
if (!parser->cursor)
|
||||
return NULL;
|
||||
|
||||
return next->token;
|
||||
fzl_reader_ll_t *next = parser->cursor->next;
|
||||
if (!next)
|
||||
return NULL;
|
||||
|
||||
return next->token;
|
||||
}
|
||||
|
||||
// Consume token at cursor and move to the next
|
||||
static fzl_token_t *consume(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser->cursor) return NULL;
|
||||
fzl_token_t *tok = parser->cursor->token;
|
||||
parser->cursor = parser->cursor->next;
|
||||
return tok;
|
||||
if (!parser->cursor)
|
||||
return NULL;
|
||||
fzl_token_t *tok = parser->cursor->token;
|
||||
parser->cursor = parser->cursor->next;
|
||||
return tok;
|
||||
}
|
||||
|
||||
// Parse primary
|
||||
fzl_node_t *parse_primary(fzl_parser_t *parser)
|
||||
{
|
||||
if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_STR_LITERAL)
|
||||
{
|
||||
fzl_token_t *tok = consume(parser);
|
||||
return fzl_mknode(FZL_NODETYPE_LITERAL, tok);
|
||||
}
|
||||
if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_STR_LITERAL)
|
||||
{
|
||||
fzl_token_t *tok = consume(parser);
|
||||
return fzl_mknode(FZL_NODETYPE_LITERAL, tok);
|
||||
}
|
||||
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"failed to parse primary at %d", peek(parser)->i0);
|
||||
return NULL;
|
||||
snprintf(last_err, sizeof(last_err), "failed to parse primary at %d",
|
||||
peek(parser)->i0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *parse_expression(fzl_parser_t *parser, int precedence);
|
||||
@@ -84,131 +91,133 @@ fzl_node_t *parse_expression(fzl_parser_t *parser, int precedence);
|
||||
// Parse call expression
|
||||
fzl_node_t *parse_call(fzl_parser_t *parser)
|
||||
{
|
||||
fzl_token_t *tok = consume(parser); // <NAME>
|
||||
consume(parser); // (
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_CALL, tok);
|
||||
node->list.entry_count = 0;
|
||||
fzl_token_t *tok = consume(parser); // <NAME>
|
||||
consume(parser); // (
|
||||
|
||||
size_t capacity = 4;
|
||||
node->list.entries = malloc(capacity * sizeof(fzl_node_t*));
|
||||
node->list.entry_count = 0;
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_CALL, tok);
|
||||
node->list.entry_count = 0;
|
||||
|
||||
if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_RPAIR)
|
||||
{
|
||||
consume(parser);
|
||||
return node;
|
||||
}
|
||||
size_t capacity = 4;
|
||||
node->list.entries = malloc(capacity * sizeof(fzl_node_t *));
|
||||
node->list.entry_count = 0;
|
||||
|
||||
while (peek(parser) && peek(parser)->type != FZL_TOKTYPE_RPAIR)
|
||||
{
|
||||
fzl_node_t *arg = parse_expression(parser, 0);
|
||||
if (!arg) return NULL;
|
||||
if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_RPAIR)
|
||||
{
|
||||
consume(parser);
|
||||
return node;
|
||||
}
|
||||
|
||||
if (node->list.entry_count == capacity)
|
||||
{
|
||||
capacity *= 2;
|
||||
node->list.entries = realloc(node->list.entries, capacity * sizeof(fzl_node_t*));
|
||||
}
|
||||
while (peek(parser) && peek(parser)->type != FZL_TOKTYPE_RPAIR)
|
||||
{
|
||||
fzl_node_t *arg = parse_expression(parser, 0);
|
||||
if (!arg)
|
||||
return NULL;
|
||||
|
||||
node->list.entries[node->list.entry_count++] = arg;
|
||||
if (node->list.entry_count == capacity)
|
||||
{
|
||||
capacity *= 2;
|
||||
node->list.entries =
|
||||
realloc(node->list.entries, capacity * sizeof(fzl_node_t *));
|
||||
}
|
||||
|
||||
if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_COMMA)
|
||||
consume(parser);
|
||||
else if (peek(parser) && peek(parser)->type != FZL_TOKTYPE_RPAIR)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err), "expected ',' or ')' after arg list");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
node->list.entries[node->list.entry_count++] = arg;
|
||||
|
||||
consume(parser);
|
||||
return node;
|
||||
if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_COMMA)
|
||||
consume(parser);
|
||||
else if (peek(parser) && peek(parser)->type != FZL_TOKTYPE_RPAIR)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"expected ',' or ')' after arg list");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
consume(parser);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Expression parsing
|
||||
fzl_node_t *parse_expression(fzl_parser_t *parser, int precedence)
|
||||
{
|
||||
if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_NAME)
|
||||
{
|
||||
if (next(parser) && next(parser)->type == FZL_TOKTYPE_LPAIR)
|
||||
return parse_call(parser);
|
||||
}
|
||||
else if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_STR_LITERAL)
|
||||
return parse_primary(parser);
|
||||
if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_NAME)
|
||||
{
|
||||
if (next(parser) && next(parser)->type == FZL_TOKTYPE_LPAIR)
|
||||
return parse_call(parser);
|
||||
}
|
||||
else if (peek(parser) && peek(parser)->type == FZL_TOKTYPE_STR_LITERAL)
|
||||
return parse_primary(parser);
|
||||
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"failed to parse expression at %d",
|
||||
peek(parser)->i0);
|
||||
return NULL;
|
||||
snprintf(last_err, sizeof(last_err), "failed to parse expression at %d",
|
||||
peek(parser)->i0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Statement parsing
|
||||
fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
{
|
||||
return parse_expression(parser, 0);
|
||||
return parse_expression(parser, 0);
|
||||
}
|
||||
|
||||
// Internal parsing entry point
|
||||
fzl_node_t *parse_program(fzl_parser_t *parser)
|
||||
{
|
||||
fzl_node_t *first = NULL;
|
||||
fzl_node_t *last = NULL;
|
||||
fzl_node_t *node = NULL;
|
||||
while (peek(parser) != NULL)
|
||||
{
|
||||
node = parse_statement(parser);
|
||||
if (!node) return NULL;
|
||||
fzl_node_t *first = NULL;
|
||||
fzl_node_t *last = NULL;
|
||||
fzl_node_t *node = NULL;
|
||||
while (peek(parser) != NULL)
|
||||
{
|
||||
node = parse_statement(parser);
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
if (!last)
|
||||
{
|
||||
first = node;
|
||||
last = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
last->next = node;
|
||||
last = node;
|
||||
}
|
||||
}
|
||||
if (!last)
|
||||
{
|
||||
first = node;
|
||||
last = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
last->next = node;
|
||||
last = node;
|
||||
}
|
||||
}
|
||||
|
||||
if (!first)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err), "empty ;(");
|
||||
return NULL;
|
||||
}
|
||||
if (!first)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err), "empty ;(");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return first;
|
||||
return first;
|
||||
}
|
||||
|
||||
|
||||
// Parse tokens and build AST
|
||||
int fzl_parse(fzl_parser_t *parser)
|
||||
{
|
||||
fzl_node_t *ast = parse_program(parser);
|
||||
if (!ast) return -1;
|
||||
fzl_node_t *ast = parse_program(parser);
|
||||
if (!ast)
|
||||
return -1;
|
||||
|
||||
parser->root = ast;
|
||||
return 0;
|
||||
parser->root = ast;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --- Parse zone end ---
|
||||
|
||||
char *fzl_parser_geterror()
|
||||
{
|
||||
return last_err;
|
||||
}
|
||||
char *fzl_parser_geterror() { return last_err; }
|
||||
|
||||
void fzl_freenode(fzl_node_t *node)
|
||||
{
|
||||
if (!node) return;
|
||||
if (node->token) fzl_freetoken(node->token);
|
||||
free(node);
|
||||
if (!node)
|
||||
return;
|
||||
if (node->token)
|
||||
fzl_freetoken(node->token);
|
||||
free(node);
|
||||
}
|
||||
|
||||
void fzl_freeparser(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser) return;
|
||||
free(parser);
|
||||
if (!parser)
|
||||
return;
|
||||
free(parser);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user