User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

lex-yacc-sample [2019-02-28 10:04] (current)
ziggi created
Line 1: Line 1:
  
 +=====Bison/​Lex sample=====
 +
 +<code c parser.y>​
 +%parse-param { void* scanner }
 +%lex-param { void* scanner }
 +%defines "​parser.h"​
 +%output "​parser.c"​
 +%locations
 +%{
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +#include <​string.h>​
 +#include "​parser.h"​
 +
 +
 +#define TRACING 1
 +#ifdef TRACING
 +#define TRACE(_p) printf _p
 +#else
 +#define TRACE(_p)
 +#endif
 +
 +//#define YYERROR_VERBOSE 1
 +//#define YYPARSE_PARAM scanner /* the same as default */
 +//#define YYLEX_PARAM ​  ​scanner /* the same as default */
 +
 +/* int yyerror(void*,​ const char*); */
 +int yyerror(YYLTYPE *, void*, const char*);
 +
 +
 +%}
 +
 +%language "​c"​
 +%pure-parser
 +
 +%union
 +{
 +    char *string;
 +    int integer;
 +};
 +
 +%token <​string>​ TIMESTAMP QUEUEID EMAIL IP4 NETNAME NUM
 +%token <​string>​ SYMB_IN SYMB_OUT SYMB_COMPL
 +%token <​string>​ DELIM NL
 +%token <​string>​ LB RB LSB RSB LA RA
 +%token <​string>​ COL SCOL AL
 +
 +
 +%token <​string>​ SYMB_HELO HELO_NAME HELO_IPADDR
 +%token <​string>​ SYMB_ROUTER SYMB_TRANSP
 +%token <​string>​ SYMB_PROTO PROTO
 +%token <​string>​ SYMB_IFACE
 +%token <​string>​ SYMB_CIPH
 +%token <​string>​ SYMB_CERTV
 +%token <​string>​ SYMB_SIZE
 +%token <​string>​ SYMB_MESID
 +%token <​string>​ SYMB_FROM
 +%token <​string>​ SYMB_FROM2 SYMB_FOR2
 +%token <​string>​ SYMB_DNAME DN
 +%token <​string>​ SYMB_CONF CONF
 +%token <​string>​ SYMB_QT
 +%token <​string>​ SYMB_AUTH
 +%token <​string>​ SYMB_USER
 +
 +%start record
 +%%
 +
 +record:
 + NL
 + | in some
 + | out some
 + | compl
 + ;
 +
 +out:
 + TIMESTAMP DELIM QUEUEID DELIM SYMB_OUT DELIM EMAIL DELIM LB EMAIL RB DELIM LA EMAIL RA DELIM {
 +  ​ TRACE(("​ [TIMESTAMP:​%s]\n",​ $1)); 
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [OUTPUT]\n"​));​
 +  ​ TRACE(("​ [TO_ORIG:​%s]\n",​ $7));
 +  ​ TRACE(("​ [TO_REAL:​%s]\n",​ $9));
 +  ​ TRACE(("​ [TO_REAL2:​%s]\n",​ $14));
 + }
 + /* a@b.com <abc> */
 + | TIMESTAMP DELIM QUEUEID DELIM SYMB_OUT DELIM EMAIL DELIM LA NETNAME RA DELIM  {
 +  ​ TRACE(("​ [TIMESTAMP:​%s]\n",​ $1)); 
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [OUTPUT]\n"​));​
 +  ​ TRACE(("​ [USERNAME:​%s]\n",​ $8));
 +  ​ TRACE(("​ [TO:​%s]\n",​ $10));
 + }
 + /* abc <​a@b.com>​ */
 + | TIMESTAMP DELIM QUEUEID DELIM SYMB_OUT DELIM NETNAME DELIM LA EMAIL RA DELIM  {
 +  ​ TRACE(("​ [TIMESTAMP:​%s]\n",​ $1)); 
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [OUTPUT]\n"​));​
 +  ​ TRACE(("​ [USERNAME:​%s]\n",​ $8));
 +  ​ TRACE(("​ [TO:​%s]\n",​ $10));
 + }
 + /* => manager_suppliers@center.lazurit.com (kursk_buh@kur.lazurit.com) <​kursk_buh@kur.lazurit.com>​ */
 + | TIMESTAMP DELIM QUEUEID DELIM SYMB_OUT DELIM LA EMAIL RA  DELIM  {
 +  ​ TRACE(("​ [TIMESTAMP:​%s]\n",​ $1)); 
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [OUTPUT]\n"​));​
 +  ​ TRACE(("​ [TO:​%s]\n",​ $7));
 + }
 + /* a@b.com */
 + | TIMESTAMP DELIM QUEUEID DELIM SYMB_OUT DELIM EMAIL DELIM  {
 +  ​ TRACE(("​ [TIMESTAMP:​%s]\n",​ $1)); 
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [OUTPUT]\n"​));​
 +  ​ TRACE(("​ [TO:​%s]\n",​ $7));
 + }
 + ;
 +
 +in:
 + TIMESTAMP DELIM QUEUEID DELIM SYMB_IN DELIM EMAIL DELIM  {
 +  ​ TRACE(("​ [TIMESTAMP:​%s]\n",​ $1)); 
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [INPUT]\n"​));​
 +  ​ TRACE(("​ [FROM:​%s]\n",​ $7));
 + }
 + | TIMESTAMP DELIM QUEUEID DELIM SYMB_IN DELIM EMAIL LA NETNAME RA  DELIM  {
 +  ​ TRACE(("​ [TIMESTAMP:​%s]\n",​ $1)); 
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [INPUT]\n"​));​
 +  ​ TRACE(("​ [FROM:​%s]\n",​ $7));
 +  ​ TRACE(("​ [FROM_REDIR:​%s]\n",​ $9));
 + }
 + | TIMESTAMP DELIM QUEUEID DELIM SYMB_IN DELIM EMAIL LA EMAIL RA  DELIM  {
 +  ​ TRACE(("​ [TIMESTAMP:​%s]\n",​ $1)); 
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [INPUT]\n"​));​
 +  ​ TRACE(("​ [FROM:​%s]\n",​ $7));
 +  ​ TRACE(("​ [FROM_REDIR:​%s]\n",​ $9));
 + }
 + ;
 +
 +compl:
 + TIMESTAMP DELIM QUEUEID DELIM SYMB_COMPL NL {
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [COMPL]\n"​));​
 + }
 + | TIMESTAMP DELIM QUEUEID DELIM SYMB_COMPL DELIM qt NL {
 +  ​ TRACE(("​ [QUEUEID:​%s]\n",​ $3));
 +  ​ TRACE(("​ [COMPL]\n"​));​
 + }
 + ;
 +
 +
 +qt:
 + SYMB_QT NETNAME {
 +  ​ TRACE(("​ [QT:​%s]\n",​ $2));
 + }
 + ;
 +
 +some:
 + exp DELIM some
 + | exp some
 + | exp NL
 + | exp
 + | NL
 + ;
 +
 +exp:
 + /* empty */
 + | helo
 + | proto
 + | auth
 + | iface
 + | ciph
 + | certv
 + | size
 + | mesid
 + | from
 + | from2
 + | router
 + | trans
 + | dname
 + | conf
 + | user
 + ;
 +
 +helo:
 + SYMB_HELO LB NETNAME RB DELIM LSB IP4 RSB {
 +  ​ TRACE(("​ [HELO:​%s]\n",​ $3));
 +  ​ TRACE(("​ [IP:​%s]\n",​ $7));
 + }
 + | SYMB_HELO NETNAME DELIM LSB IP4 RSB {
 +  ​ TRACE(("​ [HELO:​%s]\n",​ $2));
 +  ​ TRACE(("​ [IP:​%s]\n",​ $5));
 + }
 + | SYMB_HELO LB LSB IP4 RSB RB DELIM LSB IP4 RSB {
 +  ​ TRACE(("​ [HELO:​%s]\n",​ $4));
 +  ​ TRACE(("​ [IP:​%s]\n",​ $9));
 + }
 + /* for strange hello H=mx1.lazurit.com (LAZURIT-SMTP-IN) [xxx.xxx.xxx.xxx] */
 + | SYMB_HELO NETNAME DELIM LB NETNAME RB DELIM LSB IP4 RSB {
 +  ​ TRACE(("​ [HELO:​%s]\n",​ $2));
 +  ​ TRACE(("​ [IP:​%s]\n",​ $9));
 + }
 + /* output "​hello"​ */
 + | SYMB_HELO IP4 DELIM LSB IP4 RSB {
 +  ​ TRACE(("​ [HOST_IPADDR:​%s]\n",​ $2));
 +  ​ TRACE(("​ [OUT_IP:​%s]\n",​ $5));
 + }
 + ;
 +
 +proto:
 + SYMB_PROTO PROTO {
 +  ​ TRACE(("​ [PROTO:​%s]\n",​ $2));
 + }
 + | SYMB_PROTO LA EMAIL RA {
 +  ​ TRACE(("​ [RETURN_PATH:​%s]\n",​ $3));
 + }
 + ;
 +
 +
 +auth:
 + SYMB_AUTH NETNAME COL EMAIL {
 +  ​ TRACE(("​ [AUTH_PROTO:​%s]\n",​ $2));
 +  ​ TRACE(("​ [AUTH_NAME:​%s]\n",​ $4));
 + }
 + | SYMB_AUTH NETNAME COL NETNAME {
 +  ​ TRACE(("​ [AUTH_PROTO:​%s]\n",​ $2));
 +  ​ TRACE(("​ [AUTH_NAME:​%s]\n",​ $4));
 + }
 + ;
 +
 +iface:
 + SYMB_IFACE LSB IP4 RSB COL NUM {
 +  ​ TRACE(("​ [IFACE:​%s]\n",​ $3));
 +  ​ TRACE(("​ [IF_PORT:​%s]\n",​ $6));
 + }
 + | SYMB_IFACE LSB IP4 RSB {
 +  ​ TRACE(("​ [IFACE:​%s]\n",​ $3));
 + }
 + ;
 +
 +ciph:
 + SYMB_CIPH NETNAME COL NETNAME COL NUM {
 +  ​ TRACE(("​ [CIPHER:​%s:​%s:​%s]\n",​ $2, $4, $6));
 + }
 + ;
 +
 +certv:
 + SYMB_CERTV NETNAME {
 +  ​ TRACE(("​ [CERTV:​%s]\n",​ $2));
 + }
 + ;
 +
 +size:
 + SYMB_SIZE NUM {
 +  ​ TRACE(("​ [SIZE:​%s]\n",​ $2));
 + }
 + ;
 +
 +mesid:
 + SYMB_MESID EMAIL {
 +  ​ TRACE(("​ [MESID:​%s]\n",​ $2));
 + }
 + | SYMB_MESID NETNAME {
 +  ​ TRACE(("​ [MESID:​%s]\n",​ $2));
 + }
 + | SYMB_MESID NETNAME AL NETNAME {
 +  ​ TRACE(("​ [MESID:​%s@%s]\n",​ $2, $4));
 + }
 + ;
 +
 +from:
 + SYMB_FROM LA EMAIL RA {
 +  ​ TRACE(("​ [FROM:​%s]\n",​ $3));
 + }
 + ;
 +
 +from2:
 + SYMB_FROM2 LA EMAIL RA DELIM SYMB_FOR2 email_list {
 +  ​ TRACE(("​ [FROM2:​%s]\n",​ $3));
 +  ​ /* TRACE(("​ [FOR2:​%s]\n",​ $7)); */
 + }
 + | SYMB_FROM2 EMAIL DELIM SYMB_FOR2 email_list {
 +  ​ TRACE(("​ [FROM2:​%s]\n",​ $3));
 +  ​ /* TRACE(("​ [FOR2:​%s]\n",​ $5)); */
 + }
 + ;
 +
 +email_list:
 + EMAIL DELIM email_list {
 +  ​ TRACE(("​ [FOR2:​%s]\n",​ $1));
 + }
 + | EMAIL {
 +  ​ TRACE(("​ [FOR2:​%s]\n",​ $1));
 + }
 + | NETNAME DELIM email_list {
 +  ​ TRACE(("​ [FOR2:​%s]\n",​ $1));
 + }
 + | NETNAME {
 +  ​ TRACE(("​ [FOR2:​%s]\n",​ $1));
 + }
 + ;
 +
 +
 +router:
 + SYMB_ROUTER NETNAME {
 +  ​ TRACE(("​ [ROUTER:​%s]\n",​ $2));
 + }
 + /* return mail */
 + | SYMB_ROUTER QUEUEID {
 +  ​ TRACE(("​ [RETURN:​%s]\n",​ $2));
 + }
 + ;
 +
 +trans:
 + SYMB_TRANSP NETNAME {
 +  ​ TRACE(("​ [TRANSPORT:​%s]\n",​ $2));
 + }
 + ;
 +
 +dname:
 + SYMB_DNAME DN {
 +  ​ TRACE(("​ [DNAME:​%s]\n",​ $2));
 + }
 + ;
 +
 +conf:
 + SYMB_CONF CONF {
 +   TRACE(("​ [CONFIRM:​%s]\n",​ $2));
 + }
 + ;
 +
 +user:
 + SYMB_USER NETNAME {
 +   TRACE(("​ [USER:​%s]\n",​ $2));
 + }
 + ;
 +
 +%%
 +
 +/*
 +some:  elem
 + | some DELIM elem
 +        ;
 + */
 +
 +
 +int yyerror(YYLTYPE *location, void* scanner, const char* msg) {
 +    (void)location;​
 +    (void)scanner;​
 +//    TRACE(("​%s\n",​msg));​
 +    return 0;
 +}
 +
 +/* EOF */
 +</​code>​
 +
 +
 +<code c lexer.l>
 +%{
 +/* $Id: lexer.l,v 1.4 2016/08/14 22:43:12 root Exp root $ */
 +
 +#include <​stdio.h>​
 +#include "​parser.h"​
 +
 +//#define TRACING ​
 +#ifdef TRACING
 +#define TRACE(_p) printf _p
 +#else
 +#define TRACE(_p)
 +#endif
 +
 +
 +static char* _newstring(char* in_string);
 +%}
 +
 +%option 8bit reentrant
 +%option bison-bridge bison-locations
 +%option outfile="​lexer.c"​ header-file="​lexer.h" ​
 +%option nomain nounput noyy_top_state noyywrap nowarn
 +
 +DELIM [ ]+
 +NL [\n]+
 +NUM [0-9]+
 +IP4 [0-9]{1,​3}\.[0-9]{1,​3}\.[0-9]{1,​3}\.[0-9]{1,​3}
 +
 +TIMESTAMP [0-9]{4}-[0-9]{2}-[0-9]{2}[ ][0-9]{2}:​[0-9]{2}:​[0-9]{2}
 +QUEUEID [a-zA-Z0-9]{6}-[a-zA-Z0-9]{6}-[a-zA-Z0-9]{2}
 +EMAIL [A-Z0-9a-z_][A-Z0-9a-z._\-+=]+@[A-Za-z0-9\.\-]+\.[A-Za-z]{2,​16}|<>​
 +NETNAME [A-Za-z0-9._\-]+
 +
 +DN [A-Z0-9a-z._\-(),​\*\/​= ]+
 +CONF [A-Z0-9a-z._\-(),​\*\/​=+:​\;​\[\] ]+
 +PROTO smtp|esmtp|esmtps|esmtpsa|esmtpa|local
 +COMPL Completed
 +
 +%x DNAME
 +%x CONFIRM
 +
 +%%
 +
 +{TIMESTAMP} { BEGIN(INITIAL);​ yyget_lval(yyscanner)->​string = _newstring(yytext);​ return TIMESTAMP; }
 +{QUEUEID} { yyget_lval(yyscanner)->​string = _newstring(yytext);​ return QUEUEID; }
 +{COMPL} { return SYMB_COMPL; }
 +{PROTO} { yyget_lval(yyscanner)->​string = _newstring(yytext); ​
 +   TRACE(("<​PROTO:​%s>",​ yytext)); ​
 +   return PROTO;
 + }
 +{IP4} { yyget_lval(yyscanner)->​string = _newstring(yytext);​ return IP4; }
 +{EMAIL} { yyget_lval(yyscanner)->​string = _newstring(yytext); ​
 +   TRACE(("​ <​EMAIL:​%s>",​ yytext));
 +   return EMAIL; }
 +{NUM} { yyget_lval(yyscanner)->​string = _newstring(yytext);​ return NUM; }
 +{NETNAME} { yyget_lval(yyscanner)->​string = _newstring(yytext); ​
 +   TRACE(("​ <​NETNAME:​%s>",​ yytext));
 +   return NETNAME; ​
 + }
 +
 +"​DN=\""​ { BEGIN(DNAME);​ return SYMB_DNAME; }
 +<​DNAME>​{DN} { ​ yyget_lval(yyscanner)->​string = _newstring(yytext);​ return DN; }
 +<​DNAME>"​\""​ { BEGIN(INITIAL);​ }
 +
 +"​C=\""​ { BEGIN(CONFIRM);​ return SYMB_CONF; }
 +<​CONFIRM>​{CONF} { yyget_lval(yyscanner)->​string = _newstring(yytext);​
 +   TRACE(("​ <​CONF:​%s>",​ yytext));
 +   return CONF; 
 + }
 +<​CONFIRM>"​\""​ { TRACE(("​ <​CONFIRM_END>"​));​ BEGIN(INITIAL);​ }
 +
 +" id="​ { return SYMB_MESID; }
 +"​QT="​ { return SYMB_QT; }
 +"<​="​ { return SYMB_IN; }
 +"​=>"​ { return SYMB_OUT;}
 +"​R="​ { return SYMB_ROUTER;​ }
 +"​T="​ { return SYMB_TRANSP;​ }
 +"​H="​ { return SYMB_HELO; }
 +"​P="​ { return SYMB_PROTO; }
 +"​I="​ { return SYMB_IFACE; }
 +"​X="​ { return SYMB_CIPH; }
 +"​CV="​ { return SYMB_CERTV; }
 +"​S="​ { return SYMB_SIZE; }
 +"​F="​ { return SYMB_FROM; }
 +"​A="​ { return SYMB_AUTH; }
 +"​U="​ { return SYMB_USER; }
 +"from " { return SYMB_FROM2; }
 +"for " { return SYMB_FOR2; }
 +
 +"<"​ { return LA; }
 +">"​ { return RA; }
 +"​["​ { return LSB; }
 +"​]"​ { return RSB; }
 +"​("​ { return LB; }
 +"​)"​ { return RB; }
 +":"​ { return COL; }
 +";"​ { return SCOL; }
 +"​@"​ { return AL; }
 +
 +{DELIM} { return DELIM; }
 +{NL} { return NL; }
 +
 +.
 +
 +%%
 +
 +static char* _newstring(char* in_string) {
 +    char* out_string = (char*) malloc(strlen(in_string)+1);​
 +    sprintf(out_string,"​%s",​in_string);​
 +    return out_string;
 +}
 +/* EOF */
 +
 +
 +
 +</​code>​