P
pavel.orehov
Hi,
I am using flex and bizon to write HTTP parser.
I am passing well flex and bison tools but can't compile their output.
================= Flex file (http_parser.lpp) ==============
%{
#include <iostream>
#include "http_parser.tab.hpp"
#define ECHO yyerror("Parse error.")
%}
%x REQUEST
%x AFTER_METHOD
%x RESP_VERSION
%x AFTER_RESP_VERSION
%x RESP_CODE
%x AFTER_RESP_CODE
%x RESP_MSG
%x AFTER_RESP_MSG
%x REQ_HOST
%x REQ_AFTER_HOST
%x REQ_PORT_DELIMITER
%x REQ_PORT
%x REQ_PATH
%x AFTER_REQ_PATH
%x REQ_BEFORE_VERSION
%x REQ_VERSION
%x AFTER_REQ_VERSION
%x HEADER_NAME
%x HEADER_DELIMITER
%x HEADER_VALUE
%x AFTER_HEADER_VALUE
WS [\x20\t]+
CRLF (\r\n|\r|\n)
TOKEN [^\x80-\xFF\x7F\x00-\x1F\x20\x22\r\n\t]+
LETTER [a-zA-Z]
HEADER_NAME [-_a-zA-Z]+
DIGIT [0-9]
PROTOCOL (http:\/\/|ftp:\/\/)
HOST [^\x2F\x3A\x80-\xFF\x7F\x00-\x1F\x20\x22\r\n\t]+
PORT {DIGIT}+
METHOD {LETTER}+
%%
{METHOD}/{WS} {
BEGIN AFTER_METHOD;
std::cout << "REQUEST\n";
std::cout << "METHOD='" << YYText() << "'\n";
return T_REQ_METHOD;
}
<AFTER_METHOD>{WS} {
BEGIN REQUEST;
}
"HTTP/" {
BEGIN RESP_VERSION;
std::cout << "RESPONSE\n";
}
<RESP_VERSION>{DIGIT}+\.{DIGIT}+/{WS} {
BEGIN AFTER_RESP_VERSION;
std::cout << "RESP_VERSION='" << YYText() << "'\n";
return T_RESP_VERSION;
}
<AFTER_RESP_VERSION>{WS} {
BEGIN RESP_CODE;
}
<RESP_CODE>{DIGIT}+/{WS} {
BEGIN AFTER_RESP_CODE;
std::cout << "RESP_CODE='" << YYText() << "'\n";
return T_RESP_CODE;
}
<AFTER_RESP_CODE>{WS} {
BEGIN RESP_MSG;
}
<RESP_MSG>{TOKEN}/{CRLF} {
BEGIN AFTER_RESP_MSG;
std::cout << "RESP_MSG='" << YYText() << "'\n";
return T_RESP_MSG;
}
<AFTER_RESP_MSG>{CRLF} {
BEGIN HEADER_NAME;
}
<REQUEST>"/" {
BEGIN REQ_PATH;
std::cout << "REQ_RELATIVE_1\n";
}
<REQUEST>"/"{WS} {
BEGIN REQ_BEFORE_VERSION;
std::cout << "REQ_RELATIVE_2\n";
}
<REQUEST>{PROTOCOL} {
BEGIN REQ_HOST;
std::cout << "REQ_ABSOLUTE_1\n";
std::cout << "PROTOCOL='" << YYText() << "'\n";
return T_REQ_PROTOCOL;
}
<REQ_HOST>{HOST}/: {
BEGIN REQ_PORT_DELIMITER;
std::cout << "REQ_HOST_1='" << YYText() << "'\n";
return T_REQ_HOST;
}
<REQ_HOST>{HOST}/\/ {
BEGIN REQ_PATH;
std::cout << "REQ_HOST_2='" << YYText() << "'\n";
return T_REQ_HOST;
}
<REQ_HOST>{HOST}/{WS} {
BEGIN REQ_AFTER_HOST;
std::cout << "REQ_HOST_3='" << YYText() << "'\n";
return T_REQ_HOST;
}
<REQ_AFTER_HOST>{WS} {
BEGIN REQ_BEFORE_VERSION;
}
<REQ_PORT_DELIMITER>":" {
BEGIN REQ_PORT;
}
<REQ_PORT>{PORT}/\/ {
BEGIN REQ_PATH;
std::cout << "REQ_PORT_1='" << YYText() << "'\n";
return T_REQ_PORT;
}
<REQ_PORT>{PORT}/{WS} {
BEGIN REQ_BEFORE_VERSION;
std::cout << "REQ_PORT_2='" << YYText() << "'\n";
return T_REQ_PORT;
}
REQ_PATH>{TOKEN}/{WS} {
BEGIN AFTER_REQ_PATH;
std::cout << "REQ_PATH='" << YYText() << "'\n";
return T_REQ_PATH;
}
<AFTER_REQ_PATH>{WS} {
BEGIN REQ_BEFORE_VERSION;
}
<REQ_BEFORE_VERSION>"HTTP/" {
BEGIN REQ_VERSION;
}
<REQ_VERSION>{DIGIT}+\.{DIGIT}+/{CRLF} {
BEGIN AFTER_REQ_VERSION;
std::cout << "REQ_VERSION='" << YYText() << "'\n";
return T_REQ_VERSION;
}
<AFTER_REQ_VERSION>{CRLF} {
BEGIN HEADER_NAME;
}
<HEADER_NAME>{HEADER_NAME}+/:{WS} {
BEGIN HEADER_DELIMITER;
std::cout << "HEADER_NAME='" << YYText() << "'\n";
return T_HEADER_NAME;
}
<HEADER_DELIMITER>:{WS} {
BEGIN HEADER_VALUE;
}
<HEADER_VALUE>[^\r\n]*/{CRLF} {
BEGIN AFTER_HEADER_VALUE;
std::cout << "HEADER_VALUE='" << YYText() << "'\n";
return T_HEADER_VALUE;
}
<AFTER_HEADER_VALUE>{CRLF} {
BEGIN HEADER_NAME;
}
<AFTER_HEADER_VALUE>{CRLF}{CRLF} { ; }
%%
============== Bizon file (http_parser.ypp) ================
%{
#include <iostream>
extern "C"
{
void yyerror(char *);
int yyparse(void);
int yylex(void);
int yywrap();
}
%}
%token T_REQ_METHOD
%token T_REQ_PROTOCOL
%token T_REQ_HOST
%token T_REQ_PORT
%token T_REQ_PATH
%token T_REQ_VERSION
%token T_RESP_VERSION
%token T_RESP_CODE
%token T_RESP_MSG
%token T_HEADER_NAME
%token T_HEADER_VALUE
%%
program:
| request
| response
;
request:
/* Absolute requests */
T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST T_REQ_PORT T_REQ_PATH
T_REQ_VERSION headers {
std::cout << "ABS => T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST
T_REQ_PORT T_REQ_PATH T_REQ_VERSION headers\n";
}
|
T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST T_REQ_PATH T_REQ_VERSION
headers {
std::cout << "ABS => T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST
T_REQ_PATH T_REQ_VERSION headers\n";
}
|
T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST T_REQ_VERSION headers {
std::cout << "ABS => T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST
T_REQ_VERSION headers\n";
}
|
/* Relative requests */
T_REQ_METHOD T_REQ_PATH T_REQ_VERSION headers {
std::cout << "REL => T_REQ_METHOD T_REQ_PATH T_REQ_VERSION
headers\n";
}
|
T_REQ_METHOD T_REQ_VERSION headers {
std::cout << "REL => T_REQ_METHOD T_REQ_VERSION headers\n";
}
;
response:
T_RESP_VERSION T_RESP_CODE T_RESP_MSG headers {
std::cout << "T_RESP_VERSION T_RESP_CODE T_RESP_MSG headers\n";
}
;
headers:
headers header
|
;
header:
T_HEADER_NAME T_HEADER_VALUE {
std::cout << "T_HEADER_NAME T_HEADER_VALUE\n";
}
;
%%
int yywrap(void) {
return 1;
}
void yyerror(char * msg)
{
std::cout << "ERROR: " << msg << std::endl;
}
int main( void )
{
FlexLexer* lexer = new yyFlexLexer;
while(lexer->yylex() != 0)
;
return 0;
}
===================== Compile ====================
1. flex --c++ http_parser.lpp
OK
2. bison -d http_parser.ypp
OK
3. Files list
http_parser.lpp
http_parser.tab.cpp
http_parser.tab.hpp
http_parser.ypp
lex.yy.cc
4. g++ -c lex.yy.cc http_parser.tab.cpp
http_parser.lpp: In member function `virtual int yyFlexLexer::yylex()':
http_parser.lpp:222: error: `yyerror' undeclared (first use this
function)
http_parser.lpp:222: error: (Each undeclared identifier is reported
only once
for each function it appears in.)
lex.yy.cc:1174: error: `yywrap' undeclared (first use this function)
http_parser.ypp: In function `int main()':
http_parser.ypp:90: error: `FlexLexer' undeclared (first use this
function)
http_parser.ypp:90: error: (Each undeclared identifier is reported only
once
for each function it appears in.)
http_parser.ypp:90: error: `lexer' undeclared (first use this function)
http_parser.ypp:90: error: parse error before `;' token
What i am doing wrong ???
Thanks a lot.
I am using flex and bizon to write HTTP parser.
I am passing well flex and bison tools but can't compile their output.
================= Flex file (http_parser.lpp) ==============
%{
#include <iostream>
#include "http_parser.tab.hpp"
#define ECHO yyerror("Parse error.")
%}
%x REQUEST
%x AFTER_METHOD
%x RESP_VERSION
%x AFTER_RESP_VERSION
%x RESP_CODE
%x AFTER_RESP_CODE
%x RESP_MSG
%x AFTER_RESP_MSG
%x REQ_HOST
%x REQ_AFTER_HOST
%x REQ_PORT_DELIMITER
%x REQ_PORT
%x REQ_PATH
%x AFTER_REQ_PATH
%x REQ_BEFORE_VERSION
%x REQ_VERSION
%x AFTER_REQ_VERSION
%x HEADER_NAME
%x HEADER_DELIMITER
%x HEADER_VALUE
%x AFTER_HEADER_VALUE
WS [\x20\t]+
CRLF (\r\n|\r|\n)
TOKEN [^\x80-\xFF\x7F\x00-\x1F\x20\x22\r\n\t]+
LETTER [a-zA-Z]
HEADER_NAME [-_a-zA-Z]+
DIGIT [0-9]
PROTOCOL (http:\/\/|ftp:\/\/)
HOST [^\x2F\x3A\x80-\xFF\x7F\x00-\x1F\x20\x22\r\n\t]+
PORT {DIGIT}+
METHOD {LETTER}+
%%
{METHOD}/{WS} {
BEGIN AFTER_METHOD;
std::cout << "REQUEST\n";
std::cout << "METHOD='" << YYText() << "'\n";
return T_REQ_METHOD;
}
<AFTER_METHOD>{WS} {
BEGIN REQUEST;
}
"HTTP/" {
BEGIN RESP_VERSION;
std::cout << "RESPONSE\n";
}
<RESP_VERSION>{DIGIT}+\.{DIGIT}+/{WS} {
BEGIN AFTER_RESP_VERSION;
std::cout << "RESP_VERSION='" << YYText() << "'\n";
return T_RESP_VERSION;
}
<AFTER_RESP_VERSION>{WS} {
BEGIN RESP_CODE;
}
<RESP_CODE>{DIGIT}+/{WS} {
BEGIN AFTER_RESP_CODE;
std::cout << "RESP_CODE='" << YYText() << "'\n";
return T_RESP_CODE;
}
<AFTER_RESP_CODE>{WS} {
BEGIN RESP_MSG;
}
<RESP_MSG>{TOKEN}/{CRLF} {
BEGIN AFTER_RESP_MSG;
std::cout << "RESP_MSG='" << YYText() << "'\n";
return T_RESP_MSG;
}
<AFTER_RESP_MSG>{CRLF} {
BEGIN HEADER_NAME;
}
<REQUEST>"/" {
BEGIN REQ_PATH;
std::cout << "REQ_RELATIVE_1\n";
}
<REQUEST>"/"{WS} {
BEGIN REQ_BEFORE_VERSION;
std::cout << "REQ_RELATIVE_2\n";
}
<REQUEST>{PROTOCOL} {
BEGIN REQ_HOST;
std::cout << "REQ_ABSOLUTE_1\n";
std::cout << "PROTOCOL='" << YYText() << "'\n";
return T_REQ_PROTOCOL;
}
<REQ_HOST>{HOST}/: {
BEGIN REQ_PORT_DELIMITER;
std::cout << "REQ_HOST_1='" << YYText() << "'\n";
return T_REQ_HOST;
}
<REQ_HOST>{HOST}/\/ {
BEGIN REQ_PATH;
std::cout << "REQ_HOST_2='" << YYText() << "'\n";
return T_REQ_HOST;
}
<REQ_HOST>{HOST}/{WS} {
BEGIN REQ_AFTER_HOST;
std::cout << "REQ_HOST_3='" << YYText() << "'\n";
return T_REQ_HOST;
}
<REQ_AFTER_HOST>{WS} {
BEGIN REQ_BEFORE_VERSION;
}
<REQ_PORT_DELIMITER>":" {
BEGIN REQ_PORT;
}
<REQ_PORT>{PORT}/\/ {
BEGIN REQ_PATH;
std::cout << "REQ_PORT_1='" << YYText() << "'\n";
return T_REQ_PORT;
}
<REQ_PORT>{PORT}/{WS} {
BEGIN REQ_BEFORE_VERSION;
std::cout << "REQ_PORT_2='" << YYText() << "'\n";
return T_REQ_PORT;
}
REQ_PATH>{TOKEN}/{WS} {
BEGIN AFTER_REQ_PATH;
std::cout << "REQ_PATH='" << YYText() << "'\n";
return T_REQ_PATH;
}
<AFTER_REQ_PATH>{WS} {
BEGIN REQ_BEFORE_VERSION;
}
<REQ_BEFORE_VERSION>"HTTP/" {
BEGIN REQ_VERSION;
}
<REQ_VERSION>{DIGIT}+\.{DIGIT}+/{CRLF} {
BEGIN AFTER_REQ_VERSION;
std::cout << "REQ_VERSION='" << YYText() << "'\n";
return T_REQ_VERSION;
}
<AFTER_REQ_VERSION>{CRLF} {
BEGIN HEADER_NAME;
}
<HEADER_NAME>{HEADER_NAME}+/:{WS} {
BEGIN HEADER_DELIMITER;
std::cout << "HEADER_NAME='" << YYText() << "'\n";
return T_HEADER_NAME;
}
<HEADER_DELIMITER>:{WS} {
BEGIN HEADER_VALUE;
}
<HEADER_VALUE>[^\r\n]*/{CRLF} {
BEGIN AFTER_HEADER_VALUE;
std::cout << "HEADER_VALUE='" << YYText() << "'\n";
return T_HEADER_VALUE;
}
<AFTER_HEADER_VALUE>{CRLF} {
BEGIN HEADER_NAME;
}
<AFTER_HEADER_VALUE>{CRLF}{CRLF} { ; }
%%
============== Bizon file (http_parser.ypp) ================
%{
#include <iostream>
extern "C"
{
void yyerror(char *);
int yyparse(void);
int yylex(void);
int yywrap();
}
%}
%token T_REQ_METHOD
%token T_REQ_PROTOCOL
%token T_REQ_HOST
%token T_REQ_PORT
%token T_REQ_PATH
%token T_REQ_VERSION
%token T_RESP_VERSION
%token T_RESP_CODE
%token T_RESP_MSG
%token T_HEADER_NAME
%token T_HEADER_VALUE
%%
program:
| request
| response
;
request:
/* Absolute requests */
T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST T_REQ_PORT T_REQ_PATH
T_REQ_VERSION headers {
std::cout << "ABS => T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST
T_REQ_PORT T_REQ_PATH T_REQ_VERSION headers\n";
}
|
T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST T_REQ_PATH T_REQ_VERSION
headers {
std::cout << "ABS => T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST
T_REQ_PATH T_REQ_VERSION headers\n";
}
|
T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST T_REQ_VERSION headers {
std::cout << "ABS => T_REQ_METHOD T_REQ_PROTOCOL T_REQ_HOST
T_REQ_VERSION headers\n";
}
|
/* Relative requests */
T_REQ_METHOD T_REQ_PATH T_REQ_VERSION headers {
std::cout << "REL => T_REQ_METHOD T_REQ_PATH T_REQ_VERSION
headers\n";
}
|
T_REQ_METHOD T_REQ_VERSION headers {
std::cout << "REL => T_REQ_METHOD T_REQ_VERSION headers\n";
}
;
response:
T_RESP_VERSION T_RESP_CODE T_RESP_MSG headers {
std::cout << "T_RESP_VERSION T_RESP_CODE T_RESP_MSG headers\n";
}
;
headers:
headers header
|
;
header:
T_HEADER_NAME T_HEADER_VALUE {
std::cout << "T_HEADER_NAME T_HEADER_VALUE\n";
}
;
%%
int yywrap(void) {
return 1;
}
void yyerror(char * msg)
{
std::cout << "ERROR: " << msg << std::endl;
}
int main( void )
{
FlexLexer* lexer = new yyFlexLexer;
while(lexer->yylex() != 0)
;
return 0;
}
===================== Compile ====================
1. flex --c++ http_parser.lpp
OK
2. bison -d http_parser.ypp
OK
3. Files list
http_parser.lpp
http_parser.tab.cpp
http_parser.tab.hpp
http_parser.ypp
lex.yy.cc
4. g++ -c lex.yy.cc http_parser.tab.cpp
http_parser.lpp: In member function `virtual int yyFlexLexer::yylex()':
http_parser.lpp:222: error: `yyerror' undeclared (first use this
function)
http_parser.lpp:222: error: (Each undeclared identifier is reported
only once
for each function it appears in.)
lex.yy.cc:1174: error: `yywrap' undeclared (first use this function)
http_parser.ypp: In function `int main()':
http_parser.ypp:90: error: `FlexLexer' undeclared (first use this
function)
http_parser.ypp:90: error: (Each undeclared identifier is reported only
once
for each function it appears in.)
http_parser.ypp:90: error: `lexer' undeclared (first use this function)
http_parser.ypp:90: error: parse error before `;' token
What i am doing wrong ???
Thanks a lot.