feat: implement extern block reading and parsing

This commit is contained in:
samsonium
2026-10-29 22:13:28 +03:00
parent 0448be0d38
commit f769313169
13 changed files with 719 additions and 3 deletions
+5
View File
@@ -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
View File
@@ -12,7 +12,7 @@ extern "libglfw" {
int greenBits;
int blueBits;
int refreshRate;
}
};
/// GLFWvidmode*
type GLFWvidmodeRef ref GLFWvidmode;
+55 -1
View File
@@ -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;
+6
View File
@@ -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);
+29
View File
@@ -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
View File
@@ -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");
+192
View File
@@ -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;
}
+154
View File
@@ -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;
}
+38
View File
@@ -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;
}
+3
View File
@@ -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);
+133
View File
@@ -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;
}
+81
View File
@@ -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;
}
+21
View File
@@ -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)