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

« back to all changes in this revision

Viewing changes to weka/core/parser/JFlex/Emitter.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.io.*;
 
24
import java.util.*;
 
25
import java.text.*;
 
26
 
 
27
/**
 
28
 * This class manages the actual code generation, putting
 
29
 * the scanner together, filling in skeleton sections etc.
 
30
 *
 
31
 * Table compression, String packing etc. is also done here.
 
32
 *
 
33
 * @author Gerwin Klein
 
34
 * @version JFlex 1.4.1, $Revision: 1.1 $, $Date: 2008/05/09 09:14:11 $
 
35
 */
 
36
final public class Emitter {
 
37
    
 
38
  // bit masks for state attributes
 
39
  static final private int FINAL = 1;
 
40
  static final private int PUSHBACK = 2;
 
41
  static final private int LOOKEND = 4;
 
42
  static final private int NOLOOK = 8;
 
43
 
 
44
  static final private String date = (new SimpleDateFormat()).format(new Date());
 
45
 
 
46
  private File inputFile;
 
47
 
 
48
  private PrintWriter out;
 
49
  private Skeleton skel;
 
50
  private LexScan scanner;
 
51
  private LexParse parser;
 
52
  private DFA dfa;
 
53
 
 
54
  // for switch statement:
 
55
  // table[i][j] is the set of input characters that leads from state i to state j
 
56
  private CharSet table[][];
 
57
 
 
58
  private boolean isTransition[];
 
59
  
 
60
  // noTarget[i] is the set of input characters that have no target state in state i
 
61
  private CharSet noTarget[];
 
62
      
 
63
  // for row killing:
 
64
  private int numRows;
 
65
  private int [] rowMap;
 
66
  private boolean [] rowKilled;
 
67
  
 
68
  // for col killing:
 
69
  private int numCols;
 
70
  private int [] colMap;
 
71
  private boolean [] colKilled;
 
72
  
 
73
 
 
74
  /** maps actions to their switch label */
 
75
  private Hashtable actionTable = new Hashtable();
 
76
 
 
77
  private CharClassInterval [] intervalls;
 
78
 
 
79
  private String visibility = "public";
 
80
 
 
81
  public Emitter(File inputFile, LexParse parser, DFA dfa) throws IOException {
 
82
 
 
83
    String name = parser.scanner.className+".java";
 
84
 
 
85
    File outputFile = normalize(name, inputFile);
 
86
 
 
87
    Out.println("Writing code to \""+outputFile+"\"");
 
88
    
 
89
    this.out = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
 
90
    this.parser = parser;
 
91
    this.scanner = parser.scanner;
 
92
    this.visibility = scanner.visibility;
 
93
    this.inputFile = inputFile;
 
94
    this.dfa = dfa;
 
95
    this.skel = new Skeleton(out);
 
96
  }
 
97
 
 
98
 
 
99
  /**
 
100
   * Constructs a file in Options.getDir() or in the same directory as
 
101
   * another file. Makes a backup if the file already exists.
 
102
   *
 
103
   * @param name  the name (without path) of the file
 
104
   * @param path  the path where to construct the file
 
105
   * @param input fallback location if path = <tt>null</tt>
 
106
   *              (expected to be a file in the directory to write to)   
 
107
   */
 
108
  public static File normalize(String name, File input) {
 
109
    File outputFile;
 
110
 
 
111
    if ( Options.getDir() == null ) 
 
112
      if ( input == null || input.getParent() == null )
 
113
        outputFile = new File(name);
 
114
      else
 
115
        outputFile = new File(input.getParent(), name);
 
116
    else 
 
117
      outputFile = new File(Options.getDir(), name);
 
118
        
 
119
    if ( outputFile.exists() && !Options.no_backup ) {      
 
120
      File backup = new File( outputFile.toString()+"~" );
 
121
      
 
122
      if ( backup.exists() ) backup.delete();
 
123
      
 
124
      if ( outputFile.renameTo( backup ) )
 
125
        Out.println("Old file \""+outputFile+"\" saved as \""+backup+"\"");
 
126
      else
 
127
        Out.println("Couldn't save old file \""+outputFile+"\", overwriting!");
 
128
    }
 
129
 
 
130
    return outputFile;
 
131
  }
 
132
  
 
133
  private void println() {
 
134
    out.println();
 
135
  }
 
136
 
 
137
  private void println(String line) {
 
138
    out.println(line);
 
139
  }
 
140
 
 
141
  private void println(int i) {
 
142
    out.println(i);
 
143
  }
 
144
 
 
145
  private void print(String line) {
 
146
    out.print(line);
 
147
  }
 
148
 
 
149
  private void print(int i) {
 
150
    out.print(i);
 
151
  }
 
152
 
 
153
  private void print(int i, int tab) {
 
154
    int exp;
 
155
 
 
156
    if (i < 0) 
 
157
      exp = 1;
 
158
    else
 
159
      exp = 10;
 
160
 
 
161
    while (tab-- > 1) {
 
162
      if (Math.abs(i) < exp) print(" ");
 
163
      exp*= 10;
 
164
    }
 
165
 
 
166
    print(i);
 
167
  }
 
168
 
 
169
  private void emitScanError() {
 
170
    print("  private void zzScanError(int errorCode)");
 
171
    
 
172
    if (scanner.scanErrorException != null) 
 
173
      print(" throws "+scanner.scanErrorException);
 
174
 
 
175
    println(" {");
 
176
 
 
177
    skel.emitNext();
 
178
 
 
179
    if (scanner.scanErrorException == null)
 
180
      println("    throw new Error(message);");
 
181
    else
 
182
      println("    throw new "+scanner.scanErrorException+"(message);");    
 
183
 
 
184
    skel.emitNext();
 
185
 
 
186
    print("  "+visibility+" void yypushback(int number) ");     
 
187
    
 
188
    if (scanner.scanErrorException == null)
 
189
      println(" {");
 
190
    else       
 
191
      println(" throws "+scanner.scanErrorException+" {");
 
192
  }
 
193
 
 
194
  private void emitMain() {
 
195
    if ( !(scanner.standalone || scanner.debugOption || scanner.cupDebug) ) return;
 
196
 
 
197
    if ( scanner.cupDebug ) {
 
198
      println("  /**");
 
199
      println("   * Converts an int token code into the name of the");
 
200
      println("   * token by reflection on the cup symbol class/interface "+scanner.cupSymbol);
 
201
      println("   *");
 
202
      println("   * This code was contributed by Karl Meissner <meissnersd@yahoo.com>"); 
 
203
      println("   */");
 
204
      println("  private String getTokenName(int token) {");
 
205
      println("    try {");
 
206
      println("      java.lang.reflect.Field [] classFields = " + scanner.cupSymbol + ".class.getFields();");
 
207
      println("      for (int i = 0; i < classFields.length; i++) {");
 
208
      println("        if (classFields[i].getInt(null) == token) {");
 
209
      println("          return classFields[i].getName();");
 
210
      println("        }");
 
211
      println("      }");
 
212
      println("    } catch (Exception e) {");
 
213
      println("      e.printStackTrace(System.err);");
 
214
      println("    }");
 
215
      println("");
 
216
      println("    return \"UNKNOWN TOKEN\";");
 
217
      println("  }");
 
218
      println("");
 
219
      println("  /**");
 
220
      println("   * Same as "+scanner.functionName+" but also prints the token to standard out");
 
221
      println("   * for debugging.");
 
222
      println("   *");
 
223
      println("   * This code was contributed by Karl Meissner <meissnersd@yahoo.com>"); 
 
224
      println("   */");
 
225
 
 
226
      print("  "+visibility+" ");
 
227
      if ( scanner.tokenType == null ) {
 
228
        if ( scanner.isInteger )
 
229
          print( "int" );
 
230
        else 
 
231
          if ( scanner.isIntWrap )
 
232
            print( "Integer" );
 
233
          else
 
234
            print( "Yytoken" );
 
235
      }
 
236
      else
 
237
        print( scanner.tokenType );
 
238
      
 
239
      print(" debug_");
 
240
      
 
241
      print(scanner.functionName);
 
242
      
 
243
      print("() throws java.io.IOException");
 
244
    
 
245
      if ( scanner.lexThrow != null ) {
 
246
        print(", ");
 
247
        print(scanner.lexThrow);
 
248
      }
 
249
 
 
250
      if ( scanner.scanErrorException != null ) {
 
251
        print(", ");
 
252
        print(scanner.scanErrorException);
 
253
      }
 
254
      
 
255
      println(" {");
 
256
 
 
257
      println("    java_cup.runtime.Symbol s = "+scanner.functionName+"();");
 
258
      print("    System.out.println( ");
 
259
      if (scanner.lineCount) print("\"line:\" + (yyline+1) + ");
 
260
      if (scanner.columnCount) print("\" col:\" + (yycolumn+1) + ");
 
261
      println("\" --\"+ yytext() + \"--\" + getTokenName(s.sym) + \"--\");");
 
262
      println("    return s;");
 
263
      println("  }");
 
264
      println("");
 
265
    }
 
266
 
 
267
    if ( scanner.standalone ) {
 
268
      println("  /**");
 
269
      println("   * Runs the scanner on input files.");
 
270
      println("   *");
 
271
      println("   * This is a standalone scanner, it will print any unmatched");
 
272
      println("   * text to System.out unchanged.");      
 
273
      println("   *");
 
274
      println("   * @param argv   the command line, contains the filenames to run");
 
275
      println("   *               the scanner on.");
 
276
      println("   */");
 
277
    }
 
278
    else {
 
279
      println("  /**");
 
280
      println("   * Runs the scanner on input files.");
 
281
      println("   *");
 
282
      println("   * This main method is the debugging routine for the scanner.");
 
283
      println("   * It prints debugging information about each returned token to");
 
284
      println("   * System.out until the end of file is reached, or an error occured.");
 
285
      println("   *"); 
 
286
      println("   * @param argv   the command line, contains the filenames to run");
 
287
      println("   *               the scanner on."); 
 
288
      println("   */"); 
 
289
    }      
 
290
    
 
291
    println("  public static void main(String argv[]) {");
 
292
    println("    if (argv.length == 0) {");
 
293
    println("      System.out.println(\"Usage : java "+scanner.className+" <inputfile>\");");
 
294
    println("    }");
 
295
    println("    else {");
 
296
    println("      for (int i = 0; i < argv.length; i++) {");
 
297
    println("        "+scanner.className+" scanner = null;");
 
298
    println("        try {");
 
299
    println("          scanner = new "+scanner.className+"( new java.io.FileReader(argv[i]) );");
 
300
 
 
301
    if ( scanner.standalone ) {      
 
302
      println("          while ( !scanner.zzAtEOF ) scanner."+scanner.functionName+"();");
 
303
    }
 
304
    else if (scanner.cupDebug ) {
 
305
      println("          while ( !scanner.zzAtEOF ) scanner.debug_"+scanner.functionName+"();");
 
306
    }
 
307
    else {
 
308
      println("          do {");
 
309
      println("            System.out.println(scanner."+scanner.functionName+"());");
 
310
      println("          } while (!scanner.zzAtEOF);");
 
311
      println("");
 
312
    }
 
313
 
 
314
    println("        }");
 
315
    println("        catch (java.io.FileNotFoundException e) {");
 
316
    println("          System.out.println(\"File not found : \\\"\"+argv[i]+\"\\\"\");");
 
317
    println("        }");
 
318
    println("        catch (java.io.IOException e) {");
 
319
    println("          System.out.println(\"IO error scanning file \\\"\"+argv[i]+\"\\\"\");");
 
320
    println("          System.out.println(e);");
 
321
    println("        }"); 
 
322
    println("        catch (Exception e) {");
 
323
    println("          System.out.println(\"Unexpected exception:\");");
 
324
    println("          e.printStackTrace();");
 
325
    println("        }"); 
 
326
    println("      }");
 
327
    println("    }");
 
328
    println("  }");
 
329
    println("");    
 
330
  }
 
331
  
 
332
  private void emitNoMatch() {
 
333
    println("            zzScanError(ZZ_NO_MATCH);");
 
334
  }
 
335
  
 
336
  private void emitNextInput() {
 
337
    println("          if (zzCurrentPosL < zzEndReadL)");
 
338
    println("            zzInput = zzBufferL[zzCurrentPosL++];");
 
339
    println("          else if (zzAtEOF) {");
 
340
    println("            zzInput = YYEOF;");
 
341
    println("            break zzForAction;");
 
342
    println("          }");
 
343
    println("          else {");
 
344
    println("            // store back cached positions");
 
345
    println("            zzCurrentPos  = zzCurrentPosL;");
 
346
    println("            zzMarkedPos   = zzMarkedPosL;");
 
347
    if ( scanner.lookAheadUsed ) 
 
348
      println("            zzPushbackPos = zzPushbackPosL;");
 
349
    println("            boolean eof = zzRefill();");
 
350
    println("            // get translated positions and possibly new buffer");
 
351
    println("            zzCurrentPosL  = zzCurrentPos;");
 
352
    println("            zzMarkedPosL   = zzMarkedPos;");
 
353
    println("            zzBufferL      = zzBuffer;");
 
354
    println("            zzEndReadL     = zzEndRead;");
 
355
    if ( scanner.lookAheadUsed ) 
 
356
      println("            zzPushbackPosL = zzPushbackPos;");
 
357
    println("            if (eof) {");
 
358
    println("              zzInput = YYEOF;");
 
359
    println("              break zzForAction;");  
 
360
    println("            }");
 
361
    println("            else {");
 
362
    println("              zzInput = zzBufferL[zzCurrentPosL++];");
 
363
    println("            }");
 
364
    println("          }"); 
 
365
  }
 
366
 
 
367
  private void emitHeader() {
 
368
    println("/* The following code was generated by JFlex "+Main.version+" on "+date+" */");   
 
369
    println(""); 
 
370
  } 
 
371
 
 
372
  private void emitUserCode() {
 
373
    if ( scanner.userCode.length() > 0 )
 
374
      println(scanner.userCode.toString());
 
375
  }
 
376
 
 
377
  private void emitClassName() {    
 
378
    if (!endsWithJavadoc(scanner.userCode)) {
 
379
      String path = inputFile.toString();
 
380
      // slashify path (avoid backslash u sequence = unicode escape)
 
381
      if (File.separatorChar != '/') {
 
382
            path = path.replace(File.separatorChar, '/');
 
383
      }
 
384
        
 
385
      println("/**");
 
386
      println(" * This class is a scanner generated by ");
 
387
      println(" * <a href=\"http://www.jflex.de/\">JFlex</a> "+Main.version);
 
388
      println(" * on "+date+" from the specification file");    
 
389
      println(" * <tt>"+path+"</tt>");      
 
390
      println(" */");
 
391
    }   
 
392
 
 
393
    if ( scanner.isPublic ) print("public ");
 
394
 
 
395
    if ( scanner.isAbstract) print("abstract ");
 
396
   
 
397
    if ( scanner.isFinal ) print("final ");
 
398
    
 
399
    print("class ");
 
400
    print(scanner.className);
 
401
    
 
402
    if ( scanner.isExtending != null ) {
 
403
      print(" extends ");
 
404
      print(scanner.isExtending);
 
405
    }
 
406
 
 
407
    if ( scanner.isImplementing != null ) {
 
408
      print(" implements ");
 
409
      print(scanner.isImplementing);
 
410
    }   
 
411
    
 
412
    println(" {");
 
413
  }  
 
414
 
 
415
  /**
 
416
   * Try to find out if user code ends with a javadoc comment 
 
417
   * 
 
418
   * @param buffer   the user code
 
419
   * @return true    if it ends with a javadoc comment
 
420
   */
 
421
  public static boolean endsWithJavadoc(StringBuffer usercode) {
 
422
    String s = usercode.toString().trim();
 
423
        
 
424
    if (!s.endsWith("*/")) return false;
 
425
    
 
426
    // find beginning of javadoc comment   
 
427
    int i = s.lastIndexOf("/**");    
 
428
    if (i < 0) return false; 
 
429
       
 
430
    // javadoc comment shouldn't contain a comment end
 
431
    return s.substring(i,s.length()-2).indexOf("*/") < 0;
 
432
  }
 
433
 
 
434
 
 
435
  private void emitLexicalStates() {
 
436
    Enumeration stateNames = scanner.states.names();
 
437
    
 
438
    while ( stateNames.hasMoreElements() ) {
 
439
      String name = (String) stateNames.nextElement();
 
440
      
 
441
      int num = scanner.states.getNumber(name).intValue();
 
442
 
 
443
      if (scanner.bolUsed)      
 
444
        println("  "+visibility+" static final int "+name+" = "+2*num+";");
 
445
      else
 
446
        println("  "+visibility+" static final int "+name+" = "+dfa.lexState[2*num]+";");
 
447
    }
 
448
    
 
449
    if (scanner.bolUsed) {
 
450
      println("");
 
451
      println("  /**");
 
452
      println("   * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l");
 
453
      println("   * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l");
 
454
      println("   *                  at the beginning of a line");
 
455
      println("   * l is of the form l = 2*k, k a non negative integer");
 
456
      println("   */");
 
457
      println("  private static final int ZZ_LEXSTATE[] = { ");
 
458
  
 
459
      int i, j = 0;
 
460
      print("    ");
 
461
 
 
462
      for (i = 0; i < dfa.lexState.length-1; i++) {
 
463
        print( dfa.lexState[i], 2 );
 
464
 
 
465
        print(", ");
 
466
 
 
467
        if (++j >= 16) {
 
468
          println();
 
469
          print("    ");
 
470
          j = 0;
 
471
        }
 
472
      }
 
473
            
 
474
      println( dfa.lexState[i] );
 
475
      println("  };");
 
476
 
 
477
    }
 
478
  }
 
479
 
 
480
  private void emitDynamicInit() {    
 
481
    int count = 0;
 
482
    int value = dfa.table[0][0];
 
483
 
 
484
    println("  /** ");
 
485
    println("   * The transition table of the DFA");
 
486
    println("   */");
 
487
 
 
488
    CountEmitter e = new CountEmitter("Trans");
 
489
    e.setValTranslation(+1); // allow vals in [-1, 0xFFFE]
 
490
    e.emitInit();
 
491
    
 
492
    for (int i = 0; i < dfa.numStates; i++) {
 
493
      if ( !rowKilled[i] ) {
 
494
        for (int c = 0; c < dfa.numInput; c++) {
 
495
          if ( !colKilled[c] ) {
 
496
            if (dfa.table[i][c] == value) {
 
497
              count++;
 
498
            } 
 
499
            else {
 
500
              e.emit(count, value);
 
501
 
 
502
              count = 1;
 
503
              value = dfa.table[i][c];              
 
504
            }
 
505
          }
 
506
        }
 
507
      }
 
508
    }
 
509
 
 
510
    e.emit(count, value);
 
511
    e.emitUnpack();
 
512
    
 
513
    println(e.toString());
 
514
  }
 
515
 
 
516
 
 
517
  private void emitCharMapInitFunction() {
 
518
 
 
519
    CharClasses cl = parser.getCharClasses();
 
520
    
 
521
    if ( cl.getMaxCharCode() < 256 ) return;
 
522
 
 
523
    println("");
 
524
    println("  /** ");
 
525
    println("   * Unpacks the compressed character translation table.");
 
526
    println("   *");
 
527
    println("   * @param packed   the packed character translation table");
 
528
    println("   * @return         the unpacked character translation table");
 
529
    println("   */");
 
530
    println("  private static char [] zzUnpackCMap(String packed) {");
 
531
    println("    char [] map = new char[0x10000];");
 
532
    println("    int i = 0;  /* index in packed string  */");
 
533
    println("    int j = 0;  /* index in unpacked array */");
 
534
    println("    while (i < "+2*intervalls.length+") {");
 
535
    println("      int  count = packed.charAt(i++);");
 
536
    println("      char value = packed.charAt(i++);");
 
537
    println("      do map[j++] = value; while (--count > 0);");
 
538
    println("    }");
 
539
    println("    return map;");
 
540
    println("  }");
 
541
  }
 
542
 
 
543
  private void emitZZTrans() {    
 
544
 
 
545
    int i,c;
 
546
    int n = 0;
 
547
    
 
548
    println("  /** ");
 
549
    println("   * The transition table of the DFA");
 
550
    println("   */");
 
551
    println("  private static final int ZZ_TRANS [] = {"); //XXX
 
552
 
 
553
    print("    ");
 
554
    for (i = 0; i < dfa.numStates; i++) {
 
555
      
 
556
      if ( !rowKilled[i] ) {        
 
557
        for (c = 0; c < dfa.numInput; c++) {          
 
558
          if ( !colKilled[c] ) {            
 
559
            if (n >= 10) {
 
560
              println();
 
561
              print("    ");
 
562
              n = 0;
 
563
            }
 
564
            print( dfa.table[i][c] );
 
565
            if (i != dfa.numStates-1 || c != dfa.numInput-1)
 
566
              print( ", ");
 
567
            n++;
 
568
          }
 
569
        }
 
570
      }
 
571
    }
 
572
 
 
573
    println();
 
574
    println("  };");
 
575
  }
 
576
  
 
577
  private void emitCharMapArrayUnPacked() {
 
578
   
 
579
    CharClasses cl = parser.getCharClasses();
 
580
    intervalls = cl.getIntervalls();
 
581
    
 
582
    println("");
 
583
    println("  /** ");
 
584
    println("   * Translates characters to character classes");
 
585
    println("   */");
 
586
    println("  private static final char [] ZZ_CMAP = {");
 
587
  
 
588
    int n = 0;  // numbers of entries in current line    
 
589
    print("    ");
 
590
    
 
591
    int max =  cl.getMaxCharCode();
 
592
    int i = 0;     
 
593
    while ( i < intervalls.length && intervalls[i].start <= max ) {
 
594
 
 
595
      int end = Math.min(intervalls[i].end, max);
 
596
      for (int c = intervalls[i].start; c <= end; c++) {
 
597
 
 
598
        print(colMap[intervalls[i].charClass], 2);
 
599
 
 
600
        if (c < max) {
 
601
          print(", ");        
 
602
          if ( ++n >= 16 ) { 
 
603
            println();
 
604
            print("    ");
 
605
            n = 0; 
 
606
          }
 
607
        }
 
608
      }
 
609
 
 
610
      i++;
 
611
    }
 
612
 
 
613
    println();
 
614
    println("  };");
 
615
    println();
 
616
  }
 
617
 
 
618
  private void emitCharMapArray() {       
 
619
    CharClasses cl = parser.getCharClasses();
 
620
 
 
621
    if ( cl.getMaxCharCode() < 256 ) {
 
622
      emitCharMapArrayUnPacked();
 
623
      return;
 
624
    }
 
625
 
 
626
    // ignores cl.getMaxCharCode(), emits all intervalls instead
 
627
 
 
628
    intervalls = cl.getIntervalls();
 
629
    
 
630
    println("");
 
631
    println("  /** ");
 
632
    println("   * Translates characters to character classes");
 
633
    println("   */");
 
634
    println("  private static final String ZZ_CMAP_PACKED = ");
 
635
  
 
636
    int n = 0;  // numbers of entries in current line    
 
637
    print("    \"");
 
638
    
 
639
    int i = 0; 
 
640
    while ( i < intervalls.length-1 ) {
 
641
      int count = intervalls[i].end-intervalls[i].start+1;
 
642
      int value = colMap[intervalls[i].charClass];
 
643
      
 
644
      printUC(count);
 
645
      printUC(value);
 
646
 
 
647
      if ( ++n >= 10 ) { 
 
648
        println("\"+");
 
649
        print("    \"");
 
650
        n = 0; 
 
651
      }
 
652
 
 
653
      i++;
 
654
    }
 
655
 
 
656
    printUC(intervalls[i].end-intervalls[i].start+1);
 
657
    printUC(colMap[intervalls[i].charClass]);
 
658
 
 
659
    println("\";");
 
660
    println();
 
661
 
 
662
    println("  /** ");
 
663
    println("   * Translates characters to character classes");
 
664
    println("   */");
 
665
    println("  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);");
 
666
    println();
 
667
  }
 
668
 
 
669
 
 
670
  /**
 
671
   * Print number as octal/unicode escaped string character.
 
672
   * 
 
673
   * @param c   the value to print
 
674
   * @prec  0 <= c <= 0xFFFF 
 
675
   */
 
676
  private void printUC(int c) {
 
677
    if (c > 255) {
 
678
      out.print("\\u");
 
679
      if (c < 0x1000) out.print("0");
 
680
      out.print(Integer.toHexString(c));
 
681
    }
 
682
    else {
 
683
      out.print("\\");
 
684
      out.print(Integer.toOctalString(c));
 
685
    }    
 
686
  }
 
687
 
 
688
 
 
689
  private void emitRowMapArray() {
 
690
    println("");
 
691
    println("  /** ");
 
692
    println("   * Translates a state to a row index in the transition table");
 
693
    println("   */");
 
694
    
 
695
    HiLowEmitter e = new HiLowEmitter("RowMap");
 
696
    e.emitInit();
 
697
    for (int i = 0; i < dfa.numStates; i++) {
 
698
      e.emit(rowMap[i]*numCols);
 
699
    }    
 
700
    e.emitUnpack();
 
701
    println(e.toString());
 
702
  }
 
703
 
 
704
 
 
705
  private void emitAttributes() {
 
706
    println("  /**");
 
707
    println("   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>");
 
708
    println("   */");
 
709
    
 
710
    CountEmitter e = new CountEmitter("Attribute");    
 
711
    e.emitInit();
 
712
    
 
713
    int count = 1;
 
714
    int value = 0; 
 
715
    if ( dfa.isFinal[0]    ) value = FINAL;
 
716
    if ( dfa.isPushback[0] ) value|= PUSHBACK;
 
717
    if ( dfa.isLookEnd[0]  ) value|= LOOKEND;
 
718
    if ( !isTransition[0]  ) value|= NOLOOK;
 
719
       
 
720
    for (int i = 1;  i < dfa.numStates; i++) {      
 
721
      int attribute = 0;      
 
722
      if ( dfa.isFinal[i]    ) attribute = FINAL;
 
723
      if ( dfa.isPushback[i] ) attribute|= PUSHBACK;
 
724
      if ( dfa.isLookEnd[i]  ) attribute|= LOOKEND;
 
725
      if ( !isTransition[i]  ) attribute|= NOLOOK;
 
726
 
 
727
      if (value == attribute) {
 
728
        count++;
 
729
      }
 
730
      else {        
 
731
        e.emit(count, value);
 
732
        count = 1;
 
733
        value = attribute;
 
734
      }
 
735
    }
 
736
    
 
737
    e.emit(count, value);    
 
738
    e.emitUnpack();
 
739
    
 
740
    println(e.toString());
 
741
  }
 
742
 
 
743
 
 
744
  private void emitClassCode() {
 
745
    if ( scanner.eofCode != null ) {
 
746
      println("  /** denotes if the user-EOF-code has already been executed */");
 
747
      println("  private boolean zzEOFDone;");
 
748
      println("");
 
749
    }
 
750
    
 
751
    if ( scanner.classCode != null ) {
 
752
      println("  /* user code: */");
 
753
      println(scanner.classCode);
 
754
    }
 
755
  }
 
756
 
 
757
  private void emitConstructorDecl() {
 
758
    
 
759
    print("  ");
 
760
 
 
761
    if ( scanner.isPublic ) print("public ");   
 
762
    print( scanner.className );      
 
763
    print("(java.io.Reader in)");
 
764
    
 
765
    if ( scanner.initThrow != null ) {
 
766
      print(" throws ");
 
767
      print( scanner.initThrow );
 
768
    }
 
769
    
 
770
    println(" {");
 
771
 
 
772
    if ( scanner.initCode != null ) {
 
773
      print("  ");
 
774
      print( scanner.initCode );
 
775
    }
 
776
 
 
777
    println("    this.zzReader = in;");
 
778
 
 
779
    println("  }");
 
780
    println();
 
781
 
 
782
    
 
783
    println("  /**");
 
784
    println("   * Creates a new scanner.");
 
785
    println("   * There is also java.io.Reader version of this constructor.");
 
786
    println("   *");
 
787
    println("   * @param   in  the java.io.Inputstream to read input from.");
 
788
    println("   */");
 
789
 
 
790
    print("  ");
 
791
    if ( scanner.isPublic ) print("public ");    
 
792
    print( scanner.className );      
 
793
    print("(java.io.InputStream in)");
 
794
    
 
795
    if ( scanner.initThrow != null ) {
 
796
      print(" throws ");
 
797
      print( scanner.initThrow );
 
798
    }
 
799
    
 
800
    println(" {");    
 
801
    println("    this(new java.io.InputStreamReader(in));");
 
802
    println("  }");
 
803
  }
 
804
 
 
805
 
 
806
  private void emitDoEOF() {
 
807
    if ( scanner.eofCode == null ) return;
 
808
    
 
809
    println("  /**");
 
810
    println("   * Contains user EOF-code, which will be executed exactly once,");
 
811
    println("   * when the end of file is reached");
 
812
    println("   */");
 
813
    
 
814
    print("  private void zzDoEOF()");
 
815
    
 
816
    if ( scanner.eofThrow != null ) {
 
817
      print(" throws ");
 
818
      print(scanner.eofThrow);
 
819
    }
 
820
    
 
821
    println(" {");
 
822
    
 
823
    println("    if (!zzEOFDone) {");
 
824
    println("      zzEOFDone = true;");
 
825
    println("    "+scanner.eofCode );
 
826
    println("    }");
 
827
    println("  }");
 
828
    println("");
 
829
    println("");
 
830
  }
 
831
 
 
832
  private void emitLexFunctHeader() {
 
833
    
 
834
    if (scanner.cupCompatible)  {
 
835
      // force public, because we have to implement java_cup.runtime.Symbol
 
836
      print("  public ");
 
837
    }
 
838
    else {
 
839
      print("  "+visibility+" ");
 
840
    }
 
841
    
 
842
    if ( scanner.tokenType == null ) {
 
843
      if ( scanner.isInteger )
 
844
        print( "int" );
 
845
      else 
 
846
      if ( scanner.isIntWrap )
 
847
        print( "Integer" );
 
848
      else
 
849
        print( "Yytoken" );
 
850
    }
 
851
    else
 
852
      print( scanner.tokenType );
 
853
      
 
854
    print(" ");
 
855
    
 
856
    print(scanner.functionName);
 
857
      
 
858
    print("() throws java.io.IOException");
 
859
    
 
860
    if ( scanner.lexThrow != null ) {
 
861
      print(", ");
 
862
      print(scanner.lexThrow);
 
863
    }
 
864
 
 
865
    if ( scanner.scanErrorException != null ) {
 
866
      print(", ");
 
867
      print(scanner.scanErrorException);
 
868
    }
 
869
    
 
870
    println(" {");
 
871
    
 
872
    skel.emitNext();
 
873
 
 
874
    if ( scanner.useRowMap ) {
 
875
      println("    int [] zzTransL = ZZ_TRANS;");
 
876
      println("    int [] zzRowMapL = ZZ_ROWMAP;");
 
877
      println("    int [] zzAttrL = ZZ_ATTRIBUTE;");
 
878
 
 
879
    }
 
880
 
 
881
    if ( scanner.lookAheadUsed ) {
 
882
      println("    int zzPushbackPosL = zzPushbackPos = -1;");
 
883
      println("    boolean zzWasPushback;");
 
884
    }
 
885
 
 
886
    skel.emitNext();    
 
887
        
 
888
    if ( scanner.charCount ) {
 
889
      println("      yychar+= zzMarkedPosL-zzStartRead;");
 
890
      println("");
 
891
    }
 
892
    
 
893
    if ( scanner.lineCount || scanner.columnCount ) {
 
894
      println("      boolean zzR = false;");
 
895
      println("      for (zzCurrentPosL = zzStartRead; zzCurrentPosL < zzMarkedPosL;");
 
896
      println("                                                             zzCurrentPosL++) {");
 
897
      println("        switch (zzBufferL[zzCurrentPosL]) {");
 
898
      println("        case '\\u000B':"); 
 
899
      println("        case '\\u000C':"); 
 
900
      println("        case '\\u0085':");
 
901
      println("        case '\\u2028':"); 
 
902
      println("        case '\\u2029':"); 
 
903
      if ( scanner.lineCount )
 
904
        println("          yyline++;");
 
905
      if ( scanner.columnCount )
 
906
        println("          yycolumn = 0;");
 
907
      println("          zzR = false;");
 
908
      println("          break;");      
 
909
      println("        case '\\r':");
 
910
      if ( scanner.lineCount )
 
911
        println("          yyline++;");
 
912
      if ( scanner.columnCount )
 
913
        println("          yycolumn = 0;");
 
914
      println("          zzR = true;");
 
915
      println("          break;");
 
916
      println("        case '\\n':");
 
917
      println("          if (zzR)");
 
918
      println("            zzR = false;");
 
919
      println("          else {");
 
920
      if ( scanner.lineCount )
 
921
        println("            yyline++;");
 
922
      if ( scanner.columnCount )
 
923
        println("            yycolumn = 0;");
 
924
      println("          }");
 
925
      println("          break;");
 
926
      println("        default:");
 
927
      println("          zzR = false;");
 
928
      if ( scanner.columnCount ) 
 
929
        println("          yycolumn++;");
 
930
      println("        }");
 
931
      println("      }");
 
932
      println();
 
933
 
 
934
      if ( scanner.lineCount ) {
 
935
        println("      if (zzR) {");
 
936
        println("        // peek one character ahead if it is \\n (if we have counted one line too much)");
 
937
        println("        boolean zzPeek;");
 
938
        println("        if (zzMarkedPosL < zzEndReadL)");
 
939
        println("          zzPeek = zzBufferL[zzMarkedPosL] == '\\n';");
 
940
        println("        else if (zzAtEOF)");
 
941
        println("          zzPeek = false;");
 
942
        println("        else {");
 
943
        println("          boolean eof = zzRefill();");
 
944
        println("          zzEndReadL = zzEndRead;");
 
945
        println("          zzMarkedPosL = zzMarkedPos;");
 
946
        println("          zzBufferL = zzBuffer;");
 
947
        println("          if (eof) ");
 
948
        println("            zzPeek = false;");
 
949
        println("          else ");
 
950
        println("            zzPeek = zzBufferL[zzMarkedPosL] == '\\n';");
 
951
        println("        }");
 
952
        println("        if (zzPeek) yyline--;");
 
953
        println("      }");
 
954
      }
 
955
    }
 
956
 
 
957
    if ( scanner.bolUsed ) {
 
958
      // zzMarkedPos > zzStartRead <=> last match was not empty
 
959
      // if match was empty, last value of zzAtBOL can be used
 
960
      // zzStartRead is always >= 0
 
961
      println("      if (zzMarkedPosL > zzStartRead) {");
 
962
      println("        switch (zzBufferL[zzMarkedPosL-1]) {");
 
963
      println("        case '\\n':");
 
964
      println("        case '\\u000B':"); 
 
965
      println("        case '\\u000C':"); 
 
966
      println("        case '\\u0085':");
 
967
      println("        case '\\u2028':"); 
 
968
      println("        case '\\u2029':"); 
 
969
      println("          zzAtBOL = true;");
 
970
      println("          break;"); 
 
971
      println("        case '\\r': "); 
 
972
      println("          if (zzMarkedPosL < zzEndReadL)");
 
973
      println("            zzAtBOL = zzBufferL[zzMarkedPosL] != '\\n';");
 
974
      println("          else if (zzAtEOF)");
 
975
      println("            zzAtBOL = false;");
 
976
      println("          else {");
 
977
      println("            boolean eof = zzRefill();");
 
978
      println("            zzMarkedPosL = zzMarkedPos;");
 
979
      println("            zzEndReadL = zzEndRead;");
 
980
      println("            zzBufferL = zzBuffer;");
 
981
      println("            if (eof) ");
 
982
      println("              zzAtBOL = false;");
 
983
      println("            else ");
 
984
      println("              zzAtBOL = zzBufferL[zzMarkedPosL] != '\\n';");
 
985
      println("          }");      
 
986
      println("          break;"); 
 
987
      println("        default:"); 
 
988
      println("          zzAtBOL = false;");
 
989
      println("        }"); 
 
990
      println("      }"); 
 
991
    }
 
992
 
 
993
    skel.emitNext();
 
994
    
 
995
    if (scanner.bolUsed) {
 
996
      println("      if (zzAtBOL)");
 
997
      println("        zzState = ZZ_LEXSTATE[zzLexicalState+1];");
 
998
      println("      else");    
 
999
      println("        zzState = ZZ_LEXSTATE[zzLexicalState];");
 
1000
      println();
 
1001
    }
 
1002
    else {
 
1003
      println("      zzState = zzLexicalState;");
 
1004
      println();
 
1005
    }
 
1006
 
 
1007
    if (scanner.lookAheadUsed)
 
1008
      println("      zzWasPushback = false;");
 
1009
 
 
1010
    skel.emitNext();
 
1011
  }
 
1012
 
 
1013
  
 
1014
  private void emitGetRowMapNext() {
 
1015
    println("          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];");
 
1016
    println("          if (zzNext == "+DFA.NO_TARGET+") break zzForAction;");
 
1017
    println("          zzState = zzNext;");
 
1018
    println();
 
1019
 
 
1020
    println("          int zzAttributes = zzAttrL[zzState];");
 
1021
 
 
1022
    if ( scanner.lookAheadUsed ) {
 
1023
      println("          if ( (zzAttributes & "+PUSHBACK+") == "+PUSHBACK+" )");
 
1024
      println("            zzPushbackPosL = zzCurrentPosL;");
 
1025
      println();
 
1026
    }
 
1027
 
 
1028
    println("          if ( (zzAttributes & "+FINAL+") == "+FINAL+" ) {");
 
1029
    if ( scanner.lookAheadUsed ) 
 
1030
      println("            zzWasPushback = (zzAttributes & "+LOOKEND+") == "+LOOKEND+";");
 
1031
 
 
1032
    skel.emitNext();
 
1033
    
 
1034
    println("            if ( (zzAttributes & "+NOLOOK+") == "+NOLOOK+" ) break zzForAction;");
 
1035
 
 
1036
    skel.emitNext();    
 
1037
  }  
 
1038
 
 
1039
  private void emitTransitionTable() {
 
1040
    transformTransitionTable();
 
1041
    
 
1042
    println("          zzInput = zzCMapL[zzInput];");
 
1043
    println();
 
1044
 
 
1045
    if ( scanner.lookAheadUsed ) 
 
1046
      println("          boolean zzPushback = false;");
 
1047
      
 
1048
    println("          boolean zzIsFinal = false;");
 
1049
    println("          boolean zzNoLookAhead = false;");
 
1050
    println();
 
1051
    
 
1052
    println("          zzForNext: { switch (zzState) {");
 
1053
 
 
1054
    for (int state = 0; state < dfa.numStates; state++)
 
1055
      if (isTransition[state]) emitState(state);
 
1056
 
 
1057
    println("            default:");
 
1058
    println("              // if this is ever reached, there is a serious bug in JFlex");
 
1059
    println("              zzScanError(ZZ_UNKNOWN_ERROR);");
 
1060
    println("              break;");
 
1061
    println("          } }");
 
1062
    println();
 
1063
    
 
1064
    println("          if ( zzIsFinal ) {");
 
1065
    
 
1066
    if ( scanner.lookAheadUsed ) 
 
1067
      println("            zzWasPushback = zzPushback;");
 
1068
    
 
1069
    skel.emitNext();
 
1070
    
 
1071
    println("            if ( zzNoLookAhead ) break zzForAction;");
 
1072
 
 
1073
    skel.emitNext();    
 
1074
  }
 
1075
 
 
1076
 
 
1077
  /**
 
1078
   * Escapes all " ' \ tabs and newlines
 
1079
   */
 
1080
  private String escapify(String s) {
 
1081
    StringBuffer result = new StringBuffer(s.length()*2);
 
1082
    
 
1083
    for (int i = 0; i < s.length(); i++) {
 
1084
      char c = s.charAt(i);
 
1085
      switch (c) {
 
1086
      case '\'': result.append("\\\'"); break;
 
1087
      case '\"': result.append("\\\""); break;
 
1088
      case '\\': result.append("\\\\"); break;
 
1089
      case '\t': result.append("\\t"); break;
 
1090
      case '\r': if (i+1 == s.length() || s.charAt(i+1) != '\n') result.append("\"+ZZ_NL+\""); 
 
1091
                 break;
 
1092
      case '\n': result.append("\"+ZZ_NL+\""); break;
 
1093
      default: result.append(c);
 
1094
      }
 
1095
    }
 
1096
 
 
1097
    return result.toString();
 
1098
  }
 
1099
 
 
1100
  public void emitActionTable() {
 
1101
    int lastAction = 1;    
 
1102
    int count = 0;
 
1103
    int value = 0;
 
1104
 
 
1105
    println("  /** ");
 
1106
    println("   * Translates DFA states to action switch labels.");
 
1107
    println("   */");
 
1108
    CountEmitter e = new CountEmitter("Action");    
 
1109
    e.emitInit();
 
1110
 
 
1111
    for (int i = 0; i < dfa.numStates; i++) {
 
1112
      int newVal; 
 
1113
      if ( dfa.isFinal[i] ) {
 
1114
        Action action = dfa.action[i];
 
1115
        Integer stored = (Integer) actionTable.get(action);
 
1116
        if ( stored == null ) { 
 
1117
          stored = new Integer(lastAction++);
 
1118
          actionTable.put(action, stored);
 
1119
        }
 
1120
        newVal = stored.intValue();
 
1121
      }
 
1122
      else {
 
1123
        newVal = 0;
 
1124
      }
 
1125
      
 
1126
      if (value == newVal) {
 
1127
        count++;
 
1128
      }
 
1129
      else {
 
1130
        if (count > 0) e.emit(count,value);
 
1131
        count = 1;
 
1132
        value = newVal;        
 
1133
      }
 
1134
    }
 
1135
    
 
1136
    if (count > 0) e.emit(count,value);
 
1137
 
 
1138
    e.emitUnpack();    
 
1139
    println(e.toString());
 
1140
  }
 
1141
 
 
1142
  private void emitActions() {
 
1143
    println("      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {");
 
1144
 
 
1145
    int i = actionTable.size()+1;  
 
1146
    Enumeration actions = actionTable.keys();
 
1147
    while ( actions.hasMoreElements() ) {
 
1148
      Action action = (Action) actions.nextElement();
 
1149
      int label = ((Integer) actionTable.get(action)).intValue();
 
1150
 
 
1151
      println("        case "+label+": "); 
 
1152
      
 
1153
      if ( scanner.debugOption ) {
 
1154
        print("          System.out.println(");
 
1155
        if ( scanner.lineCount )
 
1156
          print("\"line: \"+(yyline+1)+\" \"+");
 
1157
        if ( scanner.columnCount )
 
1158
          print("\"col: \"+(yycolumn+1)+\" \"+");
 
1159
        println("\"match: --\"+yytext()+\"--\");");        
 
1160
        print("          System.out.println(\"action ["+action.priority+"] { ");
 
1161
        print(escapify(action.content));
 
1162
        println(" }\");");
 
1163
      }
 
1164
      
 
1165
      println("          { "+action.content);
 
1166
      println("          }");
 
1167
      println("        case "+(i++)+": break;"); 
 
1168
    }
 
1169
  }
 
1170
 
 
1171
  private void emitEOFVal() {
 
1172
    EOFActions eofActions = parser.getEOFActions();
 
1173
 
 
1174
    if ( scanner.eofCode != null ) 
 
1175
      println("            zzDoEOF();");
 
1176
      
 
1177
    if ( eofActions.numActions() > 0 ) {
 
1178
      println("            switch (zzLexicalState) {");
 
1179
      
 
1180
      Enumeration stateNames = scanner.states.names();
 
1181
 
 
1182
      // record lex states already emitted:
 
1183
      Hashtable used = new Hashtable();
 
1184
 
 
1185
      // pick a start value for break case labels. 
 
1186
      // must be larger than any value of a lex state:
 
1187
      int last = dfa.numStates;
 
1188
      
 
1189
      while ( stateNames.hasMoreElements() ) {
 
1190
        String name = (String) stateNames.nextElement();
 
1191
        int num = scanner.states.getNumber(name).intValue();
 
1192
        Action action = eofActions.getAction(num);
 
1193
 
 
1194
        // only emit code if the lex state is not redundant, so
 
1195
        // that case labels don't overlap
 
1196
        // (redundant = points to the same dfa state as another one).
 
1197
        // applies only to scanners that don't use BOL, because
 
1198
        // in BOL scanners lex states get mapped at runtime, so
 
1199
        // case labels will always be unique.
 
1200
        boolean unused = true;                
 
1201
        if (!scanner.bolUsed) {
 
1202
          Integer key = new Integer(dfa.lexState[2*num]);
 
1203
          unused = used.get(key) == null;
 
1204
          
 
1205
          if (!unused) 
 
1206
            Out.warning("Lexical states <"+name+"> and <"+used.get(key)+"> are equivalent.");
 
1207
          else
 
1208
            used.put(key,name);
 
1209
        }
 
1210
 
 
1211
        if (action != null && unused) {
 
1212
          println("            case "+name+": {");
 
1213
          if ( scanner.debugOption ) {
 
1214
            print("              System.out.println(");
 
1215
            if ( scanner.lineCount )
 
1216
              print("\"line: \"+(yyline+1)+\" \"+");
 
1217
            if ( scanner.columnCount )
 
1218
              print("\"col: \"+(yycolumn+1)+\" \"+");
 
1219
            println("\"match: <<EOF>>\");");        
 
1220
            print("              System.out.println(\"action ["+action.priority+"] { ");
 
1221
            print(escapify(action.content));
 
1222
            println(" }\");");
 
1223
          }
 
1224
          println("              "+action.content);
 
1225
          println("            }");
 
1226
          println("            case "+(++last)+": break;");
 
1227
        }
 
1228
      }
 
1229
      
 
1230
      println("            default:");
 
1231
    }
 
1232
 
 
1233
    Action defaultAction = eofActions.getDefault();
 
1234
 
 
1235
    if (defaultAction != null) {
 
1236
      println("              {");
 
1237
      if ( scanner.debugOption ) {
 
1238
        print("                System.out.println(");
 
1239
        if ( scanner.lineCount )
 
1240
          print("\"line: \"+(yyline+1)+\" \"+");
 
1241
        if ( scanner.columnCount )
 
1242
          print("\"col: \"+(yycolumn+1)+\" \"+");
 
1243
        println("\"match: <<EOF>>\");");        
 
1244
        print("                System.out.println(\"action ["+defaultAction.priority+"] { ");
 
1245
        print(escapify(defaultAction.content));
 
1246
        println(" }\");");
 
1247
      }
 
1248
      println("                " + defaultAction.content);
 
1249
      println("              }");
 
1250
    }
 
1251
    else if ( scanner.eofVal != null ) 
 
1252
      println("              { " + scanner.eofVal + " }");
 
1253
    else if ( scanner.isInteger ) 
 
1254
      println("            return YYEOF;");
 
1255
    else
 
1256
      println("            return null;");
 
1257
 
 
1258
    if (eofActions.numActions() > 0)
 
1259
      println("            }");
 
1260
  }
 
1261
  
 
1262
  private void emitState(int state) {
 
1263
    
 
1264
    println("            case "+state+":");
 
1265
    println("              switch (zzInput) {");
 
1266
   
 
1267
    int defaultTransition = getDefaultTransition(state);
 
1268
    
 
1269
    for (int next = 0; next < dfa.numStates; next++) {
 
1270
            
 
1271
      if ( next != defaultTransition && table[state][next] != null ) {
 
1272
        emitTransition(state, next);
 
1273
      }
 
1274
    }
 
1275
    
 
1276
    if ( defaultTransition != DFA.NO_TARGET && noTarget[state] != null ) {
 
1277
      emitTransition(state, DFA.NO_TARGET);
 
1278
    }
 
1279
    
 
1280
    emitDefaultTransition(state, defaultTransition);
 
1281
    
 
1282
    println("              }");
 
1283
    println("");
 
1284
  }
 
1285
  
 
1286
  private void emitTransition(int state, int nextState) {
 
1287
 
 
1288
    CharSetEnumerator chars;
 
1289
    
 
1290
    if (nextState != DFA.NO_TARGET) 
 
1291
      chars = table[state][nextState].characters();
 
1292
    else 
 
1293
      chars = noTarget[state].characters();
 
1294
  
 
1295
    print("                case ");
 
1296
    print((int)chars.nextElement());
 
1297
    print(": ");
 
1298
    
 
1299
    while ( chars.hasMoreElements() ) {
 
1300
      println();
 
1301
      print("                case ");
 
1302
      print((int)chars.nextElement());
 
1303
      print(": ");
 
1304
    } 
 
1305
    
 
1306
    if ( nextState != DFA.NO_TARGET ) {
 
1307
      if ( dfa.isFinal[nextState] )
 
1308
        print("zzIsFinal = true; ");
 
1309
        
 
1310
      if ( dfa.isPushback[nextState] ) 
 
1311
        print("zzPushbackPosL = zzCurrentPosL; ");
 
1312
      
 
1313
      if ( dfa.isLookEnd[nextState] )
 
1314
        print("zzPushback = true; ");
 
1315
 
 
1316
      if ( !isTransition[nextState] )
 
1317
        print("zzNoLookAhead = true; ");
 
1318
        
 
1319
      if ( nextState == state ) 
 
1320
        println("break zzForNext;");
 
1321
      else
 
1322
        println("zzState = "+nextState+"; break zzForNext;");
 
1323
    }
 
1324
    else
 
1325
      println("break zzForAction;");
 
1326
  }
 
1327
  
 
1328
  private void emitDefaultTransition(int state, int nextState) {
 
1329
    print("                default: ");
 
1330
    
 
1331
    if ( nextState != DFA.NO_TARGET ) {
 
1332
      if ( dfa.isFinal[nextState] )
 
1333
        print("zzIsFinal = true; ");
 
1334
        
 
1335
      if ( dfa.isPushback[nextState] ) 
 
1336
        print("zzPushbackPosL = zzCurrentPosL; ");
 
1337
 
 
1338
      if ( dfa.isLookEnd[nextState] )
 
1339
        print("zzPushback = true; ");
 
1340
          
 
1341
      if ( !isTransition[nextState] )
 
1342
        print("zzNoLookAhead = true; ");
 
1343
        
 
1344
      if ( nextState == state ) 
 
1345
        println("break zzForNext;");
 
1346
      else
 
1347
        println("zzState = "+nextState+"; break zzForNext;");
 
1348
    }
 
1349
    else
 
1350
      println( "break zzForAction;" );
 
1351
  }
 
1352
  
 
1353
  private void emitPushback() {
 
1354
    println("      if (zzWasPushback)");
 
1355
    println("        zzMarkedPos = zzPushbackPosL;");
 
1356
  }
 
1357
  
 
1358
  private int getDefaultTransition(int state) {
 
1359
    int max = 0;
 
1360
    
 
1361
    for (int i = 0; i < dfa.numStates; i++) {
 
1362
      if ( table[state][max] == null )
 
1363
        max = i;
 
1364
      else
 
1365
      if ( table[state][i] != null && table[state][max].size() < table[state][i].size() )
 
1366
        max = i;
 
1367
    }
 
1368
    
 
1369
    if ( table[state][max] == null ) return DFA.NO_TARGET;
 
1370
    if ( noTarget[state] == null ) return max;
 
1371
    
 
1372
    if ( table[state][max].size() < noTarget[state].size() ) 
 
1373
      max = DFA.NO_TARGET;
 
1374
    
 
1375
    return max;
 
1376
  }
 
1377
 
 
1378
  // for switch statement:
 
1379
  private void transformTransitionTable() {
 
1380
    
 
1381
    int numInput = parser.getCharClasses().getNumClasses()+1;
 
1382
 
 
1383
    int i;    
 
1384
    char j;
 
1385
    
 
1386
    table = new CharSet[dfa.numStates][dfa.numStates];
 
1387
    noTarget = new CharSet[dfa.numStates];
 
1388
    
 
1389
    for (i = 0; i < dfa.numStates;  i++) 
 
1390
      for (j = 0; j < dfa.numInput; j++) {
 
1391
 
 
1392
        int nextState = dfa.table[i][j];
 
1393
        
 
1394
        if ( nextState == DFA.NO_TARGET ) {
 
1395
          if ( noTarget[i] == null ) 
 
1396
            noTarget[i] = new CharSet(numInput, colMap[j]);
 
1397
          else
 
1398
            noTarget[i].add(colMap[j]);
 
1399
        }
 
1400
        else {
 
1401
          if ( table[i][nextState] == null ) 
 
1402
            table[i][nextState] = new CharSet(numInput, colMap[j]);
 
1403
          else
 
1404
            table[i][nextState].add(colMap[j]);
 
1405
        }
 
1406
      }
 
1407
  }
 
1408
 
 
1409
  private void findActionStates() {
 
1410
    isTransition = new boolean [dfa.numStates];
 
1411
    
 
1412
    for (int i = 0; i < dfa.numStates;  i++) {
 
1413
      char j = 0;
 
1414
      while ( !isTransition[i] && j < dfa.numInput )
 
1415
        isTransition[i] = dfa.table[i][j++] != DFA.NO_TARGET;
 
1416
    }
 
1417
  }
 
1418
 
 
1419
  
 
1420
  private void reduceColumns() {
 
1421
    colMap = new int [dfa.numInput];
 
1422
    colKilled = new boolean [dfa.numInput];
 
1423
 
 
1424
    int i,j,k;
 
1425
    int translate = 0;
 
1426
    boolean equal;
 
1427
 
 
1428
    numCols = dfa.numInput;
 
1429
 
 
1430
    for (i = 0; i < dfa.numInput; i++) {
 
1431
      
 
1432
      colMap[i] = i-translate;
 
1433
      
 
1434
      for (j = 0; j < i; j++) {
 
1435
        
 
1436
        // test for equality:
 
1437
        k = -1;
 
1438
        equal = true;        
 
1439
        while (equal && ++k < dfa.numStates) 
 
1440
          equal = dfa.table[k][i] == dfa.table[k][j];
 
1441
        
 
1442
        if (equal) {
 
1443
          translate++;
 
1444
          colMap[i] = colMap[j];
 
1445
          colKilled[i] = true;
 
1446
          numCols--;
 
1447
          break;
 
1448
        } // if
 
1449
      } // for j
 
1450
    } // for i
 
1451
  }
 
1452
  
 
1453
  private void reduceRows() {
 
1454
    rowMap = new int [dfa.numStates];
 
1455
    rowKilled = new boolean [dfa.numStates];
 
1456
    
 
1457
    int i,j,k;
 
1458
    int translate = 0;
 
1459
    boolean equal;
 
1460
 
 
1461
    numRows = dfa.numStates;
 
1462
 
 
1463
    // i is the state to add to the new table
 
1464
    for (i = 0; i < dfa.numStates; i++) {
 
1465
      
 
1466
      rowMap[i] = i-translate;
 
1467
      
 
1468
      // check if state i can be removed (i.e. already
 
1469
      // exists in entries 0..i-1)
 
1470
      for (j = 0; j < i; j++) {
 
1471
        
 
1472
        // test for equality:
 
1473
        k = -1;
 
1474
        equal = true;
 
1475
        while (equal && ++k < dfa.numInput) 
 
1476
          equal = dfa.table[i][k] == dfa.table[j][k];
 
1477
        
 
1478
        if (equal) {
 
1479
          translate++;
 
1480
          rowMap[i] = rowMap[j];
 
1481
          rowKilled[i] = true;
 
1482
          numRows--;
 
1483
          break;
 
1484
        } // if
 
1485
      } // for j
 
1486
    } // for i
 
1487
    
 
1488
  } 
 
1489
 
 
1490
 
 
1491
  /**
 
1492
   * Set up EOF code sectioin according to scanner.eofcode 
 
1493
   */
 
1494
  private void setupEOFCode() {
 
1495
    if (scanner.eofclose) {
 
1496
      scanner.eofCode = LexScan.conc(scanner.eofCode, "  yyclose();");
 
1497
      scanner.eofThrow = LexScan.concExc(scanner.eofThrow, "java.io.IOException");
 
1498
    }    
 
1499
  } 
 
1500
 
 
1501
 
 
1502
  /**
 
1503
   * Main Emitter method.  
 
1504
   */
 
1505
  public void emit() {    
 
1506
 
 
1507
    setupEOFCode();
 
1508
 
 
1509
    if (scanner.functionName == null) 
 
1510
      scanner.functionName = "yylex";
 
1511
 
 
1512
    reduceColumns();
 
1513
    findActionStates();
 
1514
 
 
1515
    emitHeader();
 
1516
    emitUserCode();
 
1517
    emitClassName();
 
1518
    
 
1519
    skel.emitNext();
 
1520
    
 
1521
    println("  private static final int ZZ_BUFFERSIZE = "+scanner.bufferSize+";");
 
1522
 
 
1523
    if (scanner.debugOption) {
 
1524
      println("  private static final String ZZ_NL = System.getProperty(\"line.separator\");");
 
1525
    }
 
1526
 
 
1527
    skel.emitNext();
 
1528
 
 
1529
    emitLexicalStates();
 
1530
   
 
1531
    emitCharMapArray();
 
1532
    
 
1533
    emitActionTable();
 
1534
    
 
1535
    if (scanner.useRowMap) {
 
1536
     reduceRows();
 
1537
    
 
1538
      emitRowMapArray();
 
1539
 
 
1540
      if (scanner.packed)
 
1541
        emitDynamicInit();
 
1542
      else
 
1543
        emitZZTrans();
 
1544
    }
 
1545
    
 
1546
    skel.emitNext();
 
1547
    
 
1548
    if (scanner.useRowMap) 
 
1549
      emitAttributes();    
 
1550
 
 
1551
    skel.emitNext();
 
1552
    
 
1553
    emitClassCode();
 
1554
    
 
1555
    skel.emitNext();
 
1556
    
 
1557
    emitConstructorDecl();
 
1558
        
 
1559
    emitCharMapInitFunction();
 
1560
 
 
1561
    skel.emitNext();
 
1562
    
 
1563
    emitScanError();
 
1564
 
 
1565
    skel.emitNext();        
 
1566
 
 
1567
    emitDoEOF();
 
1568
    
 
1569
    skel.emitNext();
 
1570
    
 
1571
    emitLexFunctHeader();
 
1572
    
 
1573
    emitNextInput();
 
1574
 
 
1575
    if (scanner.useRowMap)
 
1576
      emitGetRowMapNext();
 
1577
    else
 
1578
      emitTransitionTable();
 
1579
        
 
1580
    if (scanner.lookAheadUsed) 
 
1581
      emitPushback();
 
1582
        
 
1583
    skel.emitNext();
 
1584
 
 
1585
    emitActions();
 
1586
        
 
1587
    skel.emitNext();
 
1588
 
 
1589
    emitEOFVal();
 
1590
    
 
1591
    skel.emitNext();
 
1592
    
 
1593
    emitNoMatch();
 
1594
 
 
1595
    skel.emitNext();
 
1596
    
 
1597
    emitMain();
 
1598
    
 
1599
    skel.emitNext();
 
1600
 
 
1601
    out.close();
 
1602
  }
 
1603
 
 
1604
}