Re: [boost] compile time parser generator

I'm not sure it's possible to get a string literal in a template< char ... > class string; 'Literals transformation is redefined into two distinct phases: raw and cooked. A raw literal is a sequence of characters of some specific type, while the cooked literal is of a separate type. The C++ literal 1234, as a raw literal, is this sequence of characters '1', '2', '3', '4'. As a cooked literal, it is the integer 1234. The C++ literal 0xA in raw form is '0', 'x', 'A', while in cooked form it is the integer 10. Literals can be extended in both raw and cooked forms, with the exception of string literals, which can only be processed in cooked form. This exception is due to the fact that strings have prefixes that affect the specific meaning and type of the characters in question.' - source: wikipedia - http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals . Parsing string literals with constexpr is described in this article: http://akrzemi1.wordpress.com/2011/05/11/parsing-strings-at-compile-time-par... For building the parser generator I used compile time polymorphism. Each symbol in EBNF would be represented as a class. The interface each symbol defines looks like this: struct symbol { constexpr symbol( const_string str , unsigned int begin = 0 ); //for an implementation of const_string see the article I linked constexpr bool valid(); constexpr unsigned int end(); }; For example, a symbol that parses a single character 'a' looks like this: struct sym_a { constexpr sym_a( const_string str , unsigned int begin = 0 ) : m_end ( begin >= str.size() ? 0u - 1 : //invalid index str[ begin ] == 'a' ? begin + 1 : 0u - 1 ) { } constexpr bool valid() { return m_end != 0u - 1; } constexpr unsigned int end() { return m_end; } unsigned int m_end; }; constexpr sym_a s1( "a" ); constexpr sym_a s2( "b" ); static_assert( s1.valid() , "" ); static_assert( !s2.valid() , "" ); The source for my current version of the parser generator is appended. I've also created a simple calculator that can handle + and * (and will accept any digit sequence as number, including "00000"). Notice, that currently only char strings are completely supported, defining terminals and the opt< T > operator won't work with other literals. (I know I can improve this for terminals, but I'm not sure about opt< T >.) The source compiles with gcc 4.6 and c++11 turned on without errors. -- NEU: FreePhone - 0ct/min Handyspartarif mit Geld-zurück-Garantie! Jetzt informieren: http://www.gmx.net/de/go/freephone

I'm not sure it's possible to get a string literal in a template< char ...> class string; 'Literals transformation is redefined into two distinct phases: raw and cooked. A raw literal is a sequence of characters of some specific type, while the cooked literal is of a separate type. The C++ literal 1234, as a raw literal, is this sequence of characters '1', '2', '3', '4'. As a cooked literal, it is the integer 1234. The C++ literal 0xA in raw form is '0', 'x', 'A', while in cooked form it is the integer 10.
Literals can be extended in both raw and cooked forms, with the exception of string literals, which can only be processed in cooked form. This exception is due to the fact that strings have prefixes that affect the specific meaning and type of the characters in question.' - source: wikipedia - http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals . Right below that Wikipedia describes a variadic template-based mechanism, where the compiler instantiates a template operator and
Hi Martin, passes the characters as template arguments to it. The return type of that operator could be an MPL list of boxed characters and we could access it using decltype - at least this is the idea. Your approach is different than ours, since it is based on constexpr while ours is based on template metaprogramming. I think it would be interesting to compare the two. Could you implement something like the type-safe printf using this approach? (Parsing the format string at compile-time, generate a list of expected types and type check the rest of the printf arguments.) Regards, Ábel

