wip: working on classes
This commit is contained in:
@@ -65,6 +65,10 @@ add_test(
|
|||||||
NAME compile_comment
|
NAME compile_comment
|
||||||
COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/comment.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/comment.fzs"
|
COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/comment.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/comment.fzs"
|
||||||
)
|
)
|
||||||
|
add_test(
|
||||||
|
NAME compile_class
|
||||||
|
COMMAND fzc -o "${CMAKE_CURRENT_BINARY_DIR}/class.fzb" "${CMAKE_CURRENT_SOURCE_DIR}/exl/class.fzs"
|
||||||
|
)
|
||||||
|
|
||||||
set_tests_properties(compile_problematic_hw PROPERTIES WILL_FAIL TRUE)
|
set_tests_properties(compile_problematic_hw PROPERTIES WILL_FAIL TRUE)
|
||||||
|
|
||||||
@@ -100,4 +104,8 @@ add_test(
|
|||||||
NAME runtime_comment
|
NAME runtime_comment
|
||||||
COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/comment.fzb"
|
COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/comment.fzb"
|
||||||
)
|
)
|
||||||
|
add_test(
|
||||||
|
NAME runtime_class
|
||||||
|
COMMAND fz "${CMAKE_CURRENT_BINARY_DIR}/class.fzb"
|
||||||
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
class Point
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
// Move point by [dx,dy]
|
||||||
|
fn move(int dx, int dy) {
|
||||||
|
this.x = this.x + dx;
|
||||||
|
this.y = this.y + dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: WHY THE FUCK THIS FUCKING COMPILER REQUIRES ';' AFTER '='?!
|
||||||
|
// |
|
||||||
|
// v
|
||||||
|
Point obj = new Point;
|
||||||
|
obj.x = 1;
|
||||||
|
obj.y = 2;
|
||||||
|
|
||||||
|
printline("Current X,Y:");
|
||||||
|
printline(obj.x);
|
||||||
|
printline(obj.y);
|
||||||
|
|
||||||
|
obj.move(9, 8);
|
||||||
|
printline("X,Y after move:");
|
||||||
|
printline(obj.x);
|
||||||
|
printline(obj.y);
|
||||||
|
|
||||||
|
if (obj.x == 10 && obj.y == 10)
|
||||||
|
printline("Test passed");
|
||||||
|
else printline("Test failed");
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef FZL_PARSER_H
|
#ifndef FZL_PARSER_H
|
||||||
#define FZL_PARSER_H
|
#define FZL_PARSER_H
|
||||||
|
|
||||||
#include "common/fzl_types.h"
|
|
||||||
#include <compiler/fzl_reader.h>
|
#include <compiler/fzl_reader.h>
|
||||||
#include <compiler/fzl_token.h>
|
#include <compiler/fzl_token.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -16,6 +15,8 @@ typedef enum
|
|||||||
FZL_NODETYPE_CONDITIONAL,
|
FZL_NODETYPE_CONDITIONAL,
|
||||||
FZL_NODETYPE_FUNCTION,
|
FZL_NODETYPE_FUNCTION,
|
||||||
FZL_NODETYPE_RETURN,
|
FZL_NODETYPE_RETURN,
|
||||||
|
FZL_NODETYPE_CLASS,
|
||||||
|
FZL_NODETYPE_FIELD,
|
||||||
|
|
||||||
FZL_NODETYPE_ADD,
|
FZL_NODETYPE_ADD,
|
||||||
FZL_NODETYPE_SUB,
|
FZL_NODETYPE_SUB,
|
||||||
@@ -113,6 +114,25 @@ typedef struct fzl_node
|
|||||||
{
|
{
|
||||||
struct fzl_node *value;
|
struct fzl_node *value;
|
||||||
} ret;
|
} ret;
|
||||||
|
|
||||||
|
// Class declaration
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
fzl_token_t *name;
|
||||||
|
|
||||||
|
struct fzl_node **fields;
|
||||||
|
size_t fields_count;
|
||||||
|
|
||||||
|
struct fzl_node **methods;
|
||||||
|
size_t methods_count;
|
||||||
|
} class;
|
||||||
|
|
||||||
|
// Member access
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct fzl_node *parent;
|
||||||
|
struct fzl_node *field;
|
||||||
|
} memb;
|
||||||
};
|
};
|
||||||
} fzl_node_t;
|
} fzl_node_t;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
// Token type
|
// Token type
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
FZL_TOKTYPE_CLASS, // class
|
||||||
|
FZL_TOKTYPE_NEW, // new
|
||||||
|
|
||||||
|
FZL_TOKTYPE_FUNCTION, // fn
|
||||||
FZL_TOKTYPE_RETURN, // return
|
FZL_TOKTYPE_RETURN, // return
|
||||||
|
|
||||||
FZL_TOKTYPE_IF, // if
|
FZL_TOKTYPE_IF, // if
|
||||||
|
|||||||
+279
-97
@@ -170,7 +170,14 @@ fzl_node_t *parse_primary(fzl_parser_t *parser)
|
|||||||
else if (is(parser, FZL_TOKTYPE_NAME))
|
else if (is(parser, FZL_TOKTYPE_NAME))
|
||||||
{
|
{
|
||||||
fzl_token_t *name = consume(parser);
|
fzl_token_t *name = consume(parser);
|
||||||
|
if (!is(parser, FZL_TOKTYPE_NAME))
|
||||||
return fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
|
return fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
|
||||||
|
|
||||||
|
fzl_token_t *realname = consume(parser); // :D
|
||||||
|
fzl_node_t *decl = fzl_mknode(FZL_NODETYPE_DECLARATION, name);
|
||||||
|
decl->var.type = name;
|
||||||
|
decl->var.identifier = fzl_mknode(FZL_NODETYPE_IDENTIFIER, realname);
|
||||||
|
return decl;
|
||||||
}
|
}
|
||||||
else if (is(parser, FZL_TOKTYPE_TYPE))
|
else if (is(parser, FZL_TOKTYPE_TYPE))
|
||||||
{
|
{
|
||||||
@@ -215,6 +222,8 @@ fzl_node_t *parse_postfix(fzl_parser_t *parser)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is(parser, FZL_TOKTYPE_LPAREN))
|
||||||
|
{
|
||||||
while (is(parser, FZL_TOKTYPE_LPAREN))
|
while (is(parser, FZL_TOKTYPE_LPAREN))
|
||||||
{
|
{
|
||||||
consume(parser);
|
consume(parser);
|
||||||
@@ -262,6 +271,24 @@ fzl_node_t *parse_postfix(fzl_parser_t *parser)
|
|||||||
|
|
||||||
left = node;
|
left = node;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (is(parser, FZL_TOKTYPE_DOT))
|
||||||
|
{
|
||||||
|
while (is(parser, FZL_TOKTYPE_DOT))
|
||||||
|
{
|
||||||
|
consume(parser);
|
||||||
|
|
||||||
|
fzl_node_t *right = parse_primary(parser);
|
||||||
|
if (!right)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FIELD, right->token);
|
||||||
|
node->memb.parent = left;
|
||||||
|
node->memb.field = right;
|
||||||
|
|
||||||
|
left = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
@@ -540,38 +567,199 @@ fzl_node_t *parse_or(fzl_parser_t *parser)
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expression parsing
|
// Assignments parsing
|
||||||
fzl_node_t *parse_expression(fzl_parser_t *parser) { return parse_and(parser); }
|
fzl_node_t *parse_assignment(fzl_parser_t *parser)
|
||||||
|
|
||||||
// Statement parsing
|
|
||||||
fzl_node_t *parse_statement(fzl_parser_t *parser)
|
|
||||||
{
|
{
|
||||||
fzl_node_t *res = NULL;
|
fzl_node_t *left = parse_or(parser);
|
||||||
|
if (!left)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (is(parser, FZL_TOKTYPE_TYPE))
|
if (is(parser, FZL_TOKTYPE_EQ))
|
||||||
{
|
{
|
||||||
fzl_token_t *type = peek(parser);
|
fzl_token_t *asn = consume(parser);
|
||||||
if (type->type == FZL_TOKTYPE_TYPE)
|
if (left->type != FZL_NODETYPE_IDENTIFIER &&
|
||||||
consume(parser);
|
left->type != FZL_NODETYPE_DECLARATION &&
|
||||||
|
left->type != FZL_NODETYPE_FIELD)
|
||||||
if (type->type == FZL_TOKTYPE_TYPE &&
|
|
||||||
next(parser)->type == FZL_TOKTYPE_LPAREN)
|
|
||||||
{
|
|
||||||
fzl_token_t *tok = consume(parser);
|
|
||||||
if (tok->type != FZL_TOKTYPE_NAME)
|
|
||||||
{
|
{
|
||||||
snprintf(plast_err, sizeof(plast_err),
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
"'%s': expected name in function definition at %ld:%ld",
|
"'%s': cannot assign to '%s' at %ld:%ld", left->token->filename,
|
||||||
tok->filename, tok->ln, tok->cn);
|
(char *)left->token->value, asn->ln, asn->cn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fzl_token_t *lparen = consume(parser);
|
fzl_node_t *right = parse_assignment(parser);
|
||||||
if (lparen->type != FZL_TOKTYPE_LPAREN)
|
if (!right)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_ASSIGN, asn);
|
||||||
|
node->binary_op.left = left;
|
||||||
|
node->binary_op.right = right;
|
||||||
|
|
||||||
|
left = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expression parsing
|
||||||
|
fzl_node_t *parse_expression(fzl_parser_t *parser)
|
||||||
|
{
|
||||||
|
return parse_assignment(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_node_t *parse_statement(fzl_parser_t *parser);
|
||||||
|
|
||||||
|
// Parse class definition
|
||||||
|
fzl_node_t *parse_class(fzl_parser_t *parser)
|
||||||
|
{
|
||||||
|
if (!parser)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fzl_token_t *class = consume(parser);
|
||||||
|
fzl_token_t *name = consume(parser);
|
||||||
|
if (name->type != FZL_TOKTYPE_NAME)
|
||||||
{
|
{
|
||||||
snprintf(plast_err, sizeof(plast_err),
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
"'%s': expected '(' after name at %ld:%ld", lparen->filename,
|
"'%s': expected class name at %ld:%ld", name->filename, name->ln,
|
||||||
lparen->ln, lparen->cn);
|
name->cn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_token_t *lbrace = consume(parser);
|
||||||
|
if (lbrace->type != FZL_TOKTYPE_LBRACE)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"'%s': expected '{' after class name at %ld:%ld", lbrace->filename,
|
||||||
|
lbrace->ln, lbrace->cn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fremainder = 2;
|
||||||
|
size_t fcount = 0;
|
||||||
|
fzl_node_t **fields = malloc(fremainder * sizeof(fzl_node_t *));
|
||||||
|
if (!fields)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"failed to allocate space for class fields");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mremainder = 2;
|
||||||
|
size_t mcount = 0;
|
||||||
|
fzl_node_t **methods = malloc(mremainder * sizeof(fzl_node_t *));
|
||||||
|
if (!methods)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"failed to allocate space for class fields");
|
||||||
|
free(fields);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!is(parser, FZL_TOKTYPE_RBRACE))
|
||||||
|
{
|
||||||
|
fzl_node_t *node = parse_statement(parser);
|
||||||
|
if (!node)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (node->type == FZL_NODETYPE_DECLARATION)
|
||||||
|
{
|
||||||
|
if (fremainder <= fcount)
|
||||||
|
{
|
||||||
|
fremainder *= 2;
|
||||||
|
fields = realloc(fields, fremainder * sizeof(fzl_node_t *));
|
||||||
|
if (!fields)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"failed to resize fields array");
|
||||||
|
free(methods);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fields[fcount++] = node;
|
||||||
|
}
|
||||||
|
else if (node->type == FZL_NODETYPE_FUNCTION)
|
||||||
|
{
|
||||||
|
if (mremainder <= mcount)
|
||||||
|
{
|
||||||
|
mremainder *= 2;
|
||||||
|
methods = realloc(methods, mremainder * sizeof(fzl_node_t *));
|
||||||
|
if (!methods)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"failed to resize methods array");
|
||||||
|
free(fields);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_node_t **new_args = realloc(node->fn.args, ++node->fn.args_count);
|
||||||
|
memcpy(&new_args[1], new_args,
|
||||||
|
(node->fn.args_count - 1) * sizeof(fzl_node_t *));
|
||||||
|
|
||||||
|
fzl_token_t *this_tok =
|
||||||
|
fzl_mktoken(FZL_TOKTYPE_NAME, node->fn.name->ln, node->fn.name->cn,
|
||||||
|
"this", 4, node->fn.name->filename);
|
||||||
|
fzl_node_t *this_id = fzl_mknode(FZL_NODETYPE_IDENTIFIER, this_tok);
|
||||||
|
fzl_node_t *this_dec = fzl_mknode(FZL_NODETYPE_DECLARATION, name);
|
||||||
|
this_dec->var.type = name;
|
||||||
|
this_dec->var.identifier = this_id;
|
||||||
|
|
||||||
|
new_args[0] = this_dec;
|
||||||
|
methods[mcount++] = node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"'%s': unknown type of class member at %ld:%ld",
|
||||||
|
node->token->filename, node->token->ln, node->token->cn);
|
||||||
|
free(fields);
|
||||||
|
free(methods);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fzl_token_t *rbra = consume(parser);
|
||||||
|
if (rbra->type != FZL_TOKTYPE_RBRACE)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"'%s': expected '}' after class definition at %ld:%ld",
|
||||||
|
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||||
|
free(fields);
|
||||||
|
free(methods);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_CLASS, class);
|
||||||
|
node->class.name = name;
|
||||||
|
node->class.fields = fields;
|
||||||
|
node->class.fields_count = fcount;
|
||||||
|
node->class.methods = methods;
|
||||||
|
node->class.methods_count = mcount;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions parsing
|
||||||
|
fzl_node_t *parse_function(fzl_parser_t *parser)
|
||||||
|
{
|
||||||
|
if (!parser)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fzl_token_t *fn = consume(parser);
|
||||||
|
fzl_token_t *name = consume(parser);
|
||||||
|
if (!name || name->type != FZL_TOKTYPE_NAME)
|
||||||
|
{
|
||||||
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
|
"'%s': expected function name at %ld:%ld",
|
||||||
|
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': expected '(' at %ld:%ld",
|
||||||
|
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,20 +785,28 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
|||||||
consume(parser);
|
consume(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
fzl_token_t *rparen = consume(parser);
|
fzl_token_t *rpar = consume(parser);
|
||||||
if (rparen->type != FZL_TOKTYPE_RPAREN)
|
if (!rpar || rpar->type != FZL_TOKTYPE_RPAREN)
|
||||||
{
|
{
|
||||||
snprintf(plast_err, sizeof(plast_err),
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
"'%s': expected ')' after argument list at %ld:%ld",
|
"'%s': expected ')' after argument list at %ld:%ld",
|
||||||
rparen->filename, rparen->ln, rparen->cn);
|
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fzl_token_t *type;
|
||||||
|
if (is(parser, FZL_TOKTYPE_TYPE) || is(parser, FZL_TOKTYPE_NAME))
|
||||||
|
type = consume(parser);
|
||||||
|
|
||||||
|
if (!type)
|
||||||
|
type = fzl_mktoken(FZL_TOKTYPE_TYPE, last_known_tok->ln, last_known_tok->cn,
|
||||||
|
"null", 4, last_known_tok->filename);
|
||||||
|
|
||||||
if (!is(parser, FZL_TOKTYPE_LBRACE))
|
if (!is(parser, FZL_TOKTYPE_LBRACE))
|
||||||
{
|
{
|
||||||
fzl_token_t *tok = peek(parser);
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
snprintf(plast_err, sizeof(plast_err), "'%s': expected '{' at %ld:%ld",
|
"'%s': expected '{' after function declaration at %ld:%ld",
|
||||||
tok->filename, tok->ln, tok->cn);
|
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,77 +814,22 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
|||||||
if (!body)
|
if (!body)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FUNCTION, tok);
|
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FUNCTION, name);
|
||||||
node->fn.args = args;
|
node->fn.args = args;
|
||||||
node->fn.args_count = count;
|
node->fn.args_count = count;
|
||||||
node->fn.body = body;
|
node->fn.body = body;
|
||||||
node->fn.name = tok;
|
node->fn.name = name;
|
||||||
node->fn.type = type;
|
node->fn.type = type;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
else if (type->type == FZL_TOKTYPE_TYPE ||
|
|
||||||
next(parser)->type == FZL_TOKTYPE_EQ)
|
|
||||||
{
|
|
||||||
|
|
||||||
fzl_node_t *identifier = parse_primary(parser);
|
// Return parsing
|
||||||
if (!identifier || identifier->type != FZL_NODETYPE_IDENTIFIER)
|
fzl_node_t *parse_return(fzl_parser_t *parser)
|
||||||
{
|
{
|
||||||
snprintf(plast_err, sizeof(plast_err),
|
if (!parser)
|
||||||
"'%s': expected identifier at %ld:%ld", type->filename,
|
|
||||||
type->ln, type->cn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fzl_node_t *left = fzl_mknode(FZL_NODETYPE_DECLARATION, type);
|
|
||||||
left->var.type = type;
|
|
||||||
left->var.identifier = identifier;
|
|
||||||
|
|
||||||
if (is(parser, FZL_TOKTYPE_EQ))
|
|
||||||
{
|
|
||||||
fzl_node_t *right;
|
|
||||||
while (is(parser, FZL_TOKTYPE_EQ))
|
|
||||||
{
|
|
||||||
fzl_token_t *asn = consume(parser);
|
|
||||||
right = parse_expression(parser);
|
|
||||||
if (!right)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_ASSIGN, asn);
|
|
||||||
node->binary_op.left = left;
|
|
||||||
node->binary_op.right = right;
|
|
||||||
|
|
||||||
left = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res = left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (is(parser, FZL_TOKTYPE_NAME) && next(parser)->type == FZL_TOKTYPE_EQ)
|
|
||||||
{
|
|
||||||
fzl_token_t *name = consume(parser);
|
|
||||||
fzl_node_t *left = fzl_mknode(FZL_NODETYPE_IDENTIFIER, name);
|
|
||||||
|
|
||||||
while (is(parser, FZL_TOKTYPE_EQ))
|
|
||||||
{
|
|
||||||
fzl_token_t *eq = consume(parser);
|
|
||||||
|
|
||||||
fzl_node_t *right = parse_expression(parser);
|
|
||||||
if (!right)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
fzl_node_t *assn = fzl_mknode(FZL_NODETYPE_ASSIGN, eq);
|
|
||||||
assn->binary_op.left = left;
|
|
||||||
assn->binary_op.right = right;
|
|
||||||
|
|
||||||
left = assn;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = left;
|
|
||||||
}
|
|
||||||
else if (is(parser, FZL_TOKTYPE_RETURN))
|
|
||||||
{
|
|
||||||
fzl_token_t *ret = consume(parser);
|
fzl_token_t *ret = consume(parser);
|
||||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_RETURN, ret);
|
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_RETURN, ret);
|
||||||
|
|
||||||
@@ -701,17 +842,21 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
|||||||
node->ret.value = retval;
|
node->ret.value = retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = node;
|
return node;
|
||||||
}
|
}
|
||||||
else if (is(parser, FZL_TOKTYPE_IF))
|
|
||||||
|
fzl_node_t *parse_if(fzl_parser_t *parser)
|
||||||
{
|
{
|
||||||
|
if (!parser)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
fzl_token_t *if_tok = consume(parser);
|
fzl_token_t *if_tok = consume(parser);
|
||||||
fzl_token_t *lparen = consume(parser);
|
fzl_token_t *lparen = consume(parser);
|
||||||
if (lparen->type != FZL_TOKTYPE_LPAREN)
|
if (lparen->type != FZL_TOKTYPE_LPAREN)
|
||||||
{
|
{
|
||||||
snprintf(plast_err, sizeof(plast_err),
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
"'%s': expected '(' before condition at %ld:%ld",
|
"'%s': expected '(' before condition at %ld:%ld", lparen->filename,
|
||||||
lparen->filename, lparen->ln, lparen->cn);
|
lparen->ln, lparen->cn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,8 +868,8 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
|||||||
if (rparen->type != FZL_TOKTYPE_RPAREN)
|
if (rparen->type != FZL_TOKTYPE_RPAREN)
|
||||||
{
|
{
|
||||||
snprintf(plast_err, sizeof(plast_err),
|
snprintf(plast_err, sizeof(plast_err),
|
||||||
"'%s': expected ')' after condition at %ld:%ld",
|
"'%s': expected ')' after condition at %ld:%ld", rparen->filename,
|
||||||
rparen->filename, rparen->ln, rparen->cn);
|
rparen->ln, rparen->cn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -748,8 +893,13 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
|||||||
|
|
||||||
return stmt_node;
|
return stmt_node;
|
||||||
}
|
}
|
||||||
else if (is(parser, FZL_TOKTYPE_LBRACE))
|
|
||||||
|
// Block statement parsing
|
||||||
|
fzl_node_t *parse_block(fzl_parser_t *parser)
|
||||||
{
|
{
|
||||||
|
if (!parser)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
fzl_token_t *block_tok = consume(parser);
|
fzl_token_t *block_tok = consume(parser);
|
||||||
|
|
||||||
size_t remainder = 2;
|
size_t remainder = 2;
|
||||||
@@ -785,12 +935,27 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Statement parsing
|
||||||
|
fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||||
|
{
|
||||||
|
fzl_node_t *res = NULL;
|
||||||
|
|
||||||
|
if (is(parser, FZL_TOKTYPE_CLASS))
|
||||||
|
return parse_class(parser);
|
||||||
|
else if (is(parser, FZL_TOKTYPE_FUNCTION))
|
||||||
|
return parse_function(parser);
|
||||||
|
else if (is(parser, FZL_TOKTYPE_RETURN))
|
||||||
|
res = parse_return(parser);
|
||||||
|
else if (is(parser, FZL_TOKTYPE_IF))
|
||||||
|
return parse_if(parser);
|
||||||
|
else if (is(parser, FZL_TOKTYPE_LBRACE))
|
||||||
|
return parse_block(parser);
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
res = parse_expression(parser);
|
res = parse_expression(parser);
|
||||||
|
|
||||||
if (!is(parser, FZL_TOKTYPE_SEMICOLON))
|
if (!is(parser, FZL_TOKTYPE_SEMICOLON))
|
||||||
{
|
{
|
||||||
printf("Current token are %d\n", last_known_tok->type);
|
|
||||||
snprintf(plast_err, sizeof(plast_err), "'%s': missing ';' at %ld:%ld",
|
snprintf(plast_err, sizeof(plast_err), "'%s': missing ';' at %ld:%ld",
|
||||||
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
last_known_tok->filename, last_known_tok->ln, last_known_tok->cn);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -908,9 +1073,26 @@ void fzl_freeast(fzl_node_t *root)
|
|||||||
free(root->fn.args);
|
free(root->fn.args);
|
||||||
fzl_freenode(root->fn.body);
|
fzl_freenode(root->fn.body);
|
||||||
}
|
}
|
||||||
|
else if (root->type == FZL_NODETYPE_RETURN)
|
||||||
|
{
|
||||||
|
if (root->ret.value)
|
||||||
|
fzl_freenode(root->ret.value);
|
||||||
|
}
|
||||||
|
else if (root->type == FZL_NODETYPE_CLASS)
|
||||||
|
{
|
||||||
|
if (root->class.fields_count)
|
||||||
|
for (size_t i = 0; i < root->class.fields_count; i++)
|
||||||
|
fzl_freenode(root->class.fields[i]);
|
||||||
|
free(root->class.fields);
|
||||||
|
|
||||||
|
if (root->class.methods_count)
|
||||||
|
for (size_t i = 0; i < root->class.methods_count; i++)
|
||||||
|
fzl_freenode(root->class.methods[i]);
|
||||||
|
free(root->class.methods);
|
||||||
|
}
|
||||||
|
|
||||||
fzl_freenode(root);
|
|
||||||
root = root->next;
|
root = root->next;
|
||||||
|
free(root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,15 @@ fzl_token_t *parse_name(fzl_reader_t *reader)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(value, "return") == 0)
|
if (strcmp(value, "class") == 0)
|
||||||
|
tok =
|
||||||
|
fzl_mktoken(FZL_TOKTYPE_CLASS, l.line, l.col, value, size, l.filename);
|
||||||
|
else if (strcmp(value, "new") == 0)
|
||||||
|
tok = fzl_mktoken(FZL_TOKTYPE_NEW, l.line, l.col, value, size, l.filename);
|
||||||
|
else if (strcmp(value, "fn") == 0)
|
||||||
|
tok = fzl_mktoken(FZL_TOKTYPE_FUNCTION, l.line, l.col, value, size,
|
||||||
|
l.filename);
|
||||||
|
else if (strcmp(value, "return") == 0)
|
||||||
tok =
|
tok =
|
||||||
fzl_mktoken(FZL_TOKTYPE_RETURN, l.line, l.col, value, size, l.filename);
|
fzl_mktoken(FZL_TOKTYPE_RETURN, l.line, l.col, value, size, l.filename);
|
||||||
else if (strcmp(value, "if") == 0)
|
else if (strcmp(value, "if") == 0)
|
||||||
@@ -86,7 +94,7 @@ fzl_token_t *parse_name(fzl_reader_t *reader)
|
|||||||
strcmp(value, "i16") == 0 || strcmp(value, "i32") == 0 ||
|
strcmp(value, "i16") == 0 || strcmp(value, "i32") == 0 ||
|
||||||
strcmp(value, "i64") == 0 || strcmp(value, "u8") == 0 ||
|
strcmp(value, "i64") == 0 || strcmp(value, "u8") == 0 ||
|
||||||
strcmp(value, "u16") == 0 || strcmp(value, "u32") == 0 ||
|
strcmp(value, "u16") == 0 || strcmp(value, "u32") == 0 ||
|
||||||
strcmp(value, "u64") == 0)
|
strcmp(value, "u64") == 0 || strcmp(value, "null") == 0)
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_TYPE, l.line, l.col, value, size, l.filename);
|
tok = fzl_mktoken(FZL_TOKTYPE_TYPE, l.line, l.col, value, size, l.filename);
|
||||||
else
|
else
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_NAME, l.line, l.col, value, size, l.filename);
|
tok = fzl_mktoken(FZL_TOKTYPE_NAME, l.line, l.col, value, size, l.filename);
|
||||||
@@ -286,6 +294,8 @@ int fzl_read(fzl_reader_t *reader)
|
|||||||
token = add_single(reader, FZL_TOKTYPE_RPAREN);
|
token = add_single(reader, FZL_TOKTYPE_RPAREN);
|
||||||
else if (curr == ',')
|
else if (curr == ',')
|
||||||
token = add_single(reader, FZL_TOKTYPE_COMMA);
|
token = add_single(reader, FZL_TOKTYPE_COMMA);
|
||||||
|
else if (curr == '.')
|
||||||
|
token = add_single(reader, FZL_TOKTYPE_DOT);
|
||||||
else if (curr == '*')
|
else if (curr == '*')
|
||||||
token = add_single(reader, FZL_TOKTYPE_STAR);
|
token = add_single(reader, FZL_TOKTYPE_STAR);
|
||||||
else if (curr == '/')
|
else if (curr == '/')
|
||||||
|
|||||||
Reference in New Issue
Block a user