Package net.sourceforge.chaperon.process.extended

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

/*
*  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.common.Decoder;
import net.sourceforge.chaperon.common.SortedCharSet;
import net.sourceforge.chaperon.common.StringSet;
import net.sourceforge.chaperon.model.extended.Definition;
import net.sourceforge.chaperon.model.extended.Element;
import net.sourceforge.chaperon.model.extended.ExtendedGrammar;
import net.sourceforge.chaperon.model.extended.Pattern;
import net.sourceforge.chaperon.model.extended.PatternIterator;
import net.sourceforge.chaperon.model.extended.PatternSet;

import org.apache.commons.logging.Log;

import java.util.HashMap;

/**
* This class contains a automaton of states.
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id: ExtendedParserAutomaton.java,v 1.3 2004/01/08 11:30:52 benedikta Exp $
*/
public class ExtendedParserAutomaton
{
  //private ArrayList states = new ArrayList();
  public State first = null;
  private ExtendedGrammar grammar;
  private Log log;

  // intermediate used sets
  private String[] symbols;
  private PatternSet[] firstSets;
  private PatternSet[] lastSets;
  private boolean[] nullable;
  private HashMap definitions = new HashMap();

  //private PatternMap kernelFollowSet;
  //private PatternMap followFirstSet;
  //private PatternMap followLastSet;

  /**
   * Create a new automaton of states, calculated with  the aid of the grammar. The constructor
   * calculates all state  and transitions and combine all states with the same core.
   *
   * @param grammar ExtendedGrammar.
   */
  public ExtendedParserAutomaton(ExtendedGrammar grammar)
  {
    this(grammar, null);
  }

  /**
   * Create a new automaton of states, calculated with  the aid of the grammar. The constructor
   * calculates all state  and transitions and combine all states with the same core.
   *
   * @param grammar ExtendedGrammar
   * @param firstsets First sets.
   * @param log Log, which should be used.
   */
  public ExtendedParserAutomaton(ExtendedGrammar grammar, Log log)
  {
    this.grammar = grammar;
    this.log = log;

    symbols = new String[grammar.getDefinitionCount()];
    firstSets = new PatternSet[grammar.getDefinitionCount()];
    lastSets = new PatternSet[grammar.getDefinitionCount()];
    nullable = new boolean[grammar.getDefinitionCount()];
    definitions = new HashMap();

    for (int i = 0; i<grammar.getDefinitionCount(); i++)
    {
      symbols[i] = grammar.getDefinition(i).getSymbol();
      firstSets[i] = grammar.getDefinition(i).getFirstSet();
      lastSets[i] = grammar.getDefinition(i).getLastSet();
      nullable[i] = grammar.getDefinition(i).isNullable();

      for (PatternIterator pattern = firstSets[i].getPattern(); pattern.hasNext();)
        definitions.put(pattern.next(), grammar.getDefinition(i));

      for (PatternIterator pattern = lastSets[i].getPattern(); pattern.hasNext();)
        definitions.put(pattern.next(), grammar.getDefinition(i));
    }

    grammar.update();

    //System.out.println("followLastSet=\n"+followLastSet);
    // C = closure( [S'=^S] )
    addState(getStartState());

    for (State state = first; state!=null; state = state.next)
    {
      //State state = getState(i);
      //System.out.println("\nState "+i+"\n"+state);
      SortedCharSet limits = new SortedCharSet();
      StringSet nonterminals = new StringSet();
      PatternSet gotoPattern = new PatternSet();

      for (Item item = state.first; item!=null; item = item.next)
      {
        if (item.position==Item.SHIFT)
        {
          if (item.pattern.getSymbol()!=null)
            nonterminals.addString(item.pattern.getSymbol());

          limits.addChar(item.pattern.getLimits());
        }
        else if (item.position==Item.GOTO)
          gotoPattern.addPattern(item.pattern);

        limits.addChar(item.lookahead.getLimits());
      }

//      System.out.println("limits="+limits);
//      System.out.println("nonterminals="+nonterminals);
//      System.out.println("gotoPattern="+gotoPattern);
      // for all other characters from the begin
      if ((limits.getCharCount()>=1) && (limits.getChar(0)>'\u0000'))
      {
        addShiftAction(state, '\u0000', (char)(limits.getChar(0)-1));
        addReduceAction(state, '\u0000', (char)(limits.getChar(0)-1));
      }

      // for each character
      for (int j = 0; j<limits.getCharCount(); j++)
      {
        if ((j>0) && ((limits.getChar(j)-limits.getChar(j-1))>1))
        {
          addShiftAction(state, (char)(limits.getChar(j-1)+1), (char)(limits.getChar(j)-1));
          addReduceAction(state, (char)(limits.getChar(j-1)+1), (char)(limits.getChar(j)-1));
        }

        addShiftAction(state, limits.getChar(j), limits.getChar(j));
        addReduceAction(state, limits.getChar(j), limits.getChar(j));
      }

      // for all other characters to the end
      if (limits.getCharCount()>=1)
      {
        addShiftAction(state, (char)(limits.getChar(limits.getCharCount()-1)+1), '\u4000');
        addReduceAction(state, (char)(limits.getChar(limits.getCharCount()-1)+1), '\u4000');
      }

      // for universal characters
      if (limits.getCharCount()==0)
      {
        addShiftAction(state, '\u0000', '\u4000');
        addReduceAction(state, '\u0000', '\u4000');
      }

      // for each nonterminal
      for (int j = 0; j<nonterminals.getStringCount(); j++)
        addGotoAction(state, nonterminals.getString(j));

      for (PatternIterator pattern = gotoPattern.getPattern(); pattern.hasNext();)
        addGotoAction(state, pattern.next());

      addReduceAction(state);
    }
  }

