KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JFlex > Emitter


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 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: 2.26 $, $Date: 2004/11/07 03:12:46 $
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 JavaDoc 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 JavaDoc visibility = "public";
80
81   public Emitter(File inputFile, LexParse parser, DFA dfa) throws IOException {
82
83     String JavaDoc 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 JavaDoc 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 JavaDoc line) {
138     out.println(line);
139   }
140
141   private void println(int i) {
142     out.println(i);
143   }
144
145   private void print(String JavaDoc 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 JavaDoc 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 JavaDoc usercode) {
422     String JavaDoc 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 JavaDoc name = (String JavaDoc) 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 JavaDoc escapify(String JavaDoc s) {
1081    StringBuffer JavaDoc result = new StringBuffer JavaDoc(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 JavaDoc stored = (Integer JavaDoc) actionTable.get(action);
1116        if ( stored == null ) {
1117          stored = new Integer JavaDoc(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 JavaDoc) 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 JavaDoc name = (String JavaDoc) 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 JavaDoc key = new Integer JavaDoc(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}
1605
Popular Tags