add string + array + scirpt parser

This commit is contained in:
SimonFJ20 2023-04-13 02:28:08 +02:00
parent ca043f7b57
commit dd73b32372
19 changed files with 742 additions and 90 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
build/
bin/
session.vim

View File

@ -14,7 +14,7 @@ all: compile_flags.txt dirs scirpt
UTILS_SRC = stringmap.c
UTILS_OBJ = $(patsubst %.c, build/utils/%.o, $(UTILS_SRC))
SCIRPT_SRC = main.c lexer.c parser.c
SCIRPT_SRC = main.c lexer.c ast.c parser.c
SCIRPT_OBJ = $(patsubst %.c, build/scirpt/%.o, $(SCIRPT_SRC))
scirpt: $(SCIRPT_OBJ) $(UTILS_OBJ)

28
include/scirpt/ast.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef SCIRPT_AST_H
#define SCIRPT_AST_H
#include <stdbool.h>
#include <stdint.h>
typedef enum {
ScirptAstExprTypeEof,
ScirptAstExprTypeError,
ScirptAstExprTypeId,
ScirptAstExprTypeInt,
ScirptAstExprTypeString,
ScirptAstExprTypeBool,
} ScirptAstExprType;
typedef struct {
ScirptAstExprType type;
union {
char* id_value;
int64_t int_value;
char* string_value;
bool bool_value;
};
} ScirptAstExpr;
void scirpt_ast_expr_delete(ScirptAstExpr* expr);
#endif

View File

@ -1,4 +1,29 @@
#ifndef SCIRPT_PARSER_H
#define SCIRPT_PARSER_H
#include "scirpt/ast.h"
#include "scirpt/lexer.h"
#include "utils/generic_array.h"
#include "utils/string.h"
#include <stdlib.h>
typedef struct {
HeapString message;
ScirptPosition pos;
} ScirptParserError;
GENERIC_ARRAY(
ScirptParserError, ScirptParserErrorArray, scirpt_parser_error_array
)
typedef struct ScirptParserErrorArray ScirptParserErrorArray;
typedef struct ScirptParser ScirptParser;
ScirptParser*
scirpt_parser_new(const char* text, size_t text_length, ScirptLexer* lexer);
void scirpt_parser_delete(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_next_expr(ScirptParser* parser);
bool scirpt_parser_ok(const ScirptParser* parser);
const ScirptParserErrorArray* scirpt_parser_errors(const ScirptParser* parser);
#endif

View File

@ -7,6 +7,8 @@
typedef enum {
ScirptTokenTypeEof,
ScirptTokenTypeInvalidChar,
ScirptTokenTypeMalformedComment,
ScirptTokenTypeMalformedString,
ScirptTokenTypeId,
ScirptTokenTypeInt,
ScirptTokenTypeString,
@ -21,11 +23,29 @@ typedef enum {
ScirptTokenTypeColon,
ScirptTokenTypeSemicolon,
ScirptTokenTypePlus,
ScirptTokenTypePlusEqual,
ScirptTokenTypeMinus,
ScirptTokenTypeMinusEqual,
ScirptTokenTypeAsterisk,
ScirptTokenTypeAsteriskEqual,
ScirptTokenTypeSlash,
ScirptTokenTypeSlashEqual,
ScirptTokenTypePercent,
ScirptTokenTypePercentEqual,
ScirptTokenTypeEqual,
ScirptTokenTypeEqualEqual,
ScirptTokenTypeExclamation,
ScirptTokenTypeExclamationEqual,
ScirptTokenTypeLt,
ScirptTokenTypeLtEqual,
ScirptTokenTypeGt,
ScirptTokenTypeGtEqual,
ScirptTokenTypeNull,
ScirptTokenTypeFalse,
ScirptTokenTypeTrue,
ScirptTokenTypeNot,
ScirptTokenTypeAnd,
ScirptTokenTypeOr,
ScirptTokenTypeLet,
ScirptTokenTypeIf,
ScirptTokenTypeElse,

View File

@ -0,0 +1,61 @@
#ifndef UTILS_GENERIC_ARRAY_H
#define UTILS_GENERIC_ARRAY_H
#include <stddef.h>
#include <stdlib.h>
#define GENERIC_ARRAY(Type, struct_name, function_prefix) \
struct struct_name { \
Type* data; \
size_t length, capacity; \
}; \
\
static inline void function_prefix##_construct(struct struct_name* array) \
{ \
*array = (struct struct_name) { \
.data = NULL, \
.length = 0, \
.capacity = 0, \
}; \
} \
\
static inline void function_prefix##_destroy(struct struct_name* array) \
{ \
if (array->data) \
free(array->data); \
} \
\
static inline size_t function_prefix##_length( \
const struct struct_name* array \
) \
{ \
return array->length; \
} \
\
static inline Type* function_prefix##_get( \
const struct struct_name* array, size_t index \
) \
{ \
if (index >= array->length) \
return NULL; \
else \
return &array->data[index]; \
} \
\
static inline void function_prefix##_append( \
struct struct_name* array, Type value \
) \
{ \
if (array->data == NULL) { \
array->capacity = 8; \
array->data = malloc(sizeof(Type) * array->capacity); \
} else if (array->length == array->capacity) { \
array->capacity *= 2; \
array->data \
= realloc(array->data, sizeof(Type) * array->capacity); \
} \
array->data[array->length] = value; \
array->length++; \
}
#endif

