Package xtc.parser

Source Code of xtc.parser.ElementVoider

/*
* xtc - The eXTensible Compiler
* Copyright (C) 2005-2007 Robert Grimm
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package xtc.parser;

import xtc.tree.Location;
import xtc.tree.Visitor;

import xtc.util.Runtime;

import xtc.type.AST;

/**
* Visitor to void ordered choices, repetitions, and options.  This
* visitor voids ordered choices, repetitions, and options, if all
* expressions appearing in such an expression are either void
* nonterminals or explicitly voided.  It requires that a grammar has
* been {@link Resolver resolved} into a single module, that text-only
* productions have been {@link TextTester marked} as such, and that
* all expressions have been {@link Simplifier simplified}.
*
* @author Robert Grimm
* @version $Revision: 1.15 $
*/
public class ElementVoider extends Visitor {

  /** The runtime. */
  protected final Runtime runtime;

  /** The analyzer utility. */
  protected final Analyzer analyzer;

  /** The flag for the top-level element. */
  protected boolean isTopLevel;

  /** The flag for the last element. */
  protected boolean isLastElement;

  /** The flag for suppressing the insertion of voided elements. */
  protected boolean suppressVoided;

  /** The flag for potentially having a value. */
  protected boolean hasValue;

  /**
   * Create a new element voider.
   *
   * @param runtime The runtime.
   * @param analyzer The analyzer.
   */
  public ElementVoider(Runtime runtime, Analyzer analyzer) {
    this.runtime  = runtime;
    this.analyzer = analyzer;
  }

  /**
   * Wrap the specified element in a voiding operator.
   *
   * @param el The element to wrap.
   * @return The wrapped element.
   */
  protected Element wrap(Element el) {
    Element  result  = new VoidedElement(el);
    Location loc     = el.getLocation();
    result.setLocation(loc);

    if (runtime.test("optionVerbose")) {
      System.err.println("[Voiding expression at " + loc.line + ":" +
                         loc.column + " in " + analyzer.current().qName + "]");
    }

    return result;
  }

  /** Visit the specified self-contained module. */
  public void visit(Module m) {
    // Initialize the per-grammar state.
    analyzer.register(this);
    analyzer.init(m);

    // Process the productioins.
    for (Production p : m.productions) analyzer.process(p);
  }

  /** Visit the specified full production. */
  public void visit(FullProduction p) {
    // Text-only and token-level productions are ignored.
    if (p.getBooleanProperty(Properties.TEXT_ONLY) ||
        p.getBooleanProperty(Properties.TOKEN)) {
      return;
    }

    isTopLevel     = true;
    isLastElement  = false;
    suppressVoided = AST.isVoid(p.type);
    hasValue       = false;

    p.choice       = (OrderedChoice)dispatch(p.choice);
  }

  /** Visit the specified ordered choice. */
  public Element visit(OrderedChoice c) {
    boolean top   = isTopLevel;
    isTopLevel    = false;
    boolean last  = isLastElement;
    boolean value = hasValue;

    if ((! top) && (! last)) {
      hasValue    = false;
    }

    final int size = c.alternatives.size();
    for (int i=0; i<size; i++) {
      isLastElement = top || last;
      c.alternatives.set(i, (Sequence)dispatch(c.alternatives.get(i)));
    }

    isLastElement  = false;
    Element result = c;
    if ((! top) && (! last)) {
      if (hasValue) {
        hasValue   = true;
      } else {
        hasValue   = value;
        if (! suppressVoided) {
          result   = wrap(result);
        }
      }
    }

    return result;
  }

  /** Visit the specified quantification. */
  public Element visit(Quantification q) {
    isTopLevel     = false;
    isLastElement  = true;
    boolean value  = hasValue;
    hasValue       = false;

    q.element      = (Element)dispatch(q.element);

    isLastElement  = false;
    Element result = q;
    if (hasValue) {
      hasValue     = true;
    } else {
      hasValue     = value;
      if (! suppressVoided) {
        result     = wrap(result);
      }
    }

    return result;
  }

  /** Visit the specified sequence. */
  public Element visit(Sequence s) {
    isTopLevel     = false;
    boolean   last = isLastElement;
    final int size = s.size();

    for (int i=0; i<size; i++) {
      isLastElement = last && (i == size-1);
      s.elements.set(i, (Element)dispatch(s.get(i)));
    }

    isLastElement = false;

    return s;
  }

  /** Visit the specified predicate. */
  public Element visit(Predicate p) {
    isTopLevel       = false;
    isLastElement    = true;
    boolean value    = hasValue;
    hasValue         = false;
    boolean suppress = suppressVoided;
    suppressVoided   = true;

    p.element        = (Element)dispatch(p.element);

    isLastElement    = false;
    hasValue         = value;
    suppressVoided   = suppress;

    return p;
  }

  /** Visit the specified voided element. */
  public VoidedElement visit(VoidedElement v) {
    isTopLevel       = false;
    isLastElement    = true;
    boolean value    = hasValue;
    hasValue         = false;
    boolean suppress = suppressVoided;
    suppressVoided   = true;

    v.element        = (Element)dispatch(v.element);

    isLastElement    = false;
    hasValue         = value;
    suppressVoided   = suppress;

    return v;
  }

  /** Visit the specified binding. */
  public Binding visit(Binding b) {
    isTopLevel       = false;
    isLastElement    = true;
    hasValue         = false;
    boolean suppress = suppressVoided;
    suppressVoided   = false;

    b.element        = (Element)dispatch(b.element);
    if (b.element instanceof VoidedElement) {
      runtime.error("binding for expression without value", b);
    }

    isLastElement    = false;
    hasValue         = true;
    suppressVoided   = suppress;

    return b;
  }

  /** Visit the specified string match. */
  public StringMatch visit(StringMatch m) {
    isTopLevel       = false;
    isLastElement    = true;
    hasValue         = false;
    boolean suppress = suppressVoided;
    suppressVoided   = false;

    m.element        = (Element)dispatch(m.element);
    if (m.element instanceof VoidedElement) {
      runtime.error("match for expression without value", m);
    }

    isLastElement    = false;
    hasValue         = true;
    suppressVoided   = suppress;

    return m;
  }

  /** Visit the specified parser action. */
  public ParserAction visit(ParserAction pa) {
    isTopLevel    = false;
    isLastElement = false;
    hasValue      = true;

    return pa;
  }

  /** Visit the specified action. */
  public Action visit(Action a) {
    isTopLevel    = false;
    isLastElement = false;

    if (a.setsValue()) {
      hasValue = true;
    }

    return a;
  }

  /** Visit the specified nonterminal. */
  public NonTerminal visit(NonTerminal nt) {
    isTopLevel    = false;
    isLastElement = false;

    FullProduction p = analyzer.lookup(nt);
    if (! AST.isVoid(p.type)) {
      hasValue = true;
    }

    return nt;
  }

  /**
   * Visit the specified element.  This method provides the default
   * implementation for terminals, parse tree nodes, null literals,
   * node markers, and value elements.
   */
  public Element visit(Element e) {
    isTopLevel    = false;
    isLastElement = false;
    hasValue      = true;
    return e;
  }

}
TOP

Related Classes of xtc.parser.ElementVoider

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.