  private boolean isNullable(String symbol)
  {
    for (int i = 0; i<symbols.length; i++)
      if (symbols[i].equals(symbol))
        return nullable[i];

    return true;
  }

  private String getSymbol(Pattern pattern)
  {
    return ((Definition)definitions.get(pattern)).getSymbol();
  }

  /**
   * Return the state as start point for the calculation.
   *
   * @return Start point for the calculation.
   */
  private State getStartState()
  {
    if (grammar.getStartSymbol()==null)
      throw new IllegalArgumentException("Start symbol is not defined");

    PatternSet firstSet = grammar.getFirstSet();

    System.out.println("firstset = "+firstSet);

    State state = new State(grammar);

    for (PatternIterator pattern = firstSet.getPattern(); pattern.hasNext();)
    {
      Pattern firstPattern = pattern.next();
      Item item =
        new Item(((Definition)definitions.get(firstPattern)).getSymbol(), firstPattern, Item.SHIFT,
                 null);

      //item.end = true;
      state.addItem(item);
    }

    closure(state);

    return state;
  }

  public ExtendedGrammar getExtendedGrammar()
  {
    return grammar;
  }

  /**
   * Add a state to this automaton.
   *
   * @param state State.
   *
   * @return Index of the state in the automaton.
   */
  public State addState(State newState)
  {
    if (first==null)
    {
      first = newState;
      return newState;
    }

    for (State state = first; state!=null; state = state.next)
    {
      if (state.equals(newState))
        return state;

      if (state.next==null)
      {
        state.next = newState;
        return newState;
      }
    }

    return newState;
  }

  /**
   * Return the index of an state. If the automaton does not contain the state, then return this
   * method will return -1.
   *
   * @param state State, which should be found.
   *
   * @return Index of the state.
   */
  public int indexOf(State foreignState)
  {
    int index = 0;
    for (State state = first; state!=null; state = state.next, index++)
      if (state.equals(foreignState))
        return index;

    return -1;
  }

  /**
   * If this automaton contains the state.
   *
   * @param state State, which should be found.
   *
   * @return True, if the automaton contains the state.
   */
  public boolean contains(State foreignState)
  {
    for (State state = first; state!=null; state = state.next)
      if (state.equals(foreignState))
        return true;

    return false;
  }

