बूस्ट स्पिरिट x3: कम्पाउंड विशेषता संकलन टाइम एरर (एनम क्लास)
मैं हाल ही में बढ़ावा देने की भावना x3 का उपयोग करते हुए एक सरल संभव पार्सर लिख रहा था । इसमें 2 नियम शामिल हैं: पहचानकर्ता और एक एकल वर्ण ऑपरेटर । स्वाभाविक रूप से, मैंने एक प्रतीक तालिका का उपयोग करके ऑपरेटर को लागू किया , जो एक ऑपरेटर प्रकार का उत्पादन करता है enum class
। पहचानकर्ता के रूप में पार्स किए जाते हैं std::string
। हालांकि, कोड को पहचानने और ऑपरेटरों को एक ही पार्सर में संयोजित करने से इनकार करता है (प्रश्न के अंत में कोड टुकड़ा देखें)।
ध्यान दें, यदि आप एक पूर्णांक के साथ ऑपरेटर प्रकार एनम बदलते हैं, तो सब कुछ ठीक काम करता है। अलग होने पर भी ऑपरेटर और पहचानकर्ता अच्छी तरह से पारस हो जाते हैं।
टेम्पलेट त्रुटि संदेश संलग्न होने के लिए काफी बड़ा है और मुझे समझने के लिए बहुत अस्पष्ट है, लेकिन मुझे संदेह है कि इसका निर्माण / चालबाज़ी के साथ कुछ करना है std::variant<std::string, OperType>
। हालांकि, enum class
मैदान से बहुत अलग नहीं होना चाहिए int
। क्या enum class
डिफॉल्ट कंस्ट्रक्टर से इसका कोई लेना-देना है ? इसे कैसे दरकिनार किया जा सकता है?
यहाँ कोडपीस है
#include <variant>
#include <string>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
auto addCharacter = [](auto &context) {
x3::_val(context).push_back(x3::_attr(context));
};
x3::rule<class IdentifierTag, std::string> identifier{"identifier"};
const auto identifier_def = x3::lexeme[x3::char_("a-zA-Z")[addCharacter] >> *(x3::char_("a-zA-Z0-9")[addCharacter])];
BOOST_SPIRIT_DEFINE(identifier);
enum class OperType
{
plus,
minus
};
struct Opers_ : x3::symbols<OperType>
{
Opers_()
{
add("+", OperType::plus)("-", OperType::minus);
}
} opers_;
x3::rule<class OperTypeTag, OperType> oper{"operator"};
const auto oper_def = x3::lexeme[opers_];
BOOST_SPIRIT_DEFINE(oper);
int main()
{
std::string input{"iden1 + - iden2"};
std::vector<std::variant<std::string, OperType>> tokens;
auto start = input.cbegin();
auto result = x3::phrase_parse(start, input.cend(), (+(identifier | oper)), x3::space, tokens);
return 0;
}
क्या यौगिक पार्सर लिखते समय कोई नुकसान होता है? मैं क्या खो रहा हूँ? आपके समय के लिए धन्यवाद।
जवाब
std::variant
अभी तक विशेषता संगतता के लिए समर्थित नहीं है।
boost::variant
इसे संकलित करने के लिए बदलना : कंपाइलर एक्सप्लोरर
वैकल्पिक रूप से, यहां ऐसे तरीके हैं जो वास्तव में काम करते हैं, अगर आपको std की आवश्यकता है :: variant: Boost Spirit parser को बढ़ावा देने से बढ़ावा देना :: variant to std :: variant
#include <boost/spirit/home/x3.hpp>
#include <variant>
#include <fmt/ranges.h>
#include <fmt/ostream.h>
namespace x3 = boost::spirit::x3;
auto addCharacter = [](auto& context) {
x3::_val(context).push_back(x3::_attr(context));
};
x3::rule<class IdentifierTag, std::string> identifier{"identifier"};
const auto identifier_def =
x3::lexeme[x3::char_("a-zA-Z")[addCharacter] >> *(x3::char_("a-zA-Z0-9")[addCharacter])];
BOOST_SPIRIT_DEFINE(identifier)
enum class OperType
{
plus,
minus
};
static inline std::ostream& operator<<(std::ostream& os, OperType ot) {
switch(ot) {
case OperType::plus: return os << "plus";
case OperType::minus: return os << "minus";
}
return os << "?";
}
struct Opers_ : x3::symbols<OperType>
{
Opers_()
{
add("+", OperType::plus)
("-", OperType::minus);
}
} opers_;
x3::rule<class OperTypeTag, OperType> oper{"operator"};
const auto oper_def = x3::lexeme[opers_];
BOOST_SPIRIT_DEFINE(oper)
int main() {
std::string const input{"iden1 + - iden2"};
std::vector<boost::variant<std::string, OperType>> tokens;
auto f = input.begin(), l = input.end();
auto result = x3::phrase_parse(
f, l,
+(identifier | oper),
x3::space,
tokens);
if (result) {
fmt::print("Parsed: {}\n", tokens);
} else {
fmt::print("Parse failed\n");
}
if (f!=l) {
fmt::print("Remaining: '{}'\n", std::string(f,l));
}
}
प्रिंटों
Parsed: {iden1, plus, minus, iden2}