Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

YAMBi: YAML Plugin Based on Parser Generated by Bison #2225

Merged
merged 53 commits into from Sep 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
81bed38
Yan LR: Fix spelling of method name
sanssecours Sep 1, 2018
54e652d
Yan LR: Use correct variable in log message
sanssecours Sep 1, 2018
5faa9dc
Yan LR: Add missing Doxygen attributes
sanssecours Sep 3, 2018
47bcd74
Yan LR: Improve formatting of grammar
sanssecours Sep 3, 2018
118afec
Yan LR: Use `1` as initial column number
sanssecours Sep 3, 2018
9accf50
Yan LR: Simplify CMake code
sanssecours Sep 3, 2018
cf18a6c
CPP Template: Unify variable names
sanssecours Sep 3, 2018
c8a8833
Yan LR: Fix outdated comment in MSR test
sanssecours Sep 3, 2018
7762e5b
YAMBi: Add initial version of plugin
sanssecours Sep 3, 2018
15781ea
YAMBi: Add code to generate parser
sanssecours Sep 3, 2018
f9e4cc7
Check OCLint: Reformat file with `shfmt`
sanssecours Sep 3, 2018
bcd9134
Check OCLint: Analyze YAMBi plugin
sanssecours Sep 3, 2018
22864c0
YAMBi: Add parser source files
sanssecours Sep 3, 2018
51a6df2
YAMBi: Fix minor spelling mistake
sanssecours Sep 3, 2018
643b60c
YAMBi: Fix error caused by unknown CMake command
sanssecours Sep 3, 2018
9525073
YAMBi: Simplify CMake code
sanssecours Sep 3, 2018
137c554
YAMBi: Improve error message
sanssecours Sep 3, 2018
5860018
YAMBi: Require Bison 3 or later
sanssecours Sep 3, 2018
fe98406
Travis: Install Bison
sanssecours Sep 3, 2018
d078b1c
YAMBi: Fix Bison detection on Linux
sanssecours Sep 3, 2018
1accb03
YAMBi: Require header file `codecvt`
sanssecours Sep 3, 2018
b456048
YAMBi: Integrate parser code into plugin
sanssecours Sep 4, 2018
5069fae
YAMBi: Disable parser debug output
sanssecours Sep 4, 2018
de74142
YAMBi: Do not write error message to `stderr`
sanssecours Sep 4, 2018
a22247b
YAMBi: Add basic MSR test
sanssecours Sep 4, 2018
660a72e
YAMBi: Add MSR tests for array keys
sanssecours Sep 4, 2018
0cf6d97
YAMBi: Add limitations to ReadMe
sanssecours Sep 4, 2018
70d8d12
YAMBi: Add test data
sanssecours Sep 4, 2018
c247d81
YAMBi: Don’t check undefined behavior in GCC build
sanssecours Sep 4, 2018
e780171
CFramework: Allow inclusion of header in C++ code
sanssecours Sep 5, 2018
a366a75
YAMBi: Add tests for data files
sanssecours Sep 4, 2018
e31c7c1
YAMBi: Catch lexer exceptions
sanssecours Sep 5, 2018
3e10e5a
Release: Add info about YAMBi plugin
sanssecours Sep 5, 2018
22e8bb7
CSV Storage: Require Directory Value for MSR test
sanssecours Sep 6, 2018
0a9bd85
Rename: Require mINI plugin for MSR test
sanssecours Sep 6, 2018
d28bf01
YAJL: Require Directory Value for MSR test
sanssecours Sep 6, 2018
4ef1b43
Yan LR: Require Directory Value for MSR test
sanssecours Sep 6, 2018
c26ad6a
YAMBi: Require plugins for MSR test
sanssecours Sep 6, 2018
73e698b
Test: Require Directory Value for YAJL tests
sanssecours Sep 6, 2018
d166ab6
Travis: Exclude plugins from `🍏 Clang ASAN`
sanssecours Sep 6, 2018
7354376
YAMBi: Move dependency checking code into function
sanssecours Sep 9, 2018
12f5c2b
YAMBi: Rephrase sentence about Bison dependency
sanssecours Sep 9, 2018
9a561bb
YAMBi: Remove `shelltest` tag from plugin contract
sanssecours Sep 9, 2018
11863de
YAMBi: Extend include guard
sanssecours Sep 9, 2018
b7f03e2
YAMBi: Add missing Doxygen keyword `retval`
sanssecours Sep 9, 2018
3892f8c
YAMBi: Delete using directives from header files
sanssecours Sep 9, 2018
ffd0b9d
YAMBi: Throw exception in case of array overflow
sanssecours Sep 9, 2018
e752b54
YAMBi: Add description for input class
sanssecours Sep 9, 2018
47b9751
YAMBi: Add description for driver class
sanssecours Sep 9, 2018
afa0c8f
Lexer: Simplify code
sanssecours Sep 9, 2018
0c47d02
YAMBi: Use upper case name for macro
sanssecours Sep 9, 2018
656f0e4
YAMBi: Capitalize parser class name
sanssecours Sep 9, 2018
776bd51
YAMBi: Fix warning about shadow declaration
sanssecours Sep 9, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Expand Up @@ -43,6 +43,7 @@ matrix:
# [timeout]: https://docs.travis-ci.com/user/customizing-the-build/#build-timeouts
- TOOLS=kdb
- BINDINGS=cpp
- PLUGINS='ALL;-camel;-directoryvalue;-mini;-yambi;-yamlcpp;-yanlr'
- TEST_COMMAND="ctest --output-on-failure -E 'testscr_check_(bashisms|doc|formatting|meta|oclint|plugins)'"

