/*******************************************************************************
* Copyright (c) 2008 Scott Stanchfield.
* 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:
* Based on the ANTLR parser generator by Terence Parr, http://antlr.org
* Ric Klaren <klaren@cs.utwente.nl>
* Scott Stanchfield - Modifications for XML Parsing
*******************************************************************************/
package com.javadude.antxr;
import com.javadude.antxr.collections.AST;
public class ASTIterator {
protected AST cursor = null;
protected AST original = null;
public ASTIterator(AST t) {
original = cursor = t;
}
/** Is 'sub' a subtree of 't' beginning at the root? */
public boolean isSubtree(AST t, AST sub) {
AST sibling;
// the empty tree is always a subset of any tree.
if (sub == null) {
return true;
}
// if the tree is empty, return true if the subtree template is too.
if (t == null) {
return false;
}
// Otherwise, start walking sibling lists. First mismatch, return false.
for (sibling = t;
sibling != null && sub != null;
sibling = sibling.getNextSibling(), sub = sub.getNextSibling()) {
// as a quick optimization, check roots first.
if (sibling.getType() != sub.getType()) {
return false;
}
// if roots match, do full match test on children.
if (sibling.getFirstChild() != null) {
if (!isSubtree(sibling.getFirstChild(), sub.getFirstChild())) {
return false;
}
}
}
return true;
}
/** Find the next subtree with structure and token types equal to
* those of 'template'.
*/
public AST next(AST template) {
AST t = null;
if (cursor == null) { // do nothing if no tree to work on
return null;
}
// Start walking sibling list looking for subtree matches.
for (; cursor != null; cursor = cursor.getNextSibling()) {
// as a quick optimization, check roots first.
if (cursor.getType() == template.getType()) {
// if roots match, do full match test on children.
if (cursor.getFirstChild() != null) {
if (isSubtree(cursor.getFirstChild(), template.getFirstChild())) {
return cursor;
}
}
}
}
return t;
}
}