Skip to content

Commit

Permalink
Update Glue (#43)
Browse files Browse the repository at this point in the history
* update CPM

* update extension

* v1.9

* update tests
  • Loading branch information
TheLartians authored May 4, 2019
1 parent 6cf5db2 commit 1a85480
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 94 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
# ---- Project ----

project(LarsParser
VERSION 1.8
VERSION 1.9
LANGUAGES CXX
)

Expand Down Expand Up @@ -35,7 +35,7 @@ if(${LARS_PARSER_BUILD_GLUE_EXTENSION})
CPMAddPackage(
NAME Glue
GIT_REPOSITORY https://github.com/TheLartians/Glue.git
VERSION 0.5
VERSION 0.7
)
endif()

Expand Down
48 changes: 34 additions & 14 deletions cmake/CPM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
# =================================================
# See https://github.com/TheLartians/CPM for usage and update instructions.
#
# MIT License
#[[ -----------
# MIT License
# -----------
#[[
Copyright (c) 2019 Lars Melchior

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand All @@ -27,12 +28,23 @@

cmake_minimum_required(VERSION 3.14 FATAL_ERROR)

set(CURRENT_CPM_VERSION 0.8.1)

if(CPM_DIRECTORY)
if(NOT ${CPM_DIRECTORY} MATCHES ${CMAKE_CURRENT_LIST_DIR})
if (${CPM_VERSION} VERSION_LESS ${CURRENT_CPM_VERSION})
message(AUTHOR_WARNING "${CPM_INDENT} \
A dependency is using a more recent CPM (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \
It is recommended to upgrade CPM to the most recent version. \
See https://github.com/TheLartians/CPM for more information.\
")
endif()
return()
endif()
endif()

set(CPM_VERSION ${CURRENT_CPM_VERSION} CACHE INTERNAL "")

set(CPM_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "")
set(CPM_PACKAGES "" CACHE INTERNAL "")

Expand All @@ -46,13 +58,9 @@ if(NOT CPM_INDENT)
set(CPM_INDENT "CPM:")
endif()

function(CPM_REGISTER_PACKAGE PACKAGE VERSION)
LIST(APPEND CPM_PACKAGES ${CPM_ARGS_NAME})
function(CPMRegisterPackage PACKAGE VERSION)
list(APPEND CPM_PACKAGES ${PACKAGE})
set(CPM_PACKAGES ${CPM_PACKAGES} CACHE INTERNAL "")
CPM_SET_PACKAGE_VERSION(${PACKAGE} ${VERSION})
endfunction()

function(CPM_SET_PACKAGE_VERSION PACKAGE VERSION)
set("CPM_PACKAGE_${PACKAGE}_VERSION" ${VERSION} CACHE INTERNAL "")
endfunction()

Expand All @@ -70,11 +78,11 @@ function(CPM_PARSE_OPTION OPTION)
endfunction()

function(CPMAddPackage)

set(oneValueArgs
NAME
VERSION
GIT_TAG
DOWNLOAD_ONLY
)

set(multiValueArgs
Expand Down Expand Up @@ -108,6 +116,12 @@ function(CPMAddPackage)
set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION})
endif()

if(CPM_ARGS_DOWNLOAD_ONLY)
set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY})
else()
set(DOWNLOAD_ONLY NO)
endif()

if (${CPM_ARGS_NAME} IN_LIST CPM_PACKAGES)
CPM_GET_PACKAGE_VERSION(${CPM_ARGS_NAME})
if(${CPM_PACKAGE_VERSION} VERSION_LESS ${CPM_ARGS_VERSION})
Expand All @@ -121,11 +135,11 @@ function(CPMAddPackage)
endif()
endforeach()
endif()
CPM_FETCH_PACKAGE(${CPM_ARGS_NAME})
CPM_FETCH_PACKAGE(${CPM_ARGS_NAME} ${DOWNLOAD_ONLY})
return()
endif()

CPM_REGISTER_PACKAGE(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})
CPMRegisterPackage(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})

if (CPM_ARGS_OPTIONS)
foreach(OPTION ${CPM_ARGS_OPTIONS})
Expand All @@ -135,7 +149,7 @@ function(CPMAddPackage)
endif()

