parser2.java

来自「java jdk 1.4的源码」· Java 代码 · 共 1,790 行 · 第 1/5 页

JAVA
1,790
字号
        // XXX we can marginally speed PE handling, and certainly        // be cleaner (hence potentially more correct), by using        // the observations that expanded PEs only start and stop        // where whitespace is allowed.  getc wouldn't need any        // "lexical" PE expansion logic, and no other method needs        // to handle termination of PEs.  (parsing of literals would        // still need to pop entities, but not parsing of references        // in content.)        char c = getc();        boolean saw = false;        while (c == ' ' || c == '\t' || c == '\n' || c == '\r') {            saw = true;            // this gracefully ends things when we stop playing            // with internal parameters.  caller should have a            // grammar rule allowing whitespace at end of entity.            if (in.isEOF () && !in.isInternal ())                return saw;            c = getc ();        }        ungetc ();        return saw;    }    private String maybeGetName ()    throws IOException, SAXException    {        NameCacheEntry  entry = maybeGetNameCacheEntry ();        return (entry == null) ? null : entry.name;    }    private NameCacheEntry maybeGetNameCacheEntry ()    throws IOException, SAXException    {        // [5] Name ::= (Letter|'_'|':') (Namechar)*        char            c = getc ();        if (!XmlChars.isLetter (c) && c != ':' && c != '_') {            ungetc ();            return null;        }        return nameCharString (c);    }    // Used when parsing enumerations    private String getNmtoken ()    throws SAXException, IOException    {        // [7] Nmtoken ::= (Namechar)+        char c = getc ();        if (!XmlChars.isNameChar (c))            fatal ("P-006", new Object [] { new Character (c) });        return nameCharString (c).name;    }    // n.b. this gets used when parsing attribute values (for    // internal references) so we can't use strTmp; it's also    // a hotspot for CPU and memory in the parser (called at least    // once for each element) so this has been optimized a bit.    private NameCacheEntry nameCharString (char c)    throws IOException, SAXException    {        int     i = 1;        nameTmp [0] = c;        for (;;) {            if ((c = in.getNameChar ()) == 0)                break;            if (i >= nameTmp.length) {                char tmp [] = new char [nameTmp.length + 10];                System.arraycopy (nameTmp, 0, tmp, 0, nameTmp.length);                nameTmp = tmp;            }            nameTmp [i++] = c;        }        return nameCache.lookupEntry (nameTmp, i);    }    //    // much similarity between parsing entity values in DTD    // and attribute values (in DTD or content) ... both follow    // literal parsing rules, newline canonicalization, etc    //    // leaves value in 'strTmp' ... either a "replacement text" (4.5),    // or else partially normalized attribute value (the first bit    // of 3.3.3's spec, without the "if not CDATA" bits).    //    private void parseLiteral (boolean isEntityValue)    throws IOException, SAXException    {        // [9] EntityValue ::=        //      '"' ([^"&%] | Reference | PEReference)* '"'        //    | "'" ([^'&%] | Reference | PEReference)* "'"        // [10] AttValue ::=        //      '"' ([^"&]  | Reference              )* '"'        //    | "'" ([^'&]  | Reference              )* "'"        // Only expand PEs in getc() when processing entity value literals        // and do not expand when processing AttValue.  Save state of        // doLexicalPE and restore it before returning.        boolean savedLexicalPE = doLexicalPE;//         doLexicalPE = isEntityValue;        char            quote = getc ();        char            c;        InputEntity     source = in;        if (quote != '\'' && quote != '"')            fatal ("P-007");        // don't report entity expansions within attributes,        // they're reported "fully expanded" via SAX        isInAttribute = !isEntityValue;        // get value into strTmp        strTmp = new StringBuffer ();        // scan, allowing entity push/pop wherever ...        // expanded entities can't terminate the literal!        for (;;) {            if (in != source && in.isEOF ()) {                // we don't report end of parsed entities                // within attributes (no SAX hooks)                in = in.pop ();                continue;            }            if ((c = getc ()) == quote && in == source)                break;            //            // Basically the "reference in attribute value"            // row of the chart in section 4.4 of the spec            //            if (c == '&') {                String  entityName = maybeGetName ();                if (entityName != null) {                    nextChar (';', "F-020", entityName);                    // 4.4 says:  bypass these here ... we'll catch                    // forbidden refs to unparsed entities on use                    if (isEntityValue) {                        strTmp.append ('&');                        strTmp.append (entityName);                        strTmp.append (';');                        continue;                    }                    expandEntityInLiteral (entityName, entities, isEntityValue);                // character references are always included immediately                } else if ((c = getc ()) == '#') {                    int tmp = parseCharNumber ();                    if (tmp > 0xffff) {                        tmp = surrogatesToCharTmp (tmp);                        strTmp.append (charTmp [0]);                        if (tmp == 2)                            strTmp.append (charTmp [1]);                    } else                        strTmp.append ((char) tmp);                } else                    fatal ("P-009");                continue;            }            // expand parameter entities only within entity value literals            if (c == '%' && isEntityValue) {                String  entityName = maybeGetName ();                if (entityName != null) {                    nextChar (';', "F-021", entityName);                    if (inExternalPE)                        expandEntityInLiteral (entityName,                                params, isEntityValue);                    else                        fatal ("P-010", new Object [] { entityName });                    continue;                } else                    fatal ("P-011");            }            // For attribute values ...            if (!isEntityValue) {                // 3.3.3 says whitespace normalizes to space...                if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {                    strTmp.append (' ');                    continue;                }                // "<" not legal in parsed literals ...                if (c == '<')                    fatal ("P-012");            }            strTmp.append (c);        }        isInAttribute = false;//         doLexicalPE = savedLexicalPE;    }    // does a SINGLE expansion of the entity (often reparsed later)    private void expandEntityInLiteral (        String          name,        SimpleHashtable table,        boolean         isEntityValue    ) throws SAXException, IOException    {        Object  entity = table.get (name);                //throw fatal error when entity expansion count reaches the limit set by application        //if we don't want to have any costraint on number of entity that can be expanaded         //set the DEFAULT_ENTITY_EXPANSION_LIMIT to -1.        if( entityExpansionLimit != -1 && entityExpansionCount++ >= entityExpansionLimit){            fatal ("P-086", new Object[] {new Integer(entityExpansionLimit)});        };        //        // Note:  if entity is a PE (value.isPE) there is an XML        // requirement that the content be "markkupdecl", but that error        // is ignored here (as permitted by the XML spec).        //        if (entity instanceof InternalEntity) {            InternalEntity value = (InternalEntity) entity;            if (supportValidation && isValidating                    && isStandalone                    && !value.isFromInternalSubset)                error ("V-002", new Object [] { name });            pushReader (value.buf, name, !value.isPE);        } else if (entity instanceof ExternalEntity) {            if (!isEntityValue) // must be a PE ...                fatal ("P-013", new Object [] { name });            // XXX if this returns false ...            pushReader ((ExternalEntity) entity);        } else if (entity == null) {            //            // Note:  much confusion about whether spec requires such            // errors to be fatal in many cases, but none about whether            // it allows "normal" errors to be unrecoverable!            //            fatal (                (table == params) ? "V-022" : "P-014",                new Object [] { name });        }    }    // [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")    // for PUBLIC and SYSTEM literals, also "<?xml ...type='literal'?>'        // NOTE:  XML spec should explicitly say that PE ref syntax is    // ignored in PIs, comments, SystemLiterals, and Pubid Literal    // values ... can't process the XML spec's own DTD without doing    // that for comments.    private String getQuotedString (String type, String extra)    throws IOException, SAXException    {        // use in.getc to bypass PE processing        char             quote = in.getc ();        if (quote != '\'' && quote != '"')            fatal ("P-015", new Object [] {                messages.getMessage (locale, type, new Object [] { extra })                });        char            c;        strTmp = new StringBuffer ();        while ((c = in.getc ()) != quote)            strTmp.append ((char)c);        return strTmp.toString ();    }    private String parsePublicId ()    throws IOException, SAXException    {        // [12] PubidLiteral ::= ('"' PubidChar* '"') | ("'" PubidChar* "'")        // [13] PubidChar ::= #x20|#xd|#xa|[a-zA-Z0-9]|[-'()+,./:=?;!*#@$_%]        String retval = getQuotedString ("F-033", null);        for (int i = 0; i < retval.length (); i++) {            char c = retval.charAt (i);            if (" \r\n-'()+,./:=?;!*#@$_%0123456789".indexOf(c) == -1                    && !(c >= 'A' && c <= 'Z')                    && !(c >= 'a' && c <= 'z'))                fatal ("P-016", new Object [] { new Character (c) });        }        strTmp = new StringBuffer ();        strTmp.append (retval);        return normalize (false);    }        // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)        // handled by:  InputEntity.parsedContent()    private boolean maybeComment (boolean skipStart)    throws IOException, SAXException    {        // [15] Comment ::= '<!--'        //              ( (Char - '-') | ('-' (Char - '-'))*        //              '-->'        if (!in.peek (skipStart ? "!--" : "<!--", null))            return false;        boolean         savedLexicalPE = doLexicalPE;        doLexicalPE = false;        boolean saveCommentText = lexicalHandler != nullHandler;        if (saveCommentText) {            strTmp = new StringBuffer ();        }    oneComment:        for (;;) {            try {                // bypass PE expansion, but permit PEs                // to complete ... valid docs won't care.                for (;;) {                    int c = getc ();                    if (c == '-') {                        c = getc ();                        if (c != '-') {                            if (saveCommentText)                                strTmp.append ('-');                            ungetc ();                            continue;                        }                        nextChar ('>', "F-022", null);                        break oneComment;                    }                    if (saveCommentText)                        strTmp.append ((char)c);                }            } catch (EndOfInputException e) {                //                // This is fatal EXCEPT when we're processing a PE...                // in which case a validating processor reports an error.                // External PEs are easy to detect; internal ones we                // infer by being an internal entity outside an element.                //                if (inExternalPE || (!donePrologue && in.isInternal ())) {                    if (supportValidation && isValidating)                        error ("V-021", null);                    in = in.pop ();                    continue;                }                fatal ("P-017");            }        }        doLexicalPE = savedLexicalPE;        if (saveCommentText) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?