blob: 6bf7c94285f467ae8e96f4e37c971acc7fe8d80b [file] [log] [blame]
/****************************************************************
* 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. *
****************************************************************/
options {
static=false;
JDK_VERSION = "1.5";
OUTPUT_DIRECTORY = "../../../../../../../../../target/generated-sources/javacc";
//DEBUG_PARSER = true;
//DEBUG_TOKEN_MANAGER = true;
}
PARSER_BEGIN(StructuredFieldParser)
/****************************************************************
* 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.structured.parser;
/**
* Parses generic structure fields.
* Unfolds and removes comments.
*/
public class StructuredFieldParser {
private boolean preserveFolding = false;
/**
* Should the \r\n folding sequence be preserved?
*/
public boolean isFoldingPreserved() {
return preserveFolding;
}
/**
* Sets whether the \r\n folding sequence should be preserved.
*/
public void setFoldingPreserved(boolean preserveFolding) {
this.preserveFolding = preserveFolding;
}
/**
* Unfolds the input and removes comments.
* @return unfolded header value with comments removed
*/
public String parse() throws ParseException {
try {
return doParse();
} catch (TokenMgrError e) {
// An issue with the TOKENiser
// but it's not polite to throw an Error
// when executing on a server
throw new ParseException(e);
}
}
}
PARSER_END(StructuredFieldParser)
private String doParse() :
{
Token t;
StringBuffer buffer = new StringBuffer(50);
boolean whitespace = false;
boolean first = true;
}
{
(
t = <CONTENT>
{
if (first) {
first = false;
} else if (whitespace) {
buffer.append(" ");
whitespace = false;
}
buffer.append(t.image);
}
|
t = <STRING_CONTENT>
{
buffer.append(t.image);
}
|
t = <QUOTEDSTRING>
{
if (first) {
first = false;
} else if (whitespace) {
buffer.append(" ");
whitespace = false;
}
buffer.append(t.image);
}
|
t = <FOLD>
{
if (preserveFolding) buffer.append("\r\n");
}
|
t = <WS>
{
whitespace = true;
}
)*
{return buffer.toString();}
}
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.
int commentNest;
}
SKIP :
{
// starts a comment
"(" : INCOMMENT
}
<INCOMMENT> SKIP :
{
// ends a comment
")" : DEFAULT
// if this is ever changed to not be a SKIP, need
// to make sure matchedToken.token = token.toString()
// is called.
}
<INCOMMENT> SKIP :
{
"(" { commentNest = 1; } : NESTED_COMMENT
}
<INCOMMENT> SKIP :
{
<~[ "(", ")" ]>
}
<NESTED_COMMENT> SKIP:
{
"(" { ++commentNest; System.out.println("+++ COMMENT NEST=" + commentNest);}
| ")" { --commentNest; System.out.println("+++ COMMENT NEST=" + commentNest); if (commentNest == 0) SwitchTo(INCOMMENT); }
}
<NESTED_COMMENT> SKIP :
{
< <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
}
<NESTED_COMMENT> SKIP:
{
<~[ "(", ")" ]>
}
// QUOTED STRINGS
SKIP :
{
"\"" : INQUOTEDSTRING
}
<INQUOTEDSTRING> MORE :
{
< <QUOTEDPAIR> > { image.deleteCharAt(image.length() - 2); }
}
<INQUOTEDSTRING> TOKEN :
{
< STRING_CONTENT : (~["\"", "\\", "\r"])+ >
// Preserve line break within quotes but not trailing white space
| < FOLD: "\r\n" ( [" ", "\t"] )* >
| < QUOTEDSTRING: "\"" > { matchedToken.image = image.substring(0, image.length() - 1); } : DEFAULT
}
<DEFAULT>
TOKEN :
{
< WS: ( [" ", "\t", "\r", "\n"] )+ >
}
<DEFAULT>
TOKEN :
{
< CONTENT: (~[" ", "\t", "\r", "\n", "(", "\""])+ >
}
<*>
TOKEN :
{
< #QUOTEDPAIR: "\\" <ANY> >
| < #ANY: (~[])+ >
}