/*
* hgcommons 7
* Hammurapi Group Common Library
* Copyright (C) 2003 Hammurapi Group
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
* e-Mail: support@hammurapi.biz
*/
package biz.hammurapi.antlr;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import antlr.Token;
import biz.hammurapi.util.DispatchException;
import biz.hammurapi.util.PoliteVisitor;
/**
* Visits Token and dispatches invocations by
* node names.
* @author Pavel Vlasov
* @version $Revision: 1.2 $
*/
public class TokenVisitor implements PoliteVisitor {
private Method[] visitMethods;
private Method[] leaveMethods;
/**
* @param tokenTypeNames - can be obtained from Parser.
* @param visitPrefix - visit method name prefix. E.g. if prefix is <code>visit_</code>
* then visit of Token with type name <code>LITERAL_throws</code> will be dispatched
* to method <code>visit_LITERAL_throws</code> if such method is present.
* @param leavePrefix - leave method name prefix.
*/
public TokenVisitor(String[] tokenTypeNames, String visitPrefix, String leavePrefix) {
Class thisClass=this.getClass();
for (int i=0, mc=thisClass.getMethods().length; i<mc; i++) {
Method m=thisClass.getMethods()[i];
if (!m.getName().equals(visitPrefix)
&& Modifier.isPublic(m.getModifiers())
&& m.getName().startsWith(visitPrefix)
&& m.getParameterTypes().length==1
&& Token.class.isAssignableFrom(m.getParameterTypes()[0])
&& (boolean.class.equals(m.getReturnType()) || void.class.equals(m.getReturnType()))) {
for (int j=0; j<tokenTypeNames.length; j++) {
if (m.getName().substring(visitPrefix.length()).equals(tokenTypeNames[j])) {
visitMethods[j]=m;
}
}
}
if (!m.getName().equals(leavePrefix)
&& Modifier.isPublic(m.getModifiers())
&& m.getName().startsWith(leavePrefix)
&& m.getParameterTypes().length==1
&& Token.class.isAssignableFrom(m.getParameterTypes()[0])
&& void.class.equals(m.getReturnType())) {
for (int j=0; j<tokenTypeNames.length; j++) {
if (m.getName().substring(leavePrefix.length()).equals(tokenTypeNames[j])) {
leaveMethods[j]=m;
}
}
}
}
}
public boolean visit(Object target) {
if (target instanceof AST) {
Method m=visitMethods[((AST) target).getType()];
if (m==null) {
return true;
}
try {
Object ret = m.invoke(this, new Object[] {target});
return ret instanceof Boolean ? ((Boolean) ret).booleanValue() : true;
} catch (IllegalArgumentException e) {
throw new DispatchException(e);
} catch (IllegalAccessException e) {
throw new DispatchException(e);
} catch (InvocationTargetException e) {
throw new DispatchException(e);
}
}
return false;
}
public void leave(Object target) {
if (target instanceof Token) {
Method m=visitMethods[((Token) target).getType()];
if (m!=null) {
try {
m.invoke(this, new Object[] {target});
} catch (IllegalArgumentException e) {
throw new DispatchException(e);
} catch (IllegalAccessException e) {
throw new DispatchException(e);
} catch (InvocationTargetException e) {
throw new DispatchException(e);
}
}
}
}
}
|