For sample. Now parse only 4 header line types.
/* * * 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
/* * * 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
%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; } %%
%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; }