On 08/01/12 09:42, Ábel Sinkovics wrote:
Hi Martin,
I'm not sure it's possible to get a string literal in a template< char ...> class string; 'Literals transformation is redefined into two distinct phases: raw and cooked. A raw literal is a sequence of characters of some specific type, while the cooked literal is of a separate type. The C++ literal 1234, as a raw literal, is this sequence of characters '1', '2', '3', '4'. As a cooked literal, it is the integer 1234. The C++ literal 0xA in raw form is '0', 'x', 'A', while in cooked form it is the integer 10.
Literals can be extended in both raw and cooked forms, with the exception of string literals, which can only be processed in cooked form. This exception is due to the fact that strings have prefixes that affect the specific meaning and type of the characters in question.' - source: wikipedia - http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals . Right below that Wikipedia describes a variadic template-based mechanism, where the compiler instantiates a template operator and passes the characters as template arguments to it. The return type of that operator could be an MPL list of boxed characters and we could access it using decltype - at least this is the idea.
That interface is only available for integer and floating-point literals, not string literals (which that page also says). The only way to get at characters of a string literal at compile time is through constexpr functions.
Your approach is different than ours, since it is based on constexpr while ours is based on template metaprogramming. I think it would be interesting to compare the two. Could you implement something like the type-safe printf using this approach? (Parsing the format string at compile-time, generate a list of expected types and type check the rest of the printf arguments.)
(disclaimer: I've not written any serious code; I'm just pondering and playing around) I *thought* it was possible to make something like this work: printf<const_string("%d %d\n")>(11, 13); but it doesn't work in gcc 4.6, and, on closer reading of N3290, it's not supposed to work. Values of integral and enumeration types are still the only values we can pass as template arguments. It seems that the only way to take the output of a constexpr function (which is necessarily a value) and turn it into something type-ish (as needed to type-check a printf call) is to go via an integer. So, my next idea was: printf<format("%d %d\n")>(11, 13); where format returns some packed integer representation of (int, int). I guess you need ~4 bits to encode each argument type, so with 64-bit ints it could support up to 16 arguments. This would allow type-checking, but unfortunately the actual format string has been thrown away and isn't available for use by printf, so the best I can see is this: printf<format("%d %d\n")>("%d %d\n", 11, 13); wrapped up in a macro so you don't have to pass the format string twice. And that sucks. Can anyone see a better solution? John Bytheway

From: Of John Bytheway
Literals can be extended in both raw and cooked forms, with the exception of string literals, which can only be processed in cooked form. This exception is due to the fact that strings have prefixes that affect the specific meaning and type of the characters in question.' - source: wikipedia - http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals . Right below that Wikipedia describes a variadic template-based mechanism, where the compiler instantiates a template operator and passes the characters as template arguments to it. The return type of that operator could be an MPL list of boxed characters and we could access it using decltype - at least this is the idea. That interface is only available for integer and floating-point literals, not string literals (which that page also says). The only way to get at characters of a string literal at compile time is through constexpr functions.
So the question is, is there any way to get from a literal string to an MPL list of literal char for each character. From there it is just simple metaprogramming to do whatever with the string. It seems the constexper approach promises this, but I'd like to see the code example for what it looks like to use it and also how it works. Regards, Luke

on Sun Jan 08 2012, "Simonson, Lucanus J" <lucanus.j.simonson-AT-intel.com> wrote:
From: Of John Bytheway
Literals can be extended in both raw and cooked forms, with the exception of string literals, which can only be processed in cooked form. This exception is due to the fact that strings have prefixes that affect the specific meaning and type of the characters in question.' - source: wikipedia - http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals . Right below that Wikipedia describes a variadic template-based mechanism, where the compiler instantiates a template operator and passes the characters as template arguments to it. The return type of that operator could be an MPL list of boxed characters and we could access it using decltype - at least this is the idea. That interface is only available for integer and floating-point literals, not string literals (which that page also says). The only way to get at characters of a string literal at compile time is through constexpr functions.
So the question is, is there any way to get from a literal string to an MPL list of literal char for each character.
Nope.
From there it is just simple metaprogramming to do whatever with the string. It seems the constexper approach promises this, but I'd like to see the code example for what it looks like to use it and also how it works.
constexpr is somewhat crippled: although a constexpr function executes at compile-time, it has to obey the same rules as any other function. For example, its return type can depend on the type, but never on the *value*, of its arguments, and once you're inside the function, the contents of the argument are not treated as compile-time constants. So, I think constexpr actually doesn't promise it. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

From: Dave Abrahams
So the question is, is there any way to get from a literal string to an MPL list of literal char for each character. Nope. constexpr is somewhat crippled: although a constexpr function executes at compile-time, it has to obey the same rules as any other function. For example, its return type can depend on the type, but never on the *value*, of its arguments, and once you're inside the function, the contents of the argument are not treated as compile-time constants. So, I think constexpr actually doesn't promise it.
Well, there goes all my excitement. How then would the original proposal by Martin to use constexpr to "parse strings in C++ at compile time" work? You and Eric seemed to know what Marin had in mind and agree that a constexper string-based regex library was feasible, though differed on whether it was worthwhile. What am I missing? I was afraid of thatly yours, Luke

