Compare commits
3
Commits
6f54286724
...
f769313169
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f769313169 | ||
|
|
0448be0d38 | ||
|
|
01dabd2bdd |
@@ -65,6 +65,8 @@ if (NOT FZL_SKIP_C)
|
|||||||
src/compiler/parser/pa_class.c
|
src/compiler/parser/pa_class.c
|
||||||
src/compiler/parser/pa_cond.c
|
src/compiler/parser/pa_cond.c
|
||||||
src/compiler/parser/pa_expression.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_factor.c
|
||||||
src/compiler/parser/pa_for.c
|
src/compiler/parser/pa_for.c
|
||||||
src/compiler/parser/pa_function.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_power.c
|
||||||
src/compiler/parser/pa_primary.c
|
src/compiler/parser/pa_primary.c
|
||||||
src/compiler/parser/pa_program.c
|
src/compiler/parser/pa_program.c
|
||||||
|
src/compiler/parser/pa_ref.c
|
||||||
src/compiler/parser/pa_return.c
|
src/compiler/parser/pa_return.c
|
||||||
src/compiler/parser/pa_statement.c
|
src/compiler/parser/pa_statement.c
|
||||||
|
src/compiler/parser/pa_struct.c
|
||||||
src/compiler/parser/pa_term.c
|
src/compiler/parser/pa_term.c
|
||||||
|
src/compiler/parser/pa_typedef.c
|
||||||
src/compiler/parser/pa_unary.c
|
src/compiler/parser/pa_unary.c
|
||||||
src/compiler/parser/pa_while.c
|
src/compiler/parser/pa_while.c
|
||||||
src/compiler/parser/utility.c
|
src/compiler/parser/utility.c
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ build:
|
|||||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release $(COMPARING)
|
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release $(COMPARING)
|
||||||
cmake --build build $(COMPARING)
|
cmake --build build $(COMPARING)
|
||||||
|
|
||||||
install: build-release
|
install:
|
||||||
cmake --install build
|
cmake --install build
|
||||||
|
|
||||||
debug-c: build-debug
|
debug-c: build-debug
|
||||||
|
|||||||
+8
-5
@@ -1,18 +1,21 @@
|
|||||||
extern "libglfw" {
|
extern "libglfw" {
|
||||||
type GLFWwindow = handle;
|
|
||||||
type GLFWmonitor = handle;
|
|
||||||
|
|
||||||
struct GLFWvidmode {
|
// Opaque types
|
||||||
|
type GLFWwindow handle;
|
||||||
|
type GLFWmonitor handle;
|
||||||
|
|
||||||
|
// Struct definition
|
||||||
|
type GLFWvidmode struct {
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int redBits;
|
int redBits;
|
||||||
int greenBits;
|
int greenBits;
|
||||||
int blueBits;
|
int blueBits;
|
||||||
int refreshRate;
|
int refreshRate;
|
||||||
}
|
};
|
||||||
|
|
||||||
/// GLFWvidmode*
|
/// GLFWvidmode*
|
||||||
type GLFWvidmodeRef = ref GLFWvidmode;
|
type GLFWvidmodeRef ref GLFWvidmode;
|
||||||
|
|
||||||
/// Create window with specified [width], [height] and [title]
|
/// Create window with specified [width], [height] and [title]
|
||||||
fn glfw_mkWindow(
|
fn glfw_mkWindow(
|
||||||
|
|||||||
@@ -8,17 +8,31 @@
|
|||||||
// AST node type
|
// AST node type
|
||||||
typedef enum
|
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_BLOCK,
|
||||||
FZL_NODETYPE_CALL,
|
|
||||||
FZL_NODETYPE_LITERAL,
|
FZL_NODETYPE_LITERAL,
|
||||||
FZL_NODETYPE_FMT_STRING,
|
FZL_NODETYPE_FMT_STRING,
|
||||||
|
|
||||||
FZL_NODETYPE_IDENTIFIER,
|
FZL_NODETYPE_IDENTIFIER,
|
||||||
|
|
||||||
FZL_NODETYPE_CONDITIONAL,
|
FZL_NODETYPE_CONDITIONAL,
|
||||||
|
|
||||||
FZL_NODETYPE_FUNCTION,
|
FZL_NODETYPE_FUNCTION,
|
||||||
FZL_NODETYPE_RETURN,
|
FZL_NODETYPE_RETURN,
|
||||||
|
FZL_NODETYPE_CALL,
|
||||||
|
|
||||||
FZL_NODETYPE_CLASS,
|
FZL_NODETYPE_CLASS,
|
||||||
FZL_NODETYPE_FIELD,
|
FZL_NODETYPE_FIELD,
|
||||||
FZL_NODETYPE_CONSTRUCT,
|
FZL_NODETYPE_CONSTRUCT,
|
||||||
|
|
||||||
FZL_NODETYPE_LOOP,
|
FZL_NODETYPE_LOOP,
|
||||||
FZL_NODETYPE_BREAK,
|
FZL_NODETYPE_BREAK,
|
||||||
|
|
||||||
@@ -153,6 +167,46 @@ typedef struct fzl_node
|
|||||||
|
|
||||||
struct fzl_node *body;
|
struct fzl_node *body;
|
||||||
} loop;
|
} 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;
|
} 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_assignment(fzl_parser_t *parser);
|
||||||
fzl_node_t *pa_expression(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_class(fzl_parser_t *parser);
|
||||||
fzl_node_t *pa_function(fzl_parser_t *parser);
|
fzl_node_t *pa_function(fzl_parser_t *parser);
|
||||||
fzl_node_t *pa_return(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_while(fzl_parser_t *parser);
|
||||||
fzl_node_t *pa_loop(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_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_statement(fzl_parser_t *parser);
|
||||||
fzl_node_t *pa_program(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)
|
switch (root->type)
|
||||||
{
|
{
|
||||||
|
case FZL_NODETYPE_REFERENCE:
|
||||||
|
case FZL_NODETYPE_ALIAS:
|
||||||
|
case FZL_NODETYPE_HANDLE:
|
||||||
case FZL_NODETYPE_BREAK:
|
case FZL_NODETYPE_BREAK:
|
||||||
case FZL_NODETYPE_IDENTIFIER:
|
case FZL_NODETYPE_IDENTIFIER:
|
||||||
case FZL_NODETYPE_LITERAL:
|
case FZL_NODETYPE_LITERAL:
|
||||||
break;
|
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_FMT_STRING:
|
||||||
case FZL_NODETYPE_BLOCK:
|
case FZL_NODETYPE_BLOCK:
|
||||||
if (root->list.entries)
|
if (root->list.entries)
|
||||||
|
|||||||
+1
-1
@@ -200,7 +200,7 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
if (i > 0 && i < walker->op_count)
|
if (i > 0 && i < walker->op_count)
|
||||||
printf("->");
|
printf("->");
|
||||||
printf("%lu", walker->ops[i]);
|
printf("%lX", walker->ops[i]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
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_parser.h>
|
||||||
|
#include <compiler/fzl_token.h>
|
||||||
#include <compiler/internals/parser.h>
|
#include <compiler/internals/parser.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -24,6 +25,8 @@ fzl_node_t *pa_statement(fzl_parser_t *parser)
|
|||||||
return pa_loop(parser);
|
return pa_loop(parser);
|
||||||
else if (is(parser, FZL_TOKTYPE_BREAK))
|
else if (is(parser, FZL_TOKTYPE_BREAK))
|
||||||
res = pa_break(parser);
|
res = pa_break(parser);
|
||||||
|
else if (is(parser, FZL_TOKTYPE_EXTERN))
|
||||||
|
return pa_extern(parser);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
res = pa_expression(parser);
|
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/fzl_reader.h>
|
||||||
#include <compiler/internals/reader.h>
|
#include <compiler/internals/reader.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -38,6 +39,26 @@ fzl_token_t *rd_name(fzl_reader_t *reader)
|
|||||||
if (strcmp(value, "class") == 0)
|
if (strcmp(value, "class") == 0)
|
||||||
tok =
|
tok =
|
||||||
fzl_mktoken(FZL_TOKTYPE_CLASS, l.line, l.col, value, size, l.filename);
|
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)
|
else if (strcmp(value, "for") == 0)
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_FOR, l.line, l.col, value, size, l.filename);
|
tok = fzl_mktoken(FZL_TOKTYPE_FOR, l.line, l.col, value, size, l.filename);
|
||||||
else if (strcmp(value, "while") == 0)
|
else if (strcmp(value, "while") == 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user