Package net.sourceforge.chaperon.parser

Source Code of net.sourceforge.chaperon.parser.Parser$ProductionContainer

/*
*  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.parser;

import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Stack;
import java.util.Vector;

import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.Logger;

import net.sourceforge.chaperon.helpers.Decoder;
import net.sourceforge.chaperon.helpers.IntegerList;

import net.sourceforge.chaperon.parser.output.EventListener;
import net.sourceforge.chaperon.parser.output.EventQueue;

/**
* A LR Parser, which implements a stack maschine
*
* @author Stephan Michels
* @version CVS $Id: Parser.java,v 1.11 2002/05/07 11:01:49 benedikta Exp $
*/
public class Parser implements LogEnabled
{

  private Logger _logger;

  /**
   * Provide component with a logger.
   *
   * @param logger the logger
   */
  public void enableLogging(Logger logger)
  {
    _logger = logger;
  }

  /*
   * Parse the document given by an inputstream
   *
   * @param table Parser table
   * @param input InputStream
   *
   * @return Structured document
   *
   * @throws ParserException
   */
  public EventQueue parse(ParserTable table, InputStream input) throws ParserException
  {
    try
    {
      return parse(table, input, null);
    } catch (UnsupportedEncodingException uee)
    {
      System.err.println("Encoding is not supported:"+uee.getMessage());
    }
    return null;
  }

  /*
   * Parse the document given by an inputstream
   *
   * @param table Parser table
   * @param input InputStream
   * @param encoding Encoding the document
   *
   * @return Structured document
   *
   * @throws ParserException
   */
  public EventQueue parse(ParserTable table, InputStream input, String encoding)
    throws ParserException, UnsupportedEncodingException
  {
    if (input== null)
      throw new NullPointerException("Inputstream is null");

    if (table == null)
      throw new NullPointerException("ParserTable is null");

    Scanner scanner = new Scanner(table);
    if ((encoding!=null) && (encoding.length()>0))
      scanner.parse(input, encoding);
    else
      scanner.parse(input);

    char[] text = scanner.getTextAsChars();

    long time = System.currentTimeMillis();

    int state = 0; // Current state
    int i, j, oldstate;
    IntegerList stack = new IntegerList();
    stack.push(0); // First state is zero
    Stack treestack = new Stack();

    int tokenindex = -1;   // Index of the token from the input

    while (true)
    {
      state = stack.peek();

      /* ============================= Reading token ================================ */
      if (tokenindex < 0)
      {
        do
        {
          scanner.readNextToken(state);
          tokenindex = scanner.getTokenIndex();

          //System.out.println("tokenindex="+tokenindex+" ignorable="+scanner.isIgnorable());

          if (scanner.isIgnorable())
          {
            TokenContainer tokencontainer = new TokenContainer();
            tokencontainer.tokenindex = tokenindex;
            tokencontainer.textstart = scanner.getTextStart();
            tokencontainer.textlength = scanner.getTextLength();
            tokencontainer.ignorable = true;
            treestack.push(tokencontainer);
          }
        } while ((tokenindex>=0) && (scanner.isIgnorable()));

        if (tokenindex < 0)
        {
          if (_logger!=null)
            _logger.debug("State " + state + " no token could get recognized");

          Vector acceptedsymbols = new Vector();

          for (tokenindex = 0; tokenindex < table.getTerminalSymbolCount(); tokenindex++)
            if (!table.isErrorAction(state, tokenindex))
              acceptedsymbols.addElement(table.getTerminalSymbol(tokenindex));

          String[] symbols = new String[acceptedsymbols.size()];

          for (i = 0; i < acceptedsymbols.size(); i++)
            symbols[i] = (String) acceptedsymbols.elementAt(i);

          throw new ParserException("Token was not recognized",
                                    scanner.getLineNumber(),
                                    scanner.getColumnNumber(), symbols);
        }
      }

      switch (table.getAction(state, tokenindex))
      {
      /* ================================== Error =================================== */
      case ParserTable.ERROR :
        if (_logger!=null)
          _logger.debug("State " + state + " error token \"" +
                        Decoder.decode(new String(text, scanner.getTextStart(), scanner.getTextLength())) +
                        "\"("+table.getTerminalSymbol(tokenindex)+")");

        Vector acceptedsymbols = new Vector();

        for (tokenindex = 0; tokenindex < table.getTerminalSymbolCount(); tokenindex++)
          if (!table.isErrorAction(state, tokenindex))
            acceptedsymbols.addElement(table.getTerminalSymbol(tokenindex));

        String[] symbols = new String[acceptedsymbols.size()];

        for (i = 0; i < acceptedsymbols.size(); i++)
          symbols[i] = (String) acceptedsymbols.elementAt(i);

        throw new ParserException("Token was not recognized",
                                  scanner.getLineNumber(),
                                  scanner.getColumnNumber(), symbols);

      /* ==================================== Shift  =================================== */
      case ParserTable.SHIFT :
        if (_logger!=null)
          _logger.debug("State " + state + " shift token \"" +
                        Decoder.decode(new String(text, scanner.getTextStart(), scanner.getTextLength())) +
                        "\"("+table.getTerminalSymbol(tokenindex)+")");
        TokenContainer tokencontainer = new TokenContainer();
        tokencontainer.tokenindex = tokenindex;
        tokencontainer.textstart = scanner.getTextStart();
        tokencontainer.textlength = scanner.getTextLength();
        treestack.push(tokencontainer);

        stack.push(table.getActionArgument(state, tokenindex));
        tokenindex = -1;
        break;
     
      /* ============================ Reduce & Accept =================================== */
      case ParserTable.REDUCE :
      case ParserTable.ACCEPT :
        if (_logger!=null)
          _logger.debug("State " + state + " reduce by " +
                        table.getNonTerminalSymbol(table.getProductionSymbol(
                          table.getActionArgument(state, tokenindex))) +
                        " (" + (table.getActionArgument(state, tokenindex)) + ")");
        ProductionContainer newcontainer = new ProductionContainer();
        newcontainer.productionindex = table.getActionArgument(state, tokenindex);

        for (i = 0; i < table.getProductionLength(table.getActionArgument(state, tokenindex));  i++)
        {
          if (treestack.peek() instanceof ProductionContainer)
          {
            stack.pop();
            ProductionContainer container = (ProductionContainer) treestack.pop();
            switch (table.getProductionReduceType(container.productionindex))
            {
              case ParserTable.APPEND : // APPEND
                if (table.getProductionSymbol(newcontainer.productionindex)==
                    table.getProductionSymbol(container.productionindex))
                  newcontainer.insertChilds(container);
                else
                  newcontainer.insert(container);
                break;
 
              case ParserTable.RESOLVE : // RESOLVE
                newcontainer.insertChilds(container);
                break;

              case ParserTable.NORMAL : // NORMAL
                newcontainer.insert(container);
                break;
 
              case ParserTable.NEGLECT : // NEGLECT
                break;
            }
          }
          else
          {
            TokenContainer container = (TokenContainer) treestack.pop();
            newcontainer.insert(container);

            if (container.ignorable)
              i--;
            else
              stack.pop();
          }
        }
        oldstate = stack.peek();
        treestack.push(newcontainer);
        //stack.push(table.getTransition(oldstate, table.getProductionSymbol(table.getActionArgument(state,
        //            tokenindex))));

      /* ================================== Accept =================================== */
        if ((table.isAcceptAction(state, tokenindex)) && (stack.getSize() == 1))
        {
          if (_logger!=null)
           _logger.debug("State " + state + " accept & reduce production " +
                         table.getActionArgument(state, tokenindex));

          stack.pop();
          DocumentContainer documentcontainer = new DocumentContainer(table, text,
            (ProductionContainer)treestack.pop());

          if (_logger!=null)
            _logger.debug("Parsing time " + (System.currentTimeMillis() - time) + " ms");
          return documentcontainer;
        }
        else
          stack.push(table.getTransition(oldstate, table.getProductionSymbol(
            table.getActionArgument(state, tokenindex))));
      }
    }
  }