Hi Dave,
constexpr is somewhat crippled: although a constexpr function executes at compile-time, it has to obey the same rules as any other function. For example, its return type can depend on the type, but never on the *value*, of its arguments, and once you're inside the function, the contents of the argument are not treated as compile-time constants. So, I think constexpr actually doesn't promise it. A constexpr can still be used to access the characters of a string at compile-time. Having access to each character we can build an MPL list of characters. Here is an example of what I'm thinking of:
---- using namespace boost::mpl; template <int N> constexpr char nth(const char s[N], int n) { return n >= N ? 0 : s[n]; } #define S "cool" typedef push_back< push_back< push_back< push_back< push_back< push_back< string<>, char_<nth<sizeof(S)>(S, 0)>
::type, char_<nth<sizeof(S)>(S, 1)> ::type, char_<nth<sizeof(S)>(S, 2)> ::type, char_<nth<sizeof(S)>(S, 3)> ::type, char_<nth<sizeof(S)>(S, 4)> ::type, char_<nth<sizeof(S)>(S, 5)> ::type str;
int main() { std::cout << c_str<str>::type::value << std::endl; } ---- The code getting the characters one by one and building the MPL list (or string in the above example) can be generated by a macros - I know it is not that nice and the length of the string will be tricky, but we'll have something. The above code snippet compiles with gcc 4.6. Regards, Ábel

on Mon Jan 09 2012, Ábel Sinkovics <abel-AT-elte.hu> wrote:
Hi Dave,
constexpr is somewhat crippled: although a constexpr function executes at compile-time, it has to obey the same rules as any other function. For example, its return type can depend on the type, but never on the *value*, of its arguments, and once you're inside the function, the contents of the argument are not treated as compile-time constants. So, I think constexpr actually doesn't promise it. A constexpr can still be used to access the characters of a string at compile-time. Having access to each character we can build an MPL list of characters. Here is an example of what I'm thinking of:
----
using namespace boost::mpl;
template <int N> constexpr char nth(const char s[N], int n) { return n >= N ? 0 : s[n]; }
#define S "cool"
typedef push_back< push_back< push_back< push_back< push_back< push_back< string<>, char_<nth<sizeof(S)>(S, 0)>
::type, char_<nth<sizeof(S)>(S, 1)> ::type, char_<nth<sizeof(S)>(S, 2)> ::type, char_<nth<sizeof(S)>(S, 3)> ::type, char_<nth<sizeof(S)>(S, 4)> ::type, char_<nth<sizeof(S)>(S, 5)> ::type str;
int main() { std::cout << c_str<str>::type::value << std::endl; }
----
Yeah, what you can't do is: 1. generate that type based on the /value/ of a function argument (yes, you can deduce the length of the string, and thus that type, from the /type/ of a string literal argument). 2. Generate any types or choose template specializations based on the actual characters used in the string literal. I don't see how you're going to generate anything other than a table-based regexp recognizer if you can't do that. The fundamental limitation with constexpr functions is that the function you're calling must be valid even if its arguments are /not/ compile-time constants. Combine that with the lack of raw user-defined string literals, and, well... we're cooked.
The code getting the characters one by one and building the MPL list (or string in the above example) can be generated by a macros - I know it is not that nice and the length of the string will be tricky, but we'll have something. The above code snippet compiles with gcc 4.6.
If you can demonstrate something that works, I'll be really excited. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