CPM_DECLARE_PACKAGE(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION} ${CPM_ARGS_GIT_TAG} "${CPM_ARGS_UNPARSED_ARGUMENTS}")
CPM_FETCH_PACKAGE(${CPM_ARGS_NAME})
CPM_FETCH_PACKAGE(${CPM_ARGS_NAME} ${DOWNLOAD_ONLY})
endfunction()

function (CPM_DECLARE_PACKAGE PACKAGE VERSION GIT_TAG)
Expand All @@ -148,9 +162,15 @@ function (CPM_DECLARE_PACKAGE PACKAGE VERSION GIT_TAG)
)
endfunction()

function (CPM_FETCH_PACKAGE PACKAGE)
function (CPM_FETCH_PACKAGE PACKAGE DOWNLOAD_ONLY)
set(CPM_OLD_INDENT "${CPM_INDENT}")
set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:")
FetchContent_MakeAvailable(${PACKAGE})
if(${DOWNLOAD_ONLY})
if(NOT "${PACKAGE}_POPULATED")
FetchContent_Populate(${PACKAGE})
endif()
else()
FetchContent_MakeAvailable(${PACKAGE})
endif()
set(CPM_INDENT "${CPM_OLD_INDENT}")
endfunction()
6 changes: 3 additions & 3 deletions include/lars/parser/extension.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once

#include <lars/glue.h>
#include <glue/element.h>