21
include/utils/math.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef UTILS_MATH_H
#define UTILS_MATH_H
#include <stdint.h>
// https://stackoverflow.com/questions/466204/rounding-up-to-next-power-of-2
// https://stackoverflow.com/questions/1322510/given-an-integer-how-do-i-find-the-next-largest-power-of-two-using-bit-twiddlin/1322548#1322548
static inline uint64_t utils_nearest_bigger_power_of_2_u64(uint64_t value)
{
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value |= value >> 32;
value++;
return value;
}
#endif

37
include/utils/string.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef UTILS_STRING_H
#define UTILS_STRING_H
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
const char* data;
size_t length;
} StringView;
typedef struct {
char* data;
size_t length;
} HeapString;
static inline HeapString heapstring_from(const char* text, size_t length)
{
char* allocated = malloc(sizeof(char) * length + 1);
strncpy(allocated, text, length);
HeapString string = {
.data = allocated,
.length = length,
};
return string;
}
static inline HeapString heapstring_from_cstring(const char* text)
{
return heapstring_from(text, strlen(text));
}
static inline void heapstring_destroy(HeapString* string)
{
free(string->data);
}
#endif

View File

@ -0,0 +1,38 @@
#ifndef UTILS_STRING_ARRAY_H
#define UTILS_STRING_ARRAY_H
#include "utils/generic_array.h"
#include "utils/string.h"
#include <stdlib.h>
GENERIC_ARRAY(StringView, StringViewArray, stringview_array)
typedef struct StringViewArray StringViewArray;
static inline StringViewArray* stringview_array_new(void)
{
StringViewArray* array = malloc(sizeof(StringViewArray));
stringview_array_construct(array);
return array;
}
static inline void stringview_array_delete(StringViewArray* array)
{
stringview_array_destroy(array);
free(array);
}
GENERIC_ARRAY(HeapString, HeapStringArray, heapstring_array)
typedef struct HeapStringArray HeapStringArray;
static inline HeapStringArray* heapstring_array_new(void)
{
HeapStringArray* array = malloc(sizeof(HeapStringArray));
heapstring_array_construct(array);
return array;
}
static inline void heapstring_array_delete(HeapStringArray* array)
{
heapstring_array_destroy(array);
free(array);
}
#endif

View File