From: Dave Abrahams
The code getting the characters one by one and building the MPL list (or string in the above example) can be generated by a macros - I know it is not that nice and the length of the string will be tricky, but we'll have something. The above code snippet compiles with gcc 4.6.
If you can demonstrate something that works, I'll be really excited.
The return value of the constexr is a compile time constant. We ought to be able to use it as a template parameter. Doesn't Abel's example work? I tried this little test: #include <stdio.h> template <int N> constexpr char nth(const char s[N], int n) { return n >= N ? 0 : s[n]; } #define S "cool" template <char T> void foo() { printf("not cool\n"); } template <> void foo<'c'>() { printf( "cool\n"); } template <> void foo<'o'>() { printf( "way cool\n"); } template <> void foo<'l'>() { printf( "way way cool\n"); } int main() { foo<nth<sizeof(S)>(S, 0)>(); foo<nth<sizeof(S)>(S, 1)>(); foo<nth<sizeof(S)>(S, 2)>(); foo<nth<sizeof(S)>(S, 3)>(); return 0; } With compile line: gcc/4.6.2/bin/g++ -std=c++0x And got the following output: cool way cool way cool way way cool It looks like you can specialize a template based on the individual characters within a string literal using constexpr quite simply. From here we ought to be able to perform arbitrary TMP on the contents of string literals. I would think that an ebnf as a string literal in a template parameter (with a macro call around it) ought to be able to generate a function that matches that grammar as an extreme example. Regards, Luke

On Mon, Jan 9, 2012 at 3:09 PM, Simonson, Lucanus J < lucanus.j.simonson@intel.com> wrote:
From: Dave Abrahams
The code getting the characters one by one and building the MPL list (or string in the above example) can be generated by a macros - I know it is not that nice and the length of the string will be tricky, but we'll have something. The above code snippet compiles with gcc 4.6.
If you can demonstrate something that works, I'll be really excited.
The return value of the constexr is a compile time constant. We ought to be able to use it as a template parameter.
Doesn't Abel's example work?
I tried this little test:
#include <stdio.h>
template <int N> constexpr char nth(const char s[N], int n) { return n >= N ? 0 : s[n]; }
#define S "cool"
template <char T> void foo() { printf("not cool\n"); } template <> void foo<'c'>() { printf( "cool\n"); } template <> void foo<'o'>() { printf( "way cool\n"); } template <> void foo<'l'>() { printf( "way way cool\n"); }
int main() { foo<nth<sizeof(S)>(S, 0)>(); foo<nth<sizeof(S)>(S, 1)>(); foo<nth<sizeof(S)>(S, 2)>(); foo<nth<sizeof(S)>(S, 3)>(); return 0; }
With compile line: gcc/4.6.2/bin/g++ -std=c++0x
And got the following output:
cool way cool way cool way way cool
It looks like you can specialize a template based on the individual characters within a string literal using constexpr quite simply. From here we ought to be able to perform arbitrary TMP on the contents of string literals. I would think that an ebnf as a string literal in a template parameter (with a macro call around it) ought to be able to generate a function that matches that grammar as an extreme example.
Regards, Luke
A little code improvement #include <stdio.h> template <typename ArrayType, size_t N> constexpr ArrayType nth( const ArrayType (&s)[N], int n ) { return n >= N ? 0 : s[n]; } #define S "cool" template <char T> void foo() { printf("not cool\n"); } template <> void foo<'c'>() { printf( "cool\n"); } template <> void foo<'o'>() { printf( "way cool\n"); } template <> void foo<'l'>() { printf( "way way cool\n"); } int main() { foo<nth(S, 0)>(); foo<nth(S, 1)>(); foo<nth(S, 2)>(); foo<nth(S, 3)>(); return 0; } Regards, Fernando.

From: Fernando Pelliccioni
A little code improvement
template <typename ArrayType, size_t N> constexpr ArrayType nth( const ArrayType (&s)[N], int n ) { return n >= N ? 0 : s[n]; }
Hmmm, now that I think of it: int S[] = {1, 1, 2, 3, 5, 8}; some_template<nth<size_of(S)>(S, 3)> is pretty nice to have in TMP too. Thanks, Luke

Hi,
From: Fernando Pelliccioni
A little code improvement
template<typename ArrayType, size_t N> constexpr ArrayType nth( const ArrayType (&s)[N], int n ) { return n>= N ? 0 : s[n]; } Hmmm, now that I think of it:
int S[] = {1, 1, 2, 3, 5, 8};
some_template<nth<size_of(S)>(S, 3)>
is pretty nice to have in TMP too.
Thanks, Luke
I made an implementation of it part of the compile-time parsing library (metaparse) on github. Its purpose is to simplify the definition of boost::mpl::string values the following way: instead of boost::mpl::string<'hell','o wo','rld'> you can write _S("hello world") It has an "nth" (I called it array_at there) constexpr function and a metafunction building the mpl::string. Using a helper metafunction it converts string literals of any length (up to MPLLIBS_METAPARSE_STRING_MAX_LENGTH) to boost::mpl::string. It uses a helper metafunction to avoid appending 0 characters at the end when the string literal is shorter than the max length. Implementation: https://github.com/sabel83/mpllibs/blob/master/mpllibs/metaparse/string.hpp. It contains Fernando's improvement to the code as well. Regards, Ábel

