/**************************************************************** | |
* 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. * | |
****************************************************************/ | |
/** | |
* RFC2045 Content-Type parser. | |
* | |
* Created 10/2/2004 | |
* by Joe Cheng <code@joecheng.com> | |
*/ | |
options { | |
STATIC=false; | |
LOOKAHEAD=1; | |
JDK_VERSION = "1.5"; | |
OUTPUT_DIRECTORY = "../../../../../../../../../target/generated-sources/javacc"; | |
//DEBUG_PARSER=true; | |
//DEBUG_TOKEN_MANAGER=true; | |
} | |
PARSER_BEGIN(ContentTypeParser) | |
/**************************************************************** | |
* 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.james.mime4j.field.contenttype.parser; | |
import java.util.List; | |
import java.util.ArrayList; | |
public class ContentTypeParser { | |
private String type; | |
private String subtype; | |
private List<String> paramNames = new ArrayList<String>(); | |
private List<String> paramValues = new ArrayList<String>(); | |
public String getType() { return type; } | |
public String getSubType() { return subtype; } | |
public List<String> getParamNames() { return paramNames; } | |
public List<String> getParamValues() { return paramValues; } | |
public static void main(String args[]) throws ParseException { | |
while (true) { | |
try { | |
ContentTypeParser parser = new ContentTypeParser(System.in); | |
parser.parseLine(); | |
} catch (Exception x) { | |
x.printStackTrace(); | |
return; | |
} | |
} | |
} | |
} | |
PARSER_END(ContentTypeParser) | |
void parseLine() : | |
{} | |
{ | |
parse() ["\r"] "\n" | |
} | |
void parseAll() : | |
{} | |
{ | |
parse() <EOF> | |
} | |
void parse() : | |
{ | |
Token type; | |
Token subtype; | |
} | |
{ | |
type=<ATOKEN> "/" subtype=<ATOKEN> | |
{ | |
this.type = type.image; | |
this.subtype = subtype.image; | |
} | |
( ";" (parameter())? )* | |
} | |
void parameter() : | |
{ | |
Token attrib; | |
String val; | |
} | |
{ | |
attrib=<ATOKEN> "=" val=value() | |
{ | |
paramNames.add(attrib.image); | |
paramValues.add(val); | |
} | |
} | |
String value() : | |
{Token t;} | |
{ | |
( t=<ATOKEN> | |
| t=<DIGITS> | |
| t=<QUOTEDSTRING> | |
) | |
{ return t.image; } | |
} | |
SPECIAL_TOKEN : | |
{ | |
< WS: ( [" ", "\t"] )+ > | |
} | |
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 : | |
{ | |
// 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 | |
} | |
TOKEN : | |
{ | |
< DIGITS: ( ["0"-"9"] )+ > | |
} | |
TOKEN : | |
{ | |
< ATOKEN: ( ~[" ", "\t", "(", ")", "<", ">", "@", ",", ";", ":", "\\", "\"", "/", "[", "]", "?", "="] )+ > | |
} | |
// GLOBALS | |
<*> | |
TOKEN : | |
{ | |
< #QUOTEDPAIR: "\\" <ANY> > | |
| < #ANY: ~[] > | |
} |