001 /* 002 @license.text@ 003 */ 004 package biz.hammurapi.antlr; 005 006 import java.lang.reflect.InvocationTargetException; 007 import java.lang.reflect.Method; 008 import java.lang.reflect.Modifier; 009 010 import antlr.Token; 011 import biz.hammurapi.util.DispatchException; 012 import biz.hammurapi.util.PoliteVisitor; 013 014 015 /** 016 * Visits Token and dispatches invocations by 017 * node names. 018 * @author Pavel Vlasov 019 * @version $Revision: 1.2 $ 020 */ 021 public class TokenVisitor implements PoliteVisitor { 022 private Method[] visitMethods; 023 private Method[] leaveMethods; 024 025 /** 026 * @param tokenTypeNames - can be obtained from Parser. 027 * @param visitPrefix - visit method name prefix. E.g. if prefix is <code>visit_</code> 028 * then visit of Token with type name <code>LITERAL_throws</code> will be dispatched 029 * to method <code>visit_LITERAL_throws</code> if such method is present. 030 * @param leavePrefix - leave method name prefix. 031 */ 032 public TokenVisitor(String[] tokenTypeNames, String visitPrefix, String leavePrefix) { 033 Class thisClass=this.getClass(); 034 for (int i=0, mc=thisClass.getMethods().length; i<mc; i++) { 035 Method m=thisClass.getMethods()[i]; 036 if (!m.getName().equals(visitPrefix) 037 && Modifier.isPublic(m.getModifiers()) 038 && m.getName().startsWith(visitPrefix) 039 && m.getParameterTypes().length==1 040 && Token.class.isAssignableFrom(m.getParameterTypes()[0]) 041 && (boolean.class.equals(m.getReturnType()) || void.class.equals(m.getReturnType()))) { 042 for (int j=0; j<tokenTypeNames.length; j++) { 043 if (m.getName().substring(visitPrefix.length()).equals(tokenTypeNames[j])) { 044 visitMethods[j]=m; 045 } 046 } 047 } 048 049 if (!m.getName().equals(leavePrefix) 050 && Modifier.isPublic(m.getModifiers()) 051 && m.getName().startsWith(leavePrefix) 052 && m.getParameterTypes().length==1 053 && Token.class.isAssignableFrom(m.getParameterTypes()[0]) 054 && void.class.equals(m.getReturnType())) { 055 for (int j=0; j<tokenTypeNames.length; j++) { 056 if (m.getName().substring(leavePrefix.length()).equals(tokenTypeNames[j])) { 057 leaveMethods[j]=m; 058 } 059 } 060 } 061 } 062 } 063 064 public boolean visit(Object target) { 065 if (target instanceof AST) { 066 Method m=visitMethods[((AST) target).getType()]; 067 if (m==null) { 068 return true; 069 } 070 071 try { 072 Object ret = m.invoke(this, new Object[] {target}); 073 return ret instanceof Boolean ? ((Boolean) ret).booleanValue() : true; 074 } catch (IllegalArgumentException e) { 075 throw new DispatchException(e); 076 } catch (IllegalAccessException e) { 077 throw new DispatchException(e); 078 } catch (InvocationTargetException e) { 079 throw new DispatchException(e); 080 } 081 } 082 083 return false; 084 } 085 086 public void leave(Object target) { 087 if (target instanceof Token) { 088 Method m=visitMethods[((Token) target).getType()]; 089 if (m!=null) { 090 try { 091 m.invoke(this, new Object[] {target}); 092 } catch (IllegalArgumentException e) { 093 throw new DispatchException(e); 094 } catch (IllegalAccessException e) { 095 throw new DispatchException(e); 096 } catch (InvocationTargetException e) { 097 throw new DispatchException(e); 098 } 099 } 100 } 101 } 102 }