| /* |
| * 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><!DOCTYPE ...></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><!DOCTYPE ...></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><name ...></code>, <code><name |
| * .../></code> or <code></name ></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 = "..."</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>&...;</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><!-- ... --></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><[CDATA[ ... ]></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><?name ...?></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>"#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>"#$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>"#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); |
| } |
| } |