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
2 changes: 1 addition & 1 deletion .github/workflows/cmake-multi-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name: CMake on multiple platforms

on:
push:
branches: [ "main" ]
branches: [ "main", "dev" ]
pull_request:
branches: [ "main" ]

Expand Down
53 changes: 50 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.26)
set(CMAKE_COMPILE_WARNING_AS_ERROR ON)
project(akoc
LANGUAGES C
VERSION 0.1.0
VERSION 1.0.0
DESCRIPTION "A C implementation of the Ako config language"
HOMEPAGE_URL "https://github.com/Tuyuji/AkoC"
)
Expand All @@ -18,7 +18,10 @@ add_library(akoc
src/ako.c
src/mem/dyn_string.c
src/lex/parser.c)
target_include_directories(akoc PUBLIC include)
target_include_directories(akoc PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

#Test
project(akotest C)
Expand All @@ -30,4 +33,48 @@ enable_testing()

add_test(NAME akotest
COMMAND $<TARGET_FILE:akotest>
)
)

# A bunch of small cli tools
add_subdirectory(utils)

include(GNUInstallDirs)

install(TARGETS akoc
EXPORT akocTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h"
)

install(EXPORT akocTargets
FILE akocTargets.cmake
NAMESPACE akoc::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/akoc
)

include(CMakePackageConfigHelpers)

configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/akocConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/akocConfig.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/akoc
)

write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/akocConfigVersion.cmake"
VERSION ${akoc_VERSION}
COMPATIBILITY SameMajorVersion
)

install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/akocConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/akocConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/akoc
)
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ int main()
return 1;
}

//You can get elements like this:
ako_elem_t* win = ako_elem_table_get(root, "window");
ako_elem_t* size = ako_elem_table_get(win, "size");

ako_int w = ako_elem_get_int(ako_elem_array_get(size, 0));
ako_int h = ako_elem_get_int(ako_elem_array_get(size, 1));

//Or like this, you should make sure ako_elem_get isn't null as
//ako_elem_get_int will assert if you pass it a NULL ptr.
w = ako_elem_get_int(ako_elem_get(root, "window.size.0"));
h = ako_elem_get_int(ako_elem_get(root, "window.size.1"));

printf("Window size: %d x %d\n", w, h);

ako_elem_table_add(win, "title", ako_elem_create_string("Hello, world"));
Expand Down
9 changes: 9 additions & 0 deletions cmake/akocConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)

# Include the exported targets
include("${CMAKE_CURRENT_LIST_DIR}/akocTargets.cmake")

# Check that all required components are found
check_required_components(akoc)
1 change: 1 addition & 0 deletions include/ako/ako.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define AKO_VMAJOR 0
#define AKO_VMINOR 1
#define AKO_VPATCH 0
#define AKO_VERSION_STR "0.1.0"

#include <ako/elem.h>

Expand Down
3 changes: 2 additions & 1 deletion include/ako/ako.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// SPDX-License-Identifier: MIT
#pragma once

extern "C" {
extern "C"
{
#include "ako.h"
#include "elem.h"
#include "types.h"
Expand Down
8 changes: 7 additions & 1 deletion include/ako/elem.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,10 @@ ako_elem_t* ako_elem_create_string(const char* str);
ako_elem_t* ako_elem_create_shorttype(const char* str);
ako_elem_t* ako_elem_create_bool(bool value);
ako_elem_t* ako_elem_create_error(const char* error);
ako_elem_t* ako_elem_create_errorf(const char* fmt, ...);
ako_elem_t* ako_elem_create_errorf(const char* fmt, ...);

// Accepts a path in ako format: e.g "song.artist"
// Returns the found element or NULL if not found
// If an error occurs, it will return an error element
// If ignore_error is true, it will return NULL if an error occurs
ako_elem_t* ako_elem_get(ako_elem_t* root, const char* path);
18 changes: 15 additions & 3 deletions src/ako.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,23 @@ void ako_free_string(const char* str)

ako_elem_t* ako_parse(const char* source)
{
static char* err = NULL;
dyn_array_t tokens = ako_tokenize(source, &err);
if (source == NULL || strlen(source) == 0)
{
return NULL;
}

ako_elem_t* err = NULL;
dyn_array_t tokens = ako_tokenize(source, &err, false);
if (err != NULL)
{
// uh oh
return err;
}

if (tokens.size == 0)
{
return ako_elem_create_error(err);
// no tokens
return NULL;
}

/*for(size_t i = 0; i < tokens.size; i++)
Expand Down
104 changes: 104 additions & 0 deletions src/elem.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <string.h>

#include "ako/ako.h"
#include "lex/token.h"
#include "private.h"

#define IS_TABLE_OR_ARRAY(type) (type == AT_TABLE || type == AT_ARRAY)
Expand Down Expand Up @@ -410,3 +411,106 @@ ako_elem_t* ako_elem_create_errorf(const char* fmt, ...)
elem->str = str;
return elem;
}

ako_elem_t* ako_elem_get(ako_elem_t* root, const char* path)
{
// When tokenizatio this will be our error checking
// once done were using this for our current table
ako_elem_t* elem;

dyn_array_t tokens = ako_tokenize(path, &elem, true);
if (elem != NULL)
{
ako_elem_destroy(elem);
return NULL;
}

// We only support a small subset of the tokens
// We only support the following tokens: AKO_TT_IDENT AKO_TT_STRING AKO_TT_DOT AKO_TT_INT
elem = root;
for (size_t i = 0; i < tokens.size; ++i)
{
token_t* token = dyn_array_get(&tokens, i);
if (token->type != AKO_TT_IDENT && token->type != AKO_TT_STRING && token->type != AKO_TT_DOT &&
token->type != AKO_TT_INT)
{
// no clue what do with what ever token this is
goto giveup;
}

bool is_end = false;
if (i == tokens.size - 1)
{
is_end = true;
}

if (is_end)
{
if (ako_elem_get_type(elem) == AT_ARRAY)
{
// if its an array we only support int
if (token->type != AKO_TT_INT)
{
goto giveup;
}
elem = ako_elem_array_get(elem, token->value_int);
goto valid;
}
else
{
// Only support string or ident at the end
if (!(token->type == AKO_TT_STRING || token->type == AKO_TT_IDENT))
{
goto giveup;
}

elem = ako_elem_table_get(elem, token->value_string);
goto valid;
}

goto giveup;
}

if (ako_elem_get_type(elem) == AT_ARRAY)
{
if (token->type != AKO_TT_INT)
{
goto giveup;
}

elem = ako_elem_array_get(elem, token->value_int);
}
else
{
if (!(token->type == AKO_TT_STRING || token->type == AKO_TT_IDENT))
{
// Unsupported
goto giveup;
}

elem = ako_elem_table_get(elem, token->value_string);
}

if (elem == NULL)
{
goto giveup;
}

// ensure our next token is a dot
i++;
token = dyn_array_get(&tokens, i);
if (token->type != AKO_TT_DOT)
{
// Incorrect
goto giveup;
}
}

giveup:
ako_free_tokens(&tokens);
return NULL;

valid:
ako_free_tokens(&tokens);
return elem;
}
4 changes: 3 additions & 1 deletion src/lex/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ typedef struct

size_t location_format(const location_t* loc, char* output, size_t output_size);

typedef struct ako_elem ako_elem_t;

// Returns an array of Token_t, please destroy the returned array when finished :)
dyn_array_t ako_tokenize(const char* source, char** err);
dyn_array_t ako_tokenize(const char* source, ako_elem_t** err, bool ignore_floats);
void ako_free_tokens(dyn_array_t* tokens);
Loading
Loading