Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/common/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ void Buffer_Deinit(Buffer *buffer) {
buffer->buffer = NULL;
}

void Buffer_Clear(Buffer *buffer) {
buffer->count = 0;
buffer->cursor = 0;
}

void Buffer_Enqueue(Buffer *buffer, const void *element) {
if (buffer->count >= buffer->capacity) {
logError("Buffer overflow. Element dropped.");
Expand All @@ -65,19 +70,23 @@ bool Buffer_Dequeue(Buffer *buffer, void *out_element) {
return true;
}

bool Buffer_IsEmpty(Buffer *buffer) {
bool Buffer_IsEmpty(const Buffer *buffer) {
return buffer->count == 0;
}

size_t Buffer_Size(Buffer *buffer) {
size_t Buffer_Size(const Buffer *buffer) {
return buffer->count;
}

size_t Buffer_Capacity(Buffer *buffer) {
size_t Buffer_Capacity(const Buffer *buffer) {
return buffer->capacity;
}

bool Buffer_Peek(Buffer *buffer, size_t lookahead, void *out_element) {
bool Buffer_HasSpace(const Buffer *buffer) {
return buffer->count < buffer->capacity - 1;
}
Comment thread
defname marked this conversation as resolved.

bool Buffer_Peek(const Buffer *buffer, size_t lookahead, void *out_element) {
if (lookahead >= buffer->count) {
logError("Buffer underflow on Peek (lookahead: %zu, count: %zu).", lookahead, buffer->count);
return false;
Expand Down
16 changes: 12 additions & 4 deletions src/common/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ void Buffer_Init(Buffer *buffer, size_t capacity, size_t element_size);
*/
void Buffer_Deinit(Buffer *buffer);

/**
* @brief Set buffer count to 0 and cursor to the first element.
*/
void Buffer_Clear(Buffer *buffer);

/**
* @brief Adds an element to the end (tail) of the buffer.
* If the buffer is full, the element is dropped.
Expand All @@ -70,13 +75,16 @@ bool Buffer_Dequeue(Buffer *buffer, void *out_element);
* @param buffer A pointer to the Buffer struct.
* @return true if the buffer contains no elements, false otherwise.
*/
bool Buffer_IsEmpty(Buffer *buffer);
bool Buffer_IsEmpty(const Buffer *buffer);

/** @brief Returns the current number of elements in the buffer. */
size_t Buffer_Size(Buffer *buffer);
size_t Buffer_Size(const Buffer *buffer);

/** @brief Returns the maximum capacity of the buffer. */
size_t Buffer_Capacity(Buffer *buffer);
size_t Buffer_Capacity(const Buffer *buffer);

/** @brief Return true if there are empty slots. */
bool Buffer_HasSpace(const Buffer *buffer);

/**
* @brief Peeks at an element in the buffer without removing it.
Expand All @@ -85,6 +93,6 @@ size_t Buffer_Capacity(Buffer *buffer);
* @param out_element A pointer to a variable where the peeked element will be copied.
* @return true on success, false if the lookahead index is out of bounds.
*/
bool Buffer_Peek(Buffer *buffer, size_t lookahead, void *out_element);
bool Buffer_Peek(const Buffer *buffer, size_t lookahead, void *out_element);

#endif
142 changes: 95 additions & 47 deletions src/syntax/definition.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ SyntaxBlockDef *SyntaxBlockDef_Create() {
block->only_start = false;
block->children = NULL;
block->children_count = 0;
block->ends_on = NULL;
block->ends_on_count = 0;
return block;
}

Expand All @@ -55,6 +57,9 @@ void SyntaxBlockDef_Destroy(SyntaxBlockDef *block) {
if (block->children) {
free(block->children);
}
if (block->ends_on) {
free(block->ends_on);
}
if (block->name) {
free(block->name);
}
Expand Down Expand Up @@ -212,6 +217,68 @@ static SyntaxDefinitionError build_blocks(SyntaxDefinition *def, const Table *ta
return NO_ERROR;
}

static SyntaxDefinitionError map_block_names_to_blocks(SyntaxBlockDef *current_block, StringView *block_names, size_t count, SyntaxBlockDef **out, Table *blocks) {
for (size_t i=0; i<count; i++) {
String name = String_FromView(block_names[i]);
String_Trim(&name);
table_block_mapping *mapping = Table_Get(blocks, name.bytes);

if (!mapping) {
// no block with the given name
// something like
// allowed_blocks = block1, non_existing_block
SyntaxDefinitionError error = ERROR(
SYNTAXDEFINITION_BLOCK_DOES_NOT_EXIST,
"Block \"%s\" uses non-existing block \"%s\" in a list.", current_block->name, name.bytes
);
String_Deinit(&name);
return error;
}
String_Deinit(&name);
out[i] = mapping->block;
}
return NO_ERROR;
}

static SyntaxDefinitionError block_name_list_str_to_blocks(SyntaxBlockDef *current_block, const char *list_str, SyntaxBlockDef ***out, size_t *out_count, Table *blocks) {
if (!list_str) {
*out_count = 0;
return NO_ERROR;
}

String s = String_FromCStr(list_str, strlen(list_str));
ssize_t count = 0;
String delimiter = String_FromCStr(",", 1);
StringView *children = String_Split(&s, &delimiter, &count);
if (count < 0) {
logFatal("Potential error in String_Split().");
}
String_Deinit(&delimiter);
if (count == 0) {
String_Deinit(&s);
free(children);
return NO_ERROR;
}

// malloc memory for the children of SyntaxBlockDef
*out = malloc(sizeof(SyntaxBlockDef*) * count);
if (!(*out)) {
logFatal("Cannot allocate memory for children of SyntaxBlockDef.");
}

SyntaxDefinitionError error = map_block_names_to_blocks(current_block, children, count, *out, blocks);
if (error.code != SYNTAXDEFINITION_NO_ERROR) {
String_Deinit(&s);
free(children);
return error;
}

*out_count = count;
String_Deinit(&s);
free(children);

return NO_ERROR;
}

SyntaxDefinitionError link_children(SyntaxDefinition *def, Table *blocks) {
for (size_t i=0; i<def->blocks_count; i++) {
Expand All @@ -224,55 +291,31 @@ SyntaxDefinitionError link_children(SyntaxDefinition *def, Table *blocks) {
}
const Table *block_table = mapping->table;

const char *children_str = TypedTable_GetString(block_table, "allowed_blocks");
if (!children_str) {
continue;
}

String s = String_FromCStr(children_str, strlen(children_str));
ssize_t children_count = 0;
String delimiter = String_FromCStr(",", 1);
StringView *children = String_Split(&s, &delimiter, &children_count);
if (children_count < 0) {
logFatal("Potential rrror in String_Split().");
}
String_Deinit(&delimiter);
if (children_count == 0) {
String_Deinit(&s);
free(children);
continue;
const char *children_str = TypedTable_GetString(block_table, "child_blocks");
SyntaxDefinitionError error = block_name_list_str_to_blocks(block, children_str, &block->children, &block->children_count, blocks);
if (error.code != SYNTAXDEFINITION_NO_ERROR) {
return error;
}
}
return NO_ERROR;
}

// malloc memory for the children of SyntaxBlockDef
block->children = malloc(sizeof(SyntaxBlockDef*) * children_count);
if (!block->children) {
logFatal("Cannot allocate memory for children of SyntaxBlockDef.");
SyntaxDefinitionError link_ends_with(SyntaxDefinition *def, Table *blocks) {
for (size_t i=0; i<def->blocks_count; i++) {
SyntaxBlockDef *block = def->blocks[i];

// get the mapping
table_block_mapping *mapping = Table_Get(blocks, block->name);
if (!mapping) {
logFatal("Some serious design flaw detected.");
}
const Table *block_table = mapping->table;

for (size_t child_idx=0; child_idx<(size_t)children_count; child_idx++) {
String child_name = String_FromView(children[child_idx]);
String_Trim(&child_name);
table_block_mapping *child_mapping = Table_Get(blocks, child_name.bytes);

if (!child_mapping) {
// no block with the given child name
// something like
// allowed_blocks = block1, non_existing_block
SyntaxDefinitionError error = ERROR(
SYNTAXDEFINITION_BLOCK_DOES_NOT_EXIST,
"Block \"%s\" defines non-existing block \"%s\" as it's child.", block->name, child_name.bytes
);
String_Deinit(&child_name);
String_Deinit(&s);
free(children);
return error;
}
String_Deinit(&child_name);
block->children[child_idx] = child_mapping->block;
const char *ends_with_str = TypedTable_GetString(block_table, "ends_on");
SyntaxDefinitionError error = block_name_list_str_to_blocks(block, ends_with_str, &block->ends_on, &block->ends_on_count, blocks);
if (error.code != SYNTAXDEFINITION_NO_ERROR) {
return error;
}
block->children_count = children_count;
String_Deinit(&s);
free(children);
}
return NO_ERROR;
}
Expand All @@ -294,7 +337,6 @@ SyntaxDefinition *SyntaxDefinition_FromTable(const Table *table, SyntaxDefinitio
SyntaxDefinition_Destroy(def);
return NULL;
}
SyntaxDefinitionError_Deinit(error);

// temporary table mapping all block names to it's SyntaxBlockDef
Table *blocks = Table_Create();
Expand All @@ -304,7 +346,6 @@ SyntaxDefinition *SyntaxDefinition_FromTable(const Table *table, SyntaxDefinitio
Table_Destroy(blocks);
return NULL;
}
SyntaxDefinitionError_Deinit(error);

// construct the children lists
*error = link_children(def, blocks);
Expand All @@ -313,7 +354,14 @@ SyntaxDefinition *SyntaxDefinition_FromTable(const Table *table, SyntaxDefinitio
Table_Destroy(blocks);
return NULL;
}
SyntaxDefinitionError_Deinit(error);

// construct the ends_by list
*error = link_ends_with(def, blocks);
if (error->code != SYNTAXDEFINITION_NO_ERROR) {
SyntaxDefinition_Destroy(def);
Table_Destroy(blocks);
return NULL;
}

// cleanup
Table_Destroy(blocks);
Expand Down
18 changes: 17 additions & 1 deletion src/syntax/definition.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
* name = TEST
*
* [block:root]
* allowed_blocks = string, keyword
* child_blocks = string, keyword
*
* [block:string]
* start = "'"
Expand Down Expand Up @@ -99,6 +99,16 @@ typedef struct _SyntaxDefinitionError {
void SyntaxDefinitionError_Deinit(SyntaxDefinitionError *error);


/**
* @brief Helper struct to cache regex match results. This information are used by the Highlight module.
*/
typedef struct _MatchCache {
ssize_t offset; // total offset from where match was calculated
regmatch_t match; // last match
bool done; // if true the last match was already found
} MatchCache;


/**
* @brief Holds the definition of a syntax block.
*/
Expand All @@ -111,8 +121,14 @@ typedef struct _SyntaxBlockDef {

struct _SyntaxBlockDef **children; //< list of children definition which are allowed inside the block
size_t children_count; //< number of children

struct _SyntaxBlockDef **ends_on; //< list of blocks which may end this block implicitly
size_t ends_on_count; //< number of blocks which may end this block implicitly

uint8_t color; //< the color to render the block

MatchCache start_cache; //< used by the Highlight module
MatchCache end_cache; //< used by the Highlight module
} SyntaxBlockDef;

SyntaxBlockDef *SyntaxBlockDef_Create();
Expand Down
Loading