Hi Dave,
1. generate that type based on the /value/ of a function argument (yes, you can deduce the length of the string, and thus that type, from the /type/ of a string literal argument).
2. Generate any types or choose template specializations based on the actual characters used in the string literal. I don't see how you're going to generate anything other than a table-based regexp recognizer if you can't do that. We have an implemented and tested a library that can be used to easily build parsers parsing strings at compile-time (it something like a compile-time spirit). It uses metaprograms - not constexpr, thus you can build types as the result of parsing (so you can then specialise templates based on the content of the string, etc.). It uses constexpr only to turn a string literal into an MPL string. You can download and
You can pass values constexpr functions operate on to template metafunctions, but you need to write the conversion. You need to pass template instances to metafunctions. You can write constexpr functions that get the properties of the constexpr object as int, char, bool, etc. values - anything you can use as template arguments. You use pass the values these functions return when you instantiate your templates. One example for this is the string in my previous mail: the "properties" of the string were: - the length of the string (sizeof(S)) - the charachters of the string (nth(S, n)) I used these expressions when I instantiated the templates MPL provides and built MPL data-structures from constexpr values. After that the data can be processed with metaprograms, thus you can generate types. You can convert data in the other direction as well (but you could do that in C++98 as well). Having these things, you should be able to combine constexpr functions and template metafunctions if you implement the data-conversions. try it out yourself, or you can look at the examples. Full implementation: https://github.com/sabel83/mpllibs Documentation: http://abel.web.elte.hu/mpllibs/ Examples: https://github.com/sabel83/mpllibs/tree/master/libs/metaparse/example (you can find an (incomplete) wrapper for Xpressive as well) Further example: typesafe printf - this is implemented as a separate library, the source code is part of the same github project. An example program using it: https://github.com/sabel83/mpllibs/tree/master/libs/safe_printf/example/safe... The typesafe printf is important because it is more than a table-based regexp recogniser. It builds an MPL list of expected types by parsing the format string and type-checks the printf arguments using it. Thus, it demonstrates that you have full access to template metaprogramming while you're parsing. Regards, Ábel

From: Ábel Sinkovics
The typesafe printf is important because it is more than a table-based regexp recogniser. It builds an MPL list of expected types by parsing the format string and type-checks the printf arguments using it. Thus, it demonstrates that you have full access to template metaprogramming while you're parsing.
Syntax example: printf<_S("John %d, %s %d\n")>(11, "Joe", 13); Yay! That syntax doesn't suck. The _S would be BOOST_S if it were a boost library, I guess, or perhaps BOOST_MPL_STRING if we want to be very descriptive. Too bad we need the macro. It would be nice to jet get a variadic template instantiation from the language if we wrote printf<"John %d, %s, %d\n"> directly. It is pretty obvious that we can take this idea and run with it to do something really evil like: ruby<_S("_1.each {|item| puts item }")>(my_array); or perl<_S("foreach $item (@_1){ print "$item\n"; }")>(my_array); Man is that evil. Right up there with overloading the comma operator evilness. Ok, now, hands please, who wants to implement a Ruby interpreter as a template metaprogram? Laughing evilly yours, Luke

