~ubuntu-branches/ubuntu/oneiric/weka/oneiric

« back to all changes in this revision

Viewing changes to weka/core/parser/JFlex/Macros.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner, Soeren Sonnenburg, Torsten Werner
  • Date: 2008-08-10 21:27:05 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080810212705-tr8etpnkdx2ziktp
Tags: 3.5.8-1
[ Soeren Sonnenburg ]
* Bump Standards Version to 3.8.0.
* Remove references to non-free Java in debian/copyright.

[ Torsten Werner ]
* new upstream release
* Switch to openjdk-6.
* Move package to main.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
2
 * JFlex 1.4.1                                                             *
 
3
 * Copyright (C) 1998-2004  Gerwin Klein <lsf@jflex.de>                    *
 
4
 * All rights reserved.                                                    *
 
5
 *                                                                         *
 
6
 * This program is free software; you can redistribute it and/or modify    *
 
7
 * it under the terms of the GNU General Public License. See the file      *
 
8
 * COPYRIGHT for more information.                                         *
 
9
 *                                                                         *
 
10
 * This program is distributed in the hope that it will be useful,         *
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 
13
 * GNU General Public License for more details.                            *
 
14
 *                                                                         *
 
15
 * You should have received a copy of the GNU General Public License along *
 
16
 * with this program; if not, write to the Free Software Foundation, Inc., *
 
17
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                 *
 
18
 *                                                                         *
 
19
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
20
 
 
21
package weka.core.parser.JFlex;
 
22
 
 
23
import java.util.*;
 
24
 
 
25
 
 
26
/**
 
27
 * Symbol table and expander for macros.
 
28
 * 
 
29
 * Maps macros to their (expanded) definitions, detects cycles and 
 
30
 * unused macros.
 
31
 *
 
32
 * @author Gerwin Klein
 
33
 * @version JFlex 1.4.1, $Revision: 1.1 $, $Date: 2008/05/09 09:14:11 $
 
34
 */
 
