Package org.rascalmpl.interpreter.matching

Source Code of org.rascalmpl.interpreter.matching.DescendantReader

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:

*   * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*   * Paul Klint - Paul.Klint@cwi.nl - CWI
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.interpreter.matching;

import java.util.Iterator;
import java.util.Stack;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IList;
import org.eclipse.imp.pdb.facts.IMap;
import org.eclipse.imp.pdb.facts.INode;
import org.eclipse.imp.pdb.facts.ISet;
import org.eclipse.imp.pdb.facts.ITuple;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.type.Type;
import org.rascalmpl.interpreter.types.NonTerminalType;
import org.rascalmpl.interpreter.types.RascalTypeFactory;
import org.rascalmpl.values.uptr.Factory;
import org.rascalmpl.values.uptr.SymbolAdapter;
import org.rascalmpl.values.uptr.TreeAdapter;

public class DescendantReader implements Iterator<IValue> {

  Stack<Object> spine = new Stack<Object>();

  private boolean debug = false;

  // is set to true when the descendant reader is allowed to skip layout nodes and do other optimizations
  private boolean interpretTree;
 
  DescendantReader(IValue val, boolean interpretTree){
    if(debug)System.err.println("DescendantReader: " + val);
    this.interpretTree = interpretTree;
    push(val);
  }

  @SuppressWarnings("unchecked")
  public boolean hasNext() {
    while((spine.size() > 0) &&
         (spine.peek() instanceof Iterator && !((Iterator<Object>) spine.peek()).hasNext())){
      spine.pop();
    }   
    return spine.size() > 0;
  }
 
  @SuppressWarnings("unchecked")
  public IValue next() {
    if(spine.peek() instanceof Iterator){
      Iterator<Object> iter = (Iterator<Object>) spine.peek();
      if(!iter.hasNext()){
        spine.pop();
        return next();
      }
      push((IValue) iter.next());
      return next();
    }
    return (IValue) spine.pop();
  }
 
  private void push(IValue v, Iterator<IValue> children){
    spine.push(v);
    spine.push(children);
  }
 
  private void push(IValue v){
    Type type = v.getType();
    if(type.isNode() || type.isConstructor() || type.isAbstractData()){
      if(interpretTree && (type.isConstructor() || type.isAbstractData()) && type == Factory.Tree){
        pushConcreteSyntaxNode((IConstructor) v);
        return;
      }
      push(v,  ((INode) v).getChildren().iterator());
    } else
    if(type.isList()){
      push(v, ((IList) v).iterator());
    } else
    if(type.isSet()){
      push(v, ((ISet) v).iterator());
    } else
    if(type.isMap()){
      push(v, new MapKeyValueIterator((IMap) v));
    } else
    if(type.isTuple()){
      push(v, new TupleElementIterator((ITuple) v));
    } else {
      spine.push(v);
    }
  }
 
  private void pushConcreteSyntaxNode(IConstructor tree){
    if(debug)System.err.println("pushConcreteSyntaxNode: " + tree);
    String name = tree.getName();
   
    if(name.equals("sort") || name.equals("lit") ||
       name.equals("char") || name.equals("single")){
      /*
       * Don't recurse
       */
      spine.push(tree);
      return;
    }
   
    if(TreeAdapter.isAmb(tree)) {
      for (IValue alt : TreeAdapter.getAlternatives(tree)) {
        pushConcreteSyntaxNode((IConstructor) alt);
      }
      return;
//      throw new ImplementationError("Cannot handle ambiguous subject");
    }
     
    NonTerminalType ctype = (NonTerminalType) RascalTypeFactory.getInstance().nonTerminalType(tree);
    if(debug)System.err.println("ctype.getSymbol=" + ctype.getSymbol());
    IConstructor sym = ctype.getSymbol();
        if(SymbolAdapter.isAnyList(sym)){
          sym = SymbolAdapter.getSymbol(sym);
         
          int delta = 1;          // distance between "real" list elements, e.g. non-layout and non-separator
          IList listElems = (IList) tree.get(1);
      if(SymbolAdapter.isIterPlus(sym) || SymbolAdapter.isIterStar(sym)){
        if(debug)System.err.println("pushConcreteSyntaxChildren: isIterPlus or isIterStar");
        delta = 1; // new iters never have layout separators
      } else if (SymbolAdapter.isIterPlusSeps(sym) || SymbolAdapter.isIterStarSeps(sym)) {
        if(debug)System.err.println("pushConcreteSyntaxChildren: isIterPlusSeps or isIterStarSeps");
        delta = SymbolAdapter.getSeparators(sym).length() + 1;
      }
      if(debug)
        for(int i = 0; i < listElems.length(); i++){
          System.err.println("#" + i + ": " + listElems.get(i));
        }
         
      for(int i = listElems.length() - 1; i >= 0 ; i -= delta){
        if(debug)System.err.println("adding: " + listElems.get(i));
        pushConcreteSyntaxNode((IConstructor)listElems.get(i));
      }
    } else {
      if(debug)System.err.println("pushConcreteSyntaxNode: appl");
      /*
       * appl(prod(...), [child0, layout0, child1, ...])
       */
      spine.push(tree);
      IList applArgs = (IList) tree.get(1);
      int delta = (SymbolAdapter.isLiteral(sym)) ? 1 : 2;   // distance between elements
     
      for(int i = applArgs.length() - 1; i >= 0 ; i -= delta){
        //spine.push(applArgs.get(i));
        pushConcreteSyntaxNode((IConstructor) applArgs.get(i));
      }
    }
  }

  public void remove() {
    throw new UnsupportedOperationException("remove from DescendantReader");
  }
}
TOP

Related Classes of org.rascalmpl.interpreter.matching.DescendantReader

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.