summaryrefslogtreecommitdiff
path: root/test/mailbox2.rl
blob: bbaf8200ab1f7eb37b3fa1f4b43f203b9442b061 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
 * @LANG: c++
 * @CFLAGS: -I../aapl
 */

#include <iostream>
#include <string.h>

using std::cin;
using std::cout;
using std::cerr;
using std::endl;

%%{
	machine mailbox;

	action prn_char { cout << *p; }
	action prn_space { cout << ' '; }
	action prn_word { cout.write(ws, p-ws); cout << ' '; }
	action prn_addr1 { cout << "| "; cout.write(ws+1, p-ws-2); }
	action prn_addr2 { cout << "| "; cout.write(ws, p-ws); }
	action prn_tab { cout << '\t'; }
	action prn_nl { cout << '\n'; }
	action prn_separator { cout << "------\n"; } 
	action prn_from { cout << "FROM\n"; }
	action prn_to { cout << "TO\n"; }
	action prn_subj { cout << "SUBJECT\n"; }

	action start_word { ws = p; }
	action start_headers { preserve = p; }
	action end_headers {preserve = 0;}

	day = upper lower{2};
	month = upper lower{2};
	year = digit{4};
	time = digit{2} ':' digit{2} 
		( ':' digit{2} )?;
	letterZone = upper{3};
	numZone = [+\-] digit{4};
	zone = letterZone | numZone;
	dayNum = ( digit | ' ' ) digit;

	date = day ' ' month ' ' 
		dayNum ' ' time ' '
		( 
			year | 
			year ' ' zone | 
			zone ' ' year
		);

	fromLine = 'From ' [^\n]* ' ' 
		date '\n' @start_headers;

	headerChar = print - [ :];
	headersToPrint = 'From' | 
		'To' | 'Subject';
	headersToConsume = 
		headerChar+ - headersToPrint;

	consumeHeader = 
		headersToConsume ':'
		( 
			[^\n] | 
			( '\n' [ \t] )
		)*
		'\n';

	addrWS = ( [ \t]+ | '\n' [ \t]+ );
	addrComment = '(' [^)]* ')';
	addrWord = [^"'@,<>() \t\n]+;
	addrAddr1 = '<' [^>]* '>';
	addrAddr2 = addrWord '@' addrWord;
	addrString = 
		'"' [^"]* '"' |
		"'" [^']* "'";

	addrItem = (
			addrAddr1 %prn_addr1 |
			addrAddr2 %prn_addr2 |
			addrWord %prn_word |
			addrString %prn_word
		) >start_word;

	address = ( 
			addrWS |
			addrComment |
			addrItem 
		)** >prn_tab;

	addrHeader = ( 
			'From' %prn_from | 
			'To' %prn_to
		) ':'
		address ( ',' @prn_nl address )*
		'\n' %prn_nl;

	subjectHeader = 
		'Subject:' @prn_subj @prn_tab
		' '* <:
		( 
			[^\n] @prn_char  | 
			( '\n' [ \t]+ ) %prn_space
		)**
		'\n' %prn_nl;

	header = consumeHeader | 
		addrHeader | subjectHeader;

	messageLine = 
		( [^\n]* '\n' - fromLine );

	main := (
			fromLine %prn_separator
			header* 
			'\n' @end_headers
			messageLine*
		)*;
 }%%
 
%% write data;

#define BUFSIZE 8192

void test( const char *buf )
{
	int cs, len = strlen( buf );
	const char *preserve = 0, *ws = 0;

	%% write init;
	const char *p = buf;
	const char *pe = p + len;
	%% write exec;

	if ( cs == mailbox_error )
		cerr << "ERROR" << endl;

	if ( cs < mailbox_first_final )
		cerr << "DID NOT FINISH IN A FINAL STATE" << endl;
}

int main()
{
	test(
		"From user@host.com Wed Nov 28 13:30:05 2001\n"
		"From: \"Adrian D. Thurston\" <thurston@complang.org>\n"
		"Subject:   the squirrel has landed\n"
		"\n"
		"Message goes here. \n"
		"From (trick from line).\n"
		"From: not really a header\n"
		"\n"
		"From user2@host2.com Wed Nov 28 13:30:05 2001\n"
		"To: Edgar Allen Poe <ep@net.com> (da man)\n"
		"Subject:   (no subject) \n"
		"\n"
		"Message goes here. \n"
		"\n"
	);
	return 0;
}

#ifdef _____OUTPUT_____
------
FROM
	"Adrian D. Thurston" | thurston@complang.org
SUBJECT
	the squirrel has landed
------
TO
	Edgar Allen Poe | ep@net.com
SUBJECT
	(no subject) 
#endif