%option stack 8bit noyywrap
%{
#include <map>
#include <string>
#include <iostream>
#include <algorithm>

static std::string subject, sender, recipient;
static std::string strlit, *current;

static int hour = -1, minutes = -1;
static int size = -1, multiplier = 1;

typedef std::map<std::string, int> SIMT;
typedef std::map<int,         int> IIMT;

static SIMT sizesBySender;
static IIMT sizesByHour;

inline void yyerror(const char *msg) { std::cerr << msg << std::endl; }

%}

%x X_FROM X_TO X_HOURS X_MINUTES X_SIZE X_STRING

%%

<INITIAL>\"	strlit  = yytext; current = &subject;   yy_push_state(X_STRING);
<X_FROM>\"	strlit  = yytext; current = &sender;    yy_push_state(X_STRING);
<X_TO>\"	strlit  = yytext; current = &recipient; yy_push_state(X_STRING);

<INITIAL>\t+	BEGIN(X_FROM); sender = ""; 
<INITIAL>.	subject += *yytext;
<INITIAL>\n	yyerror("newline in subject");

<X_FROM>\t+	BEGIN(X_TO); recipient = "";
<X_FROM>.	sender += *yytext;
<X_FROM>\n	yyerror("newline in sender");

<X_TO>\t+	BEGIN(X_HOURS);
<X_TO>.		recipient += *yytext;
<X_TO>\n	yyerror("newline in recipient");

<X_HOURS>[[:digit:]]{1,2}	hour = strtol(yytext, NULL, 10);
<X_HOURS>":"			if (hour == -1) yyerror("illegal time: no hour specified"); else BEGIN(X_MINUTES);
<X_HOURS>\t+			yyerror("illegal time: no minutes specified");
<X_HOURS>.|\n			yyerror("illegal time: bad number (hour)");
<X_MINUTES>\t+			if (minutes == -1) yyerror("illegal time: no minutes specified"); else BEGIN(X_SIZE);
<X_MINUTES>[[:digit:]]{2}	minutes = strtol(yytext, NULL, 10);
<X_MINUTES>.|\n			yyerror("illegal time: bad number (minutes)");

<X_SIZE>[ \t]+			; /* ignore */
<X_SIZE>[[:digit:]]+		size = strtol(yytext, NULL, 10);
<X_SIZE>"KB"			multiplier = 1;
<X_SIZE>"MB"			multiplier = 1024;
<X_SIZE>.			yyerror("bad character for size");
<X_SIZE>\n			{
  size *= multiplier;
  sizesBySender[sender] += size;
  sizesByHour[hour] += size;
  BEGIN(INITIAL); subject = "";
}

<X_STRING>\\\"	strlit += yytext;
<X_STRING>\"	strlit += yytext; yy_pop_state(); *current += strlit;
<X_STRING>.	strlit += yytext;
<X_STRING>\n	yyerror("newline in string");


%%
int main() {
  typedef SIMT::value_type SIVT;
  typedef IIMT::value_type IIVT;

  yylex();
  SIMT::iterator sender = std::max_element(sizesBySender.begin(), sizesBySender.end(), [](SIVT &a, SIVT &b){return a.second < b.second;});  
  IIMT::iterator hour   = std::max_element(sizesByHour.begin(),   sizesByHour.end(),   [](IIVT &a, IIVT &b){return a.second < b.second;});  
  std::cout << sender->first << ", " << sender->second << std::endl; 
  std::cout << hour->first   << ", " << hour->second   << std::endl; 
  return 0;
}

