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.lp p) ==============
%{
#include <iostream>
#include "http_parser.ta b.hpp"
#define ECHO yyerror("Parse error.")
%}
%x REQUEST
%x AFTER_METHOD
%x RESP_VERSION
%x AFTER_RESP_VERS ION
%x RESP_CODE
%x AFTER_RESP_CODE
%x RESP_MSG
%x AFTER_RESP_MSG
%x REQ_HOST
%x REQ_AFTER_HOST
%x REQ_PORT_DELIMI TER
%x REQ_PORT
%x REQ_PATH
%x AFTER_REQ_PATH
%x REQ_BEFORE_VERS ION
%x REQ_VERSION
%x AFTER_REQ_VERSI ON
%x HEADER_NAME
%x HEADER_DELIMITE R
%x HEADER_VALUE
%x AFTER_HEADER_VA LUE
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_VERS ION;
std::cout << "RESP_VERSION=' " << YYText() << "'\n";
return T_RESP_VERSION;
}
<AFTER_RESP_VER SION>{WS} {
BEGIN RESP_CODE;
}
<RESP_CODE>{DIG IT}+/{WS} {
BEGIN AFTER_RESP_CODE ;
std::cout << "RESP_CODE= '" << YYText() << "'\n";
return T_RESP_CODE;
}
<AFTER_RESP_COD E>{WS} {
BEGIN RESP_MSG;
}
<RESP_MSG>{TOKE N}/{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_VERS ION;
std::cout << "REQ_RELATIVE_2 \n";
}
<REQUEST>{PROTO COL} {
BEGIN REQ_HOST;
std::cout << "REQ_ABSOLUTE_1 \n";
std::cout << "PROTOCOL=' " << YYText() << "'\n";
return T_REQ_PROTOCOL;
}
<REQ_HOST>{HOST }/: {
BEGIN REQ_PORT_DELIMI TER;
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_VERS ION;
}
<REQ_PORT_DELIM ITER>":" {
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_VERS ION;
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_VERS ION;
}
<REQ_BEFORE_VER SION>"HTTP/" {
BEGIN REQ_VERSION;
}
<REQ_VERSION>{D IGIT}+\.{DIGIT} +/{CRLF} {
BEGIN AFTER_REQ_VERSI ON;
std::cout << "REQ_VERSIO N='" << YYText() << "'\n";
return T_REQ_VERSION;
}
<AFTER_REQ_VERS ION>{CRLF} {
BEGIN HEADER_NAME;
}
<HEADER_NAME>{H EADER_NAME}+/:{WS} {
BEGIN HEADER_DELIMITE R;
std::cout << "HEADER_NAM E='" << YYText() << "'\n";
return T_HEADER_NAME;
}
<HEADER_DELIMIT ER>:{WS} {
BEGIN HEADER_VALUE;
}
<HEADER_VALUE >[^\r\n]*/{CRLF} {
BEGIN AFTER_HEADER_VA LUE;
std::cout << "HEADER_VALUE=' " << YYText() << "'\n";
return T_HEADER_VALUE;
}
<AFTER_HEADER_V ALUE>{CRLF} {
BEGIN HEADER_NAME;
}
<AFTER_HEADER_V ALUE>{CRLF}{CRL F} { ; }
%%
============== Bizon file (http_parser.yp p) =============== =
%{
#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_VER SION T_RESP_CODE T_RESP_MSG headers\n";
}
;
headers:
headers header
|
;
header:
T_HEADER_NAME T_HEADER_VALUE {
std::cout << "T_HEADER_N AME 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::yy lex()':
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.lp p) ==============
%{
#include <iostream>
#include "http_parser.ta b.hpp"
#define ECHO yyerror("Parse error.")
%}
%x REQUEST
%x AFTER_METHOD
%x RESP_VERSION
%x AFTER_RESP_VERS ION
%x RESP_CODE
%x AFTER_RESP_CODE
%x RESP_MSG
%x AFTER_RESP_MSG
%x REQ_HOST
%x REQ_AFTER_HOST
%x REQ_PORT_DELIMI TER
%x REQ_PORT
%x REQ_PATH
%x AFTER_REQ_PATH
%x REQ_BEFORE_VERS ION
%x REQ_VERSION
%x AFTER_REQ_VERSI ON
%x HEADER_NAME
%x HEADER_DELIMITE R
%x HEADER_VALUE
%x AFTER_HEADER_VA LUE
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_VERS ION;
std::cout << "RESP_VERSION=' " << YYText() << "'\n";
return T_RESP_VERSION;
}
<AFTER_RESP_VER SION>{WS} {
BEGIN RESP_CODE;
}
<RESP_CODE>{DIG IT}+/{WS} {
BEGIN AFTER_RESP_CODE ;
std::cout << "RESP_CODE= '" << YYText() << "'\n";
return T_RESP_CODE;
}
<AFTER_RESP_COD E>{WS} {
BEGIN RESP_MSG;
}
<RESP_MSG>{TOKE N}/{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_VERS ION;
std::cout << "REQ_RELATIVE_2 \n";
}
<REQUEST>{PROTO COL} {
BEGIN REQ_HOST;
std::cout << "REQ_ABSOLUTE_1 \n";
std::cout << "PROTOCOL=' " << YYText() << "'\n";
return T_REQ_PROTOCOL;
}
<REQ_HOST>{HOST }/: {
BEGIN REQ_PORT_DELIMI TER;
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_VERS ION;
}
<REQ_PORT_DELIM ITER>":" {
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_VERS ION;
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_VERS ION;
}
<REQ_BEFORE_VER SION>"HTTP/" {
BEGIN REQ_VERSION;
}
<REQ_VERSION>{D IGIT}+\.{DIGIT} +/{CRLF} {
BEGIN AFTER_REQ_VERSI ON;
std::cout << "REQ_VERSIO N='" << YYText() << "'\n";
return T_REQ_VERSION;
}
<AFTER_REQ_VERS ION>{CRLF} {
BEGIN HEADER_NAME;
}
<HEADER_NAME>{H EADER_NAME}+/:{WS} {
BEGIN HEADER_DELIMITE R;
std::cout << "HEADER_NAM E='" << YYText() << "'\n";
return T_HEADER_NAME;
}
<HEADER_DELIMIT ER>:{WS} {
BEGIN HEADER_VALUE;
}
<HEADER_VALUE >[^\r\n]*/{CRLF} {
BEGIN AFTER_HEADER_VA LUE;
std::cout << "HEADER_VALUE=' " << YYText() << "'\n";
return T_HEADER_VALUE;
}
<AFTER_HEADER_V ALUE>{CRLF} {
BEGIN HEADER_NAME;
}
<AFTER_HEADER_V ALUE>{CRLF}{CRL F} { ; }
%%
============== Bizon file (http_parser.yp p) =============== =
%{
#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_VER SION T_RESP_CODE T_RESP_MSG headers\n";
}
;
headers:
headers header
|
;
header:
T_HEADER_NAME T_HEADER_VALUE {
std::cout << "T_HEADER_N AME 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::yy lex()':
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.
Comment