blob: 68d243730b4d751eb22a1898c9389d36a2feb530 [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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.
*/
options{
LOOKAHEAD = 1;
CHOICE_AMBIGUITY_CHECK = 2;
OTHER_AMBIGUITY_CHECK = 1;
STATIC = false;
DEBUG_PARSER = false;
DEBUG_LOOKAHEAD = false;
DEBUG_TOKEN_MANAGER = false;
OPTIMIZE_TOKEN_MANAGER = true;
ERROR_REPORTING = true;
JAVA_UNICODE_ESCAPE = true;
UNICODE_INPUT = true;
IGNORE_CASE = false;
COMMON_TOKEN_ACTION = false;
USER_TOKEN_MANAGER = false;
USER_CHAR_STREAM = false;
BUILD_PARSER = true;
BUILD_TOKEN_MANAGER = true;
SANITY_CHECK = true;
FORCE_LA_CHECK = false;
CACHE_TOKENS = false;
}
PARSER_BEGIN(Parser)
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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.garbage.parser;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.Iterator;
import org.apache.garbage.tree.Attribute;
import org.apache.garbage.tree.CData;
import org.apache.garbage.tree.Characters;
import org.apache.garbage.tree.Comment;
import org.apache.garbage.tree.DocType;
import org.apache.garbage.tree.ElementEnd;
import org.apache.garbage.tree.ElementStart;
import org.apache.garbage.tree.Events;
import org.apache.garbage.tree.Expression;
import org.apache.garbage.tree.ProcessingInstruction;
import org.apache.garbage.tree.TemplateFor;
import org.apache.garbage.tree.TemplateIf;
import org.apache.garbage.tree.TemplateVar;
import org.apache.garbage.tree.Tree;
import org.apache.garbage.tree.TreeException;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* The <a href="http://www.experimentalstuff.com/Technologies/JavaCC">JavaCC</a>
* generated parser for <b>Garbage</b> templates.
* <p>
* This class is automatically generated, so, it might be non-obvious to determine
* how to use it. To create a new parser and parse a document, do the following:
* </p>
* <p>
* <code>InputSource source = new InputSource(...);</code><br />
* <code>Parser parser = new Parser();</code><br />
* <code>Events events = parser.parse(source);</code><br />
* </p>
* <p>
* Note that instances of this class are <b>NOT THREAD SAFE</b>, meaning that two
* threads cannot concurrently parse two documents using the same instance, but
* at the same time, one thread can safely call the <code>parse(...)</code> method
* several times (the parser will automatically re-initialize its state once the
* method is invoked).
* </p>
*
* @author <a href="mailto:pier@apache.org">Pier Fumagalli</a>, February 2003
*/
public class Parser implements Locator, ParserTables {
/** Our local InputSource */
private InputSource source = null;
/**
* Create a new instance of this <code>Parser</code>.
*/
public Parser() {
this((Reader)null);
}
/**
* Parse a specified <code>InputSource</code> and return the
* <code>Events</code> representing the parsed document.
*
* @param source The <code>InputSource</code> to parse.
* @throws SAXException In the source cannot be accessed or parsed.
* @throws SAXParseException If an exception occurred parsing the source.
* @throws IOException If an I/O error occurred.
*/
public Tree parse(InputSource source)
throws SAXException, SAXParseException, IOException {
Tree tree = new Tree();
this.source = source;
if (source == null) {
throw new SAXException("Null source specified");
} else if (source.getCharacterStream() != null) {
this.ReInit(source.getCharacterStream());
} else if (source.getByteStream() != null) {
this.ReInit(source.getByteStream());
} else if (source.getSystemId() != null) {
File file = new File(System.getProperty("user.dir")).getCanonicalFile();
URL url = new URL(file.toURL(), source.getSystemId());
InputStream in = url.openStream();
this.ReInit(new InputStreamReader(in));
} else {
throw new SAXException("Cannot access source char or byte stream");
}
try {
this.p_start(tree);
this.ReInit((Reader)null);
} catch (ParseException e) {
if (e.currentToken != null) {
throw new SAXParseException(e.getMessage(),
this.getPublicId(), this.getSystemId(),
e.currentToken.endLine, e.currentToken.endColumn, e);
}
throw new SAXParseException(e.getMessage(), this, e);
} catch (TokenMgrError e) {
throw new SAXParseException(e.getMessage(), this);
} catch (TreeException e) {
throw new SAXParseException(e.getMessage(), e, e);
}
return(tree);
}
/**
* Return the public identifier for the current document event.
*
* @return A <code>String</code> containing the public identifier,
* or <b>null</b> if none is available.
*/
public String getPublicId() {
if (this.source != null) return(source.getPublicId());
return(null);
}
/**
* Return the system identifier for the current document event.
*
* @return A <code>String</code> containing the system identifier,
* or <b>null</b> if none is available.
*/
public String getSystemId() {
if (this.source != null) return(source.getSystemId());
return(null);
}
/**
* Return the line number where the current document event ends.
*
* @return The line number, or -1 if none is available.
*/
public int getLineNumber() {
if (this.token != null) return(token.endLine);
return(-1);
}
/**
* Return the column number where the current document event ends.
*
* @return The column number, or -1 if none is available.
*/
public int getColumnNumber() {
if (this.token != null) return(token.endColumn);
return(-1);
}
/**
* Return the next available token checking its kind.
*
* @param kind An array of integers specifying the possible kind
* of the next returned token.
* @return The next available token with the correct kind.
* @throws ParseException If the token kind doesn't match one of
* those specified.
*/
final public Token getNextToken(int kind[])
throws ParseException {
Token prev_token = token;
Token local_token = this.getNextToken();
for (int x = 0; x < kind.length; x++) {
if (local_token.kind == kind[x]) {
return(local_token);
}
}
int expected[][] = new int[kind.length][1];
for (int x = 0; x < kind.length; x++) expected[x][0] = kind[x];
throw new ParseException(prev_token, expected, this.tokenImage);
}
/**
* Return the next available token checking its kind.
*
* @param kind The requited kind of the next returned token.
* @return The next available token with the correct kind.
* @throws ParseException If the token kind doesn't match.
*/
final public Token getNextToken(int kind)
throws ParseException {
int kinds[] = { kind };
return (this.getNextToken(kinds));
}
/**
* Return the next available token in a specific lexical state
* checking its kind.
*
* @param kind An array of integers specifying the possible kind
* of the next returned token.
* @param state The state in which the next token should be matched.
* @return The next available token with the correct kind.
* @throws ParseException If the token kind doesn't match one of
* those specified.
*/
final public Token getNextToken(int kind[], int state)
throws ParseException {
this.pushState(state);
Token local_token = this.getNextToken(kind);
this.popState();
return(local_token);
}
/**
* Return the next available token in a specific lexical state
* checking its kind.
*
* @param kind The requited kind of the next returned token.
* @param state The state in which the next token should be matched.
* @return The next available token with the correct kind.
* @throws ParseException If the token kind doesn't match.
*/
final public Token getNextToken(int kind, int state)
throws ParseException {
int kinds[] = { kind };
return (this.getNextToken(kinds, state));
}
/**
* Generate a parser internal error exception.
*
* @throws ParseException Every time this method is called.
*/
public void generateParseInternalError()
throws ParseException {
this.generateParseInternalError(null);
}
/**
* Generate a parser internal error exception.
*
* @param message An optional message for the exception.
* @throws ParseException Every time this method is called.
*/
public void generateParseInternalError(String message)
throws ParseException {
if (message == null) {
message = "Unrecoverable internal error";
}
if (token != null) {
message += " at line " + token.beginLine + ", column "
+ token.beginColumn + ".";
} else {
message += ".";
}
ParseException exception = new ParseException(message);
exception.currentToken = token;
exception.tokenImage = tokenImage;
throw (exception);
}
/* The parser lexical-state stack */
public int statesStk[] = new int[4096];
/* The position parser lexical-state stack */
int statesPos = 0;
/**
* Push the current lexical state in the stack and switch to new state.
*/
private final void pushState(int state) {
statesStk[statesPos++] = token_source.curLexState;
token_source.SwitchTo(state);
}
/**
* Pop the last lexical state from the stack and revert to it.
*/
private final void popState() {
int state = statesStk[--statesPos];
token_source.SwitchTo(state);
}
/**
* Convert the name of an entity reference specified as a
* <code>String</code> to its <code>char</code> equivalent.
*
* @param name The entity reference name.
* @return A <code>char</code> character.
* @throws NumberFormatException If the specified <code>name</code> was
* not found in the entities table.
*/
protected char p_entityref_byname(String name)
throws NumberFormatException {
int hash = name.hashCode();
for (int x = 0; x < entityReferences.length; x++) {
if (hash == entityReferences[x][0]) {
return ((char) entityReferences[x][1]);
}
}
String extra = (name.length() == 0 ?" (zero length)": "");
throw new NumberFormatException ("Invalid entity name supplied: \""
+ name + "\"" + extra + ".");
}
}
PARSER_END(Parser)
/* ============================================================================ *
* XML alphabet definition *
* ============================================================================ */
TOKEN : {
/* http://www.w3.org/TR/REC-xml#NT-BaseChar */
< #XML_BaseChar : ( [ "\u0041" - "\u005A" ] | [ "\u0061" - "\u007A" ] | [ "\u00C0" - "\u00D6" ] |
[ "\u00D8" - "\u00F6" ] | [ "\u00F8" - "\u00FF" ] | [ "\u0100" - "\u0131" ] |
[ "\u0134" - "\u013E" ] | [ "\u0141" - "\u0148" ] | [ "\u014A" - "\u017E" ] |
[ "\u0180" - "\u01C3" ] | [ "\u01CD" - "\u01F0" ] | [ "\u01F4" - "\u01F5" ] |
[ "\u01FA" - "\u0217" ] | [ "\u0250" - "\u02A8" ] | [ "\u02BB" - "\u02C1" ] |
[ "\u0388" - "\u038A" ] | [ "\u038E" - "\u03A1" ] | [ "\u03A3" - "\u03CE" ] |
[ "\u03D0" - "\u03D6" ] | [ "\u03E2" - "\u03F3" ] | [ "\u0401" - "\u040C" ] |
[ "\u040E" - "\u044F" ] | [ "\u0451" - "\u045C" ] | [ "\u045E" - "\u0481" ] |
[ "\u0490" - "\u04C4" ] | [ "\u04C7" - "\u04C8" ] | [ "\u04CB" - "\u04CC" ] |
[ "\u04D0" - "\u04EB" ] | [ "\u04EE" - "\u04F5" ] | [ "\u04F8" - "\u04F9" ] |
[ "\u0531" - "\u0556" ] | [ "\u0561" - "\u0586" ] | [ "\u05D0" - "\u05EA" ] |
[ "\u05F0" - "\u05F2" ] | [ "\u0621" - "\u063A" ] | [ "\u0641" - "\u064A" ] |
[ "\u0671" - "\u06B7" ] | [ "\u06BA" - "\u06BE" ] | [ "\u06C0" - "\u06CE" ] |
[ "\u06D0" - "\u06D3" ] | [ "\u06E5" - "\u06E6" ] | [ "\u0905" - "\u0939" ] |
[ "\u0958" - "\u0961" ] | [ "\u0985" - "\u098C" ] | [ "\u098F" - "\u0990" ] |
[ "\u0993" - "\u09A8" ] | [ "\u09AA" - "\u09B0" ] | [ "\u09B6" - "\u09B9" ] |
[ "\u09DC" - "\u09DD" ] | [ "\u09DF" - "\u09E1" ] | [ "\u09F0" - "\u09F1" ] |
[ "\u0A05" - "\u0A0A" ] | [ "\u0A0F" - "\u0A10" ] | [ "\u0A13" - "\u0A28" ] |
[ "\u0A2A" - "\u0A30" ] | [ "\u0A32" - "\u0A33" ] | [ "\u0A35" - "\u0A36" ] |
[ "\u0A38" - "\u0A39" ] | [ "\u0A59" - "\u0A5C" ] | [ "\u0A72" - "\u0A74" ] |
[ "\u0A85" - "\u0A8B" ] | [ "\u0A8F" - "\u0A91" ] | [ "\u0A93" - "\u0AA8" ] |
[ "\u0AAA" - "\u0AB0" ] | [ "\u0AB2" - "\u0AB3" ] | [ "\u0AB5" - "\u0AB9" ] |
[ "\u0B05" - "\u0B0C" ] | [ "\u0B0F" - "\u0B10" ] | [ "\u0B13" - "\u0B28" ] |
[ "\u0B2A" - "\u0B30" ] | [ "\u0B32" - "\u0B33" ] | [ "\u0B36" - "\u0B39" ] |
[ "\u0B5C" - "\u0B5D" ] | [ "\u0B5F" - "\u0B61" ] | [ "\u0B85" - "\u0B8A" ] |
[ "\u0B8E" - "\u0B90" ] | [ "\u0B92" - "\u0B95" ] | [ "\u0B99" - "\u0B9A" ] |
[ "\u0B9E" - "\u0B9F" ] | [ "\u0BA3" - "\u0BA4" ] | [ "\u0BA8" - "\u0BAA" ] |
[ "\u0BAE" - "\u0BB5" ] | [ "\u0BB7" - "\u0BB9" ] | [ "\u0C05" - "\u0C0C" ] |
[ "\u0C0E" - "\u0C10" ] | [ "\u0C12" - "\u0C28" ] | [ "\u0C2A" - "\u0C33" ] |
[ "\u0C35" - "\u0C39" ] | [ "\u0C60" - "\u0C61" ] | [ "\u0C85" - "\u0C8C" ] |
[ "\u0C8E" - "\u0C90" ] | [ "\u0C92" - "\u0CA8" ] | [ "\u0CAA" - "\u0CB3" ] |
[ "\u0CB5" - "\u0CB9" ] | [ "\u0CE0" - "\u0CE1" ] | [ "\u0D05" - "\u0D0C" ] |
[ "\u0D0E" - "\u0D10" ] | [ "\u0D12" - "\u0D28" ] | [ "\u0D2A" - "\u0D39" ] |
[ "\u0D60" - "\u0D61" ] | [ "\u0E01" - "\u0E2E" ] | [ "\u0E32" - "\u0E33" ] |
[ "\u0E40" - "\u0E45" ] | [ "\u0E81" - "\u0E82" ] | [ "\u0E87" - "\u0E88" ] |
[ "\u0E94" - "\u0E97" ] | [ "\u0E99" - "\u0E9F" ] | [ "\u0EA1" - "\u0EA3" ] |
[ "\u0EAA" - "\u0EAB" ] | [ "\u0EAD" - "\u0EAE" ] | [ "\u0EB2" - "\u0EB3" ] |
[ "\u0EC0" - "\u0EC4" ] | [ "\u0F40" - "\u0F47" ] | [ "\u0F49" - "\u0F69" ] |
[ "\u10A0" - "\u10C5" ] | [ "\u10D0" - "\u10F6" ] | [ "\u1102" - "\u1103" ] |
[ "\u1105" - "\u1107" ] | [ "\u110B" - "\u110C" ] | [ "\u110E" - "\u1112" ] |
[ "\u1154" - "\u1155" ] | [ "\u115F" - "\u1161" ] | [ "\u116D" - "\u116E" ] |
[ "\u1172" - "\u1173" ] | [ "\u11AE" - "\u11AF" ] | [ "\u11B7" - "\u11B8" ] |
[ "\u11BC" - "\u11C2" ] | [ "\u1E00" - "\u1E9B" ] | [ "\u1EA0" - "\u1EF9" ] |
[ "\u1F00" - "\u1F15" ] | [ "\u1F18" - "\u1F1D" ] | [ "\u1F20" - "\u1F45" ] |
[ "\u1F48" - "\u1F4D" ] | [ "\u1F50" - "\u1F57" ] | [ "\u1F5F" - "\u1F7D" ] |
[ "\u1F80" - "\u1FB4" ] | [ "\u1FB6" - "\u1FBC" ] | [ "\u1FC2" - "\u1FC4" ] |
[ "\u1FC6" - "\u1FCC" ] | [ "\u1FD0" - "\u1FD3" ] | [ "\u1FD6" - "\u1FDB" ] |
[ "\u1FE0" - "\u1FEC" ] | [ "\u1FF2" - "\u1FF4" ] | [ "\u1FF6" - "\u1FFC" ] |
[ "\u212A" - "\u212B" ] | [ "\u2180" - "\u2182" ] | [ "\u3041" - "\u3094" ] |
[ "\u30A1" - "\u30FA" ] | [ "\u3105" - "\u312C" ] | [ "\uAC00" - "\uD7A3" ] |
"\u0386" | "\u038C" | "\u03DA" | "\u03DC" | "\u03DE" | "\u03E0" | "\u0559" |
"\u06D5" | "\u093D" | "\u09B2" | "\u0A5E" | "\u0A8D" | "\u0ABD" | "\u0AE0" |
"\u0B3D" | "\u0B9C" | "\u0CDE" | "\u0E30" | "\u0E84" | "\u0E8A" | "\u0E8D" |
"\u0EA5" | "\u0EA7" | "\u0EB0" | "\u0EBD" | "\u1100" | "\u1109" | "\u113C" |
"\u113E" | "\u1140" | "\u114C" | "\u114E" | "\u1150" | "\u1159" | "\u1163" |
"\u1165" | "\u1167" | "\u1169" | "\u1175" | "\u119E" | "\u11A8" | "\u11AB" |
"\u11BA" | "\u11EB" | "\u11F0" | "\u11F9" | "\u1F59" | "\u1F5B" | "\u1F5D" |
"\u1FBE" | "\u2126" | "\u212E" ) >
/* http://www.w3.org/TR/REC-xml#NT-Ideographic */
| < #XML_Ideographic : ( [ "\u3021" - "\u3029" ] | [ "\u4E00" - "\u9FA5" ] | "\u3007" ) >
/* http://www.w3.org/TR/REC-xml#NT-CombiningChar */
| < #XML_CombinChar : ( [ "\u0300" - "\u0345" ] | [ "\u0360" - "\u0361" ] | [ "\u0483" - "\u0486" ] |
[ "\u0591" - "\u05A1" ] | [ "\u05A3" - "\u05B9" ] | [ "\u05BB" - "\u05BD" ] |
[ "\u05C1" - "\u05C2" ] | [ "\u064B" - "\u0652" ] | [ "\u06D6" - "\u06DC" ] |
[ "\u06DD" - "\u06DF" ] | [ "\u06E0" - "\u06E4" ] | [ "\u06E7" - "\u06E8" ] |
[ "\u06EA" - "\u06ED" ] | [ "\u0901" - "\u0903" ] | [ "\u093E" - "\u094C" ] |
[ "\u0951" - "\u0954" ] | [ "\u0962" - "\u0963" ] | [ "\u0981" - "\u0983" ] |
[ "\u09C0" - "\u09C4" ] | [ "\u09C7" - "\u09C8" ] | [ "\u09CB" - "\u09CD" ] |
[ "\u09E2" - "\u09E3" ] | [ "\u0A40" - "\u0A42" ] | [ "\u0A47" - "\u0A48" ] |
[ "\u0A4B" - "\u0A4D" ] | [ "\u0A70" - "\u0A71" ] | [ "\u0A81" - "\u0A83" ] |
[ "\u0ABE" - "\u0AC5" ] | [ "\u0AC7" - "\u0AC9" ] | [ "\u0ACB" - "\u0ACD" ] |
[ "\u0B01" - "\u0B03" ] | [ "\u0B3E" - "\u0B43" ] | [ "\u0B47" - "\u0B48" ] |
[ "\u0B4B" - "\u0B4D" ] | [ "\u0B56" - "\u0B57" ] | [ "\u0B82" - "\u0B83" ] |
[ "\u0BBE" - "\u0BC2" ] | [ "\u0BC6" - "\u0BC8" ] | [ "\u0BCA" - "\u0BCD" ] |
[ "\u0C01" - "\u0C03" ] | [ "\u0C3E" - "\u0C44" ] | [ "\u0C46" - "\u0C48" ] |
[ "\u0C4A" - "\u0C4D" ] | [ "\u0C55" - "\u0C56" ] | [ "\u0C82" - "\u0C83" ] |
[ "\u0CBE" - "\u0CC4" ] | [ "\u0CC6" - "\u0CC8" ] | [ "\u0CCA" - "\u0CCD" ] |
[ "\u0CD5" - "\u0CD6" ] | [ "\u0D02" - "\u0D03" ] | [ "\u0D3E" - "\u0D43" ] |
[ "\u0D46" - "\u0D48" ] | [ "\u0D4A" - "\u0D4D" ] | [ "\u0E34" - "\u0E3A" ] |
[ "\u0E47" - "\u0E4E" ] | [ "\u0EB4" - "\u0EB9" ] | [ "\u0EBB" - "\u0EBC" ] |
[ "\u0EC8" - "\u0ECD" ] | [ "\u0F18" - "\u0F19" ] | [ "\u0F71" - "\u0F84" ] |
[ "\u0F86" - "\u0F8B" ] | [ "\u0F90" - "\u0F95" ] | [ "\u0F99" - "\u0FAD" ] |
[ "\u0FB1" - "\u0FB7" ] | [ "\u20D0" - "\u20DC" ] | [ "\u302A" - "\u302F" ] |
"\u05BF" | "\u05C4" | "\u0670" | "\u093C" | "\u094D" | "\u09BC" | "\u09BE" |
"\u09BF" | "\u09D7" | "\u0A02" | "\u0A3C" | "\u0A3E" | "\u0A3F" | "\u0ABC" |
"\u0B3C" | "\u0BD7" | "\u0D57" | "\u0E31" | "\u0EB1" | "\u0F35" | "\u0F37" |
"\u0F39" | "\u0F3E" | "\u0F3F" | "\u0F97" | "\u0FB9" | "\u20E1" | "\u3099" |
"\u309A" ) >
/* http://www.w3.org/TR/REC-xml#NT-Digit */
| < #XML_Digit : ( [ "\u0030" - "\u0039" ] | [ "\u0660" - "\u0669" ] | [ "\u06F0" - "\u06F9" ] |
[ "\u0966" - "\u096F" ] | [ "\u09E6" - "\u09EF" ] | [ "\u0A66" - "\u0A6F" ] |
[ "\u0AE6" - "\u0AEF" ] | [ "\u0B66" - "\u0B6F" ] | [ "\u0BE7" - "\u0BEF" ] |
[ "\u0C66" - "\u0C6F" ] | [ "\u0CE6" - "\u0CEF" ] | [ "\u0D66" - "\u0D6F" ] |
[ "\u0E50" - "\u0E59" ] | [ "\u0ED0" - "\u0ED9" ] | [ "\u0F20" - "\u0F29" ] ) >
/* http://www.w3.org/TR/REC-xml#NT-Extender */
| < #XML_Extender : ( [ "\u3031" - "\u3035" ] | [ "\u309D" - "\u309E" ] | [ "\u30FC" - "\u30FE" ] |
"\u00B7" | "\u02D0" | "\u02D1" | "\u0387" | "\u0640" | "\u0E46" | "\u0EC6" |
"\u3005" ) >
/* http://www.w3.org/TR/REC-xml#NT-Letter */
| < #XML_Letter : ( <XML_BaseChar> | <XML_Ideographic> ) >
/* http://www.w3.org/TR/REC-xml#NT-NameChar */
| < #XML_NameChar : ( <XML_Letter> | <XML_Digit> | <XML_CombinChar> | <XML_Extender>
| "." | "-" | "_" | ":" ) >
/* http://www.w3.org/TR/REC-xml#NT-PubidChar (NOTE: excludes "'") */
| < #PubIdChar : ( "-" | "(" | ")" | "+" | "," | "." | "/" | ":" | "=" |
"?" | ";" | "!" | "*" | "#" | "@" | "$" | "_" | "%" |
[ "a" - "z" ] | ["A" - "Z" ] | [ "0" - "9" ] |
"\r" | "\n" | " " ) >
}
/* ============================================================================ *
* XML tokens definitions *
* ============================================================================ */
TOKEN : {
/* http://www.w3.org/TR/REC-xml#NT-S */
< #S : ( ( " " | "\t" | "\r" | "\n" )+ ) >
/* http://www.w3.org/TR/REC-xml#NT-Name */
| < #Name : ( ( <XML_Letter> | "_" | ":" ) ( <XML_NameChar> )* ) >
}
/* ============================================================================ *
* Main parser routines *
* ============================================================================ */
/**
* Starts parsing.
*/
void p_start (Events events) : {
} {
( p_doctype(events) )?
( p_block(events) )
( <EOF> )
}
/**
* Parse a block.
*/
void p_block (Events events) : {
} {
(
p_characters(events)
| p_element(events)
| p_entityref(events)
| p_comment(events)
| p_cdata(events)
| p_procinstr(events)
| p_expression(events)
| p_template_if(events)
| p_template_foreach(events)
| p_template_variable(events)
)+
}
/* ============================================================================ *
* CHARACTERS: available in DEFAULT state. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_CHARACTERS : ( ~[ "&", "<", "#" ] )+ >
}
/* ---------------------------------------------------------------------------- */
/**
* Parse characters outside of any tag, element...
*/
void p_characters (Events events) : {
} {
( <T_CHARACTERS> ) {
events.append(new Characters(this, token.image));
}
}
/* ============================================================================ *
* DOCTYPE: available in DEFAULT state. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_DOCTYPE : ( ( <S> )? "<!DOCTYPE" ( <S> ) ) > : DOCTYPE
}
<DOCTYPE> TOKEN: {
< T_DOCTYPE_END : ( ( <S> )? ">" ) > : DEFAULT
| < T_DOCTYPE_NAME : ( <Name> ) >
| < T_DOCTYPE_SYSTEM : ( <S> "SYSTEM" ) >
| < T_DOCTYPE_PUBLIC : ( <S> "PUBLIC" ) >
| < T_DOCTYPE_S : ( <S> ) >
}
<DOCTYPE, DOCTYPE_SYSTEM, DOCTYPE_PUBLIC> TOKEN: {
< T_DOCTYPE_QUOT : ( "\"" ) >
| < T_DOCTYPE_APOS : ( "\'" ) >
}
<DOCTYPE_SYSTEM> TOKEN : {
< T_DOCTYPE_SYSTEM_DATA : ( ~[ "\"", "\'" ] )+ >
}
<DOCTYPE_PUBLIC> TOKEN : {
< T_DOCTYPE_PUBLIC_DATA : ( <PubIdChar> )+ >
}
/* ---------------------------------------------------------------------------- */
/**
* Parse a <code>&lt;!DOCTYPE ...&gt;</code> declaration.
*/
void p_doctype (Events events) : {
String name = null;
String system_id = null;
String public_id = null;
} {
( <T_DOCTYPE> )
( <T_DOCTYPE_NAME> ) {
name = token.image;
}
(
( <T_DOCTYPE_SYSTEM> ) {
system_id = p_doctype_id(DOCTYPE_SYSTEM);
}
| ( <T_DOCTYPE_PUBLIC> ) {
public_id = p_doctype_id(DOCTYPE_PUBLIC);
system_id = p_doctype_id(DOCTYPE_SYSTEM);
}
)?
( <T_DOCTYPE_END> ) {
events.append(new DocType(this, name, public_id, system_id));
}
}
/**
* Parse the SYSTEM or PUBLIC id in a <code>&lt;!DOCTYPE ...&gt;</code>
* declaration.
*
* @param state Either DOCTYPE_SYSTEM or DOCTYPE_PUBLIC
*/
String p_doctype_id (int state) : {
Token local = null;
int kind = -1;
switch (state) {
case DOCTYPE_SYSTEM: kind = T_DOCTYPE_SYSTEM_DATA; break;
case DOCTYPE_PUBLIC: kind = T_DOCTYPE_PUBLIC_DATA; break;
default: generateParseInternalError("Invalid state " + state + "specified");
}
} {
( <T_DOCTYPE_S>
( <T_DOCTYPE_QUOT> | <T_DOCTYPE_APOS> ) {
StringBuffer value = new StringBuffer();
int start_kind = token.kind;
int expect[] = { kind, T_DOCTYPE_QUOT, T_DOCTYPE_APOS };
pushState(state);
local = getNextToken(expect);
while (local.kind != start_kind) {
value.append(local.image);
local = getNextToken(expect);
}
popState();
return(value.toString());
}
)
}
/* ============================================================================ *
* ELEMENT: available in DEFAULT state. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_ELEMENT_OPEN : ( "<" <Name> ) > : ELEMENT
| < T_ELEMENT_CLOSE : ( "</" <Name> ) > : ELEMENT
}
<ELEMENT> TOKEN : {
< T_ELEMENT_END : ( ( <S> )? ">" ) > : DEFAULT
| < T_ELEMENT_SINGLE : ( ( <S> )? "/>" ) > : DEFAULT
}
/* ---------------------------------------------------------------------------- */
/**
* Parse an element (<code>&lt;name ...&gt;</code>, <code>&lt;name
* .../&gt;</code> or <code>&lt;/name &gt;</code>) declaration.
*/
void p_element (Events events) : {
ElementStart element = null;
String name = null;
} {
(
( <T_ELEMENT_CLOSE> ) {
events.append(new ElementEnd(this, token.image.substring(2)));
}
( <T_ELEMENT_END> )
) | (
( <T_ELEMENT_OPEN> ) {
name = token.image.substring(1);
element = new ElementStart(this, name);
}
( p_attribute(element) )*
( <T_ELEMENT_END> | <T_ELEMENT_SINGLE> ) {
events.append(element);
if (token.kind == T_ELEMENT_SINGLE) {
events.append(new ElementEnd(this, name));
}
}
)
}
/* ============================================================================ *
* ATTRIBUTE: available in ELEMENT state. *
* ============================================================================ */
<ELEMENT> TOKEN: {
< T_ATTRIBUTE : ( <S> <Name> ) > : ATTRIBUTE
}
<ATTRIBUTE> TOKEN: {
< T_ATTRIBUTE_EQUALS : ( ( <S> )? "=" ( <S> )? ) >
}
<ATTRIBUTE, ATTRIBUTE_DATA> TOKEN: {
< T_ATTRIBUTE_QUOT : ( "\"" ) >
| < T_ATTRIBUTE_APOS : ( "\'" ) >
| < T_ATTRIBUTE_EXPR : ( "{" ) >
| < T_ATTRIBUTE_EREF : ( "&" ) >
}
<ATTRIBUTE_DATA> TOKEN : {
< T_ATTRIBUTE_DATA : ( ~[ "\"", "\'", "&", "{", "}", "<" ] )+ >
}
/**
* Parse an attribute (<code>name = &quot;...&quot;</code>) inside an element
* declaration.
*/
void p_attribute (ElementStart element) : {
String name = null;
Attribute attribute = null;
} {
( <T_ATTRIBUTE> ) {
attribute = new Attribute(this, token.image.trim());
}
( p_attribute_data(attribute) ) {
element.put(attribute);
token_source.SwitchTo(ELEMENT);
}
}
/**
* Parse the value of an element attribute.
*/
void p_attribute_data (Attribute attribute) : {
Token local = null;
}{
( <T_ATTRIBUTE_EQUALS>
( <T_ATTRIBUTE_QUOT> | <T_ATTRIBUTE_APOS> ) {
int start_kind = token.kind;
int expect[] = {
T_ATTRIBUTE_DATA, T_ATTRIBUTE_QUOT, T_ATTRIBUTE_APOS,
T_ATTRIBUTE_EREF, T_ATTRIBUTE_EXPR
};
pushState(ATTRIBUTE_DATA);
local = getNextToken(expect);
while (local.kind != start_kind) {
switch (local.kind) {
case T_ATTRIBUTE_EREF:
pushState(ENTITYREF);
attribute.append(new Characters(p_entityref_data()));
popState();
break;
case T_ATTRIBUTE_EXPR:
pushState(EXPRESSION);
attribute.append(new Expression(p_expression_data()));
popState();
break;
default:
attribute.append(new Characters(local.image));
break;
}
local = getNextToken(expect);
}
popState();
}
)
}
/* ============================================================================ *
* ENTITYREF: available in DEFAULT state, accessible from ATTRIBUTE state. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_ENTITYREF : ( "&" ) >
}
<ENTITYREF> TOKEN : {
< T_ENTITYREF_END : ( ";" ) >
| < T_ENTITYREF_NUM : ( "#" ( [ "0"- "9" ] )+ ) >
| < T_ENTITYREF_HEX : ( "#x" ( [ "0"- "9" ] | [ "a" - "f" ] | [ "A" - "F"] )+ ) >
| < T_ENTITYREF_NAME : ( <Name> ) >
}
/* ---------------------------------------------------------------------------- */
/**
* Parse an entity reference (<code>&amp;...;</code>) declaration.
*/
void p_entityref (Events events) : {
char value = 0;
} {
( <T_ENTITYREF> ) {
/* Push the state manually, as we can come from different states */
pushState(ENTITYREF);
}
( value = p_entityref_data() ) {
events.append(new Characters(this, value));
popState();
}
}
/**
* Parse the value of an entity reference and return its character value.
*/
char p_entityref_data() : {
int value = -1;
} {
( <T_ENTITYREF_NUM> | <T_ENTITYREF_HEX> | <T_ENTITYREF_NAME> ) {
try {
switch (token.kind) {
case T_ENTITYREF_NUM:
value = Integer.parseInt(token.image.substring(1));
break;
case T_ENTITYREF_HEX:
value = Integer.parseInt(token.image.substring(2), 16);
break;
case T_ENTITYREF_NAME:
value = p_entityref_byname(token.image);
break;
}
} catch (NumberFormatException e) {
value = -1;
}
if ((value < Character.MIN_VALUE) || (value > Character.MAX_VALUE)) {
this.generateParseInternalError("Invalid entity reference &"
+ token.image + ";");
}
}
( <T_ENTITYREF_END> ) {
return((char)value);
}
}
/* ============================================================================ *
* COMMENT: available in DEFAULT mode. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_COMMENT : ( "<!--" ) > : COMMENT
}
<COMMENT> TOKEN : {
< T_COMMENT_END : ( "-->" ) > : DEFAULT
| < T_COMMENT_DATA : ( ( ~ [ "-" ] ) | ( "-" ( ~ [ "-" ] ) ) )+ >
}
/* ---------------------------------------------------------------------------- */
/**
* Parse a comment (<code>&lt;!-- ... --&gt;</code>) section.
*/
void p_comment (Events events) : {
String data = "";
} {
( <T_COMMENT> )
(
( <T_COMMENT_DATA> ) {
data = token.image;
}
)?
( <T_COMMENT_END> ) {
events.append(new Comment(this, data));
}
}
/* ============================================================================ *
* CDATA: available in DEFAULT mode. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_CDATA : ( "<[CDATA[" ) > : CDATA
}
<CDATA> TOKEN : {
< T_CDATA_END : ( "]]>" ) > : DEFAULT
| < T_CDATA_DATA : ( ( ~ [ "]" ] ) | ( "]" ( ~ [ "]" ] ) ) | ( "]]" ( ~ [ ">" ] ) ) )+ >
}
/* ---------------------------------------------------------------------------- */
/**
* Parse a <code>&lt;[CDATA[ ... ]&gt;</code> section.
*/
void p_cdata (Events events) : {
String data = "";
} {
( <T_CDATA> )
(
( <T_CDATA_DATA> ) {
data = token.image;
}
)?
( <T_CDATA_END> ) {
events.append(new CData(this, data));
}
}
/* ============================================================================ *
* PROCINSTR: available in DEFAULT mode. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_PROCINSTR : ( "<?" ) > : PROCINSTR
}
<PROCINSTR> TOKEN : {
< T_PROCINSTR_END : ( "?>" ) > : DEFAULT
| < T_PROCINSTR_SEP : ( <S> ) > : PROCINSTR_DATA
| < T_PROCINSTR_TARGET : ( <Name> ) >
}
<PROCINSTR_DATA> TOKEN : {
< T_PROCINSTR_DATA : ( ( ~ [ "?" ] ) | ( "?" ( ~ [ ">" ] ) ) )+ > : PROCINSTR
}
/* ---------------------------------------------------------------------------- */
/**
* Parse a Processing Instruction (<code>&lt;?name ...?&gt;</code>).
*/
void p_procinstr (Events events) : {
String target = null;
String data = null;
} {
( <T_PROCINSTR> )
( <T_PROCINSTR_TARGET> ) {
target = token.image;
}
(
( <T_PROCINSTR_SEP> <T_PROCINSTR_DATA> ) {
data = token.image;
}
)?
( <T_PROCINSTR_END> ) {
events.append(new ProcessingInstruction(this, target, data));
}
}
/* ============================================================================ *
* EXPRESSION: available in DEFAULT state, accessible from ATTRIBUTE state. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_EXPRESSION : ( "#{" ) >
}
<EXPRESSION> TOKEN : {
< T_EXPRESSION_END : ( "}" ) >
| < T_EXPRESSION_DATA : ( ~ [ "{", "}" ] )+ >
}
/* ---------------------------------------------------------------------------- */
/**
* Parse an Expression (<code>{...}</code>).
*/
void p_expression(Events events) : {
String expression = null;
} {
( <T_EXPRESSION> ) {
pushState(EXPRESSION);
}
( expression = p_expression_data() ) {
events.append(new Expression(this, expression));
popState();
}
}
/**
* Parse the data contained in an Expression.
*/
String p_expression_data() : {
String expression = null;
} {
( <T_EXPRESSION_DATA> ) {
expression = token.image;
}
( <T_EXPRESSION_END> ) {
return(expression);
}
}
/* ============================================================================ *
* TEMPLATE: available in DEFAULT state. *
* ============================================================================ */
<DEFAULT> TOKEN : {
< T_TEMPLATE_IF : ( "#if" ( <S> )? "{" ) >
| < T_TEMPLATE_ELIF : ( "#elif" ( <S> )? "{" ) >
| < T_TEMPLATE_ELSE : ( "#else" ) >
| < T_TEMPLATE_FOREACH : ( "#foreach" ( <S> )? "{" ) >
| < T_TEMPLATE_END : ( "#end" ) >
| < T_TEMPLATE_VARIABLE : ( "#$" <Name> ( <S> )? "=" ( <S> )? "{" ) >
}
/**
* Parse a template foreach block (<code>&quot;#foreach...#end</code>).
*/
void p_template_foreach(Events events) : {
TemplateFor event = null;
} {
( <T_TEMPLATE_FOREACH> ) {
pushState(EXPRESSION);
event = new TemplateFor(this, p_expression_data());
popState();
p_block(event);
}
( <T_TEMPLATE_END> ) {
events.append(event);
}
}
/**
* Parse a template variable declaration (<code>&quot;#$name = {...}</code>).
*/
void p_template_variable(Events events) : {
String variable = null;
String expression = null;
} {
( <T_TEMPLATE_VARIABLE> ) {
variable = token.image.substring(2, token.image.indexOf('=')).trim();
pushState(EXPRESSION);
expression = p_expression_data();
popState();
events.append(new TemplateVar(this, variable, expression));
System.err.println("Processed #$" + variable + "={" + expression + "}");
}
}
/**
* Parse a template if block (<code>&quot;#if...#end</code>).
*/
void p_template_if(Events events) : {
String expression = null;
TemplateIf event = new TemplateIf(this);
} {
( <T_TEMPLATE_IF> ) {
pushState(EXPRESSION);
expression = p_expression_data();
popState();
p_block(event.addCondition(this, expression));
}
(
( <T_TEMPLATE_ELIF> ) {
pushState(EXPRESSION);
expression = p_expression_data();
popState();
p_block(event.addCondition(this, expression));
}
)*
(
( <T_TEMPLATE_ELSE> ) {
p_block(event.addCondition(this));
}
)?
( <T_TEMPLATE_END> ) {
events.append(event);
}
}