feat: implement extern block reading and parsing
This commit is contained in:
@@ -65,6 +65,8 @@ if (NOT FZL_SKIP_C)
|
||||
src/compiler/parser/pa_class.c
|
||||
src/compiler/parser/pa_cond.c
|
||||
src/compiler/parser/pa_expression.c
|
||||
src/compiler/parser/pa_extern.c
|
||||
src/compiler/parser/pa_externfn.c
|
||||
src/compiler/parser/pa_factor.c
|
||||
src/compiler/parser/pa_for.c
|
||||
src/compiler/parser/pa_function.c
|
||||
@@ -76,9 +78,12 @@ if (NOT FZL_SKIP_C)
|
||||
src/compiler/parser/pa_power.c
|
||||
src/compiler/parser/pa_primary.c
|
||||
src/compiler/parser/pa_program.c
|
||||
src/compiler/parser/pa_ref.c
|
||||
src/compiler/parser/pa_return.c
|
||||
src/compiler/parser/pa_statement.c
|
||||
src/compiler/parser/pa_struct.c
|
||||
src/compiler/parser/pa_term.c
|
||||
src/compiler/parser/pa_typedef.c
|
||||
src/compiler/parser/pa_unary.c
|
||||
src/compiler/parser/pa_while.c
|
||||
src/compiler/parser/utility.c
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ extern "libglfw" {
|
||||
int greenBits;
|
||||
int blueBits;
|
||||
int refreshRate;
|
||||
}
|
||||
};
|
||||
|
||||
/// GLFWvidmode*
|
||||
type GLFWvidmodeRef ref GLFWvidmode;
|
||||
|
||||
@@ -8,17 +8,31 @@
|
||||
// AST node type
|
||||
typedef enum
|
||||
{
|
||||
FZL_NODETYPE_TYPEDEF,
|
||||
FZL_NODETYPE_HANDLE,
|
||||
FZL_NODETYPE_ALIAS,
|
||||
FZL_NODETYPE_STRUCT,
|
||||
FZL_NODETYPE_REFERENCE,
|
||||
FZL_NODETYPE_EXTERN_FN,
|
||||
|
||||
FZL_NODETYPE_EXTERN,
|
||||
FZL_NODETYPE_BLOCK,
|
||||
FZL_NODETYPE_CALL,
|
||||
|
||||
FZL_NODETYPE_LITERAL,
|
||||
FZL_NODETYPE_FMT_STRING,
|
||||
|
||||
FZL_NODETYPE_IDENTIFIER,
|
||||
|
||||
FZL_NODETYPE_CONDITIONAL,
|
||||
|
||||
FZL_NODETYPE_FUNCTION,
|
||||
FZL_NODETYPE_RETURN,
|
||||
FZL_NODETYPE_CALL,
|
||||
|
||||
FZL_NODETYPE_CLASS,
|
||||
FZL_NODETYPE_FIELD,
|
||||
FZL_NODETYPE_CONSTRUCT,
|
||||
|
||||
FZL_NODETYPE_LOOP,
|
||||
FZL_NODETYPE_BREAK,
|
||||
|
||||
@@ -153,6 +167,46 @@ typedef struct fzl_node
|
||||
|
||||
struct fzl_node *body;
|
||||
} loop;
|
||||
|
||||
// Extern library
|
||||
struct
|
||||
{
|
||||
char *libname;
|
||||
|
||||
struct fzl_node **typedefs;
|
||||
size_t typedefs_count;
|
||||
|
||||
struct fzl_node **fns;
|
||||
size_t fns_count;
|
||||
} ext;
|
||||
|
||||
// Type definition
|
||||
struct
|
||||
{
|
||||
char *typename;
|
||||
struct fzl_node *type;
|
||||
} typedefinition;
|
||||
|
||||
// Structure
|
||||
struct
|
||||
{
|
||||
char *original_name;
|
||||
|
||||
struct fzl_node **entries;
|
||||
size_t entries_count;
|
||||
} structure;
|
||||
|
||||
// External function
|
||||
struct
|
||||
{
|
||||
char *name;
|
||||
char *original_name;
|
||||
|
||||
fzl_token_t *type;
|
||||
|
||||
struct fzl_node **args;
|
||||
size_t args_count;
|
||||
} ext_fn;
|
||||
};
|
||||
} fzl_node_t;
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ fzl_node_t *pa_new(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_assignment(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_expression(fzl_parser_t *parser);
|
||||
|
||||
fzl_node_t *pa_struct(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_ref(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_typedef(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_externfn(fzl_parser_t *parser);
|
||||
|
||||
fzl_node_t *pa_class(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_function(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_return(fzl_parser_t *parser);
|
||||
@@ -38,6 +43,7 @@ fzl_node_t *pa_for(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_while(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_loop(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_break(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_extern(fzl_parser_t *parser);
|
||||
|
||||
fzl_node_t *pa_statement(fzl_parser_t *parser);
|
||||
fzl_node_t *pa_program(fzl_parser_t *parser);
|
||||
|
||||
@@ -94,11 +94,40 @@ void fzl_freeast(fzl_node_t *root)
|
||||
{
|
||||
switch (root->type)
|
||||
{
|
||||
case FZL_NODETYPE_REFERENCE:
|
||||
case FZL_NODETYPE_ALIAS:
|
||||
case FZL_NODETYPE_HANDLE:
|
||||
case FZL_NODETYPE_BREAK:
|
||||
case FZL_NODETYPE_IDENTIFIER:
|
||||
case FZL_NODETYPE_LITERAL:
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_EXTERN:
|
||||
for (size_t i = 0; i < root->ext.typedefs_count; i++)
|
||||
fzl_freeast(root->ext.typedefs[i]);
|
||||
free(root->ext.typedefs);
|
||||
|
||||
for (size_t i = 0; i < root->ext.fns_count; i++)
|
||||
fzl_freeast(root->ext.fns[i]);
|
||||
free(root->ext.fns);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_EXTERN_FN:
|
||||
for (size_t i = 0; i < root->ext_fn.args_count; i++)
|
||||
fzl_freeast(root->ext_fn.args[i]);
|
||||
free(root->ext_fn.args);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_STRUCT:
|
||||
for (size_t i = 0; i < root->structure.entries_count; i++)
|
||||
fzl_freeast(root->structure.entries[i]);
|
||||
free(root->structure.entries);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_TYPEDEF:
|
||||
fzl_freeast(root->typedefinition.type);
|
||||
break;
|
||||
|
||||
case FZL_NODETYPE_FMT_STRING:
|
||||
case FZL_NODETYPE_BLOCK:
|
||||
if (root->list.entries)
|
||||
|
||||
+1
-1
@@ -200,7 +200,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
if (i > 0 && i < walker->op_count)
|
||||
printf("->");
|
||||
printf("%lu", walker->ops[i]);
|
||||
printf("%lX", walker->ops[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/parser.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Parse extern definition
|
||||
fzl_node_t *pa_extern(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser || !peek(parser))
|
||||
return NULL;
|
||||
|
||||
fzl_token_t *kw = consume(parser);
|
||||
if (!kw || kw->type != FZL_TOKTYPE_EXTERN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected 'extern' keyword",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *libname = consume(parser);
|
||||
if (!libname || libname->type != FZL_TOKTYPE_STR_LITERAL)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected library name after 'extern'",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *lbra = consume(parser);
|
||||
if (!lbra || lbra->type != FZL_TOKTYPE_LBRACE)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected '{' after library name",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Typedefs array
|
||||
size_t td_remainder = 2;
|
||||
size_t td_count = 0;
|
||||
fzl_node_t **td = malloc(td_remainder * sizeof(fzl_node_t *));
|
||||
if (!td)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Functions array
|
||||
size_t fn_remainder = 2;
|
||||
size_t fn_count = 0;
|
||||
fzl_node_t **fn = malloc(fn_remainder * sizeof(fzl_node_t *));
|
||||
if (!fn)
|
||||
{
|
||||
free(td);
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
while (peek(parser))
|
||||
{
|
||||
if (is(parser, FZL_TOKTYPE_RBRACE))
|
||||
break;
|
||||
|
||||
if (td_remainder <= td_count)
|
||||
{
|
||||
td_remainder *= 2;
|
||||
fzl_node_t **newarr = realloc(td, td_remainder * sizeof(fzl_node_t *));
|
||||
if (!newarr)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
td = newarr;
|
||||
}
|
||||
|
||||
if (fn_remainder <= fn_count)
|
||||
{
|
||||
fn_remainder *= 2;
|
||||
fzl_node_t **newarr = realloc(fn, fn_remainder * sizeof(fzl_node_t *));
|
||||
if (!newarr)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
fn = newarr;
|
||||
}
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_TYPEDEF))
|
||||
{
|
||||
fzl_node_t *result = pa_typedef(parser);
|
||||
if (!result)
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
td[td_count++] = result;
|
||||
}
|
||||
else if (is(parser, FZL_TOKTYPE_FUNCTION))
|
||||
{
|
||||
fzl_node_t *result = pa_externfn(parser);
|
||||
if (!result)
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
fn[fn_count++] = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => unexpected statement inside extern block",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
fzl_token_t *sc = consume(parser);
|
||||
if (!sc || sc->type != FZL_TOKTYPE_SEMICOLON)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => missing ';'",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
for (size_t i = 0; i < td_count; i++)
|
||||
fzl_freeast(td[i]);
|
||||
free(td);
|
||||
|
||||
for (size_t i = 0; i < fn_count; i++)
|
||||
fzl_freeast(fn[i]);
|
||||
free(fn);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *rbra = consume(parser);
|
||||
if (!rbra || rbra->type != FZL_TOKTYPE_RBRACE)
|
||||
{
|
||||
for (size_t i = 0; i < td_count; i++)
|
||||
fzl_freeast(td[i]);
|
||||
free(td);
|
||||
|
||||
for (size_t i = 0; i < fn_count; i++)
|
||||
fzl_freeast(fn[i]);
|
||||
free(fn);
|
||||
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected '}' after extern block",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_EXTERN, kw);
|
||||
if (!node)
|
||||
{
|
||||
for (size_t i = 0; i < td_count; i++)
|
||||
fzl_freeast(td[i]);
|
||||
free(td);
|
||||
|
||||
for (size_t i = 0; i < fn_count; i++)
|
||||
fzl_freeast(fn[i]);
|
||||
free(fn);
|
||||
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->ext.libname = (char *)libname->value;
|
||||
node->ext.typedefs = td;
|
||||
node->ext.typedefs_count = td_count;
|
||||
node->ext.fns = fn;
|
||||
node->ext.fns_count = fn_count;
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/parser.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Parse external function
|
||||
fzl_node_t *pa_externfn(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser || !peek(parser))
|
||||
return NULL;
|
||||
|
||||
fzl_token_t *tok = consume(parser);
|
||||
if (!tok || tok->type != FZL_TOKTYPE_FUNCTION)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected 'function' keyword",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *name = consume(parser);
|
||||
if (!name || name->type != FZL_TOKTYPE_NAME)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected function name after 'fn'",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *lpar = consume(parser);
|
||||
if (!lpar || lpar->type != FZL_TOKTYPE_LPAREN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected '(' after function name",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t remainder = 2;
|
||||
size_t count = 0;
|
||||
fzl_node_t **args = malloc(remainder * sizeof(fzl_node_t *));
|
||||
if (!args)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (peek(parser) && !is(parser, FZL_TOKTYPE_RPAREN))
|
||||
{
|
||||
if (remainder <= count)
|
||||
{
|
||||
remainder *= 2;
|
||||
fzl_node_t **newarr = realloc(args, remainder * sizeof(fzl_node_t *));
|
||||
if (!newarr)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(args[i]);
|
||||
free(args);
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
args = newarr;
|
||||
}
|
||||
|
||||
bool is_out = false;
|
||||
if (is(parser, FZL_TOKTYPE_OUT))
|
||||
{
|
||||
consume(parser);
|
||||
is_out = true;
|
||||
}
|
||||
(void)is_out;
|
||||
|
||||
fzl_node_t *node = pa_expression(parser);
|
||||
if (!node || node->type != FZL_NODETYPE_DECLARATION)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(args[i]);
|
||||
free(args);
|
||||
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected declaration",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
args[count++] = node;
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_RPAREN))
|
||||
break;
|
||||
|
||||
fzl_token_t *comma = consume(parser);
|
||||
if (!comma || comma->type != FZL_TOKTYPE_COMMA)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(args[i]);
|
||||
free(args);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => missing ',' between arguments",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
fzl_token_t *rpar = consume(parser);
|
||||
if (!rpar || rpar->type != FZL_TOKTYPE_RPAREN)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(args[i]);
|
||||
free(args);
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected ')' after arguments list",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *original_name = NULL;
|
||||
fzl_token_t *type = &null_tok;
|
||||
if (is(parser, FZL_TOKTYPE_NAME) || is(parser, FZL_TOKTYPE_TYPE))
|
||||
type = consume(parser);
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_EQ))
|
||||
{
|
||||
consume(parser);
|
||||
fzl_token_t *orig = consume(parser);
|
||||
|
||||
if (!orig || orig->type != FZL_TOKTYPE_STR_LITERAL)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(args[i]);
|
||||
free(args);
|
||||
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected original function name",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
original_name = (char *)orig->value;
|
||||
}
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_EXTERN_FN, tok);
|
||||
node->ext_fn.name = (char *)name->value;
|
||||
node->ext_fn.original_name = original_name;
|
||||
node->ext_fn.args_count = count;
|
||||
node->ext_fn.args = args;
|
||||
node->ext_fn.type = type;
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/parser.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Parse reference definition
|
||||
fzl_node_t *pa_ref(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser || !peek(parser))
|
||||
return NULL;
|
||||
|
||||
fzl_token_t *tok = consume(parser);
|
||||
if (!tok || tok->type != FZL_TOKTYPE_REFERENCE)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected 'ref' keyword", last_known_tok->filename,
|
||||
last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *name = consume(parser);
|
||||
if (!name || name->type != FZL_TOKTYPE_NAME)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected name after 'ref'",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_REFERENCE, name);
|
||||
if (!node)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/parser.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -24,6 +25,8 @@ fzl_node_t *pa_statement(fzl_parser_t *parser)
|
||||
return pa_loop(parser);
|
||||
else if (is(parser, FZL_TOKTYPE_BREAK))
|
||||
res = pa_break(parser);
|
||||
else if (is(parser, FZL_TOKTYPE_EXTERN))
|
||||
return pa_extern(parser);
|
||||
|
||||
if (!res)
|
||||
res = pa_expression(parser);
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/parser.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Parse structure
|
||||
fzl_node_t *pa_struct(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser || !peek(parser))
|
||||
return NULL;
|
||||
|
||||
fzl_token_t *tok = consume(parser);
|
||||
if (!tok || tok->type != FZL_TOKTYPE_STRUCT)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected 'struct' keyword",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *original = NULL;
|
||||
if (is(parser, FZL_TOKTYPE_NAME))
|
||||
{
|
||||
fzl_token_t *name = consume(parser);
|
||||
if (!name || name->type != FZL_TOKTYPE_NAME)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected struct name after 'struct'",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
original = (char *)name->value;
|
||||
}
|
||||
|
||||
fzl_token_t *lbra = consume(parser);
|
||||
if (!lbra || lbra->type != FZL_TOKTYPE_LBRACE)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected '{' after structure name",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t remainder = 2;
|
||||
size_t count = 0;
|
||||
fzl_node_t **entries = malloc(remainder * sizeof(fzl_node_t *));
|
||||
if (!entries)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (peek(parser))
|
||||
{
|
||||
if (is(parser, FZL_TOKTYPE_RBRACE))
|
||||
break;
|
||||
|
||||
if (remainder <= count)
|
||||
{
|
||||
remainder *= 2;
|
||||
fzl_node_t **newarr = realloc(entries, remainder * sizeof(fzl_node_t *));
|
||||
if (!newarr)
|
||||
{
|
||||
free(entries);
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
entries = newarr;
|
||||
}
|
||||
|
||||
fzl_node_t *entry = pa_statement(parser);
|
||||
if (!entry)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(entries[i]);
|
||||
free(entries);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (entry->type != FZL_NODETYPE_DECLARATION &&
|
||||
entry->type != FZL_NODETYPE_IDENTIFIER)
|
||||
{
|
||||
fzl_freeast(entry);
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(entries[i]);
|
||||
free(entries);
|
||||
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => structure entry must be a declaration or "
|
||||
"another structure name",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entries[count++] = entry;
|
||||
}
|
||||
|
||||
fzl_token_t *rbra = consume(parser);
|
||||
if (!rbra || rbra->type != FZL_TOKTYPE_RBRACE)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(entries[i]);
|
||||
free(entries);
|
||||
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected '}' after structure fields",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_STRUCT, tok);
|
||||
if (!node)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
fzl_freeast(entries[i]);
|
||||
free(entries);
|
||||
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->structure.original_name = original;
|
||||
node->structure.entries = entries;
|
||||
node->structure.entries_count = count;
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_token.h>
|
||||
#include <compiler/internals/parser.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Parse type definition
|
||||
fzl_node_t *pa_typedef(fzl_parser_t *parser)
|
||||
{
|
||||
if (!parser || !peek(parser))
|
||||
return NULL;
|
||||
|
||||
fzl_token_t *tok = consume(parser);
|
||||
if (!tok || tok->type != FZL_TOKTYPE_TYPEDEF)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected 'type' keyword",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *name = consume(parser);
|
||||
if (!name || name->type != FZL_TOKTYPE_NAME)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => expected type name after 'type'",
|
||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *result = NULL;
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_HANDLE))
|
||||
{
|
||||
result = fzl_mknode(FZL_NODETYPE_HANDLE, consume(parser));
|
||||
if (!result)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (is(parser, FZL_TOKTYPE_STRUCT))
|
||||
{
|
||||
result = pa_struct(parser);
|
||||
}
|
||||
else if (is(parser, FZL_TOKTYPE_TYPE))
|
||||
{
|
||||
result = fzl_mknode(FZL_NODETYPE_ALIAS, consume(parser));
|
||||
if (!result)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (is(parser, FZL_TOKTYPE_REFERENCE))
|
||||
{
|
||||
result = pa_ref(parser);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
if (!plast_err[0])
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"'%s':%zu:%zu => unsupported typedef type",
|
||||
last_known_tok->filename, last_known_tok->ln,
|
||||
last_known_tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_TYPEDEF, tok);
|
||||
if (!node)
|
||||
{
|
||||
fzl_freeast(result);
|
||||
snprintf(plast_err, sizeof(plast_err), "out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->typedefinition.typename = (char *)name->value;
|
||||
node->typedefinition.type = result;
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "compiler/fzl_token.h"
|
||||
#include <compiler/fzl_reader.h>
|
||||
#include <compiler/internals/reader.h>
|
||||
#include <stdio.h>
|
||||
@@ -38,6 +39,26 @@ fzl_token_t *rd_name(fzl_reader_t *reader)
|
||||
if (strcmp(value, "class") == 0)
|
||||
tok =
|
||||
fzl_mktoken(FZL_TOKTYPE_CLASS, l.line, l.col, value, size, l.filename);
|
||||
else if (strcmp(value, "import") == 0)
|
||||
tok =
|
||||
fzl_mktoken(FZL_TOKTYPE_IMPORT, l.line, l.col, value, size, l.filename);
|
||||
else if (strcmp(value, "extern") == 0)
|
||||
tok =
|
||||
fzl_mktoken(FZL_TOKTYPE_EXTERN, l.line, l.col, value, size, l.filename);
|
||||
else if (strcmp(value, "type") == 0)
|
||||
tok = fzl_mktoken(FZL_TOKTYPE_TYPEDEF, l.line, l.col, value, size,
|
||||
l.filename);
|
||||
else if (strcmp(value, "handle") == 0)
|
||||
tok =
|
||||
fzl_mktoken(FZL_TOKTYPE_HANDLE, l.line, l.col, value, size, l.filename);
|
||||
else if (strcmp(value, "struct") == 0)
|
||||
tok =
|
||||
fzl_mktoken(FZL_TOKTYPE_STRUCT, l.line, l.col, value, size, l.filename);
|
||||
else if (strcmp(value, "ref") == 0)
|
||||
tok = fzl_mktoken(FZL_TOKTYPE_REFERENCE, l.line, l.col, value, size,
|
||||
l.filename);
|
||||
else if (strcmp(value, "out") == 0)
|
||||
tok = fzl_mktoken(FZL_TOKTYPE_OUT, l.line, l.col, value, size, l.filename);
|
||||
else if (strcmp(value, "for") == 0)
|
||||
tok = fzl_mktoken(FZL_TOKTYPE_FOR, l.line, l.col, value, size, l.filename);
|
||||
else if (strcmp(value, "while") == 0)
|
||||
|
||||
Reference in New Issue
Block a user