Package net.sourceforge.chaperon.model.grammar

Source Code of net.sourceforge.chaperon.model.grammar.GrammarFactory

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

import net.sourceforge.chaperon.model.symbol.Nonterminal;
import net.sourceforge.chaperon.model.symbol.Symbol;
import net.sourceforge.chaperon.model.symbol.Terminal;

import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.util.Hashtable;
import java.util.Stack;

/**
* This class should generate a grammar from a SAX stream
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels </a>
* @version CVS $Id: GrammarFactory.java,v 1.5 2003/12/14 09:48:34 benedikta Exp $
*/
public class GrammarFactory extends DefaultHandler
{
  /** The namspace of the grammar configuration */
  public static final String NS = "http://chaperon.sourceforge.net/schema/grammar/1.0";

  /** Element name */
  public static final String GRAMMAR_ELEMENT = "grammar";

  /** Attribute name of the associativity property */

  // public final static String TOKEN_ASSOCIATIVE_ATTRIBUTE = "assoc";

  /** Element name */
  public static final String PRODUCTION_ELEMENT = "production";

  /** Attribute name of the Precedence property */
  public static final String PRECEDENCE_ATTRIBUTE = "precedence";

  /** Element name */
  public static final String NONTERMINALSYMBOL_ELEMENT = "nonterminal";

  /** Element name */
  public static final String TERMINALSYMBOL_ELEMENT = "terminal";

  /** Element name */
  public static final String ERRORSYMBOL_ELEMENT = "error";

  /** Element name */
  public static final String STARTSYMBOL_ELEMENT = "start";

  /** Element name */
  public static final String PRIORITY_ELEMENT = "priority";

  /** Element name */
  public static final String ASSOCIATIVITY_ELEMENT = "associativity";

  /** Attribute name of the associativity property */
  public static final String TYPE_ATTRIBUTE = "type";

  /** Attribute name */
  public static final String SYMBOL_ATTRIBUTE = "symbol";
  private static final int STATE_OUTER = 0;
  private static final int STATE_GRAMMAR = 1;
  private static final int STATE_PRODUCTION = 2;
  private static final int STATE_START = 3;
  private static final int STATE_NONTERMINAL = 4;
  private static final int STATE_TERMINAL = 5;
  private static final int STATE_ASSOCIATIVITY = 6;
  private static final int STATE_PRIORITY = 7;
  private static final int STATE_PRIORITYTERMINAL = 8;
  private static final int STATE_ERROR = 9;
  private int state = STATE_OUTER;
  private Grammar grammar;
  private Hashtable terminals = new Hashtable();
  private Hashtable nonterminals = new Hashtable();
  private Stack stack;
  private Locator locator = null;
  private int priorities = 0;

  /**
   * Returns the generated Grammar
   *
   * @return Grammar
   */
  public Grammar getGrammar()
  {
    return grammar;
  }

  private String getLocation()
  {
    if (locator==null)
      return "unknown";

    return locator.getSystemId()+":"+locator.getLineNumber()+":"+locator.getColumnNumber();
  }

  /**
   * Receive an object for locating the origin of SAX document events.
   */
  public void setDocumentLocator(Locator locator)
  {
    this.locator = locator;
  }

  /**
   * Receive notification of the beginning of a document.
   */
  public void startDocument()
  {
    stack = new Stack();

    state = STATE_OUTER;
  }

  /**
   * Return the content of the associatve attribute
   *
   * @param namespaceURI
   * @param localName
   * @param qName
   * @param atts Attributes of an element
   *
   * @throws SAXException
   */

  /*private Associativity getAssociativityFromAttributes(Attributes atts)
  {
    String attribute = atts.getValue(TOKEN_ASSOCIATIVE_ATTRIBUTE);

    if ((attribute != null) && (attribute.length() > 0))
      return Associativity.valueOf(attribute);
    return Associativity.NONASSOC;
  }*/

