c++ बुजुर्ग:: भावना को बढ़ावा देने के लिए बीजीय बयान कैसे सत्यापित करें?



parsing boost (1)

सबसे सरल चीज जो काम कर सकती थी, यदि आप मुझसे पूछें तो http://liveworkspace.org/code/1fvc8x$0

equation = (expression >> "=" >> expression) [ _val = _1 == _2 ];

यह दो अभिव्यक्तियों को पार्स करेगा, और लौटा दिया गया विशेषता एक bool जो यह इंगित करता है कि दोनों भाव एक ही मूल्य के लिए मूल्यांकन करते हैं।

प्रदर्शन कार्यक्रम

int main()
{
    doParse("1 + 2 * 3 = 7");
    doParse("1 + 2 * 3 = 8");
}

प्रिंट

parse success
result: true
parse success
result: false

नमूना कार्यक्रम

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi    = boost::spirit::qi;
namespace phx   = boost::phoenix;

typedef unsigned attr_t;

template <typename It, typename Skipper = qi::space_type>
    struct calculator : qi::grammar<It, bool(), Skipper>
{
    calculator() : calculator::base_type(equation)
    {
        using qi::uint_;
        using qi::_val;
        using qi::_1;
        using qi::_2;

        equation = (expression >> "=" >> expression) [ _val = _1 == _2 ];

        expression =
            term                    [_val = _1]
                >> *( ('+' >> term  [_val = _val + _1])
                    | ('-' >> term  [_val = _val - _1])
                    );

            term =
                factor                [_val = _1]
                >> *( ('*' >> factor  [_val = _val * _1])
                    | ('/' >> factor  [_val = _val / _1])
                    );

            factor =
                uint_                 [_val = _1]
                |   '(' >> expression [_val = _1] >> ')'
                |   ('-' >> factor    [_val = -_1])
                |   ('+' >> factor    [_val = _1]);
    }

  private:
    qi::rule<It, unsigned(), Skipper> expression, term, factor;
    qi::rule<It, bool(), Skipper> equation;
};

bool doParse(const std::string& input)
{
    typedef std::string::const_iterator It;
    auto f(begin(input)), l(end(input));

    calculator<It, qi::space_type> p;
    bool result;

    try
    {
        bool ok = qi::phrase_parse(f,l,p,qi::space,result);
        if (ok)   
        {
            std::cout << "parse success\n";
            std::cout << "result: " << std::boolalpha << result << "\n";
        }
        else      std::cerr << "parse failed: '" << std::string(f,l) << "'\n";

        if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
        return ok;
    } catch(const qi::expectation_failure<It>& e)
    {
        std::string frag(e.first, e.last);
        std::cerr << e.what() << "'" << frag << "'\n";
    }

    return false;
}

int main()
{
    doParse("1 + 2 * 3 = 7");
    doParse("1 + 2 * 3 = 8");
}

मैं कैलकुलेटर उदाहरण का विस्तार करने की कोशिश कर रहा हूं ताकि बीजीय अभिव्यक्ति के विश्लेषण और मूल्यांकन के बजाय, पार्सर यह निर्धारित करेगा कि क्या बीजीय बयान सही है या नहीं। इसके द्वारा मेरा मतलब है कि 1 + 5 * 5 - 10 = 19 - 3 (वांछित पार्सर्स का परिणाम true ) और 3 - 1 = 9 (वांछित पार्सर परिणाम false )।

मुझे यह स्वीकार करना है कि मैं उत्साहित हूं boost::spirit को boost::spirit लिए नया हूँ और यह इस समय सभी प्रकार की भारी संख्या में है। हालांकि, मुझे लगता है कि मैं कैलकुलेटर का उदाहरण समझता हूं कि कम से कम कुछ राजमार्ग बनाने के लिए।

प्रारंभिक बिंदु के रूप में दिए गए उदाहरण का उपयोग करना, व्याकरण इस तरह दिखता है:

