| /**************************************************************** |
| * 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; |
| VISITOR=true; |
| MULTI=true; |
| NODE_SCOPE_HOOK=true; |
| NODE_EXTENDS="org.apache.jsieve.parser.address.AddressNode"; |
| OUTPUT_DIRECTORY="./org/apache/jsieve/parser/generated/address"; |
| //DEBUG_PARSER=true; |
| //DEBUG_TOKEN_MANAGER=true; |
| JDK_VERSION="1.5"; |
| } |
| |
| PARSER_BEGIN(AddressListParser) |
| /**************************************************************** |
| * 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. * |
| ****************************************************************/ |
| package org.apache.jsieve.parser.generated.address; |
| |
| public class AddressListParser { |
| |
| 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() #void : |
| {} |
| { |
| address_list() ["\r"] "\n" |
| } |
| |
| void parseAll() #void : |
| {} |
| { |
| address_list() <EOF> |
| } |
| |
| void address_list() : |
| {} |
| { |
| [ address() ] |
| ( |
| "," |
| [ address() ] |
| )* |
| } |
| |
| void address() : |
| {} |
| { |
| LOOKAHEAD(2147483647) |
| addr_spec() |
| | angle_addr() |
| | ( phrase() (group_body() | angle_addr()) ) |
| } |
| |
| void mailbox() : |
| {} |
| { |
| LOOKAHEAD(2147483647) |
| addr_spec() |
| | angle_addr() |
| | name_addr() |
| } |
| |
| void name_addr() : |
| {} |
| { |
| phrase() angle_addr() |
| } |
| |
| void group_body() : |
| {} |
| { |
| ":" |
| [ mailbox() ] |
| ( |
| "," |
| [ mailbox() ] |
| )* |
| ";" |
| } |
| |
| void angle_addr() : |
| {} |
| { |
| "<" [ route() ] addr_spec() ">" |
| } |
| |
| void route() : |
| {} |
| { |
| "@" domain() ( (",")* "@" domain() )* ":" |
| } |
| |
| void phrase() : |
| {} |
| { |
| ( <DOTATOM> |
| | <QUOTEDSTRING> |
| )+ |
| } |
| |
| void addr_spec() : |
| {} |
| { |
| ( local_part() "@" domain() ) |
| } |
| |
| void local_part() : |
| { Token t; } |
| { |
| ( t=<DOTATOM> | t=<QUOTEDSTRING> ) |
| ( [t="."] |
| { |
| if ( t.kind == AddressListParserConstants.QUOTEDSTRING || t.image.charAt(t.image.length() - 1) != '.') |
| throw new ParseException("Words in local part must be separated by '.'"); |
| } |
| ( t=<DOTATOM> | t=<QUOTEDSTRING> ) |
| )* |
| } |
| |
| void domain() : |
| { Token t; } |
| { |
| ( 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> |
| } |
| |
| 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> > |
| } |
| |
| */ |