001: /*
002: * hgcommons 7
003: * Hammurapi Group Common Library
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.antlr;
024:
025: import java.lang.reflect.InvocationTargetException;
026: import java.lang.reflect.Method;
027: import java.lang.reflect.Modifier;
028:
029: import antlr.collections.AST;
030: import biz.hammurapi.util.DispatchException;
031: import biz.hammurapi.util.PoliteVisitor;
032:
033: /**
034: * Visits AST and dispatches invocations by
035: * node names.
036: * @author Pavel Vlasov
037: * @version $Revision: 1.2 $
038: */
039: public class AstVisitor implements PoliteVisitor {
040: private Method[] visitMethods;
041: private Method[] leaveMethods;
042:
043: /**
044: * @param tokenTypeNames - can be obtained from Parser.
045: * @param visitPrefix - visit method name prefix. E.g. if prefix is <code>visit_</code>
046: * then visit of AST with type name <code>LITERAL_throws</code> will be dispatched
047: * to method <code>visit_LITERAL_throws</code> if such method is present.
048: * @param leavePrefix - leave method name prefix.
049: */
050: public AstVisitor(String[] tokenTypeNames, String visitPrefix,
051: String leavePrefix) {
052: Class this Class = this .getClass();
053: for (int i = 0, mc = this Class.getMethods().length; i < mc; i++) {
054: Method m = this Class.getMethods()[i];
055: if (!m.getName().equals(visitPrefix)
056: && Modifier.isPublic(m.getModifiers())
057: && m.getName().startsWith(visitPrefix)
058: && m.getParameterTypes().length == 1
059: && AST.class
060: .isAssignableFrom(m.getParameterTypes()[0])
061: && (boolean.class.equals(m.getReturnType()) || void.class
062: .equals(m.getReturnType()))) {
063: for (int j = 0; j < tokenTypeNames.length; j++) {
064: if (m.getName().substring(visitPrefix.length())
065: .equals(tokenTypeNames[j])) {
066: visitMethods[j] = m;
067: }
068: }
069: }
070:
071: if (!m.getName().equals(leavePrefix)
072: && Modifier.isPublic(m.getModifiers())
073: && m.getName().startsWith(leavePrefix)
074: && m.getParameterTypes().length == 1
075: && AST.class
076: .isAssignableFrom(m.getParameterTypes()[0])
077: && void.class.equals(m.getReturnType())) {
078: for (int j = 0; j < tokenTypeNames.length; j++) {
079: if (m.getName().substring(leavePrefix.length())
080: .equals(tokenTypeNames[j])) {
081: leaveMethods[j] = m;
082: }
083: }
084: }
085: }
086: }
087:
088: public boolean visit(Object target) {
089: if (target instanceof AST) {
090: Method m = visitMethods[((AST) target).getType()];
091: if (m == null) {
092: return true;
093: }
094:
095: try {
096: Object ret = m.invoke(this , new Object[] { target });
097: return ret instanceof Boolean ? ((Boolean) ret)
098: .booleanValue() : true;
099: } catch (IllegalArgumentException e) {
100: throw new DispatchException(e);
101: } catch (IllegalAccessException e) {
102: throw new DispatchException(e);
103: } catch (InvocationTargetException e) {
104: throw new DispatchException(e);
105: }
106: }
107:
108: return false;
109: }
110:
111: public void leave(Object target) {
112: if (target instanceof AST) {
113: Method m = visitMethods[((AST) target).getType()];
114: if (m != null) {
115: try {
116: m.invoke(this , new Object[] { target });
117: } catch (IllegalArgumentException e) {
118: throw new DispatchException(e);
119: } catch (IllegalAccessException e) {
120: throw new DispatchException(e);
121: } catch (InvocationTargetException e) {
122: throw new DispatchException(e);
123: }
124: }
125: }
126: }
127: }
|