Compare commits
2
Commits
567bf49d27
...
bbdaa4a9b9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbdaa4a9b9 | ||
|
|
7c04d8b7ec |
+5
-1
@@ -26,7 +26,6 @@ add_executable(fzc
|
|||||||
src/compiler/utils/fzl_linked.c
|
src/compiler/utils/fzl_linked.c
|
||||||
src/compiler/utils/fzl_options.c
|
src/compiler/utils/fzl_options.c
|
||||||
src/compiler/utils/fzl_ctable.c
|
src/compiler/utils/fzl_ctable.c
|
||||||
src/compiler/checkers/fzl_loop_check.c
|
|
||||||
src/compiler/analyzer/utility.c
|
src/compiler/analyzer/utility.c
|
||||||
src/compiler/analyzer/context.c
|
src/compiler/analyzer/context.c
|
||||||
src/compiler/analyzer/an_assign.c
|
src/compiler/analyzer/an_assign.c
|
||||||
@@ -47,6 +46,11 @@ add_executable(fzc
|
|||||||
src/compiler/analyzer/an_return.c
|
src/compiler/analyzer/an_return.c
|
||||||
src/compiler/analyzer/an_unarycond.c
|
src/compiler/analyzer/an_unarycond.c
|
||||||
src/compiler/analyzer/an_unarymath.c
|
src/compiler/analyzer/an_unarymath.c
|
||||||
|
src/compiler/reader/rd_fmtstr.c
|
||||||
|
src/compiler/reader/rd_name.c
|
||||||
|
src/compiler/reader/rd_number.c
|
||||||
|
src/compiler/reader/rd_string_literal.c
|
||||||
|
src/compiler/reader/utility.c
|
||||||
src/compiler/fzl_analyzer.c
|
src/compiler/fzl_analyzer.c
|
||||||
src/compiler/fzl_debug.c
|
src/compiler/fzl_debug.c
|
||||||
src/compiler/fzl_parser.c
|
src/compiler/fzl_parser.c
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef INTERNALS_READER_H
|
||||||
|
#define INTERNALS_READER_H
|
||||||
|
|
||||||
|
#include <compiler/fzl_reader.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
extern char last_err[256];
|
||||||
|
|
||||||
|
size_t move(fzl_reader_t *reader, size_t len);
|
||||||
|
void rd_comment(fzl_reader_t *reader);
|
||||||
|
|
||||||
|
fzl_token_t *rd_name(fzl_reader_t *reader);
|
||||||
|
fzl_token_t *rd_string_literal(fzl_reader_t *reader);
|
||||||
|
fzl_token_t *rd_number(fzl_reader_t *reader);
|
||||||
|
fzl_token_t *rd_single(fzl_reader_t *reader, fzl_toktype_t type);
|
||||||
|
fzl_token_t *rd_double(fzl_reader_t *reader, fzl_toktype_t type);
|
||||||
|
fzl_token_t *rd_fmtstr(fzl_reader_t *reader);
|
||||||
|
|
||||||
|
#endif // INTERNALS_READER_H
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
#include <common/fzl_opcodes.h>
|
|
||||||
#include <common/fzl_types.h>
|
|
||||||
#include <compiler/fzl_parser.h>
|
|
||||||
#include <compiler/fzl_walker.h>
|
|
||||||
#include <compiler/utils/fzl_const_pool.h>
|
|
||||||
#include <compiler/utils/fzl_symtable.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
ssize_t check_top;
|
|
||||||
fzl_nodetype_t check_tree[256];
|
|
||||||
|
|
||||||
// Ghost walk AST tree (w/o adding opcodes) to check if
|
|
||||||
// variable used in condition is changed
|
|
||||||
void ghost_walk_changed(fzl_node_t *node, bool *changed, fzl_sym_t *sym)
|
|
||||||
{
|
|
||||||
if (!node || !changed || *changed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
check_tree[check_top++] = node->type;
|
|
||||||
|
|
||||||
switch (node->type)
|
|
||||||
{
|
|
||||||
case FZL_NODETYPE_BREAK:
|
|
||||||
case FZL_NODETYPE_DECLARATION:
|
|
||||||
case FZL_NODETYPE_CONSTRUCT:
|
|
||||||
case FZL_NODETYPE_CLASS:
|
|
||||||
case FZL_NODETYPE_FUNCTION:
|
|
||||||
case FZL_NODETYPE_LITERAL:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_UNARY_PLUS:
|
|
||||||
case FZL_NODETYPE_UNARY_MINUS:
|
|
||||||
case FZL_NODETYPE_NOT:
|
|
||||||
ghost_walk_changed(node->unary_op.operand, changed, sym);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_ADD:
|
|
||||||
case FZL_NODETYPE_SUB:
|
|
||||||
case FZL_NODETYPE_MUL:
|
|
||||||
case FZL_NODETYPE_DIV:
|
|
||||||
case FZL_NODETYPE_POW:
|
|
||||||
case FZL_NODETYPE_MOD:
|
|
||||||
case FZL_NODETYPE_OR:
|
|
||||||
case FZL_NODETYPE_AND:
|
|
||||||
case FZL_NODETYPE_EQUAL:
|
|
||||||
case FZL_NODETYPE_NEQUAL:
|
|
||||||
case FZL_NODETYPE_LESS:
|
|
||||||
case FZL_NODETYPE_LESS_EQUAL:
|
|
||||||
case FZL_NODETYPE_GREATER:
|
|
||||||
case FZL_NODETYPE_GREATER_EQUAL:
|
|
||||||
case FZL_NODETYPE_ASSIGN:
|
|
||||||
ghost_walk_changed(node->binary_op.left, changed, sym);
|
|
||||||
ghost_walk_changed(node->binary_op.right, changed, sym);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_FIELD:
|
|
||||||
ghost_walk_changed(node->memb.parent, changed, sym);
|
|
||||||
ghost_walk_changed(node->memb.field, changed, sym);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_RETURN:
|
|
||||||
ghost_walk_changed(node->ret.value, changed, sym);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_CONDITIONAL:
|
|
||||||
ghost_walk_changed(node->cond.condition, changed, sym);
|
|
||||||
ghost_walk_changed(node->cond.true_block, changed, sym);
|
|
||||||
ghost_walk_changed(node->cond.else_block, changed, sym);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_LOOP:
|
|
||||||
ghost_walk_changed(node->loop.cond, changed, sym);
|
|
||||||
ghost_walk_changed(node->loop.step, changed, sym);
|
|
||||||
ghost_walk_changed(node->loop.body, changed, sym);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_BLOCK:
|
|
||||||
for (size_t i = 0; i < node->list.entry_count; i++)
|
|
||||||
ghost_walk_changed(node->list.entries[i], changed, sym);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_CALL:
|
|
||||||
ghost_walk_changed(node->call.callee, changed, sym);
|
|
||||||
for (size_t i = 0; i < node->call.args_count; i++)
|
|
||||||
ghost_walk_changed(node->call.args[i], changed, sym);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_IDENTIFIER:
|
|
||||||
if (strcmp(node->token->value, sym->name) == 0)
|
|
||||||
{
|
|
||||||
*changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*changed)
|
|
||||||
{
|
|
||||||
*changed = false;
|
|
||||||
for (ssize_t i = check_top - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
fzl_nodetype_t cur_t = check_tree[i];
|
|
||||||
if (cur_t == FZL_NODETYPE_ADD || cur_t == FZL_NODETYPE_SUB ||
|
|
||||||
cur_t == FZL_NODETYPE_MUL || cur_t == FZL_NODETYPE_DIV ||
|
|
||||||
cur_t == FZL_NODETYPE_POW || cur_t == FZL_NODETYPE_MOD ||
|
|
||||||
cur_t == FZL_NODETYPE_UNARY_MINUS)
|
|
||||||
{
|
|
||||||
*changed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
check_tree[--check_top] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whether value changed in loop body
|
|
||||||
bool value_is_changed(fzl_node_t *node, fzl_sym_t *sym)
|
|
||||||
{
|
|
||||||
if (!node || !sym)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool changed = false;
|
|
||||||
check_top = 0;
|
|
||||||
memset(check_tree, 0, sizeof(check_tree));
|
|
||||||
ghost_walk_changed(node, &changed, sym);
|
|
||||||
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find symbol in loop condition node
|
|
||||||
bool retrieve_cond_sym(fzl_walker_t *walker, fzl_node_t *node, fzl_sym_t *sym)
|
|
||||||
{
|
|
||||||
if (!walker || !node)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (node->type)
|
|
||||||
{
|
|
||||||
case FZL_NODETYPE_BREAK:
|
|
||||||
case FZL_NODETYPE_BLOCK:
|
|
||||||
case FZL_NODETYPE_CALL:
|
|
||||||
case FZL_NODETYPE_LITERAL:
|
|
||||||
case FZL_NODETYPE_CONDITIONAL:
|
|
||||||
case FZL_NODETYPE_FUNCTION:
|
|
||||||
case FZL_NODETYPE_RETURN:
|
|
||||||
case FZL_NODETYPE_CLASS:
|
|
||||||
case FZL_NODETYPE_FIELD:
|
|
||||||
case FZL_NODETYPE_CONSTRUCT:
|
|
||||||
case FZL_NODETYPE_LOOP:
|
|
||||||
case FZL_NODETYPE_ASSIGN:
|
|
||||||
case FZL_NODETYPE_DECLARATION:
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_UNARY_MINUS:
|
|
||||||
case FZL_NODETYPE_UNARY_PLUS:
|
|
||||||
case FZL_NODETYPE_NOT:
|
|
||||||
return retrieve_cond_sym(walker, node->unary_op.operand, sym);
|
|
||||||
|
|
||||||
case FZL_NODETYPE_ADD:
|
|
||||||
case FZL_NODETYPE_SUB:
|
|
||||||
case FZL_NODETYPE_MUL:
|
|
||||||
case FZL_NODETYPE_DIV:
|
|
||||||
case FZL_NODETYPE_POW:
|
|
||||||
case FZL_NODETYPE_MOD:
|
|
||||||
case FZL_NODETYPE_AND:
|
|
||||||
case FZL_NODETYPE_OR:
|
|
||||||
case FZL_NODETYPE_LESS:
|
|
||||||
case FZL_NODETYPE_LESS_EQUAL:
|
|
||||||
case FZL_NODETYPE_GREATER:
|
|
||||||
case FZL_NODETYPE_GREATER_EQUAL:
|
|
||||||
case FZL_NODETYPE_EQUAL:
|
|
||||||
case FZL_NODETYPE_NEQUAL:
|
|
||||||
if (retrieve_cond_sym(walker, node->binary_op.left, sym))
|
|
||||||
return true;
|
|
||||||
if (retrieve_cond_sym(walker, node->binary_op.right, sym))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case FZL_NODETYPE_IDENTIFIER:
|
|
||||||
{
|
|
||||||
bool exists;
|
|
||||||
for (ssize_t i = walker->sym_top - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if ((exists = fzl_symt_get(walker->syms[i], (char *)node->token->value,
|
|
||||||
sym)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for infinite loop
|
|
||||||
bool is_infinite_loop(fzl_walker_t *walker, fzl_node_t *node, size_t start_ip,
|
|
||||||
size_t end_ip)
|
|
||||||
{
|
|
||||||
if (!walker)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
end_ip = (end_ip >= walker->op_count) ? (walker->op_count - 1) : end_ip;
|
|
||||||
|
|
||||||
fzl_sym_t sym;
|
|
||||||
bool sym_exists = retrieve_cond_sym(walker, node->loop.cond, &sym);
|
|
||||||
if (sym_exists)
|
|
||||||
{
|
|
||||||
if (sym.type >= FZL_TYPE_INT8)
|
|
||||||
{
|
|
||||||
bool value_changed = value_is_changed(node, &sym);
|
|
||||||
if (value_changed)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// At least has jump outside
|
|
||||||
for (size_t i = start_ip; i <= end_ip; i++)
|
|
||||||
{
|
|
||||||
if (walker->ops[i] != FZL_OPCODE_JMP)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
size_t jump_ip = walker->ops[++i];
|
|
||||||
if (jump_ip >= end_ip)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
+34
-327
@@ -1,6 +1,7 @@
|
|||||||
#include "compiler/fzl_token.h"
|
|
||||||
#include "compiler/utils/fzl_linked.h"
|
|
||||||
#include <compiler/fzl_reader.h>
|
#include <compiler/fzl_reader.h>
|
||||||
|
#include <compiler/fzl_token.h>
|
||||||
|
#include <compiler/internals/reader.h>
|
||||||
|
#include <compiler/utils/fzl_linked.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -8,7 +9,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
// Last error from reader
|
// Last error from reader
|
||||||
static char last_err[256] = {0};
|
char last_err[256];
|
||||||
|
|
||||||
fzl_reader_t *fzl_mkreader(fzl_linked_t *linked)
|
fzl_reader_t *fzl_mkreader(fzl_linked_t *linked)
|
||||||
{
|
{
|
||||||
@@ -24,303 +25,11 @@ fzl_reader_t *fzl_mkreader(fzl_linked_t *linked)
|
|||||||
reader->size = linked->total_sz;
|
reader->size = linked->total_sz;
|
||||||
reader->position = 0;
|
reader->position = 0;
|
||||||
|
|
||||||
|
memset(last_err, 0, sizeof(last_err));
|
||||||
|
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Read zone ---
|
|
||||||
|
|
||||||
// Move cursor forward
|
|
||||||
// @deprecated
|
|
||||||
static size_t move(fzl_reader_t *reader, size_t len)
|
|
||||||
{
|
|
||||||
if (!reader)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return reader->position += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try parse name
|
|
||||||
fzl_token_t *parse_name(fzl_reader_t *reader)
|
|
||||||
{
|
|
||||||
size_t lpos = reader->position;
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
lpos++;
|
|
||||||
size++;
|
|
||||||
} while ((reader->source[lpos] >= 'A' && reader->source[lpos] <= 'Z') ||
|
|
||||||
(reader->source[lpos] >= 'a' && reader->source[lpos] <= 'z') ||
|
|
||||||
(reader->source[lpos] >= '0' && reader->source[lpos] <= '9') ||
|
|
||||||
(reader->source[lpos] == '_'));
|
|
||||||
|
|
||||||
char *value = malloc(size + 1);
|
|
||||||
memcpy(value, reader->source + reader->position, size);
|
|
||||||
value[size] = '\0';
|
|
||||||
|
|
||||||
size_t start = reader->position;
|
|
||||||
move(reader, size);
|
|
||||||
|
|
||||||
fzl_token_t *tok;
|
|
||||||
fzl_file_loc l;
|
|
||||||
bool ok = fzl_linked_getpos(reader->linked, start, &l);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(value, "class") == 0)
|
|
||||||
tok =
|
|
||||||
fzl_mktoken(FZL_TOKTYPE_CLASS, 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)
|
|
||||||
tok =
|
|
||||||
fzl_mktoken(FZL_TOKTYPE_WHILE, l.line, l.col, value, size, l.filename);
|
|
||||||
else if (strcmp(value, "break") == 0)
|
|
||||||
tok =
|
|
||||||
fzl_mktoken(FZL_TOKTYPE_BREAK, 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 =
|
|
||||||
fzl_mktoken(FZL_TOKTYPE_RETURN, l.line, l.col, value, size, l.filename);
|
|
||||||
else if (strcmp(value, "if") == 0)
|
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_IF, l.line, l.col, value, size, l.filename);
|
|
||||||
else if (strcmp(value, "else") == 0)
|
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_ELSE, l.line, l.col, value, size, l.filename);
|
|
||||||
else if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0)
|
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_BOOL_LITERAL, l.line, l.col, value, size,
|
|
||||||
l.filename);
|
|
||||||
else if (strcmp(value, "null") == 0)
|
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_NULL_LITERAL, l.line, l.col, value, size,
|
|
||||||
l.filename);
|
|
||||||
else if (strcmp(value, "str") == 0 || strcmp(value, "char") == 0 ||
|
|
||||||
strcmp(value, "bool") == 0 || strcmp(value, "uint") == 0 ||
|
|
||||||
strcmp(value, "int") == 0 || strcmp(value, "i8") == 0 ||
|
|
||||||
strcmp(value, "i16") == 0 || strcmp(value, "i32") == 0 ||
|
|
||||||
strcmp(value, "i64") == 0 || strcmp(value, "u8") == 0 ||
|
|
||||||
strcmp(value, "u16") == 0 || strcmp(value, "u32") == 0 ||
|
|
||||||
strcmp(value, "u64") == 0)
|
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_TYPE, l.line, l.col, value, size, l.filename);
|
|
||||||
else
|
|
||||||
tok = fzl_mktoken(FZL_TOKTYPE_NAME, l.line, l.col, value, size, l.filename);
|
|
||||||
free(value);
|
|
||||||
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try parse string literal
|
|
||||||
fzl_token_t *parse_string_literal(fzl_reader_t *reader)
|
|
||||||
{
|
|
||||||
size_t lpos = reader->position;
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
if (reader->source[lpos] != '\'' && reader->source[lpos] != '"')
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
char open_symbol = reader->source[lpos];
|
|
||||||
char close_symbol = '\0';
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
lpos++;
|
|
||||||
size++;
|
|
||||||
|
|
||||||
if (reader->source[lpos] == open_symbol)
|
|
||||||
close_symbol = open_symbol;
|
|
||||||
|
|
||||||
} while (reader->source[lpos] != open_symbol && lpos < reader->size);
|
|
||||||
size++;
|
|
||||||
|
|
||||||
fzl_file_loc l;
|
|
||||||
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (close_symbol != open_symbol)
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err), "'%s': unterminated string at %ld:%ld",
|
|
||||||
l.filename, l.line, l.col);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 2)
|
|
||||||
{
|
|
||||||
fzl_token_t *tok =
|
|
||||||
fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, "", 0, l.filename);
|
|
||||||
move(reader, 2);
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *value = malloc(size - 2);
|
|
||||||
memcpy(value, reader->source + reader->position + 1, size - 2);
|
|
||||||
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, value,
|
|
||||||
size - 2, l.filename);
|
|
||||||
free(value);
|
|
||||||
move(reader, size);
|
|
||||||
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse numeric literal
|
|
||||||
fzl_token_t *parse_number(fzl_reader_t *reader)
|
|
||||||
{
|
|
||||||
if (!reader)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
size_t lpos = reader->position;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
size++;
|
|
||||||
lpos++;
|
|
||||||
} while ((reader->source[lpos] >= '0' && reader->source[lpos] <= '9') &&
|
|
||||||
lpos < reader->size);
|
|
||||||
|
|
||||||
char *value = malloc(size * sizeof(char) + 1);
|
|
||||||
memcpy(value, reader->source + reader->position, size);
|
|
||||||
value[size] = '\0';
|
|
||||||
|
|
||||||
fzl_file_loc l;
|
|
||||||
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_NUM_LITERAL, l.line, l.col, value,
|
|
||||||
size, l.filename);
|
|
||||||
free(value);
|
|
||||||
|
|
||||||
if (!tok)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
move(reader, size);
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add single-char token
|
|
||||||
fzl_token_t *add_single(fzl_reader_t *reader, fzl_toktype_t type)
|
|
||||||
{
|
|
||||||
fzl_file_loc l;
|
|
||||||
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
move(reader, 1);
|
|
||||||
return fzl_mktoken(type, l.line, l.col, "", 0, l.filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add double-char token
|
|
||||||
fzl_token_t *add_double(fzl_reader_t *reader, fzl_toktype_t type)
|
|
||||||
{
|
|
||||||
fzl_file_loc l;
|
|
||||||
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
move(reader, 2);
|
|
||||||
return fzl_mktoken(type, l.line, l.col, "", 0, l.filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip symbols until '\n' or EOF
|
|
||||||
void skip_comment(fzl_reader_t *reader)
|
|
||||||
{
|
|
||||||
move(reader, 2);
|
|
||||||
|
|
||||||
while (reader->position < reader->size)
|
|
||||||
{
|
|
||||||
if (reader->source[reader->position++] == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse string format
|
|
||||||
fzl_token_t *parse_fmtstring_part(fzl_reader_t *reader)
|
|
||||||
{
|
|
||||||
size_t p = reader->position;
|
|
||||||
char *src = reader->source;
|
|
||||||
|
|
||||||
fzl_file_loc l;
|
|
||||||
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src[p] == '{')
|
|
||||||
{
|
|
||||||
move(reader, 1);
|
|
||||||
fzl_token_t *id = parse_name(reader);
|
|
||||||
|
|
||||||
if (id == NULL || src[reader->position] != '}')
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err),
|
|
||||||
"'%s':%zu:%zu => failed to parse format string", l.filename,
|
|
||||||
l.line, l.col);
|
|
||||||
fzl_freetoken(id);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
move(reader, 1);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src[p] == '"')
|
|
||||||
{
|
|
||||||
move(reader, 1);
|
|
||||||
|
|
||||||
return fzl_mktoken(FZL_TOKTYPE_STR_FORMAT_END, l.line, l.col, NULL, 0,
|
|
||||||
l.filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
size_t lpos = p;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (src[lpos + 1] == '"')
|
|
||||||
break;
|
|
||||||
|
|
||||||
size++;
|
|
||||||
lpos++;
|
|
||||||
} while (lpos < reader->size && reader->source[lpos] != '{' &&
|
|
||||||
reader->source[lpos] != '"');
|
|
||||||
|
|
||||||
ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *value = malloc(size);
|
|
||||||
memcpy(value, reader->source + reader->position, size);
|
|
||||||
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, value,
|
|
||||||
size, l.filename);
|
|
||||||
free(value);
|
|
||||||
move(reader, size);
|
|
||||||
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fzl_read(fzl_reader_t *reader)
|
int fzl_read(fzl_reader_t *reader)
|
||||||
{
|
{
|
||||||
if (reader->position >= reader->size)
|
if (reader->position >= reader->size)
|
||||||
@@ -342,63 +51,63 @@ int fzl_read(fzl_reader_t *reader)
|
|||||||
|
|
||||||
if (is_format_str)
|
if (is_format_str)
|
||||||
{
|
{
|
||||||
token = parse_fmtstring_part(reader);
|
token = rd_fmtstr(reader);
|
||||||
if (token && token->type == FZL_TOKTYPE_STR_FORMAT_END)
|
if (token && token->type == FZL_TOKTYPE_STR_FORMAT_END)
|
||||||
is_format_str = false;
|
is_format_str = false;
|
||||||
}
|
}
|
||||||
else if (curr == '\'' || curr == '"')
|
else if (curr == '\'' || curr == '"')
|
||||||
token = parse_string_literal(reader);
|
token = rd_string_literal(reader);
|
||||||
else if (curr == '/' && reader->source[p + 1] == '/')
|
else if (curr == '/' && reader->source[p + 1] == '/')
|
||||||
{
|
{
|
||||||
skip_comment(reader);
|
rd_comment(reader);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (curr == '=' && reader->source[p + 1] == '=')
|
else if (curr == '=' && reader->source[p + 1] == '=')
|
||||||
token = add_double(reader, FZL_TOKTYPE_EQEQ);
|
token = rd_double(reader, FZL_TOKTYPE_EQEQ);
|
||||||
else if (curr == '>' && reader->source[p + 1] == '=')
|
else if (curr == '>' && reader->source[p + 1] == '=')
|
||||||
token = add_double(reader, FZL_TOKTYPE_REQ);
|
token = rd_double(reader, FZL_TOKTYPE_REQ);
|
||||||
else if (curr == '<' && reader->source[p + 1] == '=')
|
else if (curr == '<' && reader->source[p + 1] == '=')
|
||||||
token = add_double(reader, FZL_TOKTYPE_LEQ);
|
token = rd_double(reader, FZL_TOKTYPE_LEQ);
|
||||||
else if (curr == '!' && reader->source[p + 1] == '=')
|
else if (curr == '!' && reader->source[p + 1] == '=')
|
||||||
token = add_double(reader, FZL_TOKTYPE_NEQ);
|
token = rd_double(reader, FZL_TOKTYPE_NEQ);
|
||||||
else if (curr == '|' && reader->source[p + 1] == '|')
|
else if (curr == '|' && reader->source[p + 1] == '|')
|
||||||
token = add_double(reader, FZL_TOKTYPE_DVBAR);
|
token = rd_double(reader, FZL_TOKTYPE_DVBAR);
|
||||||
else if (curr == '&' && reader->source[p + 1] == '&')
|
else if (curr == '&' && reader->source[p + 1] == '&')
|
||||||
token = add_double(reader, FZL_TOKTYPE_DAMPERSAND);
|
token = rd_double(reader, FZL_TOKTYPE_DAMPERSAND);
|
||||||
else if (curr == '>')
|
else if (curr == '>')
|
||||||
token = add_single(reader, FZL_TOKTYPE_RANGLE);
|
token = rd_single(reader, FZL_TOKTYPE_RANGLE);
|
||||||
else if (curr == '<')
|
else if (curr == '<')
|
||||||
token = add_single(reader, FZL_TOKTYPE_LANGLE);
|
token = rd_single(reader, FZL_TOKTYPE_LANGLE);
|
||||||
else if (curr == '!')
|
else if (curr == '!')
|
||||||
token = add_single(reader, FZL_TOKTYPE_NOT);
|
token = rd_single(reader, FZL_TOKTYPE_NOT);
|
||||||
else if (curr == ';')
|
else if (curr == ';')
|
||||||
token = add_single(reader, FZL_TOKTYPE_SEMICOLON);
|
token = rd_single(reader, FZL_TOKTYPE_SEMICOLON);
|
||||||
else if (curr == '{')
|
else if (curr == '{')
|
||||||
token = add_single(reader, FZL_TOKTYPE_LBRACE);
|
token = rd_single(reader, FZL_TOKTYPE_LBRACE);
|
||||||
else if (curr == '}')
|
else if (curr == '}')
|
||||||
token = add_single(reader, FZL_TOKTYPE_RBRACE);
|
token = rd_single(reader, FZL_TOKTYPE_RBRACE);
|
||||||
else if (curr == '(')
|
else if (curr == '(')
|
||||||
token = add_single(reader, FZL_TOKTYPE_LPAREN);
|
token = rd_single(reader, FZL_TOKTYPE_LPAREN);
|
||||||
else if (curr == ')')
|
else if (curr == ')')
|
||||||
token = add_single(reader, FZL_TOKTYPE_RPAREN);
|
token = rd_single(reader, FZL_TOKTYPE_RPAREN);
|
||||||
else if (curr == ',')
|
else if (curr == ',')
|
||||||
token = add_single(reader, FZL_TOKTYPE_COMMA);
|
token = rd_single(reader, FZL_TOKTYPE_COMMA);
|
||||||
else if (curr == '.')
|
else if (curr == '.')
|
||||||
token = add_single(reader, FZL_TOKTYPE_DOT);
|
token = rd_single(reader, FZL_TOKTYPE_DOT);
|
||||||
else if (curr == '*')
|
else if (curr == '*')
|
||||||
token = add_single(reader, FZL_TOKTYPE_STAR);
|
token = rd_single(reader, FZL_TOKTYPE_STAR);
|
||||||
else if (curr == '/')
|
else if (curr == '/')
|
||||||
token = add_single(reader, FZL_TOKTYPE_SLASH);
|
token = rd_single(reader, FZL_TOKTYPE_SLASH);
|
||||||
else if (curr == '+')
|
else if (curr == '+')
|
||||||
token = add_single(reader, FZL_TOKTYPE_PLUS);
|
token = rd_single(reader, FZL_TOKTYPE_PLUS);
|
||||||
else if (curr == '-')
|
else if (curr == '-')
|
||||||
token = add_single(reader, FZL_TOKTYPE_MINUS);
|
token = rd_single(reader, FZL_TOKTYPE_MINUS);
|
||||||
else if (curr == '^')
|
else if (curr == '^')
|
||||||
token = add_single(reader, FZL_TOKTYPE_CARET);
|
token = rd_single(reader, FZL_TOKTYPE_CARET);
|
||||||
else if (curr == '%')
|
else if (curr == '%')
|
||||||
token = add_single(reader, FZL_TOKTYPE_PERCENT);
|
token = rd_single(reader, FZL_TOKTYPE_PERCENT);
|
||||||
else if (curr == '=')
|
else if (curr == '=')
|
||||||
token = add_single(reader, FZL_TOKTYPE_EQ);
|
token = rd_single(reader, FZL_TOKTYPE_EQ);
|
||||||
else if (curr == '$' && reader->source[p + 1] == '"')
|
else if (curr == '$' && reader->source[p + 1] == '"')
|
||||||
{
|
{
|
||||||
move(reader, 2);
|
move(reader, 2);
|
||||||
@@ -407,9 +116,9 @@ int fzl_read(fzl_reader_t *reader)
|
|||||||
}
|
}
|
||||||
else if ((curr >= 'A' && curr <= 'Z') || (curr >= 'a' && curr <= 'z') ||
|
else if ((curr >= 'A' && curr <= 'Z') || (curr >= 'a' && curr <= 'z') ||
|
||||||
curr == '_')
|
curr == '_')
|
||||||
token = parse_name(reader);
|
token = rd_name(reader);
|
||||||
else if (curr >= '0' && curr <= '9')
|
else if (curr >= '0' && curr <= '9')
|
||||||
token = parse_number(reader);
|
token = rd_number(reader);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fzl_file_loc l;
|
fzl_file_loc l;
|
||||||
@@ -455,8 +164,6 @@ int fzl_read(fzl_reader_t *reader)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Read zone end ---
|
|
||||||
|
|
||||||
char *fzl_reader_geterror() { return last_err; }
|
char *fzl_reader_geterror() { return last_err; }
|
||||||
|
|
||||||
void free_node_and_next(fzl_reader_ll_t *node)
|
void free_node_and_next(fzl_reader_ll_t *node)
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#include <compiler/fzl_reader.h>
|
||||||
|
#include <compiler/internals/reader.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Parse string format
|
||||||
|
fzl_token_t *rd_fmtstr(fzl_reader_t *reader)
|
||||||
|
{
|
||||||
|
size_t p = reader->position;
|
||||||
|
char *src = reader->source;
|
||||||
|
|
||||||
|
fzl_file_loc l;
|
||||||
|
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src[p] == '{')
|
||||||
|
{
|
||||||
|
move(reader, 1);
|
||||||
|
fzl_token_t *id = rd_name(reader);
|
||||||
|
|
||||||
|
if (id == NULL || src[reader->position] != '}')
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"'%s':%zu:%zu => failed to parse format string", l.filename,
|
||||||
|
l.line, l.col);
|
||||||
|
fzl_freetoken(id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
move(reader, 1);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src[p] == '"')
|
||||||
|
{
|
||||||
|
move(reader, 1);
|
||||||
|
|
||||||
|
return fzl_mktoken(FZL_TOKTYPE_STR_FORMAT_END, l.line, l.col, NULL, 0,
|
||||||
|
l.filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
size_t lpos = p;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (src[lpos + 1] == '"')
|
||||||
|
break;
|
||||||
|
|
||||||
|
size++;
|
||||||
|
lpos++;
|
||||||
|
} while (lpos < reader->size && reader->source[lpos] != '{' &&
|
||||||
|
reader->source[lpos] != '"');
|
||||||
|
|
||||||
|
ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *value = malloc(size);
|
||||||
|
memcpy(value, reader->source + reader->position, size);
|
||||||
|
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, value,
|
||||||
|
size, l.filename);
|
||||||
|
free(value);
|
||||||
|
move(reader, size);
|
||||||
|
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
#include <compiler/fzl_reader.h>
|
||||||
|
#include <compiler/internals/reader.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Try parse name
|
||||||
|
fzl_token_t *rd_name(fzl_reader_t *reader)
|
||||||
|
{
|
||||||
|
size_t lpos = reader->position;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
lpos++;
|
||||||
|
size++;
|
||||||
|
} while ((reader->source[lpos] >= 'A' && reader->source[lpos] <= 'Z') ||
|
||||||
|
(reader->source[lpos] >= 'a' && reader->source[lpos] <= 'z') ||
|
||||||
|
(reader->source[lpos] >= '0' && reader->source[lpos] <= '9') ||
|
||||||
|
(reader->source[lpos] == '_'));
|
||||||
|
|
||||||
|
char *value = malloc(size + 1);
|
||||||
|
memcpy(value, reader->source + reader->position, size);
|
||||||
|
value[size] = '\0';
|
||||||
|
|
||||||
|
size_t start = reader->position;
|
||||||
|
move(reader, size);
|
||||||
|
|
||||||
|
fzl_token_t *tok;
|
||||||
|
fzl_file_loc l;
|
||||||
|
bool ok = fzl_linked_getpos(reader->linked, start, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(value, "class") == 0)
|
||||||
|
tok =
|
||||||
|
fzl_mktoken(FZL_TOKTYPE_CLASS, 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)
|
||||||
|
tok =
|
||||||
|
fzl_mktoken(FZL_TOKTYPE_WHILE, l.line, l.col, value, size, l.filename);
|
||||||
|
else if (strcmp(value, "break") == 0)
|
||||||
|
tok =
|
||||||
|
fzl_mktoken(FZL_TOKTYPE_BREAK, 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 =
|
||||||
|
fzl_mktoken(FZL_TOKTYPE_RETURN, l.line, l.col, value, size, l.filename);
|
||||||
|
else if (strcmp(value, "if") == 0)
|
||||||
|
tok = fzl_mktoken(FZL_TOKTYPE_IF, l.line, l.col, value, size, l.filename);
|
||||||
|
else if (strcmp(value, "else") == 0)
|
||||||
|
tok = fzl_mktoken(FZL_TOKTYPE_ELSE, l.line, l.col, value, size, l.filename);
|
||||||
|
else if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0)
|
||||||
|
tok = fzl_mktoken(FZL_TOKTYPE_BOOL_LITERAL, l.line, l.col, value, size,
|
||||||
|
l.filename);
|
||||||
|
else if (strcmp(value, "null") == 0)
|
||||||
|
tok = fzl_mktoken(FZL_TOKTYPE_NULL_LITERAL, l.line, l.col, value, size,
|
||||||
|
l.filename);
|
||||||
|
else if (strcmp(value, "str") == 0 || strcmp(value, "char") == 0 ||
|
||||||
|
strcmp(value, "bool") == 0 || strcmp(value, "uint") == 0 ||
|
||||||
|
strcmp(value, "int") == 0 || strcmp(value, "i8") == 0 ||
|
||||||
|
strcmp(value, "i16") == 0 || strcmp(value, "i32") == 0 ||
|
||||||
|
strcmp(value, "i64") == 0 || strcmp(value, "u8") == 0 ||
|
||||||
|
strcmp(value, "u16") == 0 || strcmp(value, "u32") == 0 ||
|
||||||
|
strcmp(value, "u64") == 0)
|
||||||
|
tok = fzl_mktoken(FZL_TOKTYPE_TYPE, l.line, l.col, value, size, l.filename);
|
||||||
|
else
|
||||||
|
tok = fzl_mktoken(FZL_TOKTYPE_NAME, l.line, l.col, value, size, l.filename);
|
||||||
|
free(value);
|
||||||
|
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include <compiler/fzl_reader.h>
|
||||||
|
#include <compiler/fzl_token.h>
|
||||||
|
#include <compiler/internals/reader.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Parse numeric literal
|
||||||
|
fzl_token_t *rd_number(fzl_reader_t *reader)
|
||||||
|
{
|
||||||
|
if (!reader)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
size_t lpos = reader->position;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
size++;
|
||||||
|
lpos++;
|
||||||
|
} while ((reader->source[lpos] >= '0' && reader->source[lpos] <= '9') &&
|
||||||
|
lpos < reader->size);
|
||||||
|
|
||||||
|
char *value = malloc(size * sizeof(char) + 1);
|
||||||
|
memcpy(value, reader->source + reader->position, size);
|
||||||
|
value[size] = '\0';
|
||||||
|
|
||||||
|
fzl_file_loc l;
|
||||||
|
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_NUM_LITERAL, l.line, l.col, value,
|
||||||
|
size, l.filename);
|
||||||
|
free(value);
|
||||||
|
|
||||||
|
if (!tok)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
move(reader, size);
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#include <compiler/fzl_reader.h>
|
||||||
|
#include <compiler/fzl_token.h>
|
||||||
|
#include <compiler/internals/reader.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Try parse string literal
|
||||||
|
fzl_token_t *rd_string_literal(fzl_reader_t *reader)
|
||||||
|
{
|
||||||
|
size_t lpos = reader->position;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
if (reader->source[lpos] != '\'' && reader->source[lpos] != '"')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char open_symbol = reader->source[lpos];
|
||||||
|
char close_symbol = '\0';
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
lpos++;
|
||||||
|
size++;
|
||||||
|
|
||||||
|
if (reader->source[lpos] == open_symbol)
|
||||||
|
close_symbol = open_symbol;
|
||||||
|
|
||||||
|
} while (reader->source[lpos] != open_symbol && lpos < reader->size);
|
||||||
|
size++;
|
||||||
|
|
||||||
|
fzl_file_loc l;
|
||||||
|
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close_symbol != open_symbol)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "'%s': unterminated string at %ld:%ld",
|
||||||
|
l.filename, l.line, l.col);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 2)
|
||||||
|
{
|
||||||
|
fzl_token_t *tok =
|
||||||
|
fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, "", 0, l.filename);
|
||||||
|
move(reader, 2);
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *value = malloc(size - 2);
|
||||||
|
memcpy(value, reader->source + reader->position + 1, size - 2);
|
||||||
|
fzl_token_t *tok = fzl_mktoken(FZL_TOKTYPE_STR_LITERAL, l.line, l.col, value,
|
||||||
|
size - 2, l.filename);
|
||||||
|
free(value);
|
||||||
|
move(reader, size);
|
||||||
|
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#include <compiler/fzl_reader.h>
|
||||||
|
#include <compiler/internals/reader.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// Move cursor forward
|
||||||
|
size_t move(fzl_reader_t *reader, size_t len)
|
||||||
|
{
|
||||||
|
if (!reader)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return reader->position += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add single-char token
|
||||||
|
fzl_token_t *rd_single(fzl_reader_t *reader, fzl_toktype_t type)
|
||||||
|
{
|
||||||
|
fzl_file_loc l;
|
||||||
|
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
move(reader, 1);
|
||||||
|
return fzl_mktoken(type, l.line, l.col, "", 0, l.filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add double-char token
|
||||||
|
fzl_token_t *rd_double(fzl_reader_t *reader, fzl_toktype_t type)
|
||||||
|
{
|
||||||
|
fzl_file_loc l;
|
||||||
|
bool ok = fzl_linked_getpos(reader->linked, reader->position, &l);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err), "failed to locate line:col");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
move(reader, 2);
|
||||||
|
return fzl_mktoken(type, l.line, l.col, "", 0, l.filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip symbols until '\n' or EOF
|
||||||
|
void rd_comment(fzl_reader_t *reader)
|
||||||
|
{
|
||||||
|
move(reader, 2);
|
||||||
|
|
||||||
|
while (reader->position < reader->size)
|
||||||
|
{
|
||||||
|
if (reader->source[reader->position++] == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user