- /*
 - * $Id: ContentModelState.java,v 1.1.1.1 2000/11/23 01:53:33 edwingo Exp $
 - *
 - * The Apache Software License, Version 1.1
 - *
 - *
 - * Copyright (c) 2000 The Apache Software Foundation. All rights
 - * reserved.
 - *
 - * Redistribution and use in source and binary forms, with or without
 - * modification, are permitted provided that the following conditions
 - * are met:
 - *
 - * 1. Redistributions of source code must retain the above copyright
 - * notice, this list of conditions and the following disclaimer.
 - *
 - * 2. Redistributions in binary form must reproduce the above copyright
 - * notice, this list of conditions and the following disclaimer in
 - * the documentation and/or other materials provided with the
 - * distribution.
 - *
 - * 3. The end-user documentation included with the redistribution,
 - * if any, must include the following acknowledgment:
 - * "This product includes software developed by the
 - * Apache Software Foundation (http://www.apache.org/)."
 - * Alternately, this acknowledgment may appear in the software itself,
 - * if and wherever such third-party acknowledgments normally appear.
 - *
 - * 4. The names "Crimson" and "Apache Software Foundation" must
 - * not be used to endorse or promote products derived from this
 - * software without prior written permission. For written
 - * permission, please contact apache@apache.org.
 - *
 - * 5. Products derived from this software may not be called "Apache",
 - * nor may "Apache" appear in their name, without prior written
 - * permission of the Apache Software Foundation.
 - *
 - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 - * SUCH DAMAGE.
 - * ====================================================================
 - *
 - * This software consists of voluntary contributions made by many
 - * individuals on behalf of the Apache Software Foundation and was
 - * originally based on software copyright (c) 1999, Sun Microsystems, Inc.,
 - * http://www.sun.com. For more information on the Apache Software
 - * Foundation, please see <http://www.apache.org/>.
 - */
 - package org.apache.crimson.parser;
 - /**
 - * A content model state. This is basically an index into a content
 - * model node, emulating an automaton with primitives to consume tokens.
 - * It may create new content model states as a consequence of that
 - * consumption, or modify the current state. "Next" is used to track
 - * states that are pending completion after the "current automaton"
 - * completes its task.
 - *
 - * @see ContentModel
 - * @see ValidatingParser
 - *
 - * @author David Brownell
 - * @author Arthur van Hoff
 - * @version $Revision: 1.1.1.1 $
 - */
 - class ContentModelState
 - {
 - private ContentModel model;
 - private boolean sawOne;
 - private ContentModelState next;
 - /**
 - * Create a content model state for a content model. When
 - * the state advances to null, this automaton has finished.
 - */
 - ContentModelState (ContentModel model)
 - {
 - this (model, null);
 - }
 - /**
 - * Create a content model state for a content model, stacking
 - * a state for subsequent processing.
 - */
 - private ContentModelState (Object content, ContentModelState next)
 - {
 - this.model = (ContentModel)content;
 - this.next = next;
 - this.sawOne = false;
 - }
 - /**
 - * Check if the state can be terminated. That is, there are no more
 - * tokens required in the input stream.
 - * @return true if the model can terminate without further input
 - */
 - boolean terminate ()
 - {
 - switch (model.type) {
 - case '+':
 - if (!sawOne && !((ContentModel)model).empty ())
 - return false;
 - // FALLTHROUGH
 - case '*':
 - case '?':
 - return (next == null) || next.terminate ();
 - case '|':
 - return model.empty () && (next == null || next.terminate ());
 - case ',':
 - ContentModel m;
 - for (m = model; (m != null) && m.empty () ; m = m.next)
 - continue;
 - if (m != null)
 - return false;
 - return (next == null) || next.terminate ();
 - case 0:
 - return false;
 - default:
 - throw new InternalError ();
 - }
 - }
 - /**
 - * Advance this state to a new state, or throw an
 - * exception (use a more appropriate one?) if the
 - * token is illegal at this point in the content model.
 - * The current state is modified if possible, conserving
 - * memory that's already been allocated.
 - * @return next state after reducing a token
 - */
 - ContentModelState advance (String token)
 - throws EndOfInputException
 - {
 - switch (model.type) {
 - case '+':
 - case '*':
 - if (model.first (token)) {
 - sawOne = true;
 - if (model.content instanceof String)
 - return this;
 - return new ContentModelState (model.content, this)
 - .advance (token);
 - }
 - if ((model.type == '*' || sawOne) && next != null)
 - return next.advance (token);
 - break;
 - case '?':
 - if (model.first (token)) {
 - if (model.content instanceof String)
 - return next;
 - return new ContentModelState (model.content, next)
 - .advance (token);
 - }
 - if (next != null)
 - return next.advance (token);
 - break;
 - case '|':
 - for (ContentModel m = model; m != null; m = m.next) {
 - if (m.content instanceof String) {
 - if (token == m.content)
 - return next;
 - continue;
 - }
 - if (((ContentModel)m.content).first (token))
 - return new ContentModelState (m.content, next)
 - .advance (token);
 - }
 - if (model.empty () && next != null)
 - return next.advance (token);
 - break;
 - case ',':
 - if (model.first (token)) {
 - ContentModelState nextState;
 - if (model.type == 0)
 - return next;
 - if (model.next == null)
 - nextState = new ContentModelState (model.content, next);
 - else {
 - nextState = new ContentModelState (model.content, this);
 - model = model.next;
 - }
 - return nextState.advance (token);
 - } else if (model.empty () && next != null) {
 - return next.advance (token);
 - }
 - break;
 - case 0:
 - if (model.content == token)
 - return next;
 - // FALLTHROUGH
 - default:
 - // FALLTHROUGH
 - }
 - throw new EndOfInputException ();
 - }
 - }