  public void closure(State state)
  {
    System.out.println("=====================================\nbefore:\n"+state);
    for (Item item = state.first; item!=null; item = item.next)
    {
      System.out.println("item = "+item+" position="+item.position+" element="+
                         (item.pattern instanceof Element));
      if ((item.position==Item.SHIFT) && (item.pattern instanceof Element))
      {
        System.out.println("add firstset");

        String symbol = ((Element)item.pattern).getSymbol();
        System.out.println("pattern="+item.pattern);

        Definition definition = ((Definition)definitions.get(item.pattern));
        PatternSet firstSet = grammar.getFirstSet(symbol);
        for (PatternIterator pattern = firstSet.getPattern(); pattern.hasNext();)
        {
          Pattern firstPattern = pattern.next();

          //Definition definition = ((Definition)definitions.get(firstSet.getPattern(l)));
          if (definition.getLastSet().contains(item.pattern))
            state.addItem(new Item(symbol, firstPattern, Item.SHIFT, item.lookahead));

          for (PatternIterator lookaheads = item.pattern.getSuccessors(); lookaheads.hasNext();)
          {
            Pattern lookahead = lookaheads.next();
            if (!(lookahead instanceof Element))
              state.addItem(new Item(symbol, firstPattern, Item.SHIFT, lookahead));
          }

          for (PatternIterator lookaheads = item.pattern.getAscendingSuccessors();
               lookaheads.hasNext();)
          {
            Pattern lookahead = lookaheads.next();
            if (!(lookahead instanceof Element))
              state.addItem(new Item(symbol, firstPattern, Item.SHIFT, lookahead));
          }
        }
      }
    }

    System.out.println("after:\n"+state+"\n");
  }

  private void addShiftAction(State state, char minimum, char maximum)
  {
    State newState = new State(grammar);
    for (Item item = state.first; item!=null; item = item.next)
      if ((item.position==Item.SHIFT) && (item.pattern.contains(minimum, maximum)))
      {
        newState.addItem(item.getFollowItem());

        for (PatternIterator successors = item.pattern.getSuccessors(); successors.hasNext();)
          newState.addItem(new Item(item.pattern, successors.next(), Item.SHIFT, item.lookahead));
      }

    if (!newState.isEmpty())
    {
      closure(newState);
      newState = addState(newState);

      //System.out.println("add shift action for "+Decoder.toClass(minimum, maximum));
      state.addShiftAction(minimum, maximum, newState);
    }
  }

  private void addGotoAction(State state, String symbol)
  {
    State newState = new State(grammar);
    for (Item item = state.first; item!=null; item = item.next)
      if ((item.position==Item.SHIFT) && (item.pattern instanceof Element) &&
          (((Element)item.pattern).getSymbol().equals(symbol)))
      {
        newState.addItem(item.getFollowItem());

        for (PatternIterator successors = item.pattern.getSuccessors(); successors.hasNext();)
          newState.addItem(new Item(item.pattern, successors.next(), Item.SHIFT, item.lookahead));
      }

    if (!newState.isEmpty())
    {
      closure(newState);
      newState = addState(newState);
      state.addGotoAction(symbol, newState);
    }
  }

  private void addGotoAction(State state, Pattern pattern)
  {
    State newState = new State(grammar);
    for (Item item = state.first; item!=null; item = item.next)
      if ((item.position==Item.GOTO) && (item.pattern==pattern))
        newState.addItem(item.getFollowItem());

    if (!newState.isEmpty())
    {
      closure(newState);
      newState = addState(newState);
      state.addGotoAction(pattern, newState);
    }
  }

