1 ///
2 module imap.grammar;
3 
4 /++
5 	This code is not currently used or required.  An experiment with replacing custom parsing code by
6 	a PEG grammer.
7 +/
8 
9 version(SIL):
10 import pegged.grammar;
11 
12 
13 ///
14 public PT tee(PT)(PT p)
15 {
16 	import std.stdio;
17 	writeln("****");
18 	writeln(p);
19 	writeln("****");
20 	return p;
21 }
22 
23 
24 mixin(grammar(`
25 Imap:
26 	Expr			<-  ((whitespace)* Response)*
27 	whitespace		<-	[\r\n \t]
28 	dash			<-	"-"
29 	plus			<-	"+"
30 	colon			<-	":"
31 	comma			<-	","
32 	bang 			<-	"!"
33 	star			<-	"*"
34 	percent			<-	"%"
35 	LParens			<-	"("
36 	RParens			<-	")"
37 
38 	LowerCase		<-	[a-z]
39 	UpperCase		<-	[A-Z]
40 	Alpha			<-	[a-zA-Z]
41 	HexDigit		<-	[a-f0-9A-F]
42 	Digit			<-	[0-9]
43 	DigitNonZero	<-	[1-9]
44 	Digits			<~	[0-9]+
45 	Zero			<-	"0"
46 	Number			<-	Digits # unsigned 32 bit/check size
47 	NzNumber		<-	!Zero Digits
48 	Underscore		<-	"_"
49 	Base64Char		<-	[a-zA-Z0-9\+\/]
50 	Base64Terminal	<-	(Base64Char Base64Char "==") / (Base64Char Base64Char Base64Char "=")
51 	Base64			<~	Base64Char Base64Char Base64Char Base64Char Base64Terminal
52 	StrChar     	<~ backslash doublequote
53 	             		/ backslash backslash
54 	             		/ backslash [abfnrtv]
55 	             		/ (!doublequote .)
56 	CRLF			<-	"\r" "\n"
57 	TextChar		<-	!CRLF .
58 	Text			<-	Text+
59 	Char			<-	!"\0" .
60 	#literal			<-	"{" Number "}" CRLF Char*
61 	Literal			<-	Alpha*
62 	QuotedSpecial	<-	doublequote / backslash
63 	QuotedChar		<-	(!QuotedSpecial TextChar) / (backslash QuotedSpecial)
64 	Quoted			<~	doublequote QuotedChar* doublequote
65 	String			<-	Quoted / Literal
66 	CTL				<-	"\a" "\b"
67 	ListWildCard	<-	"%" / star
68 	RespSpecial		<- "]"
69 	AtomSpecial		<-	LParens / RParens / "{" / space / CTL / ListWildCard / QuotedSpecial / RespSpecial
70 	AtomChar		<-	!AtomSpecial Char
71 	Atom			<-	AtomChar+
72 	AstringChar		<-	AtomChar / RespSpecial
73 	Astring			<-	AstringChar+ / String
74 	Nil				<-	"NIL"
75 	Nstring			<-	Nil / String
76 	AddrName		<-	Nstring
77 	AddrAdl			<-	Nstring
78 	AddrMailbox		<-	Nstring
79 	AddrHost		<-	Nstring
80 	Address			<-	LParens AddrName space AddrAdl space AddrMailbox space AddrHost RParens
81 	Envelope		<-	"(" EnvDate space EnvSubject space EnvFrom space EnvSender space EnvReplyTo space EnvTo space EnvCC space EnvBCC space EnvInReplyTo space EnvMessageId ")"
82 	EnvBCC			<-	("(" Address+ ")") / Nil
83 	EnvCC			<-	( "(" Address+ ")" ) / Nil
84 	EnvDate			<-	Nstring
85 	EnvFrom			<-	( "(" Address+ ")" ) / Nil
86 	EnvInReplyTo	<-	Nstring
87 	EnvMessageId	<-	Nstring
88 	EnvReplyTo		<-	( "(" Address+ ")" ) / Nil
89 	EnvSender		<-	(LParens Address+ RParens ) / Nil
90 	EnvSubject		<- Nstring
91 	EnvTo			<-	(LParens Address+ RParens) / Nil
92 	Inbox			<-	"INBOX" / "inbox" # FIXME - should be completely case insensitive
93 	Mailbox			<-	Inbox / Astring
94 	FlagExtension	<-	backslash Atom
95 	FlagKeyword		<-	Atom
96 	Flag			<-	"\\Answered" / "\\Flagged" / "\\Deleted" / "\\Seen" / "\\Draft" / FlagKeyword / FlagExtension
97 	FlagList		<-	LParens Flag (space Flag)* RParens
98 	DateDay			<-	Digit Digit / Digit
99 	DateDayFixed	<-	Digit Digit / (space Digit)
100 	DateMonth		<-	"Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
101 	DateYear		<-	Digit Digit Digit Digit
102 	DateText		<-	DateDay dash DateMonth dash DateYear
103 	Time			<-	Digit Digit colon Digit Digit colon Digit Digit
104 	Zone			<-	( "+" / "-" ) Digit Digit Digit Digit
105 	Date			<-	DateText / (doublequote DateText doublequote)
106 	DateTime		<-	doublequote DateDayFixed dash DateMonth dash DateYear space Time space Zone doublequote
107 
108 	HeaderFldName	<-	Astring
109 	HeaderList		<-	"(" HeaderFldName (space HeaderFldName)* ")"
110 	ListMailbox		<-	AtomChar / ListWildCard / RespSpecial
111 	MailboxData		<-	"FLAGS" space FlagList / "LIST" space MailboxList / "LSUB" space MailboxList / "SEARCH" (space NzNumber)*  "STATUS" space Mailbox space "(" (StatusAttList)? ")" / Number space "EXISTS" / Number space "RECENT"
112 	MailboxList		<-	LParens (MbxListFlags)? RParens (space doublequote QuotedChar doublequote) / Nil space Mailbox
113 	MbxListFlags	<-	((MbxListOFlag space)* MbxListSFlag (MbxListOFlag)*) / (MbxListOFlag (space MbxListOFlag)*)
114 	MbxListOFlag	<-	backslash "Noinferiors" / FlagExtension
115 	MbxListSFlag	<-	backslash "Noselect" / backslash "Marked" / backslash "Unmarked"
116 	MessageData		<-	NzNumber space ("EXPUNGE" / ("FETCH" space MsgAtt))
117 	MsgAtt			<-	LParens (MsgAttDynamic / MsgAttStatic) (space MsgAttDynamic / MsgAttStatic)* RParens
118 	MsgAttDynamic	<-	"FLAGS" space (FlagFetch (space FlagFetch)*)? RParens
119 	MsgAttStatic	<-	"ENVELOPE" space Envelope /
120 						"INTERNALDATE" space DateTime /
121 						"RFC822" (".HEADER" / ".TEXT")? space Nstring /
122 						"RFC822.SIZE" space Number /
123 						"BODY" ("STRUCTURE")? space Body /
124 						"BODY" Section ("<" Number ">")? space Nstring /
125 						"UID" space UniqueId
126 	StatusAttList	<-	StatusAtt space Number (space StatusAtt space Number)*
127 	UserID			<-	Astring
128 	Password		<-	Astring
129 	Tag				<-	( !"+" AstringChar)+
130 	UniqueId		<-	NzNumber
131 	SearchKey		<-	"ALL" "ANSWERED" "BCC" space Astring / "BEFORE" space Date / "BODY" space Astring / "CC" space Astring / "DELETED" / "FLAGGED" / "FROM" space Astring / "KEYWORD" space FlagKeyword / "NEW" / "OLD" / "ON" space Date / "RECENT" / "SEEN" / "SINCE" space Date / "SUBJECT" space Astring / "TEXT" space  Astring / "TO" space Astring / "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / "UNKEYWORD" space FlagKeyword / "UNSEEN" / "DRAFT" / "HEADER" space HeaderFldName space Astring / "LARGER" space Number / "NOT" space SearchKey / "OR" space SearchKey / "SENTON" space Date / "SENTSINCE" space Date / "SMALLER" space Number / "UID" space SequenceSet / "UNDRAFT" / SequenceSet/ "(" SearchKey (space SearchKey)* ")"
132 	Section			<- "[" SectionSpec? "]"
133 	SectionMsgText	<-	"HEADER" / "HEADER.FIELDS" ".NOT"? space HeaderList / "TEXT"
134 	SectionPart		<-	NzNumber ("." NzNumber)*
135 	SectionSpec		<-	SectionMsgText / SectionPart / ("." SectionText)?
136 	SectionText		<-	SectionMsgText / "MIME"
137 	SeqNumber		<-	NzNumber / star
138 	SeqRange		<-	SeqNumber colon SeqNumber
139 	SequenceSet		<-	(SeqNumber / SeqRange) (comma SequenceSet)*
140 	FetchAtt		<-	"ENVELOPE" / "FLAGS" / "INTERNALDATE" / "RFC822" / (".HEADER" / ".SIZE" / ".TEXT")? / "BODY" ("STRUCTURE")? / "UID" / "BODY" Section ("<" Number "." NzNumber ">" )?
141 	StoreAttFlags	<-	("+" / "-") "FLAGS" (".SILENT")? space (FlagList / (Flag (space Flag)*))
142 	Uid				<-	"UID" space (Copy/Fetch/Search/Store)
143 
144 # Commands
145 	AuthType		<-	Atom
146 	Authenticate	<-	"AUTHENTICATE" space AuthType (CRLF Base64)*
147 	Capability		<-	("AUTH=" AuthType) / Atom
148 	CapabilityData	<-	"CAPABILITY" (space Capability)* space "IMAP4rev1" (space Capability)*
149 	Append			<-	"APPEND" space Mailbox (space FlagList)? (space DateTime) (space Literal)
150 	Copy			<-	"COPY" space SequenceSet space Mailbox
151 	Create			<-	"CREATE" space Mailbox
152 	Delete			<-	"DELETE" space Mailbox
153 	Examine			<-	"EXAMINE" space Mailbox
154 	FlagFetch		<-	Flag / "\\Recent"
155 	FlagPerm		<-	Flag / (backslash star)
156 	Fetch			<-	"FETCH" space SequenceSet space ("ALL" / "FULL" / "FAST" / FetchAtt / "(" FetchAtt (space FetchAtt)* ")" )
157 	List			<-	"LIST" space Mailbox space ListMailbox
158 	Login			<-	"LOGIN" space UserID Password
159 	Lsub			<-	"LSUB" space Mailbox space ListMailbox
160 	Rename			<-	"RENAME" space Mailbox space Mailbox
161 	Search			<-	"SEARCH" (space "CHARSET" space Astring)? (space SearchKey)+
162 	Select			<-	"SELECT" space Mailbox
163 	StatusAtt		<-	"MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / "UNSEEN"
164 	Status			<-	"STATUS" space Mailbox space LParens StatusAtt (space StatusAtt)* RParens
165 	Subscribe		<-	"SUBSCRIBE" space Mailbox
166 	Unsubscribe		<-	"UNSUBSCRIBE" space Mailbox
167 	XCommand		<-	"X" Atom Text #FIXME
168 
169 	Command			<-	Tag space (CommandAny / CommandAuth / CommandNonAuth / CommandSelect) CRLF
170 	CommandAuth		<-	Append / Create / Delete / Examine / List / Lsub / Rename/ Select / Status / Subscribe / Unsubscribe
171 	CommandNonAuth	<-	Login / Authenticate / "STARTTLS"
172 	CommandAny		<-	"CAPABILITY" / "LOGOUT" / "NOOP" / XCommand
173 	CommandSelect	<-	"CHECK" / "CLOSE" / "EXPUNGE" / Copy / Fetch / Store / Uid / Search
174 
175 # Response
176 	ContinueReq		<-	plus space (RespText / Base64) CRLF
177 	ResponseData	<-	star space (RespCondState / RespCondBye / MailboxData / MessageData / CapabilityData) CRLF
178 	ResponseTagged	<-	star space RespCondState CRLF
179 	ResponseFatal	<-	star RespCondBye CRLF
180 	RespCondAuth	<-	("OK" / "PREAUTH") space RespText
181 	RespCondBye		<-	"BYE" space RespText
182 	RespCondState	<-	( "OK" / "NO" / "BAD" ) / RespText
183 	RespText		<-	( "[" RespTextCode "]" space )? Text
184 	RespTextCode	<-	"ALERT" / 
185 						"BADCHARSET" (space LParens Astring (space Astring)* RParens )? /
186 						CapabilityData /
187 					   	"PARSE" /
188 						"PERMANENTFLAGS" space LParens (FlagPerm (space FlagPerm))* RParens /
189 						"READ-ONLY" /
190 						"READ-WRITE" /
191 						"TRYCREATE" /
192 						"UIDNEXT" space NzNumber /
193 						"UIDVALIDITY" space NzNumber /
194 						"UNSEEN" space NzNumber /
195 						Atom (space ( !"]" TextChar+)?)
196 	ResponseDone	<-	ResponseTagged / ResponseFatal
197 
198 	Response		<-	(ContinueReq / ResponseData)* ResponseDone
199 	Store			<-	"STORE" space SequenceSet space StoreAttFlags
200 
201 	BodyFields		<-	BodyFieldParam space BodyFieldID space BodyFieldDesc space BodyFieldEnc space BodyFieldOctets
202 	BodyFieldDesc	<-	Nstring
203 	BodyFieldDsp	<-	( "(" String space BodyFieldParam ")" ) / Nil
204 	BodyFieldEnc	<-	(doublequote ("7BIT"/"8BIT"/"BINARY"/"BASE64"/"QUOTED-PRINTABLE") doublequote) / String
205 	BodyFieldID		<-	Nstring
206 	BodyFieldLang	<-	Nstring / "(" String (space String)* ")"
207 	BodyFieldLoc	<-	Nstring
208 	BodyFieldLines	<-	Number
209 	BodyFieldMD5	<-	Nstring
210 	BodyFieldOctets	<-	Number
211 	BodyFieldParam	<-	("(" String space String (space String space String)* ")") / Nil
212 	BodyExtension	<-	Nstring / Number / ("(" BodyExtension (space BodyExtension)* ")" )
213 	BodyExtSinglePart <- BodyFieldMD5 (space BodyFieldDsp (space BodyFieldLang (space BodyFieldLoc (space BodyExtension)* )? )? )?
214 	BodyExtMultiPart <- BodyFieldParam (space BodyFieldDsp (space BodyFieldLang (space BodyFieldLoc (space BodyExtension)* )? )? )?
215 	BodyTypeSinglePart <- (BodyTypeBasic / BodyTypeMsg / BodyTypeText) (space BodyExtSinglePart)?
216 	BodyTypeBasic	<-	MediaBasic space BodyFields
217 	BodyTypeMultiPart <- Body+ space MediaSubType (space BodyExtMultiPart)?
218 	BodyTypeMsg		<-	MediaMessage space BodyFields space Envelope space Body space BodyFieldLines
219 	BodyTypeText	<-	MediaText space BodyFields space BodyFieldLines
220 	Body			<-	LParens (BodyTypeSinglePart / BodyTypeMultiPart) RParens
221 
222 	MediaBasic		<-	(( doublequote ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / "VIDEO") doublequote) / String) space MediaSubType
223 	MediaMessage	<-	doublequote "MESSAGE" doublequote space doublequote "RFC822" doublequote
224 	MediaSubType	<- String
225 	MediaText		<-	doublequote "TEXT" doublequote space MediaSubType
226 	Greeting		<-	star space (RespCondAuth / RespCondBye) CRLF
227 `));