Package dk.brics.xact.analysis.xmlgraph

Source Code of dk.brics.xact.analysis.xmlgraph.BackwardsXGAnalyzer

package dk.brics.xact.analysis.xmlgraph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;

import dk.brics.string.util.MultiMap;
import dk.brics.xmlgraph.MultiContentNode;
import dk.brics.xmlgraph.NoContentNode;
import dk.brics.xmlgraph.Node;
import dk.brics.xmlgraph.NodeProcessor;
import dk.brics.xmlgraph.SingleContentNode;
import dk.brics.xmlgraph.XMLGraph;

/**
* Base class for performing backwards dataflow analysis on XML graphs.
* Subclasses should call {@link #doAnalysis()} when the analysis should be
* performed, which by convention should be at the end of its constructor.
* <p/>
* Only reachable nodes are analyzed &ndash; requesting the lattice point for an
* unreachable node will always return <tt>null</tt>.
*
* @param <T> lattice type. Requires a working {@link #equals(Object)}.
*/
public abstract class BackwardsXGAnalyzer<T> {
   
    private XMLGraph xg;
    private MultiMap<Integer,Integer> backedges = new MultiMap<Integer,Integer>();
    private Map<Integer, T> map = new HashMap<Integer, T>();
    private HashSet<Integer> inqueue = new HashSet<Integer>();
    private PriorityQueue<Integer> queue = new PriorityQueue<Integer>();
    private Map<Integer, Integer> node2priority = new HashMap<Integer,Integer>();
    private ArrayList<Integer> priority2node = new ArrayList<Integer>();
   
    public BackwardsXGAnalyzer(XMLGraph xg) {
        this.xg = xg;
    }
    protected void doAnalysis() {
        final Set<Integer> initial = new HashSet<Integer>();
        xg.processReachableNodes(new NodeProcessor<Object>() {
            @Override
            public Object process(MultiContentNode n) {
                initialize(n);
                for (int child : n.getContents()) {
                    backedges.add(child, n.getIndex());
                }
                return this;
            }
            @Override
            public Object process(SingleContentNode n) {
                initialize(n);
                backedges.add(n.getContent(), n.getIndex());
                return this;
            }
            @Override
            public Object process(NoContentNode n) {
                initialize(n);
                return this;
            }
            private void initialize(Node node) {
                T x = initial(node);
                if (x == null) {
                    x = bottom();
                } else {
                   initial.add(node.getIndex());
                }
                map.put(node.getIndex(), x);
            }
        });
        for (int x : initial) {
            for (int pred : backedges.getView(x)) {
                enqueue(pred);
            }
        }
        while (!queue.isEmpty()) {
            int p = queue.remove();
            inqueue.remove(p);
            int index = priority2node.get(p);
            Node node = xg.getNode(index);
            T oldValue = map.get(index);
            T newValue = transfer(node, oldValue);
            if (!oldValue.equals(newValue)) {
                map.put(index, newValue);
                for (int pred : backedges.getView(index)) {
                    enqueue(pred);
                }
            }
        }
    }
   
    private void enqueue(int index) {
        Integer p = node2priority.get(index);
        if (p == null) {
            p = node2priority.size();
            node2priority.put(index, p);
            priority2node.add(index);
        }
        if (inqueue.add(p)) {
            queue.add(p);
        }
    }
   
    /**
     * Returns the lattice data associated with the given node;
     * or <tt>null</tt> if the node is unreachable.
     * @param index index of a node
     * @return a lattice point
     */
    public T get(int index) {
        return map.get(index);
    }

    /**
     * Returns the lattice data associated with the given node;
     * or <tt>null</tt> if the node is unreachable.
     * @param node a node
     * @return a lattice point
     */
    public T get(Node node) {
        return map.get(node.getIndex());
    }
   
    /**
     * Transfer function for the specified node. The node
     * should only read lattice data from its children and itself.
     * @param node in the XML graph to analyze
     * @param currentValue current lattice point for the node. Should not be modified.
     * @return a new instance of a lattice element
     */
    protected abstract T transfer(Node node, T currentValue);
   
    /**
     * Returns BOTTOM element.
     */
    protected abstract T bottom();
   
    /**
     * Returns initial value for the specified node. If node
     * has BOTTOM as initial value, return <tt>null</tt> instead.
     */
    protected abstract T initial(Node node);
   
}
TOP

Related Classes of dk.brics.xact.analysis.xmlgraph.BackwardsXGAnalyzer

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.