35
final public class Macros {
 
36
 
 
37
  /** Maps names of macros to their definition */
 
38
  private Hashtable macros;
 
39
 
 
40
  /** Maps names of macros to their "used" flag */
 
41
  private Hashtable used;
 
42
 
 
43
 
 
44
  /**
 
45
   * Creates a new macro expander.
 
46
   */
 
47
  public Macros() {
 
48
    macros = new Hashtable();
 
49
    used = new Hashtable();
 
50
  }
 
51
 
 
52
 
 
53
  /**
 
54
   * Stores a new macro and its definition.
 
55
   *
 
56
   * @param name         the name of the new macro
 
57
   * @param definition   the definition of the new macro
 
58
   *
 
59
   * @return <code>true</code>, iff the macro name has not been
 
60
   *         stored before.
 
61
   */
 
62
  public boolean insert(String name, RegExp definition) {
 
63
    
 
64
    if (Options.DEBUG) 
 
65
      Out.debug("inserting macro "+name+" with definition :"+Out.NL+definition); //$NON-NLS-1$ //$NON-NLS-2$
 
66
      
 
67
    used.put(name, Boolean.FALSE);
 
68
    return macros.put(name,definition) == null;    
 
69
  }
 
70
 
 
71
 
 
72
  /**
 
73
   * Marks a makro as used.
 
74
   *
 
75
   * @return <code>true</code>, iff the macro name has been
 
76
   *         stored before.
 
77
   */
 
78
  public boolean markUsed(String name) {
 
79
    return used.put(name, Boolean.TRUE) != null;
 
80
  }
 
81
 
 
82
 
 
83
  /**
 
84
   * Tests if a macro has been used.
 
85
   *
 
86
   * @return <code>true</code>, iff the macro has been used in 
 
87
   *         a regular expression.
 
88
   */
 
89
  public boolean isUsed(String name) {
 
90
    return ((Boolean)used.get(name)).booleanValue();
 
91
  }
 
92
 
 
93
 
 
94
  /**
 
95
   * Returns all unused macros.
 
96
   *
 
97
   * @return the enumeration of macro names that have not been used.
 
98
   */
 
99
  public Enumeration unused() {
 
100
    
 
101
    Vector unUsed = new Vector();
 
102
 
 
103
    Enumeration names = used.keys();
 
104
    while ( names.hasMoreElements() ) {
 
105
      String name = (String) names.nextElement();
 
106
      Boolean isUsed = (Boolean) used.get( name );
 
107
      if ( !isUsed.booleanValue() ) unUsed.addElement(name);
 
108
    }
 
109
    
 
110
    return unUsed.elements();
 
111
  }
 
112
 
 
113
 
 
114
  /**
 
115
   * Fetches the definition of the macro with the specified name,
 
116
   * <p>
 
117
   * The definition will either be the same as stored (expand() not 
 
118
   * called), or an equivalent one, that doesn't contain any macro 
 
119
   * usages (expand() called before).
 
120
   *
 
121
   * @param name   the name of the macro
 
122
   *
 
123
   * @return the definition of the macro, <code>null</code> if 
 
124
   *         no macro with the specified name has been stored.
 
125
   *
 
126
   * @see JFlex.Macros#expand
 
127
   */
 
128
  public RegExp getDefinition(String name) {
 
129
    return (RegExp) macros.get(name);
 
130
  }
 
131
 
 
132
 
 
133
  /**
 
134
   * Expands all stored macros, so that getDefinition always returns
 
135
   * a defintion that doesn't contain any macro usages.
 
136
   *
 
137
   * @throws MacroException   if there is a cycle in the macro usage graph.
 
138
   */
 
139
   public void expand() throws MacroException {
 
140
    
 
141
    Enumeration names;
 
142
 
 
143
    names = macros.keys();
 
144
    
 
145
    while ( names.hasMoreElements() ) {
 
146
      String name = (String) names.nextElement();
 
147
      if ( isUsed(name) )
 
148
        macros.put(name, expandMacro(name, getDefinition(name))); 
 
149
      // this put doesn't get a new key, so only a new value
 
150
      // is set for the key "name" (without changing the enumeration 
 
151
      // "names"!)
 
152
    }
 
153
  }
 
154
 
 
155
 
 
156
  /**
 
157
   * Expands the specified macro by replacing each macro usage
 
158
   * with the stored definition. 
 
159
   *   
 
160
   * @param name        the name of the macro to expand (for detecting cycles)
 
161
   * @param definition  the definition of the macro to expand
 
162
   *
 
163
   * @return the expanded definition of the macro.
 
164
   * 
 
165
   * @throws MacroException when an error (such as a cyclic definition)
 
166
   *                              occurs during expansion
 
167
   */
 
168
  private RegExp expandMacro(String name, RegExp definition) throws MacroException {
 
169
 
 
170
    // Out.print("checking macro "+name);
 
171
    // Out.print("definition is "+definition);
 
172
 
 
173
    switch ( definition.type ) {
 
174
    case sym.BAR: 
 
175
    case sym.CONCAT:   
 
176
      RegExp2 binary = (RegExp2) definition;
 
177
      binary.r1 = expandMacro(name, binary.r1);
 
178
      binary.r2 = expandMacro(name, binary.r2);
 
179
      return definition;
 
180
      
 
181
    case sym.STAR:
 
182
    case sym.PLUS:
 
183
    case sym.QUESTION: 
 
184
    case sym.BANG:
 
185
    case sym.TILDE:
 
186
      RegExp1 unary = (RegExp1) definition;
 
187
      unary.content = expandMacro(name, (RegExp) unary.content);
 
188
      return definition;
 
189
      
 
190
    case sym.MACROUSE: 
 
191
      String usename = (String) ((RegExp1) definition).content;
 
192
      
 
193
      if ( name.equals(usename) )
 
194
        throw new MacroException(ErrorMessages.get(ErrorMessages.MACRO_CYCLE, name)); 
 
195
          
 
196
      RegExp usedef = getDefinition(usename);
 
197
      
 
198
      if ( usedef == null ) 
 
199
        throw new MacroException(ErrorMessages.get(ErrorMessages.MACRO_DEF_MISSING, usename, name));
 
200
      
 
201
      markUsed(usename);
 
202
      
 
203
      return expandMacro(name, usedef);
 
204
 
 
205
    case sym.STRING:
 
206
    case sym.STRING_I:
 
207
    case sym.CHAR:
 
208
    case sym.CHAR_I:
 
209
    case sym.CCLASS:
 
210
    case sym.CCLASSNOT:
 
211
      return definition;
 
212
 
 
213
    default:
 
214
      throw new MacroException("unknown expression type "+definition.type+" in macro expansion"); //$NON-NLS-1$ //$NON-NLS-2$
 
215
    }
 
216
  }
 
217
}