1/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. /Users/jason/Projects/apache-mime4j-0.3/target/generated-sources/jjtree/org/apache/james/mime4j/field/address/parser/AddressListParser.jj */
2/*@egen*//****************************************************************
3 * Licensed to the Apache Software Foundation (ASF) under one   *
4 * or more contributor license agreements.  See the NOTICE file *
5 * distributed with this work for additional information        *
6 * regarding copyright ownership.  The ASF licenses this file   *
7 * to you under the Apache License, Version 2.0 (the            *
8 * "License"); you may not use this file except in compliance   *
9 * with the License.  You may obtain a copy of the License at   *
10 *                                                              *
11 *   http://www.apache.org/licenses/LICENSE-2.0                 *
12 *                                                              *
13 * Unless required by applicable law or agreed to in writing,   *
14 * software distributed under the License is distributed on an  *
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
16 * KIND, either express or implied.  See the License for the    *
17 * specific language governing permissions and limitations      *
18 * under the License.                                           *
19 ****************************************************************/
20
21
22/**
23 * RFC2822 address list parser.
24 *
25 * Created 9/17/2004
26 * by Joe Cheng <code@joecheng.com>
27 */
28
29options {
30	STATIC=false;
31	LOOKAHEAD=1;
32	//DEBUG_PARSER=true;
33	//DEBUG_TOKEN_MANAGER=true;
34}
35
36PARSER_BEGIN(AddressListParser)
37/*
38 *  Copyright 2004 the mime4j project
39 *
40 *  Licensed under the Apache License, Version 2.0 (the "License");
41 *  you may not use this file except in compliance with the License.
42 *  You may obtain a copy of the License at
43 *
44 *      http://www.apache.org/licenses/LICENSE-2.0
45 *
46 *  Unless required by applicable law or agreed to in writing, software
47 *  distributed under the License is distributed on an "AS IS" BASIS,
48 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
49 *  See the License for the specific language governing permissions and
50 *  limitations under the License.
51 */
52package org.apache.james.mime4j.field.address.parser;
53
54public class AddressListParser/*@bgen(jjtree)*/implements AddressListParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/
55  protected JJTAddressListParserState jjtree = new JJTAddressListParserState();
56
57/*@egen*/
58    public static void main(String args[]) throws ParseException {
59		while (true) {
60		    try {
61				AddressListParser parser = new AddressListParser(System.in);
62		    	parser.parseLine();
63		    	((SimpleNode)parser.jjtree.rootNode()).dump("> ");
64		    } catch (Exception x) {
65				x.printStackTrace();
66				return;
67		    }
68		}
69    }
70
71    private static void log(String msg) {
72    	System.out.print(msg);
73    }
74
75    public ASTaddress_list parse() throws ParseException {
76        try {
77    	    parseAll();
78    	    return (ASTaddress_list)jjtree.rootNode();
79    	} catch (TokenMgrError tme) {
80    	    throw new ParseException(tme.getMessage());
81    	}
82    }
83
84
85    void jjtreeOpenNodeScope(Node n) {
86    	((SimpleNode)n).firstToken = getToken(1);
87    }
88
89    void jjtreeCloseNodeScope(Node n) {
90    	((SimpleNode)n).lastToken = getToken(0);
91    }
92}
93
94PARSER_END(AddressListParser)
95
96void parseLine()       :
97{}
98{
99	address_list() ["\r"] "\n"
100}
101
102void parseAll()       :
103{}
104{
105	address_list() <EOF>
106}
107
108void address_list() :
109{/*@bgen(jjtree) address_list */
110  ASTaddress_list jjtn000 = new ASTaddress_list(JJTADDRESS_LIST);
111  boolean jjtc000 = true;
112  jjtree.openNodeScope(jjtn000);
113  jjtreeOpenNodeScope(jjtn000);
114/*@egen*/}
115{/*@bgen(jjtree) address_list */
116        try {
117/*@egen*/
118	[ address() ]
119	(
120		","
121		[ address() ]
122	)*/*@bgen(jjtree)*/
123        } catch (Throwable jjte000) {
124          if (jjtc000) {
125            jjtree.clearNodeScope(jjtn000);
126            jjtc000 = false;
127          } else {
128            jjtree.popNode();
129          }
130          if (jjte000 instanceof RuntimeException) {
131            throw (RuntimeException)jjte000;
132          }
133          if (jjte000 instanceof ParseException) {
134            throw (ParseException)jjte000;
135          }
136          throw (Error)jjte000;
137        } finally {
138          if (jjtc000) {
139            jjtree.closeNodeScope(jjtn000, true);
140            jjtreeCloseNodeScope(jjtn000);
141          }
142        }
143/*@egen*/
144}
145
146void address() :
147{/*@bgen(jjtree) address */
148  ASTaddress jjtn000 = new ASTaddress(JJTADDRESS);
149  boolean jjtc000 = true;
150  jjtree.openNodeScope(jjtn000);
151  jjtreeOpenNodeScope(jjtn000);
152/*@egen*/}
153{/*@bgen(jjtree) address */
154        try {
155/*@egen*/
156	LOOKAHEAD(2147483647)
157	addr_spec()
158|	angle_addr()
159|	( phrase() (group_body() | angle_addr()) )/*@bgen(jjtree)*/
160        } catch (Throwable jjte000) {
161          if (jjtc000) {
162            jjtree.clearNodeScope(jjtn000);
163            jjtc000 = false;
164          } else {
165            jjtree.popNode();
166          }
167          if (jjte000 instanceof RuntimeException) {
168            throw (RuntimeException)jjte000;
169          }
170          if (jjte000 instanceof ParseException) {
171            throw (ParseException)jjte000;
172          }
173          throw (Error)jjte000;
174        } finally {
175          if (jjtc000) {
176            jjtree.closeNodeScope(jjtn000, true);
177            jjtreeCloseNodeScope(jjtn000);
178          }
179        }
180/*@egen*/
181}
182
183void mailbox() :
184{/*@bgen(jjtree) mailbox */
185  ASTmailbox jjtn000 = new ASTmailbox(JJTMAILBOX);
186  boolean jjtc000 = true;
187  jjtree.openNodeScope(jjtn000);
188  jjtreeOpenNodeScope(jjtn000);
189/*@egen*/}
190{/*@bgen(jjtree) mailbox */
191        try {
192/*@egen*/
193	LOOKAHEAD(2147483647)
194	addr_spec()
195|	angle_addr()
196|	name_addr()/*@bgen(jjtree)*/
197        } catch (Throwable jjte000) {
198          if (jjtc000) {
199            jjtree.clearNodeScope(jjtn000);
200            jjtc000 = false;
201          } else {
202            jjtree.popNode();
203          }
204          if (jjte000 instanceof RuntimeException) {
205            throw (RuntimeException)jjte000;
206          }
207          if (jjte000 instanceof ParseException) {
208            throw (ParseException)jjte000;
209          }
210          throw (Error)jjte000;
211        } finally {
212          if (jjtc000) {
213            jjtree.closeNodeScope(jjtn000, true);
214            jjtreeCloseNodeScope(jjtn000);
215          }
216        }
217/*@egen*/
218}
219
220void name_addr() :
221{/*@bgen(jjtree) name_addr */
222  ASTname_addr jjtn000 = new ASTname_addr(JJTNAME_ADDR);
223  boolean jjtc000 = true;
224  jjtree.openNodeScope(jjtn000);
225  jjtreeOpenNodeScope(jjtn000);
226/*@egen*/}
227{/*@bgen(jjtree) name_addr */
228        try {
229/*@egen*/
230	phrase() angle_addr()/*@bgen(jjtree)*/
231        } catch (Throwable jjte000) {
232          if (jjtc000) {
233            jjtree.clearNodeScope(jjtn000);
234            jjtc000 = false;
235          } else {
236            jjtree.popNode();
237          }
238          if (jjte000 instanceof RuntimeException) {
239            throw (RuntimeException)jjte000;
240          }
241          if (jjte000 instanceof ParseException) {
242            throw (ParseException)jjte000;
243          }
244          throw (Error)jjte000;
245        } finally {
246          if (jjtc000) {
247            jjtree.closeNodeScope(jjtn000, true);
248            jjtreeCloseNodeScope(jjtn000);
249          }
250        }
251/*@egen*/
252}
253
254void group_body() :
255{/*@bgen(jjtree) group_body */
256  ASTgroup_body jjtn000 = new ASTgroup_body(JJTGROUP_BODY);
257  boolean jjtc000 = true;
258  jjtree.openNodeScope(jjtn000);
259  jjtreeOpenNodeScope(jjtn000);
260/*@egen*/}
261{/*@bgen(jjtree) group_body */
262        try {
263/*@egen*/
264	":"
265	[ mailbox() ]
266	(
267		","
268		[ mailbox() ]
269	)*
270	";"/*@bgen(jjtree)*/
271        } catch (Throwable jjte000) {
272          if (jjtc000) {
273            jjtree.clearNodeScope(jjtn000);
274            jjtc000 = false;
275          } else {
276            jjtree.popNode();
277          }
278          if (jjte000 instanceof RuntimeException) {
279            throw (RuntimeException)jjte000;
280          }
281          if (jjte000 instanceof ParseException) {
282            throw (ParseException)jjte000;
283          }
284          throw (Error)jjte000;
285        } finally {
286          if (jjtc000) {
287            jjtree.closeNodeScope(jjtn000, true);
288            jjtreeCloseNodeScope(jjtn000);
289          }
290        }
291/*@egen*/
292}
293
294void angle_addr() :
295{/*@bgen(jjtree) angle_addr */
296  ASTangle_addr jjtn000 = new ASTangle_addr(JJTANGLE_ADDR);
297  boolean jjtc000 = true;
298  jjtree.openNodeScope(jjtn000);
299  jjtreeOpenNodeScope(jjtn000);
300/*@egen*/}
301{/*@bgen(jjtree) angle_addr */
302        try {
303/*@egen*/
304	"<" [ route() ] addr_spec() ">"/*@bgen(jjtree)*/
305        } catch (Throwable jjte000) {
306          if (jjtc000) {
307            jjtree.clearNodeScope(jjtn000);
308            jjtc000 = false;
309          } else {
310            jjtree.popNode();
311          }
312          if (jjte000 instanceof RuntimeException) {
313            throw (RuntimeException)jjte000;
314          }
315          if (jjte000 instanceof ParseException) {
316            throw (ParseException)jjte000;
317          }
318          throw (Error)jjte000;
319        } finally {
320          if (jjtc000) {
321            jjtree.closeNodeScope(jjtn000, true);
322            jjtreeCloseNodeScope(jjtn000);
323          }
324        }
325/*@egen*/
326}
327
328void route() :
329{/*@bgen(jjtree) route */
330  ASTroute jjtn000 = new ASTroute(JJTROUTE);
331  boolean jjtc000 = true;
332  jjtree.openNodeScope(jjtn000);
333  jjtreeOpenNodeScope(jjtn000);
334/*@egen*/}
335{/*@bgen(jjtree) route */
336        try {
337/*@egen*/
338	"@" domain() ( (",")* "@" domain() )* ":"/*@bgen(jjtree)*/
339        } catch (Throwable jjte000) {
340          if (jjtc000) {
341            jjtree.clearNodeScope(jjtn000);
342            jjtc000 = false;
343          } else {
344            jjtree.popNode();
345          }
346          if (jjte000 instanceof RuntimeException) {
347            throw (RuntimeException)jjte000;
348          }
349          if (jjte000 instanceof ParseException) {
350            throw (ParseException)jjte000;
351          }
352          throw (Error)jjte000;
353        } finally {
354          if (jjtc000) {
355            jjtree.closeNodeScope(jjtn000, true);
356            jjtreeCloseNodeScope(jjtn000);
357          }
358        }
359/*@egen*/
360}
361
362void phrase() :
363{/*@bgen(jjtree) phrase */
364  ASTphrase jjtn000 = new ASTphrase(JJTPHRASE);
365  boolean jjtc000 = true;
366  jjtree.openNodeScope(jjtn000);
367  jjtreeOpenNodeScope(jjtn000);
368/*@egen*/}
369{/*@bgen(jjtree) phrase */
370try {
371/*@egen*/
372(	<DOTATOM>
373|	<QUOTEDSTRING>
374)+/*@bgen(jjtree)*/
375} finally {
376  if (jjtc000) {
377    jjtree.closeNodeScope(jjtn000, true);
378    jjtreeCloseNodeScope(jjtn000);
379  }
380}
381/*@egen*/
382}
383
384void addr_spec() :
385{/*@bgen(jjtree) addr_spec */
386  ASTaddr_spec jjtn000 = new ASTaddr_spec(JJTADDR_SPEC);
387  boolean jjtc000 = true;
388  jjtree.openNodeScope(jjtn000);
389  jjtreeOpenNodeScope(jjtn000);
390/*@egen*/}
391{/*@bgen(jjtree) addr_spec */
392        try {
393/*@egen*/
394	( local_part() "@" domain() )/*@bgen(jjtree)*/
395        } catch (Throwable jjte000) {
396          if (jjtc000) {
397            jjtree.clearNodeScope(jjtn000);
398            jjtc000 = false;
399          } else {
400            jjtree.popNode();
401          }
402          if (jjte000 instanceof RuntimeException) {
403            throw (RuntimeException)jjte000;
404          }
405          if (jjte000 instanceof ParseException) {
406            throw (ParseException)jjte000;
407          }
408          throw (Error)jjte000;
409        } finally {
410          if (jjtc000) {
411            jjtree.closeNodeScope(jjtn000, true);
412            jjtreeCloseNodeScope(jjtn000);
413          }
414        }
415/*@egen*/
416}
417
418void local_part() :
419{/*@bgen(jjtree) local_part */
420  ASTlocal_part jjtn000 = new ASTlocal_part(JJTLOCAL_PART);
421  boolean jjtc000 = true;
422  jjtree.openNodeScope(jjtn000);
423  jjtreeOpenNodeScope(jjtn000);
424/*@egen*/ Token t; }
425{/*@bgen(jjtree) local_part */
426        try {
427/*@egen*/
428	( t=<DOTATOM> | t=<QUOTEDSTRING> )
429	(	[t="."]
430		{
431			if (t.image.charAt(t.image.length() - 1) != '.' || t.kind == AddressListParserConstants.QUOTEDSTRING)
432				throw new ParseException("Words in local part must be separated by '.'");
433		}
434		(	t=<DOTATOM> | t=<QUOTEDSTRING> )
435	)*/*@bgen(jjtree)*/
436        } finally {
437          if (jjtc000) {
438            jjtree.closeNodeScope(jjtn000, true);
439            jjtreeCloseNodeScope(jjtn000);
440          }
441        }
442/*@egen*/
443}
444
445void domain() :
446{/*@bgen(jjtree) domain */
447  ASTdomain jjtn000 = new ASTdomain(JJTDOMAIN);
448  boolean jjtc000 = true;
449  jjtree.openNodeScope(jjtn000);
450  jjtreeOpenNodeScope(jjtn000);
451/*@egen*/ Token t; }
452{/*@bgen(jjtree) domain */
453        try {
454/*@egen*/
455	(	t=<DOTATOM>
456		(	[t="."]
457			{
458				if (t.image.charAt(t.image.length() - 1) != '.')
459					throw new ParseException("Atoms in domain names must be separated by '.'");
460			}
461			t=<DOTATOM>
462		)*
463	)
464|	<DOMAINLITERAL>/*@bgen(jjtree)*/
465        } finally {
466          if (jjtc000) {
467            jjtree.closeNodeScope(jjtn000, true);
468            jjtreeCloseNodeScope(jjtn000);
469          }
470        }
471/*@egen*/
472}
473
474SPECIAL_TOKEN :
475{
476 	< WS: ( [" ", "\t"] )+ >
477}
478
479TOKEN :
480{
481	< #ALPHA: ["a" - "z", "A" - "Z"] >
482|	< #DIGIT: ["0" - "9"] >
483|	< #ATEXT: ( <ALPHA> | <DIGIT>
484			  | "!" | "#" | "$" | "%"
485			  | "&" | "'" | "*" | "+"
486			  | "-" | "/" | "=" | "?"
487			  | "^" | "_" | "`" | "{"
488			  | "|" | "}" | "~"
489			  )>
490|	< DOTATOM: <ATEXT> ( <ATEXT> | "." )* >
491}
492
493TOKEN_MGR_DECLS :
494{
495	// Keeps track of how many levels of comment nesting
496	// we've encountered.  This is only used when the 2nd
497	// level is reached, for example ((this)), not (this).
498	// This is because the outermost level must be treated
499	// specially anyway, because the outermost ")" has a
500	// different token type than inner ")" instances.
501	static int commentNest;
502}
503
504MORE :
505{
506	// domain literal
507	"[" : INDOMAINLITERAL
508}
509
510<INDOMAINLITERAL>
511MORE :
512{
513	< <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
514|	< ~["[", "]", "\\"] >
515}
516
517<INDOMAINLITERAL>
518TOKEN :
519{
520	< DOMAINLITERAL: "]" > { matchedToken.image = image.toString(); }: DEFAULT
521}
522
523MORE :
524{
525	// starts a comment
526	"(" : INCOMMENT
527}
528
529<INCOMMENT>
530SKIP :
531{
532	// ends a comment
533	< COMMENT: ")" > : DEFAULT
534	// if this is ever changed to not be a SKIP, need
535	// to make sure matchedToken.token = token.toString()
536	// is called.
537}
538
539<INCOMMENT>
540MORE :
541{
542	< <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
543|	"(" { commentNest = 1; } : NESTED_COMMENT
544|	< <ANY>>
545}
546
547<NESTED_COMMENT>
548MORE :
549{
550	< <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
551|	"(" { ++commentNest; }
552|	")" { --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); }
553|	< <ANY>>
554}
555
556
557// QUOTED STRINGS
558
559MORE :
560{
561	"\"" { image.deleteCharAt(image.length() - 1); } : INQUOTEDSTRING
562}
563
564<INQUOTEDSTRING>
565MORE :
566{
567	< <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
568|	< (~["\"", "\\"])+ >
569}
570
571<INQUOTEDSTRING>
572TOKEN :
573{
574	< QUOTEDSTRING: "\"" > { matchedToken.image = image.substring(0, image.length() - 1); } : DEFAULT
575}
576
577// GLOBALS
578
579<*>
580TOKEN :
581{
582	< #QUOTEDPAIR: "\\" <ANY> >
583|	< #ANY: ~[] >
584}
585
586// ERROR!
587/*
588
589<*>
590TOKEN :
591{
592	< UNEXPECTED_CHAR: <ANY> >
593}
594
595*/