001    /*
002      Copyright (C) 2003 Laurent Martelli <laurent@aopsys.com>
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public
015      License along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
017      USA */
018    
019    package org.objectweb.jac.core.parsers.acc;
020    
021    import java.util.Iterator;
022    import java.util.Vector;
023    import org.apache.log4j.Logger;
024    
025    /**
026     * Represents a non terminal rule
027     */
028    public class NonTerminal extends SyntaxElement {
029        static Logger logger = Logger.getLogger("acc.parser");
030    
031        Vector children = new Vector();
032       
033        public NonTerminal(String name, SyntaxElement[] children) {
034            super(name,
035                  children[0].getLeft(),
036                  children[children.length-1].getRight());
037            for (int i=0; i<children.length; i++) {
038                addChild(children[i]);
039            }
040        }
041    
042        public NonTerminal(String name, SyntaxElement child) {
043            super(name,child.getLeft(),child.getRight());
044            addChild(child);
045        }
046    
047        public NonTerminal(String name) {
048            super(name,Integer.MAX_VALUE,-1);
049        }
050    
051        /**
052         * Add child at the end
053         */
054        public void addChild(SyntaxElement se) {
055            children.add(se);
056            childAdded(se);
057        }
058    
059        /**
060         * Add child at the beginning
061         */
062        public void insertChild(SyntaxElement se) {
063            children.add(0,se);
064            childAdded(se);
065        }
066    
067        /**
068         * Returns the child at a given index
069         */
070        public SyntaxElement getChild(int index) {
071            return (SyntaxElement)children.get(index);
072        }
073    
074        /**
075         * Returns a child with a given name, or null.
076         */
077        public SyntaxElement getChild(String name) {
078            Iterator it = children.iterator();
079            while (it.hasNext()) {
080                SyntaxElement child = (SyntaxElement)it.next();
081                if (child.getName().equals(name)) {
082                    return child;
083                }
084            }
085            return null;
086        }
087    
088        protected void childAdded(SyntaxElement se) {
089            se.setParent(this);
090            if (se.getLeft()<left) 
091                left = se.getLeft();
092            if (se.getRight()>right) 
093                right = se.getRight();
094        }
095    
096        /**
097         * Returns the terminal syntax element of a given position
098         * @param position the position
099         * @return A Terminal se such that se.getLeft()<=position &&
100         * se.getRight()>=position or null if there no such SyntaxElement.
101         */
102        public Terminal getTerminalAt(int position) {
103            Iterator it = children.iterator();
104            while (it.hasNext()) {
105                SyntaxElement se = (SyntaxElement)it.next();
106                if (se.getLeft()<=position && se.getRight()>=position) {
107                    logger.debug("Found "+se+" at "+position);
108                    if (se instanceof Terminal)
109                        return (Terminal)se;
110                    else
111                        return ((NonTerminal)se).getTerminalAt(position);
112                }
113            }
114            return null;
115        }
116    
117    
118        /**
119         * Returns the deepest syntax element at a given position
120         * @param position the position
121         * @return A SyntaxElement se such that se.getLeft()<=position &&
122         * se.getRight()>=position or null if there no such SyntaxElement.
123         */
124        public SyntaxElement getSyntaxElementAt(int position) {
125            Iterator it = children.iterator();
126            while (it.hasNext()) {
127                SyntaxElement se = (SyntaxElement)it.next();
128                if (se.getLeft()<=position && se.getRight()>=position) {
129                    logger.debug("Found "+se+" at "+position);
130                    if (se instanceof Terminal)
131                        return se;
132                    else
133                        return ((NonTerminal)se).getSyntaxElementAt(position);
134                }
135            }
136            if (getLeft()<=position && getRight()>=position)
137                return this;
138            else
139                return null;
140        }
141       
142    }