
%{
#include <stdio.h>
#include <GMScanner.h>
#include <jAssert.h>
%}

%option nodefault 8bit stack c++ full align
%option yyclass = "GMScanner"

%x SUBJECT_STATE HEADER_STATE TOSS_STATE FROM_STATE DATE_STATE CC_STATE REPTO_STATE STATUS_STATE TO_STATE

FROMLINE ^From[[:space:]]+.*.{3}[[:space:]]+.{3}[[:space:]]+[[:digit:]]+[[:space:]]+([[:digit:]]+:)+[[:digit:]]+[[:space:]]+(...[[:space:]])?[[:digit:]]{4}

%%

{FROMLINE} {
	BEGIN(HEADER_STATE);
	itsCurrentHeaderStart = itsCurrentPosition;
	itsCurrentPosition += YYLeng();
	return kHeaderStart;
}

.|\n itsCurrentPosition += YYLeng();

<HEADER_STATE>{

^Subject: {
	BEGIN(SUBJECT_STATE);
	itsCurrentPosition += YYLeng();
	}

^From: {
	BEGIN(FROM_STATE);
	itsCurrentPosition += YYLeng();
	}
	
^To: {
	BEGIN(TO_STATE);
	itsCurrentPosition += YYLeng();
	}

^Date: {
	BEGIN(DATE_STATE);
	itsCurrentPosition += YYLeng();
	}
	
^[C|c][C|c]: {
	BEGIN(CC_STATE);
	itsCurrentPosition += YYLeng();
	}

^Reply-To: {
	BEGIN(REPTO_STATE);
	itsCurrentPosition += YYLeng();
	}

^Status: {
	BEGIN(STATUS_STATE);
	itsCurrentPosition += YYLeng();
	}

^[^:\n]*: {
	BEGIN(TOSS_STATE);
	itsCurrentPosition += YYLeng();
	}

^\n {
	BEGIN(INITIAL);
	itsCurrentPosition += YYLeng();
	return kHeaderEnd;
	}

.|\n itsCurrentPosition += YYLeng();

}

<SUBJECT_STATE>{
	
.+\n([\t ].*\n)* {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	return kSubject;
	}

\n {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	}

. {
	itsCurrentPosition += YYLeng();	
	}

}

<FROM_STATE>{
	
.+\n([\t ].*\n)*	{
	itsCurrentPosition += YYLeng();
	BEGIN(HEADER_STATE);
	return kFrom;
	}

\n {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	}

. itsCurrentPosition += YYLeng();

}

<DATE_STATE>{
	
[^[:space:]\n].*	{
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	return kDate;
	}

\n {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	}

. itsCurrentPosition += YYLeng();

}

<CC_STATE>{
	
.+\n([\t ].*\n)*	{
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	return kCC;
	}

\n {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	}

. itsCurrentPosition += YYLeng();

}

<TO_STATE>{
	
.+\n([\t ].*\n)*	{
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	return kTo;
	}

\n {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	}

. itsCurrentPosition += YYLeng();

}

<REPTO_STATE>{
	
.+\n([\t ].*\n)*	{
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	return kReplyTo;
	}

\n {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	}

. itsCurrentPosition += YYLeng();

}

<STATUS_STATE>{
	
[^[:space:]\n].*	{
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	return kStatus;
	}

\n {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	}

. itsCurrentPosition += YYLeng();

}

<TOSS_STATE>{
	
\n {
	BEGIN(HEADER_STATE);
	itsCurrentPosition += YYLeng();
	}

. itsCurrentPosition += YYLeng();

}

%%