  /**
   * Return the content of the reducetype attribute
   *
   * @param atts Attributes of an element
   *
   * @return Reducetype attribute
   */

  /*private ReduceType getReduceTypeFromAttributes(Attributes atts)
  {
    String attribute = atts.getValue(PRODUCTION_REDUCETYPE_ATTRIBUTE);

    if ((attribute != null) && (attribute.length() > 0))
      return ReduceType.valueOf(attribute);
    return ReduceType.NORMAL;
  }*/

  /**
   * Receive notification of the beginning of an element.
   *
   * @param namespaceURI The Namespace URI, or the empty string if the element has no Namespace URI
   *        or if Namespace processing is not being performed.
   * @param localName The local name (without prefix), or the empty string if Namespace processing
   *        is not being performed.
   * @param qName The raw XML 1.0 name (with prefix), or the empty string if raw names are not
   *        available.
   * @param atts The attributes attached to the element. If there are no attributes, it shall be an
   *        empty Attributes object.
   */
  public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
    throws SAXException
  {
    if (namespaceURI.equals(NS))
    {
      if ((localName.equals(GRAMMAR_ELEMENT)) && (state==STATE_OUTER))
      {
        grammar = new Grammar();
        grammar.setLocation(getLocation());
        stack.push(grammar);

        state = STATE_GRAMMAR;
      }
      else if ((localName.equals(PRODUCTION_ELEMENT)) && (state==STATE_GRAMMAR))
      {
        Production production =
          new Production(getNonterminal(nonterminals, atts.getValue(SYMBOL_ATTRIBUTE)));
        production.setLocation(getLocation());

        String precedencesymbol = atts.getValue(PRECEDENCE_ATTRIBUTE);
        if ((precedencesymbol!=null) && (precedencesymbol.length()>0))
          production.setPrecedence(new Terminal(precedencesymbol));

        stack.push(production);

        state = STATE_PRODUCTION;
      }
      else if ((localName.equals(NONTERMINALSYMBOL_ELEMENT)) && (state==STATE_PRODUCTION))
      {
        stack.push(getNonterminal(nonterminals, atts.getValue(SYMBOL_ATTRIBUTE)));

        state = STATE_NONTERMINAL;
      }
      else if ((localName.equals(TERMINALSYMBOL_ELEMENT)) && (state==STATE_PRODUCTION))
      {
        stack.push(new Terminal(atts.getValue(SYMBOL_ATTRIBUTE)));

        state = STATE_TERMINAL;
      }
      else if ((localName.equals(ERRORSYMBOL_ELEMENT)) && (state==STATE_PRODUCTION))
      {
        stack.push(new Error());

        state = STATE_ERROR;
      }
      else if ((localName.equals(STARTSYMBOL_ELEMENT)) && (state==STATE_GRAMMAR))
      {
        stack.push(new Nonterminal(atts.getValue(SYMBOL_ATTRIBUTE)));

        state = STATE_START;
      }
      else if ((localName.equals(ASSOCIATIVITY_ELEMENT)) && (state==STATE_GRAMMAR))
      {
        grammar.setAssociativity(getTerminal(terminals, atts.getValue(SYMBOL_ATTRIBUTE)),
                                 new Associativity(atts.getValue(TYPE_ATTRIBUTE)));

        state = STATE_ASSOCIATIVITY;
      }
      else if ((localName.equals(PRIORITY_ELEMENT)) && (state==STATE_GRAMMAR))
      {
        priorities = 0;

        state = STATE_PRIORITY;
      }
      else if ((localName.equals(TERMINALSYMBOL_ELEMENT)) && (state==STATE_PRIORITY))
      {
        stack.push(getTerminal(terminals, atts.getValue(SYMBOL_ATTRIBUTE)));

        priorities++;

        state = STATE_PRIORITYTERMINAL;
      }
      else
        throw new SAXException("Unexpected element "+qName+" at "+getLocation());
    }
    else
      throw new SAXException("Unexpected element "+qName+" at "+getLocation());
  }

