| /*@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 */ |
| /*@egen*//**************************************************************** |
| * Licensed to the Apache Software Foundation (ASF) under one * |
| * or more contributor license agreements. See the NOTICE file * |
| * distributed with this work for additional information * |
| * regarding copyright ownership. The ASF licenses this file * |
| * to you under the Apache License, Version 2.0 (the * |
| * "License"); you may not use this file except in compliance * |
| * with the License. You may obtain a copy of the License at * |
| * * |
| * http://www.apache.org/licenses/LICENSE-2.0 * |
| * * |
| * Unless required by applicable law or agreed to in writing, * |
| * software distributed under the License is distributed on an * |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * |
| * KIND, either express or implied. See the License for the * |
| * specific language governing permissions and limitations * |
| * under the License. * |
| ****************************************************************/ |
| |
| |
| /** |
| * RFC2822 address list parser. |
| * |
| * Created 9/17/2004 |
| * by Joe Cheng <code@joecheng.com> |
| */ |
| |
| options { |
| STATIC=false; |
| LOOKAHEAD=1; |
| //DEBUG_PARSER=true; |
| //DEBUG_TOKEN_MANAGER=true; |
| } |
| |
| PARSER_BEGIN(AddressListParser) |
| /* |
| * Copyright 2004 the mime4j project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.james.mime4j.field.address.parser; |
| |
| public class AddressListParser/*@bgen(jjtree)*/implements AddressListParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/ |
| protected JJTAddressListParserState jjtree = new JJTAddressListParserState(); |
| |
| /*@egen*/ |
| public static void main(String args[]) throws ParseException { |
| while (true) { |
| try { |
| AddressListParser parser = new AddressListParser(System.in); |
| parser.parseLine(); |
| ((SimpleNode)parser.jjtree.rootNode()).dump("> "); |
| } catch (Exception x) { |
| x.printStackTrace(); |
| return; |
| } |
| } |
| } |
| |
| private static void log(String msg) { |
| System.out.print(msg); |
| } |
| |
| public ASTaddress_list parse() throws ParseException { |
| try { |
| parseAll(); |
| return (ASTaddress_list)jjtree.rootNode(); |
| } catch (TokenMgrError tme) { |
| throw new ParseException(tme.getMessage()); |
| } |
| } |
| |
| |
| void jjtreeOpenNodeScope(Node n) { |
| ((SimpleNode)n).firstToken = getToken(1); |
| } |
| |
| void jjtreeCloseNodeScope(Node n) { |
| ((SimpleNode)n).lastToken = getToken(0); |
| } |
| } |
| |
| PARSER_END(AddressListParser) |
| |
| void parseLine() : |
| {} |
| { |
| address_list() ["\r"] "\n" |
| } |
| |
| void parseAll() : |
| {} |
| { |
| address_list() <EOF> |
| } |
| |
| void address_list() : |
| {/*@bgen(jjtree) address_list */ |
| ASTaddress_list jjtn000 = new ASTaddress_list(JJTADDRESS_LIST); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) address_list */ |
| try { |
| /*@egen*/ |
| [ address() ] |
| ( |
| "," |
| [ address() ] |
| )*/*@bgen(jjtree)*/ |
| } catch (Throwable jjte000) { |
| if (jjtc000) { |
| jjtree.clearNodeScope(jjtn000); |
| jjtc000 = false; |
| } else { |
| jjtree.popNode(); |
| } |
| if (jjte000 instanceof RuntimeException) { |
| throw (RuntimeException)jjte000; |
| } |
| if (jjte000 instanceof ParseException) { |
| throw (ParseException)jjte000; |
| } |
| throw (Error)jjte000; |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void address() : |
| {/*@bgen(jjtree) address */ |
| ASTaddress jjtn000 = new ASTaddress(JJTADDRESS); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) address */ |
| try { |
| /*@egen*/ |
| LOOKAHEAD(2147483647) |
| addr_spec() |
| | angle_addr() |
| | ( phrase() (group_body() | angle_addr()) )/*@bgen(jjtree)*/ |
| } catch (Throwable jjte000) { |
| if (jjtc000) { |
| jjtree.clearNodeScope(jjtn000); |
| jjtc000 = false; |
| } else { |
| jjtree.popNode(); |
| } |
| if (jjte000 instanceof RuntimeException) { |
| throw (RuntimeException)jjte000; |
| } |
| if (jjte000 instanceof ParseException) { |
| throw (ParseException)jjte000; |
| } |
| throw (Error)jjte000; |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void mailbox() : |
| {/*@bgen(jjtree) mailbox */ |
| ASTmailbox jjtn000 = new ASTmailbox(JJTMAILBOX); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) mailbox */ |
| try { |
| /*@egen*/ |
| LOOKAHEAD(2147483647) |
| addr_spec() |
| | angle_addr() |
| | name_addr()/*@bgen(jjtree)*/ |
| } catch (Throwable jjte000) { |
| if (jjtc000) { |
| jjtree.clearNodeScope(jjtn000); |
| jjtc000 = false; |
| } else { |
| jjtree.popNode(); |
| } |
| if (jjte000 instanceof RuntimeException) { |
| throw (RuntimeException)jjte000; |
| } |
| if (jjte000 instanceof ParseException) { |
| throw (ParseException)jjte000; |
| } |
| throw (Error)jjte000; |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void name_addr() : |
| {/*@bgen(jjtree) name_addr */ |
| ASTname_addr jjtn000 = new ASTname_addr(JJTNAME_ADDR); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) name_addr */ |
| try { |
| /*@egen*/ |
| phrase() angle_addr()/*@bgen(jjtree)*/ |
| } catch (Throwable jjte000) { |
| if (jjtc000) { |
| jjtree.clearNodeScope(jjtn000); |
| jjtc000 = false; |
| } else { |
| jjtree.popNode(); |
| } |
| if (jjte000 instanceof RuntimeException) { |
| throw (RuntimeException)jjte000; |
| } |
| if (jjte000 instanceof ParseException) { |
| throw (ParseException)jjte000; |
| } |
| throw (Error)jjte000; |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void group_body() : |
| {/*@bgen(jjtree) group_body */ |
| ASTgroup_body jjtn000 = new ASTgroup_body(JJTGROUP_BODY); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) group_body */ |
| try { |
| /*@egen*/ |
| ":" |
| [ mailbox() ] |
| ( |
| "," |
| [ mailbox() ] |
| )* |
| ";"/*@bgen(jjtree)*/ |
| } catch (Throwable jjte000) { |
| if (jjtc000) { |
| jjtree.clearNodeScope(jjtn000); |
| jjtc000 = false; |
| } else { |
| jjtree.popNode(); |
| } |
| if (jjte000 instanceof RuntimeException) { |
| throw (RuntimeException)jjte000; |
| } |
| if (jjte000 instanceof ParseException) { |
| throw (ParseException)jjte000; |
| } |
| throw (Error)jjte000; |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void angle_addr() : |
| {/*@bgen(jjtree) angle_addr */ |
| ASTangle_addr jjtn000 = new ASTangle_addr(JJTANGLE_ADDR); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) angle_addr */ |
| try { |
| /*@egen*/ |
| "<" [ route() ] addr_spec() ">"/*@bgen(jjtree)*/ |
| } catch (Throwable jjte000) { |
| if (jjtc000) { |
| jjtree.clearNodeScope(jjtn000); |
| jjtc000 = false; |
| } else { |
| jjtree.popNode(); |
| } |
| if (jjte000 instanceof RuntimeException) { |
| throw (RuntimeException)jjte000; |
| } |
| if (jjte000 instanceof ParseException) { |
| throw (ParseException)jjte000; |
| } |
| throw (Error)jjte000; |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void route() : |
| {/*@bgen(jjtree) route */ |
| ASTroute jjtn000 = new ASTroute(JJTROUTE); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) route */ |
| try { |
| /*@egen*/ |
| "@" domain() ( (",")* "@" domain() )* ":"/*@bgen(jjtree)*/ |
| } catch (Throwable jjte000) { |
| if (jjtc000) { |
| jjtree.clearNodeScope(jjtn000); |
| jjtc000 = false; |
| } else { |
| jjtree.popNode(); |
| } |
| if (jjte000 instanceof RuntimeException) { |
| throw (RuntimeException)jjte000; |
| } |
| if (jjte000 instanceof ParseException) { |
| throw (ParseException)jjte000; |
| } |
| throw (Error)jjte000; |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void phrase() : |
| {/*@bgen(jjtree) phrase */ |
| ASTphrase jjtn000 = new ASTphrase(JJTPHRASE); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) phrase */ |
| try { |
| /*@egen*/ |
| ( <DOTATOM> |
| | <QUOTEDSTRING> |
| )+/*@bgen(jjtree)*/ |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void addr_spec() : |
| {/*@bgen(jjtree) addr_spec */ |
| ASTaddr_spec jjtn000 = new ASTaddr_spec(JJTADDR_SPEC); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/} |
| {/*@bgen(jjtree) addr_spec */ |
| try { |
| /*@egen*/ |
| ( local_part() "@" domain() )/*@bgen(jjtree)*/ |
| } catch (Throwable jjte000) { |
| if (jjtc000) { |
| jjtree.clearNodeScope(jjtn000); |
| jjtc000 = false; |
| } else { |
| jjtree.popNode(); |
| } |
| if (jjte000 instanceof RuntimeException) { |
| throw (RuntimeException)jjte000; |
| } |
| if (jjte000 instanceof ParseException) { |
| throw (ParseException)jjte000; |
| } |
| throw (Error)jjte000; |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void local_part() : |
| {/*@bgen(jjtree) local_part */ |
| ASTlocal_part jjtn000 = new ASTlocal_part(JJTLOCAL_PART); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/ Token t; } |
| {/*@bgen(jjtree) local_part */ |
| try { |
| /*@egen*/ |
| ( t=<DOTATOM> | t=<QUOTEDSTRING> ) |
| ( [t="."] |
| { |
| if (t.image.charAt(t.image.length() - 1) != '.' || t.kind == AddressListParserConstants.QUOTEDSTRING) |
| throw new ParseException("Words in local part must be separated by '.'"); |
| } |
| ( t=<DOTATOM> | t=<QUOTEDSTRING> ) |
| )*/*@bgen(jjtree)*/ |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| void domain() : |
| {/*@bgen(jjtree) domain */ |
| ASTdomain jjtn000 = new ASTdomain(JJTDOMAIN); |
| boolean jjtc000 = true; |
| jjtree.openNodeScope(jjtn000); |
| jjtreeOpenNodeScope(jjtn000); |
| /*@egen*/ Token t; } |
| {/*@bgen(jjtree) domain */ |
| try { |
| /*@egen*/ |
| ( t=<DOTATOM> |
| ( [t="."] |
| { |
| if (t.image.charAt(t.image.length() - 1) != '.') |
| throw new ParseException("Atoms in domain names must be separated by '.'"); |
| } |
| t=<DOTATOM> |
| )* |
| ) |
| | <DOMAINLITERAL>/*@bgen(jjtree)*/ |
| } finally { |
| if (jjtc000) { |
| jjtree.closeNodeScope(jjtn000, true); |
| jjtreeCloseNodeScope(jjtn000); |
| } |
| } |
| /*@egen*/ |
| } |
| |
| SPECIAL_TOKEN : |
| { |
| < WS: ( [" ", "\t"] )+ > |
| } |
| |
| TOKEN : |
| { |
| < #ALPHA: ["a" - "z", "A" - "Z"] > |
| | < #DIGIT: ["0" - "9"] > |
| | < #ATEXT: ( <ALPHA> | <DIGIT> |
| | "!" | "#" | "$" | "%" |
| | "&" | "'" | "*" | "+" |
| | "-" | "/" | "=" | "?" |
| | "^" | "_" | "`" | "{" |
| | "|" | "}" | "~" |
| )> |
| | < DOTATOM: <ATEXT> ( <ATEXT> | "." )* > |
| } |
| |
| TOKEN_MGR_DECLS : |
| { |
| // Keeps track of how many levels of comment nesting |
| // we've encountered. This is only used when the 2nd |
| // level is reached, for example ((this)), not (this). |
| // This is because the outermost level must be treated |
| // specially anyway, because the outermost ")" has a |
| // different token type than inner ")" instances. |
| static int commentNest; |
| } |
| |
| MORE : |
| { |
| // domain literal |
| "[" : INDOMAINLITERAL |
| } |
| |
| <INDOMAINLITERAL> |
| MORE : |
| { |
| < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } |
| | < ~["[", "]", "\\"] > |
| } |
| |
| <INDOMAINLITERAL> |
| TOKEN : |
| { |
| < DOMAINLITERAL: "]" > { matchedToken.image = image.toString(); }: DEFAULT |
| } |
| |
| MORE : |
| { |
| // starts a comment |
| "(" : INCOMMENT |
| } |
| |
| <INCOMMENT> |
| SKIP : |
| { |
| // ends a comment |
| < COMMENT: ")" > : DEFAULT |
| // if this is ever changed to not be a SKIP, need |
| // to make sure matchedToken.token = token.toString() |
| // is called. |
| } |
| |
| <INCOMMENT> |
| MORE : |
| { |
| < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } |
| | "(" { commentNest = 1; } : NESTED_COMMENT |
| | < <ANY>> |
| } |
| |
| <NESTED_COMMENT> |
| MORE : |
| { |
| < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } |
| | "(" { ++commentNest; } |
| | ")" { --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); } |
| | < <ANY>> |
| } |
| |
| |
| // QUOTED STRINGS |
| |
| MORE : |
| { |
| "\"" { image.deleteCharAt(image.length() - 1); } : INQUOTEDSTRING |
| } |
| |
| <INQUOTEDSTRING> |
| MORE : |
| { |
| < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } |
| | < (~["\"", "\\"])+ > |
| } |
| |
| <INQUOTEDSTRING> |
| TOKEN : |
| { |
| < QUOTEDSTRING: "\"" > { matchedToken.image = image.substring(0, image.length() - 1); } : DEFAULT |
| } |
| |
| // GLOBALS |
| |
| <*> |
| TOKEN : |
| { |
| < #QUOTEDPAIR: "\\" <ANY> > |
| | < #ANY: ~[] > |
| } |
| |
| // ERROR! |
| /* |
| |
| <*> |
| TOKEN : |
| { |
| < UNEXPECTED_CHAR: <ANY> > |
| } |
| |
| */ |