- os: linux
Expand Down Expand Up @@ -188,6 +189,7 @@ before_install:
# Unfortunately Xerces 3.2 causes multiple problems if we translate Elektra with GCC on macOS
brew install xerces-c
fi
brew install bison
brew install dbus
brew install discount
brew install gpgme
Expand Down
3 changes: 3 additions & 0 deletions doc/man/man7/elektra-plugins.7
Expand Up @@ -198,6 +198,9 @@ yamlcpp \fIyamlcpp/\fR reads and writes data in the YAML \fIhttp://www\.yaml\.or
yanlr \fIyanlr/\fR reads data using a parser generated by ANTLR \fIhttp://www\.antlr\.org\fR
.
.IP "\(bu" 4
yambi \fIyambi/\fR reads data using a parser generated by Bison \fIhttps://www\.gnu\.org/software/bison\fR
.
.IP "\(bu" 4
mmapstorage \fImmapstorage/\fR uses binary, not portable memory mapped file for a high performance storage
.
.IP "" 0
Expand Down
7 changes: 2 additions & 5 deletions doc/news/_preparation_next_release.md
Expand Up @@ -93,12 +93,9 @@ The following section lists news about the [modules](https://www.libelektra.org/

- The `gpgme` plugin was brought into existence to provide cryptographic functions using GnuGP via the `libgpgme` library. See [#896] *(Peter Nirschl)*

### YAMBi

### <<Plugin1>>

- <<TODO>>
- <<TODO>>
- <<TODO>>
This new plugin parses a subset of YAML using a parser generated by [Bison](https://www.gnu.org/software/bison). *(René Schwaiger)*

### <<Plugin2>>

Expand Down
1 change: 1 addition & 0 deletions src/plugins/README.md
Expand Up @@ -118,6 +118,7 @@ productive use:
- [camel](camel/) reads and writes a very limited subset of [YAML][]
- [yamlcpp](yamlcpp/) reads and writes data in the [YAML][] format using [yaml-cpp](https://github.com/jbeder/yaml-cpp)
- [yanlr](yanlr/) reads data using a parser generated by [ANTLR](http://www.antlr.org)
- [yambi](yambi/) reads data using a parser generated by [Bison](https://www.gnu.org/software/bison)
- [mmapstorage](mmapstorage/) uses binary, not portable memory mapped file for a high performance storage

[YAML]: http://www.yaml.org
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/cpptemplate/cpptemplate.hpp
Expand Up @@ -19,9 +19,9 @@ using ckdb::Plugin;
extern "C" {
int elektraCppTemplateOpen (Plugin * handle, Key * errorKey);
int elektraCppTemplateClose (Plugin * handle, Key * errorKey);
int elektraCppTemplateGet (Plugin * handle, KeySet * ks, Key * parentKey);
int elektraCppTemplateSet (Plugin * handle, KeySet * ks, Key * parentKey);
int elektraCppTemplateError (Plugin * handle, KeySet * ks, Key * parentKey);
int elektraCppTemplateGet (Plugin * handle, KeySet * returned, Key * parentKey);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tom-wa recently asked why we call this parameter "returned".

I wonder why you call the parameter differently for "Error"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why you call the parameter differently for "Error"?

I basically just copied the variable names from the template plugin. It does look like the variable names are different in the header and the source files of the template plugin too (ks vs. returned).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for fixing this! Yes, it should be consistent. I am okay with either name.

int elektraCppTemplateSet (Plugin * handle, KeySet * returned, Key * parentKey);
int elektraCppTemplateError (Plugin * handle, KeySet * conf, Key * parentKey);
int elektraCppTemplateCheckConfig (Key * errorKey, KeySet * conf);

Plugin * ELEKTRA_PLUGIN_EXPORT (cpptemplate);
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/csvstorage/CMakeLists.txt
Expand Up @@ -7,4 +7,5 @@ add_plugin (csvstorage
elektra-proposal
ADD_TEST
INSTALL_TEST_DATA
TEST_README)
TEST_README
TEST_REQUIRED_PLUGINS directoryvalue)
2 changes: 1 addition & 1 deletion src/plugins/rename/CMakeLists.txt
Expand Up @@ -3,4 +3,4 @@ add_plugin (rename
rename.c
ADD_TEST
TEST_README
TEST_REQUIRED_PLUGINS ni)
TEST_REQUIRED_PLUGINS mini)
1 change: 1 addition & 0 deletions src/plugins/yajl/CMakeLists.txt
Expand Up @@ -19,6 +19,7 @@ add_plugin (yajl
"${CMAKE_CURRENT_BINARY_DIR}/yajl.h"
ADD_TEST
TEST_README
TEST_REQUIRED_PLUGINS directoryvalue
INSTALL_TEST_DATA
INCLUDE_DIRECTORIES "${INCL}"
LINK_ELEKTRA elektra-ease
Expand Down
94 changes: 94 additions & 0 deletions src/plugins/yambi/CMakeLists.txt
@@ -0,0 +1,94 @@
include (LibAddMacros)

# ~~~
# This functions checks if the dependencies for the YAMBi plugin are available.
#
# If they are, the function sets the variable `FOUND_DEPENDENCIES` to `TRUE`. The function then also sets:
#
# - BISON_YAMBI_OUTPUT_SOURCE to the path of the source files generated by Bison, and
# - BISON_YAMBI_OUTPUT_HEADER to the path of the header files generated by Bison
#
# . If the function was unsuccessful it sets `FOUND_DEPENDENCIES` to `FALSE` and stores the reason for the failure in the variable
# `FAILURE_MESSAGE`.
# ~~~
function (check_dependencies)
set (FOUND_DEPENDENCIES FALSE PARENT_SCOPE)

include (CheckIncludeFileCXX)
set (CMAKE_REQUIRED_QUIET ON)
check_include_file_cxx (codecvt HAVE_CODECVT)
if (NOT HAVE_CODECVT)
set (FAILURE_MESSAGE "because the current C++ library does not provide header file `codecvt`" PARENT_SCOPE)
return ()
endif (NOT HAVE_CODECVT)

if (APPLE)
# Add path to Homebrew version of Bison
list (APPEND CMAKE_PREFIX_PATH
"/usr/local/opt/bison")
endif (APPLE)
find_package (BISON 3 QUIET)

if (NOT BISON_FOUND)
set (FAILURE_MESSAGE "Bison 3 (bison) not found" PARENT_SCOPE)
return ()
endif (NOT BISON_FOUND)

if (BISON_VERSION VERSION_LESS 3)
set (FAILURE_MESSAGE "Bison version 3 or later required (found version ${BISON_VERSION})" PARENT_SCOPE)
return ()
endif (BISON_VERSION VERSION_LESS 3)

bison_target (YAMBI ${CMAKE_CURRENT_SOURCE_DIR}/parser.ypp ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp)

if (NOT BISON_YAMBI_DEFINED)
set (FAILURE_MESSAGE "generating the parser code failed" PARENT_SCOPE)
return ()
endif (NOT BISON_YAMBI_DEFINED)

set (BISON_YAMBI_OUTPUT_SOURCE ${BISON_YAMBI_OUTPUT_SOURCE} PARENT_SCOPE)
set (BISON_YAMBI_OUTPUT_HEADER ${BISON_YAMBI_OUTPUT_HEADER} PARENT_SCOPE)

set (FOUND_DEPENDENCIES TRUE PARENT_SCOPE)
endfunction (check_dependencies)

if (DEPENDENCY_PHASE)
check_dependencies ()
if (NOT FOUND_DEPENDENCIES)
remove_plugin (yambi ${FAILURE_MESSAGE})
endif (NOT FOUND_DEPENDENCIES)

set (SOURCE_FILES_INPUT input.hpp input.cpp)

if (ENABLE_ASAN AND CMAKE_COMPILER_IS_GNUCXX)
# ~~~
# Ignore runtime error about member call on address, which does not point to object of type `__codecvt_abstract_base`.
# See also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81068
# ~~~
set_source_files_properties (${SOURCE_FILES_INPUT} PROPERTIES COMPILE_FLAGS "-fno-sanitize=undefined")
endif (ENABLE_ASAN AND CMAKE_COMPILER_IS_GNUCXX)

set (SOURCE_FILES
convert.hpp
convert.cpp
driver.hpp
driver.cpp
lexer.hpp
lexer.cpp
yambi.hpp
yambi.cpp
${SOURCE_FILES_INPUT}
${BISON_YAMBI_OUTPUT_SOURCE}
${BISON_YAMBI_OUTPUT_HEADER})
endif (DEPENDENCY_PHASE)

add_plugin (yambi
CPP
ADD_TEST
CPP_TEST
INSTALL_TEST_DATA
TEST_README
TEST_REQUIRED_PLUGINS directoryvalue
yamlsmith
SOURCES ${SOURCE_FILES}
INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR})
87 changes: 87 additions & 0 deletions src/plugins/yambi/README.md
@@ -0,0 +1,87 @@
- infos = Information about the yambi plugin is in keys below
- infos/author = René Schwaiger <sanssecours@me.com>
- infos/licence = BSD
- infos/needs = directoryvalue yamlsmith
- infos/provides = storage/yaml
- infos/recommends =
- infos/placements = getstorage
- infos/status = maintained unittest preview experimental unfinished nodoc concept discouraged
- infos/metadata =
- infos/description = This storage plugin use a parser generated by Bison to read YAML files

# YAMBi

## Introduction

This plugin uses Bison to generate a parser for the [YAML](http://yaml.org) serialization format.

## Dependencies

The plugin requires [Bison](https://www.gnu.org/software/bison/) (3.0 or later).

## Examples

### Mappings

```sh
# Mount plugin
sudo kdb mount config.yaml user/tests/yambi yambi

kdb set user/tests/yambi/bambi 'Mule Deer'
kdb get user/tests/yambi/bambi
#> Mule Deer

kdb set user/tests/yambi/thumper 'Rabbit'
kdb get user/tests/yambi/thumper
#> Rabbit

kdb set user/tests/yambi/bambi/baby 'Bobby Stewart'
kdb set user/tests/yambi/bambi/young 'Donnie Dunagan'
kdb set user/tests/yambi/bambi/adolescent 'Hardie Albright'
kdb set user/tests/yambi/bambi/adult 'John Sutherland'

kdb get user/tests/yambi/bambi/baby
#> Bobby Stewart

kdb ls user/tests/yambi
#> user/tests/yambi/bambi
#> user/tests/yambi/bambi/adolescent
#> user/tests/yambi/bambi/adult
#> user/tests/yambi/bambi/baby
#> user/tests/yambi/bambi/young
#> user/tests/yambi/thumper

# Undo modifications
kdb rm -r user/tests/yambi
sudo kdb umount user/tests/yambi
```

### Arrays

```sh
# Mount plugin
sudo kdb mount config.yaml user/tests/yambi yambi

kdb set user/tests/yambi/friends
kdb set user/tests/yambi/friends/#0 Thumper
kdb set user/tests/yambi/friends/#1 Flower

# Retrieve last array index
kdb getmeta user/tests/yambi/friends array
#> #1

kdb get user/tests/yambi/friends/#0
#> Thumper
kdb get user/tests/yambi/friends/#1
#> Flower

# Undo modifications
kdb rm -r user/tests/yambi
sudo kdb umount user/tests/yambi
```

## Limitations

The plugin supports the same limited YAML syntax as [Yan LR](../yanlr/).

- The plugin always assumes **UTF-8** encoded data.
69 changes: 69 additions & 0 deletions src/plugins/yambi/convert.cpp
@@ -0,0 +1,69 @@
/**
* @file
*
* @brief This file contains a function to convert a YAML file to a key set.
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*/

// -- Imports ------------------------------------------------------------------

#include "kdberrors.h"

#include "convert.hpp"
#include "driver.hpp"

using std::string;

using CppKey = kdb::Key;
using CppKeySet = kdb::KeySet;

// -- Function -----------------------------------------------------------------

/**
* @brief This function converts the given YAML file to keys and adds the
* result to `keySet`.
*
* @param keySet The function adds the converted keys to this variable.
* @param parent The function uses this parent key of `keySet` to emit error
* information.
* @param filename This parameter stores the path of the YAML file this
* function converts.
*
* @retval -3 if the file could not be opened for reading
* @retval -2 if parsing was unsuccessful due to memory exhaustion
* @retval -1 if there was an syntax error converting the YAML file
* @retval 0 if parsing was successful and the function did not change the given keyset
* @retval 1 if parsing was successful and the function did change `keySet`
*/
int addToKeySet (CppKeySet & keySet, CppKey & parent, string const & filename)
{
Driver driver{ parent };

int status = driver.parse (filename);

if (status < 0)
{
if (status == -3)
{
ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_COULD_NOT_OPEN, parent.getKey (), "Unable to open file “%s”", filename.c_str ());
}
else if (status == -2)
{
ELEKTRA_SET_ERROR (ELEKTRA_ERROR_PARSE, parent.getKey (), "Parsing failed due to memory exhaustion");
}
else if (status == -1)
{
ELEKTRA_SET_ERROR (ELEKTRA_ERROR_PARSE, parent.getKey (), driver.getErrorMessage ().c_str ());
}

return status;
}

CppKeySet keys = driver.getKeySet ();
status = (keys.size () <= 0) ? 0 : 1;

keySet.append (keys);

return status;
}
36 changes: 36 additions & 0 deletions src/plugins/yambi/convert.hpp
@@ -0,0 +1,36 @@
/**
* @file
*
* @brief This file contains a function to convert a YAML file to a key set.
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*/

#ifndef ELEKTRA_PLUGIN_YAMBI_CONVERTER_HPP
#define ELEKTRA_PLUGIN_YAMBI_CONVERTER_HPP

// -- Imports ------------------------------------------------------------------

#include <kdb.hpp>

// -- Function -----------------------------------------------------------------

/**
* @brief This function converts the given YAML file to keys and adds the
* result to `keySet`.
*
* @param keySet The function adds the converted keys to this variable.
* @param parent The function uses this parent key of `keySet` to emit error
* information.
* @param filename This parameter stores the path of the YAML file this
* function converts.
*
* @retval -3 if the file could not be opened for reading
* @retval -2 if parsing was unsuccessful due to memory exhaustion
* @retval -1 if there was an syntax error converting the YAML file
* @retval 0 if parsing was successful and the function did not change the given keyset
* @retval 1 if parsing was successful and the function did change `keySet`
*/
int addToKeySet (kdb::KeySet & keySet, kdb::Key & parent, std::string const & filename);

#endif // ELEKTRA_PLUGIN_YAMBI_CONVERTER_HPP