  /**
   * Receive notification of the end of an element.
   *
   * @param namespaceURI The Namespace URI, or the empty string if the element has no Namespace URI
   *        or if Namespace processing is not being performed.
   * @param localName The local name (without prefix), or the empty string if Namespace processing
   *        is not being performed.
   * @param qName The raw XML 1.0 name (with prefix), or the empty string if raw names are not
   *        available.
   *
   * @throws SAXException
   */
  public void endElement(String namespaceURI, String localName, String qName)
    throws SAXException
  {
    if (namespaceURI.equals(NS))
    {
      if ((localName.equals(GRAMMAR_ELEMENT)) && (state==STATE_GRAMMAR))
      {
        grammar = (Grammar)stack.pop();

        state = STATE_OUTER;
      }
      else if ((localName.equals(PRODUCTION_ELEMENT)) && (state==STATE_PRODUCTION))
      {
        Production production = (Production)stack.pop();
        Grammar grammar = (Grammar)stack.peek();

        grammar.addProduction(production);

        state = STATE_GRAMMAR;
      }
      else if ((localName.equals(NONTERMINALSYMBOL_ELEMENT)) && (state==STATE_NONTERMINAL))
      {
        Symbol ntsymbol = (Symbol)stack.pop();
        Production production = (Production)stack.peek();

        production.getDefinition().addSymbol(ntsymbol);

        state = STATE_PRODUCTION;
      }
      else if ((localName.equals(TERMINALSYMBOL_ELEMENT)) && (state==STATE_TERMINAL))
      {
        Symbol tsymbol = (Symbol)stack.pop();
        Production production = (Production)stack.peek();

        production.getDefinition().addSymbol(tsymbol);

        state = STATE_PRODUCTION;
      }
      else if ((localName.equals(ERRORSYMBOL_ELEMENT)) && (state==STATE_ERROR))
      {
        Symbol error = (Symbol)stack.pop();
        Production production = (Production)stack.peek();

        production.getDefinition().addSymbol(error);

        state = STATE_PRODUCTION;
      }
      else if ((localName.equals(STARTSYMBOL_ELEMENT)) && (state==STATE_START))
      {
        Nonterminal ssymbol = (Nonterminal)stack.pop();
        Grammar grammar = (Grammar)stack.peek();

        grammar.setStartSymbol(ssymbol);

        state = STATE_GRAMMAR;
      }
      else if ((localName.equals(ASSOCIATIVITY_ELEMENT)) && (state==STATE_ASSOCIATIVITY))
        state = STATE_GRAMMAR;
      else if ((localName.equals(PRIORITY_ELEMENT)) && (state==STATE_PRIORITY))
      {
        int i = 0;
        while (stack.peek() instanceof Terminal)
        {
          grammar.setPriority((Terminal)stack.pop(), i+1);
          i++;
        }

        state = STATE_GRAMMAR;
      }
      else if ((localName.equals(TERMINALSYMBOL_ELEMENT)) && (state==STATE_PRIORITYTERMINAL))
        state = STATE_PRIORITY;
      else
        throw new SAXException("Unexpected element "+qName+" at "+getLocation());
    }
    else
      throw new SAXException("Unexpected element "+qName+" at "+getLocation());
  }

  private Terminal getTerminal(Hashtable terminals, String name)
  {
    Terminal terminal = (Terminal)terminals.get(name);
    if (terminal==null)
    {
      terminal = new Terminal(name);
      terminals.put(name, terminal);
    }

    return terminal;
  }

  private Nonterminal getNonterminal(Hashtable nonterminals, String name)
  {
    Nonterminal nonterminal = (Nonterminal)nonterminals.get(name);
    if (nonterminal==null)
    {
      nonterminal = new Nonterminal(name);
      nonterminals.put(name, nonterminal);
    }

    return nonterminal;
  }
}
TOP

Related Classes of net.sourceforge.chaperon.model.grammar.GrammarFactory

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.