  private void addReduceAction(State state, char minimum, char maximum)
  {
    for (Item item = state.first; item!=null; item = item.next)
      if (item.position==Item.SHIFT)
      {
        for (PatternIterator successors = item.pattern.getDescendingSuccessors();
             successors.hasNext();)
          if (successors.next().contains(minimum, maximum))
            if ((item.pattern.getSymbol()!=null) && (isNullable(item.pattern.getSymbol())))
            {
              state.addLookaheadReduceAction(minimum, maximum, item.pattern.getSymbol(), 0);
              break;
            }
      }
      else if (item.position==Item.GOTO)
      {
        for (int k = 0; k<lastSets.length; k++)
          if (lastSets[k].contains(item.pattern))
          {
            for (PatternIterator successors = item.pattern.getDescendingSuccessors();
                 successors.hasNext();)
              if (successors.next().contains(minimum, maximum))
              {
                state.addLookaheadReduceAction(minimum, maximum, item.pattern, 0);

                break;
              }
          }
      }
      else if (item.position==Item.REDUCE)
      {
        for (PatternIterator successors = item.pattern.getDescendingSuccessors();
             successors.hasNext();)
          if (successors.next().contains(minimum, maximum))
          {
            if (item.symbol!=null)
              state.addLookaheadReduceAction(minimum, maximum, item.symbol, 2);
            else
              state.addLookaheadReduceAction(minimum, maximum, item.previous, 2);

            break;
          }
      }
  }

  private void addReduceAction(State state)
  {
    for (Item item = state.first; item!=null; item = item.next)
      if (item.position==Item.SHIFT)
      {
        if (grammar.getLastSet().contains(item.pattern))
          if ((item.pattern instanceof Element) &&
              (isNullable(((Element)item.pattern).getSymbol())))
            state.addReduceAction(((Element)item.pattern).getSymbol(), 0);
      }
      else if (item.position==Item.GOTO)
      {
        for (int k = 0; k<lastSets.length; k++)
          if (lastSets[k].contains(item.pattern))
          {
            if (grammar.getLastSet().contains(item.pattern))
              state.addReduceAction(item.pattern, 0);
          }
      }
      else if (item.position==Item.REDUCE)
      {
        if (grammar.getLastSet().contains(item.pattern))
        {
          if (item.symbol!=null)
            state.addReduceAction(item.symbol, 2);
          else
            state.addReduceAction(item.previous, 2);
        }
      }
  }

  /**
   * Return a string representation of the automaton.
   *
   * @return String representation of the automaton.
   */
  public String toString()
  {
    StringBuffer buffer = new StringBuffer();

    for (State state = first; state!=null; state = state.next)
    {
      buffer.append("State ");
      buffer.append(indexOf(state));
      buffer.append(":\n");
      buffer.append(state.toString());

      //buffer.append(grammar.toString(getState(i).getPreviousPattern(), getState(i).getNextPattern()));
      //buffer.append(":\n");
      ShiftAction[] shiftActions = state.getShiftActions();
      for (int index = 0; index<shiftActions.length; index++)
      {
        buffer.append("Shift  ");
        buffer.append(Decoder.toClass(shiftActions[index].minimum, shiftActions[index].maximum));
        buffer.append(" -> State ");
        buffer.append(indexOf(shiftActions[index].state));
        buffer.append("\n");
      }

      LookaheadReduceAction[] lookaheadReduceActions = state.getLookaheadReduceActions();
      for (int index = 0; index<lookaheadReduceActions.length; index++)
      {
        buffer.append("Reduce ");

        if (lookaheadReduceActions[index].symbol!=null)
          buffer.append(lookaheadReduceActions[index].symbol);
        else
          buffer.append(lookaheadReduceActions[index].pattern);

        buffer.append(" for  ");
        buffer.append(Decoder.toClass(lookaheadReduceActions[index].minimum,
                                      lookaheadReduceActions[index].maximum));

        buffer.append("\n");
      }

      ReduceAction[] reduceActions = state.getReduceActions();
      for (int index = 0; index<reduceActions.length; index++)
      {
        buffer.append("Reduce ");

        if (reduceActions[index].symbol!=null)
          buffer.append(reduceActions[index].symbol);
        else
          buffer.append(reduceActions[index].pattern);

        buffer.append("\n");
      }

      GotoAction[] gotoactions = state.getGotoActions();
      for (int index = 0; index<gotoactions.length; index++)
      {
        buffer.append("Goto ");

        if (gotoactions[index].symbol!=null)
          buffer.append(gotoactions[index].symbol);
        else
          buffer.append(gotoactions[index].pattern);

        buffer.append(" -> State ");
        buffer.append(indexOf(gotoactions[index].state));
        buffer.append("\n");
      }

      buffer.append("\n");
    }

    return buffer.toString();
  }
}
TOP

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

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.