Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Simple DSL Parser with Qt
Qt 6.12 LTS is out! See what's new in the release blog

Simple DSL Parser with Qt

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 3 Posters 3.8k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    dridk2
    wrote on last edited by dridk2
    #1

    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 ?

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

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

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      D 1 Reply Last reply
      2
      • SGaistS SGaist

        Hi,

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

        D Offline
        D Offline
        dridk2
        wrote on last edited by
        #3

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

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          No you don't.

          What expression are you using ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          D 1 Reply Last reply
          0
          • SGaistS SGaist

            No you don't.

            What expression are you using ?

            D Offline
            D Offline
            dridk2
            wrote on last edited by
            #5

            @SGaist This one : https://regex101.com/r/Lpupin/2

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

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

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

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

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

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              D 1 Reply Last reply
              1
              • SGaistS SGaist

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

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

                D Offline
                D Offline
                dridk2
                wrote on last edited by
                #7

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

                0_1523397360762_8aec107f-7865-44cf-8d91-78dfff38490c-image.png

                kshegunovK 1 Reply Last reply
                0
                • D dridk2

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

                  0_1523397360762_8aec107f-7865-44cf-8d91-78dfff38490c-image.png

                  kshegunovK Offline
                  kshegunovK Offline
                  kshegunov
                  Moderators
                  wrote on last edited by
                  #8

                  A simple adjustment should do:
                  https://regex101.com/r/emTTdh/1

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  4
                  • D Offline
                    D Offline
                    dridk2
                    wrote on last edited by dridk2
                    #9

                    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")  |
                                x3::lit("REGION");
                    
                        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])
                                               ,
                                               space
                                               );
                    
                        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;
                            std::cout<<std::flush;
                    
                        }
                    }
                    
                    kshegunovK 1 Reply Last reply
                    1
                    • D dridk2

                      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")  |
                                  x3::lit("REGION");
                      
                          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])
                                                 ,
                                                 space
                                                 );
                      
                          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;
                              std::cout<<std::flush;
                      
                          }
                      }
                      
                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

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

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt
                      • Unsolved