Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Simple DSL Parser with Qt
Forum Updated to NodeBB v4.3 + New Features

Simple DSL Parser with Qt

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 3 Posters 1.9k 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 Extensions
                      • Unsolved