calculator() : calculator::base_type(expression)
{
    using qi::uint_;
    using qi::_val;
    using qi::_1;

    expression =
        term                    [_val = _1]
            >> *( ('+' >> term  [_val = _val + _1])
                | ('-' >> term  [_val = _val - _1])
                );

        term =
            factor                [_val = _1]
            >> *( ('*' >> factor  [_val = _val * _1])
                | ('/' >> factor  [_val = _val / _1])
                );

        factor =
            uint_                 [_val = _1]
            |   '(' >> expression [_val = _1] >> ')'
            |   ('-' >> factor    [_val = -_1])
            |   ('+' >> factor    [_val = _1]);
}

जहां मैंने संक्षिप्तता के लिए डिबग मैक्रोज़ को छोड़ दिया है

समस्या के दायरे को सीमित करने के लिए, मैंने केवल एक एकल समानता चिह्न प्रति स्टेटमेंट की अनुमति देने का निर्णय लिया है। चूंकि यह अर्थहीन है (कम से कम एक नियमित अर्थ में), समानता चिह्नों को एक बंद जोड़ी के कोष्ठक के अंदर दिखाई देता है, मैंने यह भी निर्णय लिया है कि आप कोष्ठकों को भी अनुमति न दें यह वैकल्पिक '(' >> expression [_val = _1] >> ')' को हटाने की अनुमति देकर factor पार्सर्स को सरल करता factor '(' >> expression [_val = _1] >> ')'

इस समय मैं थोड़ी सी फँस गया हूं। सबसे पहले, मुझे एक एकल समानता चिन्ह स्वीकार करने के लिए पारसर की आवश्यकता है। दूसरे, अंत में एक तुलना (या तो यह वही है जो मुझे लगता है कि करने की जरूरत है) करने से पहले, मुझे व्यक्तिगत रूप से बयान में बाएं हाथ की ओर (एलएचएस) और दाहिनी ओर (आरएचएस) का मूल्यांकन करने के लिए अर्थ क्रियाओं की आवश्यकता है।

मैं सोच रहा हूं कि सबसे आसान दृष्टिकोण दो अलग-अलग पार्सर, एक एलएचएस और एक आरएचएस का निर्माण करना होगा, जो समानता चिन्ह से मेल खाने वाले तीसरे पार्सर से अलग होगा। दो पार्सर एलएचएस और आरएचएस समान होना चाहिए, सिमेंटिक क्रिया को छोड़कर, स्पष्ट रूप से, इनपुट को दो अलग-अलग श्रेणियों में अलग करने की ज़रूरत है ताकि इनके साथ तुलना की जा सके।

दो अलग-अलग पार्सर्स एलएचएस और आरएचएस लिखने की कोशिश करने से पहले, मैं मूल पार्सर को कैसे संशोधित करना सीखना चाहता था ताकि यह स्थानीय वैरिएबल में मूल्यांकन किये हुए भाव को संग्रहीत कर सके। (मुझे यह भी पता नहीं है कि कहीं भी एक व्यावहारिक रास्ता होगा, लेकिन यह सही दिशा में एक कदम की तरह लगता है।)

यही मैंने कोशिश की है:

int result;

expression =
    term                            [result = _1]
    >> *(   ('+' >> term            [result = result + _1])
        |   ('-' >> term            [result = result - _1])
        );

लेकिन यह मेरे कंपाइलर बनाता है (एप्पल LLVM 4.2 संकलक 4.2, Xcode 4.6) पागल जाओ, मुझ पर चिल्ला कि

असंगत प्रकार 'const _1_type' से 'int' को असाइन करना (उर्फ 'कॉन्स्ट अभिनेता <तर्क <0>>')

_val में, यह निश्चित रूप से समझ में आता है, क्योंकि _val को पहले स्थान पर कभी नहीं _val गया था (सभी के बाद, एपीएआई को सामान्य माना जाता है)। दूसरे शब्दों में, मुझे यह पता लगाने की आवश्यकता है कि कैसे मूल्यांकन किया गया पार्स किए गए अभिव्यक्ति अस्थायी रूप से भंडारण के लिए उपयोग करने वाले प्रकार को परिभाषित करना

सवाल यह है कि क्या कोई मुझे सही दिशा में एक कुहनी दे सकता है? क्या एलएचएस और आरएचएस में विभाजित होने का रास्ता लगता है?

कोई सुझाव काफी सराहना की है!





boost-spirit-qi