namespace lars{
namespace extensions{
std::shared_ptr<Extension> parser();
namespace glue {
::glue::Element parser();
}
}
77 changes: 40 additions & 37 deletions source/extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,75 @@
#include <stdexcept>
#include <lars/log.h>

std::shared_ptr<lars::Extension> lars::extensions::parser(){
::glue::Element lars::glue::parser(){
using namespace lars;
using namespace ::glue;

using ParserGenerator = lars::ParserGenerator<Any,Any&>;
using ParserGenerator = lars::ParserGenerator<Any,const Any &>;
using Expression = ParserGenerator::Expression;

auto expressionExtension = std::make_shared<Extension>();
expressionExtension->set_class<ParserGenerator::Expression>();
expressionExtension->add_function("evaluate", [](Expression &e,Any &d){
Element expression;
setClass<Expression>(expression);

expression["evaluate"] = [](Expression &e,const Any &d){
return e.evaluate(d);
});
};

expressionExtension->add_function("size", [](Expression &e)->unsigned{
expression["size"] = [](Expression &e)->unsigned{
return e.size();
});
};

expressionExtension->add_function("get", [](Expression &e, unsigned i){
expression["get"] = [](Expression &e, unsigned i){
if (i < e.size()) {
return e[i];
} else {
throw std::runtime_error("invalid expression index");
}
});
expressionExtension->add_function("string", [](Expression &e){
};

expression["string"] = [](Expression &e){
return e.string();
});
};

expressionExtension->add_function("position", [](Expression &e)->unsigned{
expression["position"] = [](Expression &e)->unsigned{
return e.position();
});
};

expressionExtension->add_function("length", [](Expression &e)->unsigned{
expression["length"] = [](Expression &e)->unsigned{
return e.length();
});
};


auto parserGeneratorExtension = std::make_shared<Extension>();
parserGeneratorExtension->set_class<ParserGenerator>();
parserGeneratorExtension->add_function("create", [](){ return ParserGenerator(); });
Element program;
setClass<ParserGenerator>(program);

program["create"] = [](){ return ParserGenerator(); };

parserGeneratorExtension->add_function("run", [](ParserGenerator &g, const std::string &str, Any& arg){
program["run"] = [](ParserGenerator &g, const std::string &str, const Any& arg){
return g.run(str, arg);
});
};

parserGeneratorExtension->add_function("setRule",[](ParserGenerator &g, const std::string &name, const std::string &grammar){
program["setRule"] = [](ParserGenerator &g, const std::string &name, const std::string &grammar){
return g.setRule(name, grammar);
});
};

parserGeneratorExtension->add_function("setRuleWithCallback",[](ParserGenerator &g, const std::string &name, const std::string &grammar, AnyFunction callback){
return g.setRule(name, grammar, [callback](auto e, Any v){
program["setRuleWithCallback"] = [](ParserGenerator &g, const std::string &name, const std::string &grammar, AnyFunction callback){
return g.setRule(name, grammar, [callback](auto e, const Any &v)->Any{
return callback(e, v);
});
});
};

parserGeneratorExtension->add_function("setStartRule", [](ParserGenerator &g, const std::string &name){
program["setStartRule"] = [](ParserGenerator &g, const std::string &name){
g.setStart(g.getRule(name));
});
};

parserGeneratorExtension->add_function("setSeparatorRule", [](ParserGenerator &g, const std::string &name){
program["setSeparatorRule"] = [](ParserGenerator &g, const std::string &name){
g.setSeparator(g.getRule(name));
});
};

auto extension = std::make_shared<Extension>();
extension->add_extension("Program", parserGeneratorExtension);
extension->add_extension("Expression", expressionExtension);

return extension;
Element parser;
parser["Program"] = program;
parser["Expression"] = expression;
return parser;
}
22 changes: 10 additions & 12 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,31 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
find_package(LarsParser REQUIRED)
endif()

include(FetchContent)
include(../cmake/CPM.cmake)

FetchContent_Declare(
Catch2
CPMAddPackage(
NAME Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v2.5.0
VERSION 2.5.0
)

FetchContent_MakeAvailable(Catch2)

# ---- Create binary ----

file(GLOB tests_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_executable(lars-parser-tests ${tests_sources})
target_link_libraries(lars-parser-tests PUBLIC LarsParser Catch2)
set_target_properties(lars-parser-tests PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-Wall -pedantic -Wextra -Werror")
add_executable(LarsParserTests ${tests_sources})
target_link_libraries(LarsParserTests PUBLIC LarsParser Catch2)
set_target_properties(LarsParserTests PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-Wall -pedantic -Wextra -Werror")

# ---- Add tests ----

ENABLE_TESTING()
ADD_TEST(lars-parser-tests lars-parser-tests)
ADD_TEST(LarsParserTests LarsParserTests)

# ---- code coverage ----

if (${ENABLE_TEST_COVERAGE})
set_target_properties(LarsParser PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-O0 -g -fprofile-arcs -ftest-coverage --coverage")
target_link_options(LarsParser PUBLIC "--coverage")
set_target_properties(lars-parser-tests PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-O0 -g -fprofile-arcs -ftest-coverage --coverage")
target_link_options(lars-parser-tests PUBLIC "--coverage")
set_target_properties(LarsParserTests PROPERTIES CXX_STANDARD 17 COMPILE_FLAGS "-O0 -g -fprofile-arcs -ftest-coverage --coverage")
target_link_options(LarsParserTests PUBLIC "--coverage")
endif()
54 changes: 28 additions & 26 deletions tests/extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,26 @@

TEST_CASE("Extension"){
using namespace lars;
auto extension = lars::extensions::parser();
auto extension = lars::glue::parser();

auto programExtension = extension->get_extension("Program");
auto expressionExtension = extension->get_extension("Expression");
auto programExtension = extension["Program"];
auto expressionExtension = extension["Expression"];

auto createProgram = programExtension->get_function("create");
auto setRule = programExtension->get_function("setRule");
auto setSeparator = programExtension->get_function("setSeparatorRule");
auto setStart = programExtension->get_function("setStartRule");
auto setRuleWithCallback = programExtension->get_function("setRuleWithCallback");
auto run = programExtension->get_function("run");
auto evaluate = expressionExtension->get_function("evaluate");
auto get = expressionExtension->get_function("get");
auto string = expressionExtension->get_function("string");
auto size = expressionExtension->get_function("size");
auto position = expressionExtension->get_function("position");
auto length = expressionExtension->get_function("length");
auto createProgram = programExtension["create"];
auto setRule = programExtension["setRule"];
auto setSeparator = programExtension["setSeparatorRule"];
auto setStart = programExtension["setStartRule"];
auto setRuleWithCallback = programExtension["setRuleWithCallback"];
auto run = programExtension["run"];
auto evaluate = expressionExtension["evaluate"];
auto get = expressionExtension["get"];
auto string = expressionExtension["string"];
auto size = expressionExtension["size"];
auto position = expressionExtension["position"];
auto length = expressionExtension["length"];

using VariableMap = std::unordered_map<std::string, float> ;

auto program = createProgram();
REQUIRE_NOTHROW(setRule(program, "Whitespace", "[\t ]"));
REQUIRE_NOTHROW(setSeparator(program, "Whitespace"));
Expand All @@ -31,35 +33,35 @@ TEST_CASE("Extension"){
REQUIRE_NOTHROW(setRule(program, "Product", "Multiply | Divide | Atomic"));
REQUIRE_NOTHROW(setRule(program, "Atomic", "Number | '(' Sum ')'"));

REQUIRE_NOTHROW(setRuleWithCallback(program, "Add", "Sum '+' Product", lars::AnyFunction([=](lars::Any e,lars::Any &d){
REQUIRE_NOTHROW(setRuleWithCallback(program, "Add", "Sum '+' Product", lars::AnyFunction([=](const lars::Any &e,VariableMap &d){
return evaluate(get(e,0),d).get<float>() + evaluate(get(e,1),d).get<float>();
})));

REQUIRE_NOTHROW(setRuleWithCallback(program, "Subtract", "Sum '-' Product", lars::AnyFunction([=](lars::Any e,lars::Any &d){
REQUIRE_NOTHROW(setRuleWithCallback(program, "Subtract", "Sum '-' Product", lars::AnyFunction([=](const lars::Any &e,VariableMap &d){
return evaluate(get(e,0),d).get<float>() - evaluate(get(e,1),d).get<float>();
})));

REQUIRE_NOTHROW(setRuleWithCallback(program, "Multiply", "Product '*' Atomic", lars::AnyFunction([=](lars::Any e,lars::Any &d){
REQUIRE_NOTHROW(setRuleWithCallback(program, "Multiply", "Product '*' Atomic", lars::AnyFunction([=](const lars::Any &e,VariableMap &d){
return evaluate(get(e,0),d).get<float>() * evaluate(get(e,1),d).get<float>();
})));

REQUIRE_NOTHROW(setRuleWithCallback(program, "Divide", "Product '/' Atomic", lars::AnyFunction([=](lars::Any e,lars::Any &d){
REQUIRE_NOTHROW(setRuleWithCallback(program, "Divide", "Product '/' Atomic", lars::AnyFunction([=](const lars::Any &e,VariableMap &d){
return evaluate(get(e,0),d).get<float>() / evaluate(get(e,1),d).get<float>();
})));

REQUIRE_NOTHROW(setRuleWithCallback(program, "Number", "'-'? [0-9]+ ('.' [0-9]+)?", lars::AnyFunction([=](lars::Any e,lars::Any &){
REQUIRE(size(e).get_numeric() == 0);
REQUIRE(position(e).get_numeric() >= 0);
REQUIRE(length(e).get_numeric() == string(e).get<std::string>().size());
REQUIRE_NOTHROW(setRuleWithCallback(program, "Number", "'-'? [0-9]+ ('.' [0-9]+)?", lars::AnyFunction([=](const lars::Any &e,VariableMap &){
REQUIRE(size(e).get<int>() == 0);
REQUIRE(position(e).get<int>() >= 0);
REQUIRE(length(e).get<int>() == string(e).get<std::string>().size());
return float(stof(string(e).get<std::string>()));
})));

REQUIRE_NOTHROW(setRuleWithCallback(program, "Variable", "[a-zA-Z]+", lars::AnyFunction([=](lars::Any e,lars::Any &d){
auto &vars = d.get<std::unordered_map<std::string, float>>();
REQUIRE_NOTHROW(setRuleWithCallback(program, "Variable", "[a-zA-Z]+", lars::AnyFunction([=](const lars::Any &e,VariableMap &d){
auto &vars = d;
return vars[string(e).get<std::string>()];
})));

std::unordered_map<std::string, float> variables;
VariableMap variables;
REQUIRE(run(program,"42",variables).get<float>() == Approx(42));
REQUIRE(run(program,"2+3",variables).get<float>() == Approx(5));
REQUIRE(run(program,"2*3",variables).get<float>() == Approx(6));
Expand Down

0 comments on commit 1a85480

Please sign in to comment.