User Tools

Site Tools


bison/flex based HTTP header compiler (lexer and parser)

For sample. Now parse only 4 header line types.

requestcc.cpp

requestcc.cpp
/*
 *
 * Copyright 2004-2019 Oleg Borodin  <borodin@unix7.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 */
 
#include <iostream>
#include <sstream>
 
#include "requestyy.hpp"
#include "requestll.hpp"
#include "requestcc.hpp"
 
namespace requestcc {
 
void compiler(const std::string& buffer, srv6::request& request) {
 
    std::stringstream out;
    std::stringstream in;
    in << buffer;
 
    std::cerr << in.str() << std::endl;
    std::cerr << std::endl;
 
    requestcc::lexer l(buffer, out);
    requestcc::parser parser(l, request);
    parser();
 
 
    //std::cerr << out.str() << std::endl;
    //std::cerr << std::endl;
}
 
} // namespace requestcc

requestcc.hpp

requestcc.hpp
/*
 *
 * Copyright 2004-2019 Oleg Borodin  <borodin@unix7.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 */
#ifndef REQUESTCC_HPP
#define REQUESTCC_HPP
 
namespace srv6 {
 
struct request {
    struct auth {
        std::string method;
        std::string key;
    };
 
    std::string method;
    std::string uri;
    std::string hostname;
    int clen = 0;
    auth auth;
};
 
} // namespace srv6
 
namespace requestcc {
 
void compiler(const std::string& raw, srv6::request& request);
 
} // namespace requestcc
 
#endif

request.ll

request.ll
%top{
#include <memory>
#include "requestyy.hpp"
%}
 
%option bison-cc
%option bison-locations
%option noyywrap
%option reentrant
 
%option namespace="requestcc"
%option lexer="lexer"
 
%option lex="yylex"
//%outfile="requestll.cpp"
%header-file="requestll.hpp"
%option bison-cc-namespace="requestcc"
 
%x GET
%x AUTH
%x HOST
%x CLEN
 
GET         GET|POST|HEAD
URI             \/[\/a-zA-Z0-9_%&?=.]{0,1024}
PROTO           HTTP\/1.0|HTTP\/1.1
 
HOST            (?i:host):
HNAME           [a-zA-Z_][a-zA-Z0-9\._]{0,512}
PORT            [1-6][0-9]{1,4}
 
AUTH           (?i:authorization):
AMET           (?i:SAPISIDHASH|BASIC)
AKEY           [a-zA-Z_][a-zA-Z0-9_=]{1,1024}
 
CLEN            (?i:content\-length):
CSIZE           [1-9][0-9]{1,64}
 
SEMIC           :
NL              [\t ]{0,64}\n|[\t ]{0,64}\r\n
SPACE           [\t ]{1,64}
 
%%
 
{GET}            { start(GET); yylval.str = str(); return requestcc::parser::token::GET; }
<GET>{SPACE}         { return requestcc::parser::token::SPACE; }
<GET>{URI}           { yylval.str = str(); return requestcc::parser::token::URI; }
<GET>{PROTO}         { return requestcc::parser::token::PROTO; }
<GET>{NL}            { start(INITIAL); return requestcc::parser::token::NL; }
 
{HOST}            { start(HOST); return requestcc::parser::token::HOST; }
<HOST>{HNAME}         { yylval.str = str(); return requestcc::parser::token::HNAME; }
<HOST>{PORT}          { yylval.str = str(); return requestcc::parser::token::PORT; }
<HOST>{SPACE}         { return requestcc::parser::token::SPACE; }
<HOST>{SEMIC}         { return requestcc::parser::token::SEMIC; }
<HOST>{NL}            { start(INITIAL); return requestcc::parser::token::NL; }
 
{AUTH}            { start(AUTH); return requestcc::parser::token::AUTH; }
<AUTH>{AMET}         { yylval.str = str(); return requestcc::parser::token::AMET; }
<AUTH>{AKEY}         { yylval.str = str(); return requestcc::parser::token::AKEY; }
<AUTH>{SPACE}        { return requestcc::parser::token::SPACE; }
<AUTH>{NL}           { start(INITIAL); return requestcc::parser::token::NL; }
 
{CLEN}            { start(CLEN); return requestcc::parser::token::CLEN; }
<CLEN>{CSIZE}         { yylval.str = str(); return requestcc::parser::token::CSIZE; }
<CLEN>{SPACE}         { return requestcc::parser::token::SPACE; }
<CLEN>{NL}            { start(INITIAL); return requestcc::parser::token::NL; }
 
 
%%

request.yy

request.yy
%skeleton "lalr1.cc"
%require  "3.2"
%language "c++"
 
%define parse.trace
%define parse.error verbose
 
%defines "requestyy.hpp"
%output "requestyy.cpp"
 
%define api.namespace { requestcc }
%define api.location.file "requestloc.hpp"
%locations
 
%code requires{
    #include <iostream>
    #include <string>
    #include <vector>
    #include <memory>
 
    #include "requestcc.hpp"
 
    namespace requestcc {
            class lexer;
    }
}
 
 
%parse-param {requestcc::lexer& lex} {srv6::request& req}
 
 
%code{
    #include "requestll.hpp"
 
    #undef yylex
    #define yylex lex.yylex
 
    std::string tolower(std::string s) {
        std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){
                return std::tolower(c);
        });
        return s;
    }
}
 
%code requires {
    struct lexdata {
        std::string str;
    };
}
%define api.value.type {struct lexdata}
 
%token <str> GET
%token <str> URI
%token PROTO
 
%token HOST
%token <str> HNAME
%token <str> PORT
 
%token AUTH
%token <str> AMET
%token <str> AKEY
 
%token CLEN
%token <str> CSIZE
 
%token SEMIC
%token SPACE
%token NL
%token END
 
 
%%
 
assignments : assignment
            | assignment assignments
            ;
assignment  : some NL
            ;
 
some        : req
            | host
            | auth
            | clen
            | error
            ;
req         : GET SPACE URI SPACE PROTO
                        { req.method = tolower($1); req.uri = $3; }
            ;
 
host        : HOST SPACE HNAME SEMIC PORT
                        { req.hostname = tolower($3); }
            ;
 
auth        : AUTH SPACE AMET SPACE AKEY
                        { req.auth.method = tolower($3); req.auth.key = $5; }
            ;
 
clen        : CLEN SPACE CSIZE
                        {   std::string clen($3);
                            if (clen.length() > 0) {
                                req.clen = std::stoi(clen);
                            } else {
                                req.clen = 0;
                            }
                        }
            ;
%%
void requestcc::parser::error(const location_type& loc, const std::string& msg) {
    std::cerr << msg << " at " << loc << std::endl;
}

First PagePrevious PageBack to overviewNext PageLast Page