Package net.sourceforge.chaperon.process.extended

Source Code of net.sourceforge.chaperon.process.extended.ExtendedGeneralParserProcessor

/*
*  Copyright (C) Chaperon. All rights reserved.
*  -------------------------------------------------------------------------
*  This software is published under the terms of the Apache Software License
*  version 1.1, a copy of which has been included  with this distribution in
*  the LICENSE file.
*/

package net.sourceforge.chaperon.process.extended;

import net.sourceforge.chaperon.model.extended.ExtendedGrammar;

import org.apache.commons.logging.Log;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.LocatorImpl;

/**
* This class represents a simulation of a pushdown automata using the parser automaton class.
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id: ExtendedGeneralParserProcessor.java,v 1.1 2004/01/04 16:49:12 benedikta Exp $
*/
public class ExtendedGeneralParserProcessor implements ContentHandler, LexicalHandler
{
  public static final String NS = "http://chaperon.sourceforge.net/schema/text/1.0";
  public static final String TEXT = "text";

  /** Namespace for the generated SAX events. */
  public static final String NS_OUTPUT = "http://chaperon.sourceforge.net/schema/syntaxtree/2.0";
  public static final String OUTPUT = "output";
  public static final String ERROR = "error";
  private ContentHandler contentHandler = null;
  private LexicalHandler lexicalHandler = null;
  private Locator locator = null;
  private LocatorImpl locatorImpl = null;
  private static final int STATE_OUTER = 0;
  private static final int STATE_INNER = 1;
  private int state = STATE_OUTER;
  private ExtendedParserAutomaton automaton;
  private ExtendedGrammar grammar;
  private boolean flatten = false;
  private StackNodeSet current = new StackNodeSet();
  private StackNodeSet next = new StackNodeSet();
  private Log log;
  private int maxActiveStates = 50;

  /**
   * Create a new parser processor.
   */
  public ExtendedGeneralParserProcessor() {}

  /**
   * Create a new parser processor.
   *
   * @param automaton Parser automaton, which the processor should ues.
   * @param handler Handler, which should receives the parser events.
   * @param log Log, which should used.
   */
  public ExtendedGeneralParserProcessor(ExtendedParserAutomaton automaton, Log log)
  {
    this.automaton = automaton;
    this.log = log;
  }

  /**
   * Set the parser automaton for the processor.
   *
   * @param automaton Parser automaton.
   */
  public void setExtendedParserAutomaton(ExtendedParserAutomaton automaton)
  {
    this.automaton = automaton;
    this.grammar = automaton.getExtendedGrammar();
    current.setExtendedParserAutomaton(automaton);
    next.setExtendedParserAutomaton(automaton);
  }

  /**
   * Set the <code>ContentHandler</code> that will receive XML data.
   */
  public void setContentHandler(ContentHandler handler)
  {
    this.contentHandler = handler;
  }

  /**
   * Set the <code>LexicalHandler</code> that will receive XML data.
   */
  public void setLexicalHandler(LexicalHandler handler)
  {
    this.lexicalHandler = handler;
  }

  /**
   * Provide processor with a log.
   *
   * @param log The log.
   */
  public void setLog(Log log)
  {
    this.log = log;
  }

  /**
   * If the adapter should produce a more flatten XML hirachy, which means elements which the same
   * name will be collapsed
   *
   * @param flatten True, if a more flatten hirachy should be produced.
   */
  public void setFlatten(boolean flatten)
  {
    this.flatten = flatten;
  }

  /**
   * Receive an object for locating the origin of SAX document events.
   */
  public void setDocumentLocator(Locator locator)
  {
    this.locator = locator;
    if (locator!=null)
    {
      this.locatorImpl = new LocatorImpl(locator);
      contentHandler.setDocumentLocator(locatorImpl);
    }
  }

