Skip to content

Commit e895a45

Browse files
author
duchier
committed
primitive support for parsing documents in mail message format
git-svn-id: https://gforge.info.ucl.ac.be/svn/mozart@15936 ada56829-ad1f-0410-b00f-83cda6628aec
1 parent ced7afa commit e895a45

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

net/Message.oz

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
functor
2+
export
3+
'class' : Message
4+
import
5+
MessageParser at 'MessageParser.ozf'
6+
prepare
7+
ToLower = Char.toLower
8+
S2A = String.toAtom
9+
define
10+
class Message from MessageParser.'class'
11+
attr
12+
headers
13+
HeadersTail
14+
body
15+
16+
meth init(L eol:EOL<=[crlf lf])
17+
{self acceptCRLF({Member crlf EOL})}
18+
{self acceptLF( {Member lf EOL})}
19+
{self acceptCR( {Member cr EOL})}
20+
local L in
21+
headers <- L
22+
HeadersTail <- L
23+
body <- nil
24+
end
25+
{self parse(L)}
26+
end
27+
28+
meth messageHeader(Header Value) L in
29+
((
30+
{self messageHeaderTag(Header $)} #
31+
{self messageHeaderValue(Value $)}
32+
)
33+
|L) = (HeadersTail<-L)
34+
end
35+
36+
meth messageBody(L) body<-L end
37+
38+
meth messageEnd() @HeadersTail=nil end
39+
40+
meth messageHeaderTag(Header $)
41+
{S2A {Map Header ToLower}}
42+
end
43+
44+
meth messageHeaderValue(Value $)
45+
Value
46+
end
47+
end
48+
end

net/MessageParser.oz

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
functor
2+
export
3+
'class' : MessageParser
4+
prepare
5+
IsSpace = Char.isSpace
6+
7+
fun {DropInitialSpaces L}
8+
case L
9+
of H|T andthen (H==& orelse H==&\t) then
10+
{DropInitialSpaces T}
11+
else L end
12+
end
13+
14+
class MessageParser
15+
attr
16+
AcceptCRLF : false
17+
AcceptLF : false
18+
AcceptCR : false
19+
20+
meth acceptCRLF(B) AcceptCRLF<-B end
21+
meth acceptLF( B) AcceptLF <-B end
22+
meth acceptCR( B) AcceptCR <-B end
23+
24+
meth messageStart() skip end
25+
meth messageEnd() skip end
26+
meth messageHeader(Header Value) skip end
27+
meth messageBody() skip end
28+
29+
meth parse(L)
30+
{self messageStart}
31+
MessageParser,MaybeHeader(L)
32+
{self messageEnd}
33+
end
34+
35+
meth EOL(L $)
36+
case L
37+
of &\r|&\n|L andthen @AcceptCRLF then L
38+
[] &\r |L andthen @AcceptCR then L
39+
[] &\n|L andthen @AcceptLF then L
40+
else unit end
41+
end
42+
43+
meth MaybeHeader(L)
44+
if L==nil then skip
45+
elsecase MessageParser,EOL(L $)
46+
of unit then H in MessageParser,Header(L H H)
47+
[] L then {self messageBody(L)} end
48+
end
49+
50+
meth Header(L Head Tail)
51+
case L
52+
of H|T then
53+
if H==&: then V in
54+
Tail=nil
55+
MessageParser,AfterSemiColon(
56+
{DropInitialSpaces T}
57+
Head V V)
58+
elseif {IsSpace H} then
59+
Tail=nil
60+
MessageParser,AfterHeader(T Head)
61+
else Tail2 in
62+
Tail=(H|Tail2)
63+
MessageParser,Header(T Head Tail2)
64+
end
65+
else
66+
raise messageParser(unexpectedEndOfMessage) end
67+
end
68+
end
69+
70+
meth AfterHeader(L Header)
71+
case L
72+
of H|T then
73+
if H==&: then H in
74+
MessageParser,AfterSemiColon(
75+
{DropInitialSpaces T} Header H H)
76+
elseif {IsSpace H} then
77+
MessageParser,AfterHeader(T Header)
78+
else
79+
raise messageParser(expectedSpaceOrSemiColon:L) end
80+
end
81+
else
82+
raise messageParser(unexpectedEndOfMessage) end
83+
end
84+
end
85+
86+
meth AfterSemiColon(L Header Value Tail)
87+
case MessageParser,EOL(L $)
88+
of unit then
89+
case L
90+
of H|T then Tail2 in
91+
Tail=(H|Tail2)
92+
MessageParser,AfterSemiColon(T Header Value Tail2)
93+
else
94+
Tail=nil
95+
{self messageHeader(Header Value)}
96+
end
97+
[] L then
98+
case L
99+
of H|T andthen (H==& orelse H==&\t) then Tail2 in
100+
Tail=(H|Tail2)
101+
MessageParser,AfterSemiColon(T Header Value Tail2)
102+
else
103+
Tail=nil
104+
{self messageHeader(Header Value)}
105+
MessageParser,MaybeHeader(L)
106+
end
107+
end
108+
end
109+
end
110+
end

0 commit comments

Comments
 (0)