@ -3,26 +3,11 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
// https://stackoverflow.com/questions/466204/rounding-up-to-next-power-of-2
// https://stackoverflow.com/questions/1322510/given-an-integer-how-do-i-find-the-next-largest-power-of-two-using-bit-twiddlin/1322548#1322548
static inline uint64_t utils_nearest_bigger_power_of_2_u64(uint64_t value)
{
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value |= value >> 32;
value++;
return value;
}
// https://stackoverflow.com/questions/7666509/hash-function-for-string
// http://www.cse.yorku.ca/~oz/hash.html
static inline size_t string_hash_djb2(const unsigned char* value, size_t length)
static inline size_t
utils_string_hash_djb2(const unsigned char* value, size_t length)
{
size_t hash = 5381;
for (size_t i = 0; i < length && value[i] != '\0'; ++i)
@ -44,5 +29,6 @@ void stringmap_remove(StringMap* map, const char* key, size_t key_length);
void stringmap_clean(StringMap* map);
void stringmap_shrink(StringMap* map);
void stringmap_clean_and_shrink(StringMap* map);
size_t stringmap_length(StringMap* map);
#endif

View File

@ -1 +0,0 @@
#include "parser.h"

22
scirpt/ast.c Normal file
View File

@ -0,0 +1,22 @@
#include "scirpt/ast.h"
#include <stdlib.h>
void scirpt_ast_expr_delete(ScirptAstExpr* expr)
{
switch (expr->type) {
case ScirptAstExprTypeEof:
break;
case ScirptAstExprTypeError:
break;
case ScirptAstExprTypeId:
free(expr->id_value);
break;
case ScirptAstExprTypeInt:
break;
case ScirptAstExprTypeString:
free(expr->string_value);
break;
case ScirptAstExprTypeBool:
break;
}
}

View File

@ -6,6 +6,8 @@
#include <stdlib.h>
#include <string.h>
#define TT(type) ScirptTokenType##type
static inline void step(ScirptLexer* lexer) { scirpt_lexer_step(lexer); }
static inline ScirptToken
token(const ScirptLexer* lexer, ScirptTokenType type, ScirptPosition start)
@ -49,18 +51,21 @@ void scirpt_lexer_create(
)
{
StringMap* keywords = stringmap_new();
add_keyword(keywords, "null", ScirptTokenTypeNull);
add_keyword(keywords, "false", ScirptTokenTypeFalse);
add_keyword(keywords, "true", ScirptTokenTypeTrue);
add_keyword(keywords, "let", ScirptTokenTypeLet);
add_keyword(keywords, "if", ScirptTokenTypeIf);
add_keyword(keywords, "else", ScirptTokenTypeElse);
add_keyword(keywords, "while", ScirptTokenTypeWhile);
add_keyword(keywords, "for", ScirptTokenTypeFor);
add_keyword(keywords, "in", ScirptTokenTypeIn);
add_keyword(keywords, "break", ScirptTokenTypeBreak);
add_keyword(keywords, "fn", ScirptTokenTypeFn);
add_keyword(keywords, "return", ScirptTokenTypeReturn);
add_keyword(keywords, "null", TT(Null));
add_keyword(keywords, "false", TT(False));
add_keyword(keywords, "true", TT(True));
add_keyword(keywords, "not", TT(Not));
add_keyword(keywords, "and", TT(And));
add_keyword(keywords, "or", TT(Or));
add_keyword(keywords, "let", TT(Let));
add_keyword(keywords, "if", TT(If));
add_keyword(keywords, "else", TT(Else));
add_keyword(keywords, "while", TT(While));
add_keyword(keywords, "for", TT(For));
add_keyword(keywords, "in", TT(In));
add_keyword(keywords, "break", TT(Break));
add_keyword(keywords, "fn", TT(Fn));
add_keyword(keywords, "return", TT(Return));
*lexer = (ScirptLexer) {
.text = text,
.text_length = text_length,
@ -99,27 +104,196 @@ static inline bool is_id_char(char value)
ScirptToken scirpt_lexer_next(ScirptLexer* lexer)
{
if (done(lexer)) {
return token(lexer, ScirptTokenTypeEof, pos(lexer));
} else if (is_whitespace(current(lexer))) {
return scirpt_lexer_level_1(lexer);
}
ScirptToken scirpt_lexer_level_1(ScirptLexer* lexer)
{
if (done(lexer))
return token(lexer, TT(Eof), pos(lexer));
else if (is_whitespace(current(lexer)))
return scirpt_lexer_skip_whitespace(lexer);
else if (is_id_char_excluding_numbers(current(lexer)))
return scirpt_lexer_id_token(lexer);
else
return scirpt_lexer_level_2(lexer);
}
static inline ScirptToken single_token(ScirptLexer* lexer, ScirptTokenType type)
{
ScirptPosition start = pos(lexer);
step(lexer);
return token(lexer, type, start);
}
static inline ScirptToken single_or_double_token(
ScirptLexer* lexer,
ScirptTokenType first_type,
char second_char,
ScirptTokenType second_type
)
{
ScirptPosition start = pos(lexer);
step(lexer);
if (current_is(lexer, second_char)) {
step(lexer);
while (!done(lexer) && is_whitespace(current(lexer)))
return token(lexer, second_type, start);
} else {
return token(lexer, first_type, start);
}
}
ScirptToken scirpt_lexer_level_2(ScirptLexer* lexer)
{
switch (current(lexer)) {
case '0':
return single_token(lexer, TT(Int));
case '"':
return scirpt_lexer_string_token(lexer);
case '(':
return single_token(lexer, TT(LParen));
case ')':
return single_token(lexer, TT(RParen));
case '{':
return single_token(lexer, TT(LBrace));
case '}':
return single_token(lexer, TT(RBrace));
case '[':
return single_token(lexer, TT(LBracket));
case ']':
return single_token(lexer, TT(RBracket));
case '.':
return single_token(lexer, TT(RBracket));
case ',':
return single_token(lexer, TT(RBracket));
case ':':
return single_token(lexer, TT(RBracket));
case ';':
return single_token(lexer, TT(RBracket));
case '+':
return single_or_double_token(lexer, TT(Plus), '=', TT(PlusEqual));
case '-':
return single_or_double_token(
lexer, TT(Minus), '=', TT(MinusEqual)
);
case '*':
return single_or_double_token(
lexer, TT(Asterisk), '=', TT(AsteriskEqual)
);
case '/':
return single_token(lexer, TT(RBracket));
case '%':
return single_or_double_token(
lexer, TT(Percent), '=', TT(PercentEqual)
);
case '=':
return single_or_double_token(
lexer, TT(Equal), '=', TT(EqualEqual)
);
case '!':
return single_or_double_token(
lexer, TT(Exclamation), '=', TT(ExclamationEqual)
);
case '<':
return single_or_double_token(lexer, TT(Lt), '=', TT(LtEqual));
case '>':
return single_or_double_token(lexer, TT(Gt), '=', TT(GtEqual));
default:
return scirpt_lexer_level_3(lexer);
}
}
ScirptToken scirpt_lexer_level_3(ScirptLexer* lexer)
{
if (is_int_char(current(lexer)))
return scirpt_lexer_int_token(lexer);
else
return single_token(lexer, TT(InvalidChar));
}
ScirptToken scirpt_lexer_skip_whitespace(ScirptLexer* lexer)
{
step(lexer);
while (!done(lexer) && is_whitespace(current(lexer)))
step(lexer);
return scirpt_lexer_next(lexer);
}
ScirptToken scirpt_lexer_id_token(ScirptLexer* lexer)
{
ScirptPosition start = pos(lexer);
step(lexer);
while (!done(lexer) && is_id_char(current(lexer)))
step(lexer);
size_t* found_keyword = stringmap_get(
lexer->keywords, &lexer->text[start.index], lexer->index - start.index
);
if (found_keyword)
return token(lexer, (ScirptTokenType)*found_keyword, start);
else
return token(lexer, TT(Id), start);
}
ScirptToken scirpt_lexer_int_token(ScirptLexer* lexer)
{
ScirptPosition start = pos(lexer);
step(lexer);
while (!done(lexer) && is_int_char(current(lexer)))
step(lexer);
return token(lexer, TT(Int), start);
}
ScirptToken scirpt_lexer_string_token(ScirptLexer* lexer)
{
ScirptPosition start = pos(lexer);
step(lexer);
while (!done(lexer) && current(lexer) != '\"') {
char first = current(lexer);
step(lexer);
if (!done(lexer) && first == '\\')
step(lexer);
}
if (!current_is(lexer, '"'))
return token(lexer, TT(MalformedString), start);
step(lexer);
return token(lexer, TT(String), start);
}
ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer)
{
ScirptPosition start = pos(lexer);
step(lexer);
if (current_is(lexer, TT(Slash))) {
step(lexer);
while (!done(lexer) && current(lexer) != '\n')
step(lexer);
return scirpt_lexer_next(lexer);
} else if (is_id_char_excluding_numbers(current(lexer))) {
ScirptPosition start = pos(lexer);
} else if (current_is(lexer, TT(Asterisk))) {
step(lexer);
while (!done(lexer) && is_id_char(current(lexer)))
step(lexer);
return token(lexer, ScirptTokenTypeId, start);
} else {
switch (current(lexer)) {
default: {
ScirptPosition start = pos(lexer);
step(lexer);
return token(lexer, ScirptTokenTypeInvalidChar, start);
int depth = 0;
char last_char = '\0';
while (!done(lexer)) {
if (last_char == '/' && current(lexer) == '*') {
depth++;
} else if (last_char == '*' && current(lexer) == '/') {
depth--;
if (depth == 0) {
step(lexer);
break;
}
}
last_char = current(lexer);
step(lexer);
}
if (depth != 0)
return token(lexer, TT(MalformedComment), start);
return scirpt_lexer_next(lexer);
} else if (current_is(lexer, TT(Equal))) {
step(lexer);
return token(lexer, TT(SlashEqual), start);
} else {
return token(lexer, TT(Slash), start);
}
}

View File

@ -19,6 +19,14 @@ void scirpt_lexer_create(
ScirptLexer* lexer, const char* text, size_t text_length
);
void scirpt_lexer_destroy(ScirptLexer* lexer);
ScirptToken scirpt_lexer_level_1(ScirptLexer* lexer);
ScirptToken scirpt_lexer_level_2(ScirptLexer* lexer);
ScirptToken scirpt_lexer_level_3(ScirptLexer* lexer);
ScirptToken scirpt_lexer_skip_whitespace(ScirptLexer* lexer);
ScirptToken scirpt_lexer_id_token(ScirptLexer* lexer);
ScirptToken scirpt_lexer_int_token(ScirptLexer* lexer);
ScirptToken scirpt_lexer_string_token(ScirptLexer* lexer);
ScirptToken scirpt_lexer_slash_token(ScirptLexer* lexer);
void scirpt_lexer_step(ScirptLexer* lexer);
ScirptPosition scirpt_lexer_pos(const ScirptLexer* lexer);
ScirptToken scirpt_lexer_token(

View File

@ -1,20 +1,56 @@
#include "scirpt/ast.h"
#include "scirpt/lexer.h"
#include "scirpt/parser.h"
#include "scirpt/token.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
printf("hello world\n");
const char* text = "123 if +";
printf("test program = \"\"\"\n%s\n\"\"\"\n", text);
ScirptLexer* lexer = scirpt_lexer_new(text, strlen(text));
while (true) {
ScirptToken token = scirpt_lexer_next(lexer);
if (token.type == ScirptTokenTypeEof)
break;
printf("%d\n", token.type);
{
printf("\n- test lexer\n");
ScirptLexer* lexer = scirpt_lexer_new(text, strlen(text));
while (true) {
ScirptToken token = scirpt_lexer_next(lexer);
if (token.type == ScirptTokenTypeEof)
break;
printf("%d\n", token.type);
}
scirpt_lexer_delete(lexer);
}
{
printf("\n- test lexer + parser\n");
ScirptLexer* lexer = scirpt_lexer_new(text, strlen(text));
ScirptParser* parser = scirpt_parser_new(text, strlen(text), lexer);
while (true) {
ScirptAstExpr* expr = scirpt_parser_next_expr(parser);
if (expr->type == ScirptAstExprTypeEof) {
break;
} else if (!scirpt_parser_ok(parser)) {
const ScirptParserErrorArray* errors
= scirpt_parser_errors(parser);
for (size_t i = 0; i < scirpt_parser_error_array_length(errors);
++i) {
ScirptParserError* error
= scirpt_parser_error_array_get(errors, i);
printf(
"error: %s at %d:%d\n",
error->message.data,
error->pos.line,
error->pos.col
);
}
break;
}
printf("%d\n", expr->type);
scirpt_ast_expr_delete(expr);
}
scirpt_parser_delete(parser);
}
}

View File

@ -0,0 +1,160 @@
#include "scirpt/parser.h"
#include "parser.h"
#include "scirpt/ast.h"
#include "scirpt/lexer.h"
#include "scirpt/position.h"
#include "scirpt/token.h"
#include "utils/string.h"
#include <stdint.h>
#include <stdlib.h>
#define TT(type) ScirptTokenType##type
static inline ScirptAstExpr* alloc_expr(ScirptAstExpr data)
{
ScirptAstExpr* expr = malloc(sizeof(ScirptAstExpr));
*expr = data;
return expr;
}
static inline void
error(ScirptParser* parser, HeapString message, ScirptPosition pos)
{
scirpt_parser_error(parser, message, pos);
}
static inline ScirptPosition pos(ScirptParser* parser)
{
return parser->current.pos;
}
static inline void step(ScirptParser* parser) { scirpt_parser_step(parser); }
static inline bool current_is(const ScirptParser* parser, ScirptTokenType type)
{
return scirpt_parser_current_is(parser, type);
}
static inline bool done(const ScirptParser* parser)
{
return scirpt_parser_done(parser);
}
ScirptParser*
scirpt_parser_new(const char* text, size_t text_length, ScirptLexer* lexer)
{
ScirptParser* parser = malloc(sizeof(ScirptParser));
scirpt_parser_construct(parser, text, text_length, lexer);
return parser;
}
void scirpt_parser_delete(ScirptParser* parser) { free(parser); }
ScirptAstExpr* scirpt_parser_next_expr(ScirptParser* parser)
{
if (done(parser)) {
return alloc_expr((ScirptAstExpr) {
.type = ScirptAstExprTypeEof,
});
} else {
return scirpt_parser_parse_expr(parser);
}
}
bool scirpt_parser_ok(const ScirptParser* parser) { return parser->ok; }
const ScirptParserErrorArray* scirpt_parser_errors(const ScirptParser* parser)
{
return &parser->errors;
}
void scirpt_parser_construct(
ScirptParser* parser,
const char* text,
size_t text_length,
ScirptLexer* lexer
)
{
ScirptParserErrorArray errors;
scirpt_parser_error_array_construct(&errors);
*parser = (ScirptParser) {
.text = text,
.text_length = text_length,
.lexer = lexer,
.current = scirpt_lexer_next(lexer),
.errors = errors,
.ok = true,
};
}
void scirpt_parser_destroy(ScirptParser* parser)
{
scirpt_parser_error_array_construct(&parser->errors);
}
ScirptAstExpr* scirpt_parser_parse_expr(ScirptParser* parser)
{
return scirpt_parser_parse_operand(parser);
}
ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser)
{
switch (parser->current.type) {
case ScirptTokenTypeInt: {
HeapString value_string = heapstring_from(
&parser->text[pos(parser).index], parser->current.length
);
int64_t value = atoll(value_string.data);
step(parser);
return alloc_expr((ScirptAstExpr) {
.type = ScirptAstExprTypeInt,
.int_value = value,
});
}
case ScirptTokenTypeEof: {
error(
parser,
heapstring_from_cstring("expected value, got Eof"),
pos(parser)
);
return alloc_expr((ScirptAstExpr) {
.type = ScirptAstExprTypeError,
});
}
default: {
error(
parser, heapstring_from_cstring("expected value"), pos(parser)
);
step(parser);
return alloc_expr((ScirptAstExpr) {
.type = ScirptAstExprTypeError,
});
}
}
}
void scirpt_parser_error(
ScirptParser* parser, HeapString message, ScirptPosition pos
)
{
if (parser->ok)
parser->ok = false;
scirpt_parser_error_array_append(
&parser->errors,
(ScirptParserError) {
.message = message,
.pos = pos,
}
);
}
void scirpt_parser_step(ScirptParser* parser)
{
parser->current = scirpt_lexer_next(parser->lexer);
}
bool scirpt_parser_current_is(const ScirptParser* parser, ScirptTokenType type)
{
return parser->current.type == type;
}
bool scirpt_parser_done(const ScirptParser* parser)
{
return parser->current.type == ScirptTokenTypeEof;
}

View File

@ -1,6 +1,37 @@
#ifndef PARSER_H
#define PARSER_H
#include "scirpt/ast.h"
#include "scirpt/lexer.h"
#include "scirpt/parser.h"
#include "scirpt/position.h"
#include "scirpt/token.h"
#include <stddef.h>
#include <stdlib.h>
struct ScirptParser {
const char* text;
size_t text_length;
ScirptLexer* lexer;
ScirptToken current;
ScirptParserErrorArray errors;
bool ok;
};
void scirpt_parser_construct(
ScirptParser* parser,
const char* text,
size_t text_length,
ScirptLexer* lexer
);
void scirpt_parser_destroy(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_parse_expr(ScirptParser* parser);
ScirptAstExpr* scirpt_parser_parse_operand(ScirptParser* parser);
void scirpt_parser_error(
ScirptParser* parser, HeapString message, ScirptPosition pos
);
void scirpt_parser_step(ScirptParser* parser);
bool scirpt_parser_current_is(const ScirptParser* parser, ScirptTokenType type);
bool scirpt_parser_done(const ScirptParser* parser);
#endif

View File

@ -1,4 +1,5 @@
#include "stringmap.h"
#include "utils/math.h"
#include "utils/stringmap.h"
#include <stdint.h>
#include <stdlib.h>
@ -14,18 +15,20 @@ void stringmap_delete(StringMap* map) { free(map); }
size_t* stringmap_get(const StringMap* map, const char* key, size_t key_length)
{
size_t key_hash = string_hash_djb2((const unsigned char*)key, key_length);
for (size_t i = 0; i < map->size; ++i)
if (map->entries[i].key_hash == key_hash && !map->entries[i].deleted)
return &map->entries[i].value;
size_t key_hash
= utils_string_hash_djb2((const unsigned char*)key, key_length);
for (size_t i = 0; i < map->length; ++i)
if (map->data[i].key_hash == key_hash && !map->data[i].deleted)
return &map->data[i].value;
return NULL;
}
bool stringmap_has(const StringMap* map, const char* key, size_t key_length)
{
size_t key_hash = string_hash_djb2((const unsigned char*)key, key_length);
for (size_t i = 0; i < map->size; ++i)
if (map->entries[i].key_hash == key_hash && !map->entries[i].deleted)
size_t key_hash
= utils_string_hash_djb2((const unsigned char*)key, key_length);
for (size_t i = 0; i < map->length; ++i)
if (map->data[i].key_hash == key_hash && !map->data[i].deleted)
return true;
return false;
}
@ -34,27 +37,27 @@ void stringmap_set(
StringMap* map, const char* key, size_t key_length, size_t value
)
{
size_t key_hash = string_hash_djb2((const unsigned char*)key, key_length);
for (size_t i = 0; i < map->size; ++i) {
if (map->entries[i].key_hash == key_hash && !map->entries[i].deleted) {
map->entries[i].value = value;
size_t key_hash
= utils_string_hash_djb2((const unsigned char*)key, key_length);
for (size_t i = 0; i < map->length; ++i) {
if (map->data[i].key_hash == key_hash && !map->data[i].deleted) {
map->data[i].value = value;
return;
}
}
if (map->entries == NULL) {
if (map->data == NULL) {
map->capacity = 8;
map->entries = malloc(sizeof(StringMapEntry) * map->capacity);
} else if (map->size == map->capacity) {
map->data = malloc(sizeof(StringMapEntry) * map->capacity);
} else if (map->length == map->capacity) {
map->capacity *= 2;
map->entries
= realloc(map->entries, sizeof(StringMapEntry) * map->capacity);
map->data = realloc(map->data, sizeof(StringMapEntry) * map->capacity);
}
map->entries[map->size] = (StringMapEntry) {
map->data[map->length] = (StringMapEntry) {
.deleted = false,
.key_hash = key_hash,
.value = value,
};
map->size++;
map->length++;
}
void stringmap_reserve(StringMap* map, size_t minimum_size)
@ -62,16 +65,16 @@ void stringmap_reserve(StringMap* map, size_t minimum_size)
if (map->capacity >= minimum_size)
return;
map->capacity = utils_nearest_bigger_power_of_2_u64(minimum_size);
map->entries
= realloc(map->entries, sizeof(StringMapEntry) * map->capacity);
map->data = realloc(map->data, sizeof(StringMapEntry) * map->capacity);
}
void stringmap_remove(StringMap* map, const char* key, size_t key_length)
{
size_t key_hash = string_hash_djb2((const unsigned char*)key, key_length);
for (size_t i = 0; i < map->size; ++i) {
if (map->entries[i].key_hash == key_hash && !map->entries[i].deleted) {
map->entries[i].deleted = true;
size_t key_hash
= utils_string_hash_djb2((const unsigned char*)key, key_length);
for (size_t i = 0; i < map->length; ++i) {
if (map->data[i].key_hash == key_hash && !map->data[i].deleted) {
map->data[i].deleted = true;
}
}
}
@ -79,21 +82,20 @@ void stringmap_remove(StringMap* map, const char* key, size_t key_length)
void stringmap_clean(StringMap* map)
{
size_t shift_amount = 0;
for (size_t i = 0; i < map->size; ++i) {
map->entries[i - shift_amount] = map->entries[i];
if (map->entries[i].deleted)
for (size_t i = 0; i < map->length; ++i) {
map->data[i - shift_amount] = map->data[i];
if (map->data[i].deleted)
shift_amount++;
}
}
void stringmap_shrink(StringMap* map)
{
size_t new_size = utils_nearest_bigger_power_of_2_u64(map->size);
size_t new_size = utils_nearest_bigger_power_of_2_u64(map->length);
if (new_size >= map->capacity)
return;
map->capacity = new_size;
map->entries
= realloc(map->entries, sizeof(StringMapEntry) * map->capacity);
map->data = realloc(map->data, sizeof(StringMapEntry) * map->capacity);
}
void stringmap_clean_and_shrink(StringMap* map)
@ -102,17 +104,19 @@ void stringmap_clean_and_shrink(StringMap* map)
stringmap_shrink(map);
}
size_t stringmap_length(StringMap* map) { return map->length; }
void stringmap_create(StringMap* map)
{
*map = (StringMap) {
.entries = NULL,
.size = 0,
.data = NULL,
.length = 0,
.capacity = 0,
};
}
void stringmap_destroy(StringMap* map)
{
if (map->entries)
free(map->entries);
if (map->data)
free(map->data);
}

View File

@ -11,8 +11,8 @@ typedef struct StringMapEntry {
} StringMapEntry;
struct StringMap {
StringMapEntry* entries;
size_t size, capacity;
StringMapEntry* data;
size_t length, capacity;
};
void stringmap_create(StringMap* map);