  /**
   * Receive notification of the beginning of a document.
   */
  public void startDocument() throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());
    contentHandler.startDocument();
    state = STATE_OUTER;
  }

  /**
   * Receive notification of the beginning of an element.
   */
  public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
    throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    if (state==STATE_INNER)
      throw new SAXException("Unexpected element "+qName);

    if (state==STATE_OUTER)
    {
      if ((namespaceURI!=null) && (namespaceURI.equals(NS)))
      {
        if (!localName.equals(TEXT))
          throw new SAXException("Unknown element "+qName);
      }
      else
      {
        contentHandler.startElement(namespaceURI, localName, qName, atts);
        return;
      }
    }

    state = STATE_INNER;

    System.out.println("start processing");

    // ======================= Start Text Document =======================
    current.clear();
    current.push(new TerminalStackNode('\u0000', automaton.first, null));
    next.clear();
  }

  /**
   * Receive notification of character data.
   */
  public void characters(char[] text, int textstart, int textlength)
    throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    if (state==STATE_OUTER)
    {
      contentHandler.characters(text, textstart, textlength);
      return;
    }

    System.out.println("process text \""+(new String(text, textstart, textlength))+"\"");

    for (int position = textstart; position<(textstart+textlength); position++)
    {
      System.out.println("\n===================================\nProcess "+text[position]);

      if (current.isEmpty())
        throw new IllegalStateException("Parsing process is aborted");

      printStates();

      //if (current.size()>maxActiveStates)
      //  throw new IllegalStateException("Processor occupied too many states");
      /* ============================ Reduce =================================== */
      System.out.println("Count of states : "+current.size());

      if ((log!=null) && (log.isDebugEnabled()))
        log.debug("------- check reduce actions ---------");

      int watchdog = 0;
      while (!current.isEmpty())
      {
        printStates();

        //if (watchdog++ > 220)
        //  throw new IllegalStateException("overflow");
        //printStates();
        StackNode stackNode = current.pop();

        if (stackNode.state.getShiftAction(text[position])!=null)
          ;

        next.push(stackNode);

        LookaheadReduceAction[] reduceActions = stackNode.state.getLookaheadReduceActions();

        for (int i = 0; i<reduceActions.length; i++)
          if (reduceActions[i].contains(text[position]))
          {
            LookaheadReduceAction reduceAction = reduceActions[i];

            if (reduceAction.length==0)
            {
              GotoAction gotoAction = stackNode.state.getGotoAction(reduceAction);

              if (gotoAction!=null)
              {
                if ((log!=null) && (log.isDebugEnabled()))
                  log.debug("State "+automaton.indexOf(stackNode.state)+" "+reduceAction);

                if (gotoAction.state==stackNode.state)
                  System.out.println("node rejected because states are equal");
                else
                  current.push(new DefinitionStackNode(reduceAction, 0, null, null,
                                                       gotoAction.state, stackNode));
              }
            }
            else
            {
              StackNode second = stackNode;
              for (int j = 0; j<second.ancestors.length; j++)
              {
                StackNode first = second.ancestors[j];
                for (int k = 0; k<first.ancestors.length; k++)
                {
                  StackNode previousStackNode = first.ancestors[k];

                  GotoAction gotoAction = previousStackNode.state.getGotoAction(reduceAction);

                  if (gotoAction!=null)
                  {
                    if ((log!=null) && (log.isDebugEnabled()))
                      log.debug("State "+automaton.indexOf(stackNode.state)+" "+reduceAction);

                    current.push(new DefinitionStackNode(reduceAction, 0, first, second,
                                                         gotoAction.state, previousStackNode));
                  }
                }
              }
            }
          }
      }

      swapStacks();

      printStates();

      /* ==================================== Shift  =================================== */

      //System.out.println("Count of states : "+current.size());
      if ((log!=null) && (log.isDebugEnabled()))
        log.debug("------- check shift actions ---------");

      while (!current.isEmpty())
      {
        //printStates();
        StackNode stackNode = current.pop();

        ShiftAction shiftAction = stackNode.state.getShiftAction(text[position]);

        if (shiftAction!=null)
        {
          if ((log!=null) && (log.isDebugEnabled()))
            log.debug/*"State "+state+*/
            " shift character '"+text[position]+"'");

          next.push(new TerminalStackNode(text[position], shiftAction.state, stackNode));
        }
      }

      if (next.isEmpty())
        throw new IllegalArgumentException("Character '"+text[position]+"' is not expected");

      swapStacks();

      System.out.println("------- finished check actions ---------");

      printStates();
    }
  }

  /**
   * Receive notification of the end of an element.
   */
  public void endElement(String namespaceURI, String localName, String qName)
    throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    if (state==STATE_OUTER)
      contentHandler.endElement(namespaceURI, localName, qName);

    if (state==STATE_INNER)
    {
      if ((namespaceURI!=null) && (namespaceURI.equals(NS)))
      {
        if (!localName.equals(TEXT))
          throw new SAXException("Unknown element "+qName);
      }
      else
        throw new SAXException("Unexpected element "+qName);
    }

    System.out.println("end processing");

    // ======================= End Text Document =======================
    System.out.println("\n===================================\nProcess EOF");

    while (!current.isEmpty())
    {
      printStates();

      StackNode stackNode = current.pop();

      ReduceAction[] reduceActions = stackNode.state.getReduceActions();

      for (int i = 0; i<reduceActions.length; i++)
      {
        ReduceAction reduceAction = reduceActions[i];

        if (reduceAction.length==0)
        {
          GotoAction gotoAction = stackNode.state.getGotoAction(reduceAction);

          if ((automaton.first==stackNode.state) &&
              (grammar.getStartSymbol().equals(reduceAction.symbol)))
          {
            if ((log!=null) && (log.isDebugEnabled()))
              log.debug("State "+automaton.indexOf(stackNode.state)+" accept");

            next.push(new DefinitionStackNode(reduceAction, 0, null, null, null, stackNode));
          }
          else
          {
            if ((log!=null) && (log.isDebugEnabled()))
              log.debug("State "+automaton.indexOf(stackNode.state)+" "+reduceAction);

            if (gotoAction.state==stackNode.state)
              System.out.println("node rejected because states are equal");
            else
              current.push(new DefinitionStackNode(reduceAction, 0, null, null, gotoAction.state,
                                                   stackNode));
          }
        }
        else
        {
          StackNode second = stackNode;

          //System.out.println("second="+automaton.indexOf(second.state));
          for (int j = 0; j<second.ancestors.length; j++)
          {
            StackNode first = second.ancestors[j];

            //System.out.println("first="+automaton.indexOf(first.state));
            //if (second.ancestors.length>1)
            //  System.out.println("nodes="+second.toCanonicalString(automaton));
            for (int k = 0; k<first.ancestors.length; k++)
            {
              StackNode previousStackNode = first.ancestors[k];

              GotoAction gotoAction = previousStackNode.state.getGotoAction(reduceAction);

              //System.out.println("j="+j+" k="+k);
              if ((automaton.first==previousStackNode.state) &&
                  (grammar.getStartSymbol().equals(reduceAction.symbol)))
              {
                if ((log!=null) && (log.isDebugEnabled()))
                  log.debug("State "+automaton.indexOf(stackNode.state)+" accept");

                next.push(new DefinitionStackNode(reduceAction, 0, first, second, null,
                                                  previousStackNode));
              }
              else
              {
                if ((log!=null) && (log.isDebugEnabled()))
                  log.debug("State "+automaton.indexOf(stackNode.state)+" "+reduceAction);

                current.push(new DefinitionStackNode(reduceAction, 0, first, second,
                                                     gotoAction.state, previousStackNode));

                //System.out.println("origin="+automaton.indexOf(previousStackNode.state));
              }
            }
          }
        }
      }
    }

    if (log.isDebugEnabled())
      log.debug("Parser found "+next.size()+" alternatives");

    System.out.println();

    contentHandler.startPrefixMapping("", NS_OUTPUT);
    contentHandler.startElement(NS_OUTPUT, OUTPUT, OUTPUT, new AttributesImpl());

    int index = 1;
    while (!next.isEmpty())
    {
      StackNode node = next.pop();

      node.toXML(contentHandler);
      index++;
    }

    if (next.size()>1)
      log.warn("ExtendedGrammar is ambig, found "+next.size()+" alternative trees");

    contentHandler.endElement(NS_OUTPUT, OUTPUT, OUTPUT);
    contentHandler.endPrefixMapping("");

    state = STATE_OUTER;
  }

  /**
   * Receive notification of ignorable whitespace in element content.
   */
  public void ignorableWhitespace(char[] ch, int start, int length)
    throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    if (state==STATE_OUTER)
      contentHandler.ignorableWhitespace(ch, start, length);
  }

  /**
   * Begin the scope of a prefix-URI Namespace mapping.
   */
  public void startPrefixMapping(String prefix, String uri)
    throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    contentHandler.startPrefixMapping(prefix, uri);
  }

  /**
   * End the scope of a prefix-URI mapping.
   */
  public void endPrefixMapping(String prefix) throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    contentHandler.endPrefixMapping(prefix);
  }

  /**
   * Receive notification of a processing instruction.
   */
  public void processingInstruction(String target, String data)
    throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    if (state==STATE_OUTER)
      contentHandler.processingInstruction(target, data);
  }

  /**
   * Receive notification of a skipped entity.
   */
  public void skippedEntity(String name) throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    if (state==STATE_OUTER)
      contentHandler.skippedEntity(name);
  }

  /**
   * Receive notification of the end of a document.
   */
  public void endDocument() throws SAXException
  {
    locatorImpl.setLineNumber(locator.getLineNumber());
    locatorImpl.setColumnNumber(locator.getColumnNumber());

    if (state==STATE_OUTER)
      contentHandler.endDocument();
  }

  /**
   * Report the start of DTD declarations, if any.
   */
  public void startDTD(String name, String publicId, String systemId)
    throws SAXException
  {
    if (lexicalHandler!=null)
      lexicalHandler.startDTD(name, publicId, systemId);
  }

  /**
   * Report the end of DTD declarations.
   */
  public void endDTD() throws SAXException
  {
    if (lexicalHandler!=null)
      lexicalHandler.endDTD();
  }

  /**
   * Report the beginning of an entity.
   */
  public void startEntity(String name) throws SAXException
  {
    if (lexicalHandler!=null)
      lexicalHandler.startEntity(name);
  }

  /**
   * Report the end of an entity.
   */
  public void endEntity(String name) throws SAXException
  {
    if (lexicalHandler!=null)
      lexicalHandler.endEntity(name);
  }

  /**
   * Report the start of a CDATA section.
   */
  public void startCDATA() throws SAXException
  {
    if (lexicalHandler!=null)
      lexicalHandler.startCDATA();
  }

  /**
   * Report the end of a CDATA section.
   */
  public void endCDATA() throws SAXException
  {
    if (lexicalHandler!=null)
      lexicalHandler.endCDATA();
  }

  /**
   * Report an XML comment anywhere in the document.
   */
  public void comment(char[] ch, int start, int len) throws SAXException
  {
    if (lexicalHandler!=null)
      lexicalHandler.comment(ch, start, len);
  }

  private void printStates()
  {
    System.out.println("Current states:");
    System.out.println(current.toCanonicalString());
    System.out.println("Next states:");
    System.out.println(next.toCanonicalString());
  }

  private void swapStacks()
  {
    StackNodeSet dummy = next;
    next = current;
    current = dummy;
    next.clear();
  }
}
TOP

Related Classes of net.sourceforge.chaperon.process.extended.ExtendedGeneralParserProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.