Important: Please read the Qt Code of Conduct -

Simple DSL Parser with Qt

  • I m trying to parse a simple sql like statement using Qt only. Bison, Yacc or boost::spirit are really cumbersome for my simple task.
    My parser should be able to parse the following things :

    SELECT chr, pos FROM variants 
    SELECT chr, pos FROM variants WHERE chr=3
    SELECT chr, pos FROM variants WHERE chr=3 REGION exonic 
    SELECT chr, pos FROM variants REGION exonic

    What I want :

    VqlParser parser;
    parser.parse("SELECT chr FROM variant WHERE chr>3 AND chr<5 REGION exonic")
    parser.fields() // QStringList("chr")
    parser.table() // QString("variant")
    parser.condition() // QString("chr > 3 AND chr < 5")
    parser.region() // QString("exonic")

    Any idea ? With regexp or something else ?

  • Lifetime Qt Champion


    If it's only for these 4 possible strings then QRegularExpression is likely enough to solve this.

  • @SGaist Do I have to create 4 regular expressions ?
    I didn't success to create one regexp which capture each group.

  • Lifetime Qt Champion

    No you don't.

    What expression are you using ?

  • @SGaist This one :

     SELECT(.+)FROM (\w)+ WHERE (.+) REGION (\w+)

    As you can see, I can parse the full query but not the other.

  • Lifetime Qt Champion

    You are missing the handling of optional elements and some white spaces:


  • Unfortunally, the query cannot make difference between the "where clause" and the "region clause" as you see in purple.


  • Moderators

    A simple adjustment should do:

  • Thanks !
    I put my own code if you want to check

    #include <boost/spirit.hpp>
    #include <string>
    #include <typeinfo>
    namespace VQL
    template <typename Iterator>
    auto parse(Iterator begin, Iterator end, bool &success)
        using namespace boost::spirit::x3;
        using x3::lexeme;
        using x3::alpha;
        using x3::phrase_parse;
        using x3::ascii::space;
        using x3::_attr;
        vector<std::string> select;
        std::string from;
        std::string where;
        std::string region;
        auto toSelect = [&](auto & ctx) {select = _attr(ctx);};
        auto toFrom   = [&](auto & ctx) {from   = _attr(ctx);};
        auto toWhere  = [&](auto & ctx) {where  = _attr(ctx);};
        auto toRegion = [&](auto & ctx) {region = _attr(ctx);};
        auto keywords = x3::lit("SELECT") |
                x3::lit("FROM")   |
                x3::lit("WHERE")  |
        auto word     = *(x3::alnum - keywords);
        auto cond     = *(x3::char_ - keywords);
        success = phrase_parse(begin, end,
                               "SELECT" >>
                               (word % ",")[toSelect] >>
                               ("FROM"  >> word[toFrom]) >>
                               -("WHERE" >> x3::lexeme[cond][toWhere]) >>
                               -("REGION" >> word[toRegion])
        return std::make_tuple(select,from,where,region);
    int main(int argc, char **argv)
        std::string query = "SELECT chr,   pos,chrom FROM variants WHERE chr=3 AND chr=4 REGION exonic";
        bool success = false;
        auto results = VQL::parse(query.begin(), query.end(), success);
        if (success)
            for (auto& field : std::get<0>(results))
                std::cout<<"fields "<<field<<"\n";
            std::cout<<"from "<< std::get<1>(results)<<std::endl;
            std::cout<<"where "<< std::get<2>(results)<<std::endl;
            std::cout<<"region "<< std::get<3>(results)<<std::endl;

  • Moderators

    I don't touch that. I'd rather spend half a day writing my own LL(1) parser by hand than mess with Spirit ...

Log in to reply