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 (at) joecheng.com> 27 */ 28 29 options { 30 STATIC=false; 31 LOOKAHEAD=1; 32 //DEBUG_PARSER=true; 33 //DEBUG_TOKEN_MANAGER=true; 34 } 35 36 PARSER_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 */ 52 package org.apache.james.mime4j.field.address.parser; 53 54 public 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 94 PARSER_END(AddressListParser) 95 96 void parseLine() : 97 {} 98 { 99 address_list() ["\r"] "\n" 100 } 101 102 void parseAll() : 103 {} 104 { 105 address_list() <EOF> 106 } 107 108 void 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 146 void 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 183 void 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 220 void 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 254 void 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 294 void 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 328 void 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 362 void 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 */ 370 try { 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 384 void 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 418 void 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 445 void 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 474 SPECIAL_TOKEN : 475 { 476 < WS: ( [" ", "\t"] )+ > 477 } 478 479 TOKEN : 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 493 TOKEN_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 504 MORE : 505 { 506 // domain literal 507 "[" : INDOMAINLITERAL 508 } 509 510 <INDOMAINLITERAL> 511 MORE : 512 { 513 < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } 514 | < ~["[", "]", "\\"] > 515 } 516 517 <INDOMAINLITERAL> 518 TOKEN : 519 { 520 < DOMAINLITERAL: "]" > { matchedToken.image = image.toString(); }: DEFAULT 521 } 522 523 MORE : 524 { 525 // starts a comment 526 "(" : INCOMMENT 527 } 528 529 <INCOMMENT> 530 SKIP : 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> 540 MORE : 541 { 542 < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } 543 | "(" { commentNest = 1; } : NESTED_COMMENT 544 | < <ANY>> 545 } 546 547 <NESTED_COMMENT> 548 MORE : 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 559 MORE : 560 { 561 "\"" { image.deleteCharAt(image.length() - 1); } : INQUOTEDSTRING 562 } 563 564 <INQUOTEDSTRING> 565 MORE : 566 { 567 < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } 568 | < (~["\"", "\\"])+ > 569 } 570 571 <INQUOTEDSTRING> 572 TOKEN : 573 { 574 < QUOTEDSTRING: "\"" > { matchedToken.image = image.substring(0, image.length() - 1); } : DEFAULT 575 } 576 577 // GLOBALS 578 579 <*> 580 TOKEN : 581 { 582 < #QUOTEDPAIR: "\\" <ANY> > 583 | < #ANY: ~[] > 584 } 585 586 // ERROR! 587 /* 588 589 <*> 590 TOKEN : 591 { 592 < UNEXPECTED_CHAR: <ANY> > 593 } 594 595 */