Hi Luke,
Syntax example:
printf<_S("John %d, %s %d\n")>(11, "Joe", 13);
Yay! That syntax doesn't suck. The _S would be BOOST_S if it were a boost library, I guess, or perhaps BOOST_MPL_STRING if we want to be very descriptive. Too bad we need the macro. It would be nice to jet get a variadic template instantiation from the language if we wrote printf<"John %d, %s, %d\n"> directly. It is pretty obvious that we can take this idea and run with it to do something really evil like:
ruby<_S("_1.each {|item| puts item }")>(my_array);
or
perl<_S("foreach $item (@_1){ print "$item\n"; }")>(my_array);
Man is that evil. Right up there with overloading the comma operator evilness. Ok, now, hands please, who wants to implement a Ruby interpreter as a template metaprogram? If you look at https://github.com/sabel83/mpllibs/blob/master/mpllibs/metaparse/string.hpp I call this macro MPLLIBS_METAPARSE_STRING (given that the library is called that at the moment - we can change it to BOOST_* when it goes in). _S is just an "alias" of it to simplify its usage. The shorter the name, the less disturbing it is.
If not for Perl, but for small EDSLs it may worth writing a parser (with some TMP tricks these compile-time strings could be compiled into C++ functions - no example for it yet). Given the error reporting capabilities of the parsers built using the library (demonstrated in https://github.com/sabel83/mpllibs/tree/master/libs/metaparse/example/parsin...) it may be useful/helpful. Regards, Ábel

on Mon Jan 09 2012, Ábel Sinkovics <abel-AT-elte.hu> wrote:
Full implementation: https://github.com/sabel83/mpllibs Documentation: http://abel.web.elte.hu/mpllibs/ Examples: https://github.com/sabel83/mpllibs/tree/master/libs/metaparse/example
I stand corrected! The evil magic is in the _S macro. Very nice; I suppose we're off to the races, then! -- Dave Abrahams BoostPro Computing http://www.boostpro.com

From: Dave Abrahams
Full implementation: https://github.com/sabel83/mpllibs Documentation: http://abel.web.elte.hu/mpllibs/ Examples: https://github.com/sabel83/mpllibs/tree/master/libs/metaparse/example
I stand corrected! The evil magic is in the _S macro. Very nice; I suppose we're off to the races, then!
There are a lot of tasks in TMP that are very tedious due to the verbose nature of the language. Instead of macros, could we define a language for scripting template metaprogramming that we use in string arguments to template parameters that expand at compile time into complex metaprogramming behaviors? Could this really make our lives better? Regards, Luke

Hi Luke,
There are a lot of tasks in TMP that are very tedious due to the verbose nature of the language. Instead of macros, could we define a language for scripting template metaprogramming that we use in string arguments to template parameters that expand at compile time into complex metaprogramming behaviors? Could this really make our lives better?
You can compile embedded strings into template metafunction classes. I've added an example EDSL + parser for template metaprogramming lambda expressions (https://github.com/sabel83/mpllibs/tree/master/libs/metaparse/example/meta_l...). Here is how you can use it: typedef META_LAMBDA(2 * _) metafunction_class; metafunction_class::apply<int_<13>>::type Note that it has a significant effect on the compilation speed of the C++ code. Regards, Ábel

From: Ábel Sinkovics
You can compile embedded strings into template metafunction classes. I've added an example EDSL + parser for template metaprogramming lambda expressions (https://github.com/sabel83/mpllibs/tree/master/libs/metaparse/example/meta_l...). Here is how you can use it:
typedef META_LAMBDA(2 * _) metafunction_class;
metafunction_class::apply<int_<13>>::type
Note that it has a significant effect on the compilation speed of the C++ code.
I assume you mean a significant negative effect. This is to be expected. We need to push the compilers to improve. If we can be more expressive but the compilers don't support it well then the compilers must improve. That's one role that boost serves. New usage shouldn't be expected to work well. We are doing things that no one would think to test because no one has done them before. Luke

Hi, It looks like constexpr-based compile-time parsers can be integrated into TMP-based ones (like Metaparse). I've created an example parser parsing a*b*a* in a way that the a* parts are parsed using TMP while b* in the middle is parsed using a constexpr function. Here is the code: https://github.com/sabel83/mpllibs/tree/master/libs/metaparse/example/conste... Parsers based on constexpr can return values only while parsers based on TMP can return types (typelists, metafunction classes, etc). Based on the above example parts of the TMP-based parsers could be implemented using constexpr - a lexer for example? (just an idea) Regards, Ábel
participants (6)
-
Dave Abrahams
-
Fernando Pelliccioni
-
John Bytheway
-
Martin Bidlingmaier
-
Simonson, Lucanus J
-
Ábel Sinkovics