  private class Container
  {
    public Container previoussibling = null;
    public Container nextsibling = null;
  }

  private class TokenContainer extends Container
  {
    public int tokenindex = -1;
    public int textstart = -1;
    public int textlength = -1;
    public boolean ignorable = false;
  }

  private class ProductionContainer extends Container
  {
    public int productionindex = -1;
    public Container firstchild = null;
    public Container lastchild = null;

    public void insert(Container container)
    {
      if (firstchild==null)
      {
        firstchild = container;
        lastchild = container;
      }
      else
      {
        firstchild.previoussibling = container;
        container.nextsibling = firstchild;
        firstchild = container;
      }
    }

    public void insertChilds(ProductionContainer container)
    {
      if (firstchild==null)
      {
        firstchild = container.firstchild;
        lastchild = container.lastchild;
      }
      else
      {
        firstchild.previoussibling = container.lastchild;
        container.lastchild.nextsibling = firstchild;
        firstchild = container.firstchild;
      }
    }
  }

  private class DocumentContainer implements EventQueue
  {
    private ParserTable _table = null;
    private char[] _text = null;
    private ProductionContainer _root = null;

    private DocumentContainer(ParserTable table, char[] text, ProductionContainer root)
    {
      _table = table;
      _text = text;
      _root = root;
    }

    public void fireEvents(EventListener listener)
    {
      listener.startDocument(_table);
      fireEvents(listener, _root);
      listener.endDocument(_table);
    }

    private void fireEvents(EventListener listener, Container container)
    {
      if (container instanceof ProductionContainer)
      {
        ProductionContainer productioncontainer = (ProductionContainer) container;
        listener.startProduction(_table, productioncontainer.productionindex);
        Container next = productioncontainer.firstchild;
        while (next!=null)
        {
          fireEvents(listener, next);
          next = next.nextsibling;
        }
        listener.endProduction(_table, productioncontainer.productionindex);
      }
      else
      {
        TokenContainer tokencontainer = (TokenContainer)container;
        if (tokencontainer.ignorable)
        {
          listener.startIgnorableToken(_table, tokencontainer.tokenindex,
                                               _text,
                                               tokencontainer.textstart,
                                               tokencontainer.textlength);
          listener.endIgnorableToken(_table, tokencontainer.tokenindex);
        }
        else
        {
          listener.startToken(_table, tokencontainer.tokenindex,       
                                      _text,
                                      tokencontainer.textstart,       
                                      tokencontainer.textlength);
          listener.endToken(_table, tokencontainer.tokenindex);
        }
      }
    }
  }
}
TOP

Related Classes of net.sourceforge.chaperon.parser.Parser$ProductionContainer

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.