1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3
* Copyright (C) 1998-2004 Gerwin Klein <lsf@jflex.de> *
4
* All rights reserved. *
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. *
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. *
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 *
19
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
package weka.core.parser.JFlex;
28
* This class manages the actual code generation, putting
29
* the scanner together, filling in skeleton sections etc.
31
* Table compression, String packing etc. is also done here.
33
* @author Gerwin Klein
34
* @version JFlex 1.4.1, $Revision: 1.1 $, $Date: 2008/05/09 09:14:11 $
36
final public class Emitter {
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;
44
static final private String date = (new SimpleDateFormat()).format(new Date());
46
private File inputFile;
48
private PrintWriter out;
49
private Skeleton skel;
50
private LexScan scanner;
51
private LexParse parser;
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[][];
58
private boolean isTransition[];
60
// noTarget[i] is the set of input characters that have no target state in state i
61
private CharSet noTarget[];
65
private int [] rowMap;
66
private boolean [] rowKilled;
70
private int [] colMap;
71
private boolean [] colKilled;
74
/** maps actions to their switch label */
75
private Hashtable actionTable = new Hashtable();
77
private CharClassInterval [] intervalls;
79
private String visibility = "public";
81
public Emitter(File inputFile, LexParse parser, DFA dfa) throws IOException {
83
String name = parser.scanner.className+".java";
85
File outputFile = normalize(name, inputFile);
87
Out.println("Writing code to \""+outputFile+"\"");
89
this.out = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
91
this.scanner = parser.scanner;
92
this.visibility = scanner.visibility;
93
this.inputFile = inputFile;
95
this.skel = new Skeleton(out);
100
* Constructs a file in Options.getDir() or in the same directory as
101
* another file. Makes a backup if the file already exists.
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)
108
public static File normalize(String name, File input) {
111
if ( Options.getDir() == null )
112
if ( input == null || input.getParent() == null )
113
outputFile = new File(name);
115
outputFile = new File(input.getParent(), name);
117
outputFile = new File(Options.getDir(), name);
119
if ( outputFile.exists() && !Options.no_backup ) {
120
File backup = new File( outputFile.toString()+"~" );
122
if ( backup.exists() ) backup.delete();
124
if ( outputFile.renameTo( backup ) )
125
Out.println("Old file \""+outputFile+"\" saved as \""+backup+"\"");
127
Out.println("Couldn't save old file \""+outputFile+"\", overwriting!");
133
private void println() {
137
private void println(String line) {
141
private void println(int i) {
145
private void print(String line) {
149
private void print(int i) {
153
private void print(int i, int tab) {
162
if (Math.abs(i) < exp) print(" ");
169
private void emitScanError() {
170
print(" private void zzScanError(int errorCode)");
172
if (scanner.scanErrorException != null)
173
print(" throws "+scanner.scanErrorException);
179
if (scanner.scanErrorException == null)
180
println(" throw new Error(message);");
182
println(" throw new "+scanner.scanErrorException+"(message);");
186
print(" "+visibility+" void yypushback(int number) ");
188
if (scanner.scanErrorException == null)
191
println(" throws "+scanner.scanErrorException+" {");
194
private void emitMain() {
195
if ( !(scanner.standalone || scanner.debugOption || scanner.cupDebug) ) return;
197
if ( scanner.cupDebug ) {
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);
202
println(" * This code was contributed by Karl Meissner <meissnersd@yahoo.com>");
204
println(" private String getTokenName(int token) {");
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();");
212
println(" } catch (Exception e) {");
213
println(" e.printStackTrace(System.err);");
216
println(" return \"UNKNOWN TOKEN\";");
220
println(" * Same as "+scanner.functionName+" but also prints the token to standard out");
221
println(" * for debugging.");
223
println(" * This code was contributed by Karl Meissner <meissnersd@yahoo.com>");
226
print(" "+visibility+" ");
227
if ( scanner.tokenType == null ) {
228
if ( scanner.isInteger )
231
if ( scanner.isIntWrap )
237
print( scanner.tokenType );
241
print(scanner.functionName);
243
print("() throws java.io.IOException");
245
if ( scanner.lexThrow != null ) {
247
print(scanner.lexThrow);
250
if ( scanner.scanErrorException != null ) {
252
print(scanner.scanErrorException);
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;");
267
if ( scanner.standalone ) {
269
println(" * Runs the scanner on input files.");
271
println(" * This is a standalone scanner, it will print any unmatched");
272
println(" * text to System.out unchanged.");
274
println(" * @param argv the command line, contains the filenames to run");
275
println(" * the scanner on.");
280
println(" * Runs the scanner on input files.");
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.");
286
println(" * @param argv the command line, contains the filenames to run");
287
println(" * the scanner on.");
291
println(" public static void main(String argv[]) {");
292
println(" if (argv.length == 0) {");
293
println(" System.out.println(\"Usage : java "+scanner.className+" <inputfile>\");");
296
println(" for (int i = 0; i < argv.length; i++) {");
297
println(" "+scanner.className+" scanner = null;");
299
println(" scanner = new "+scanner.className+"( new java.io.FileReader(argv[i]) );");
301
if ( scanner.standalone ) {
302
println(" while ( !scanner.zzAtEOF ) scanner."+scanner.functionName+"();");
304
else if (scanner.cupDebug ) {
305
println(" while ( !scanner.zzAtEOF ) scanner.debug_"+scanner.functionName+"();");
309
println(" System.out.println(scanner."+scanner.functionName+"());");
310
println(" } while (!scanner.zzAtEOF);");
315
println(" catch (java.io.FileNotFoundException e) {");
316
println(" System.out.println(\"File not found : \\\"\"+argv[i]+\"\\\"\");");
318
println(" catch (java.io.IOException e) {");
319
println(" System.out.println(\"IO error scanning file \\\"\"+argv[i]+\"\\\"\");");
320
println(" System.out.println(e);");
322
println(" catch (Exception e) {");
323
println(" System.out.println(\"Unexpected exception:\");");
324
println(" e.printStackTrace();");
332
private void emitNoMatch() {
333
println(" zzScanError(ZZ_NO_MATCH);");
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;");
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;");
362
println(" zzInput = zzBufferL[zzCurrentPosL++];");
367
private void emitHeader() {
368
println("/* The following code was generated by JFlex "+Main.version+" on "+date+" */");
372
private void emitUserCode() {
373
if ( scanner.userCode.length() > 0 )
374
println(scanner.userCode.toString());
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, '/');
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>");
393
if ( scanner.isPublic ) print("public ");
395
if ( scanner.isAbstract) print("abstract ");
397
if ( scanner.isFinal ) print("final ");
400
print(scanner.className);
402
if ( scanner.isExtending != null ) {
404
print(scanner.isExtending);
407
if ( scanner.isImplementing != null ) {
408
print(" implements ");
409
print(scanner.isImplementing);
416
* Try to find out if user code ends with a javadoc comment
418
* @param buffer the user code
419
* @return true if it ends with a javadoc comment
421
public static boolean endsWithJavadoc(StringBuffer usercode) {
422
String s = usercode.toString().trim();
424
if (!s.endsWith("*/")) return false;
426
// find beginning of javadoc comment
427
int i = s.lastIndexOf("/**");
428
if (i < 0) return false;
430
// javadoc comment shouldn't contain a comment end
431
return s.substring(i,s.length()-2).indexOf("*/") < 0;
435
private void emitLexicalStates() {
436
Enumeration stateNames = scanner.states.names();
438
while ( stateNames.hasMoreElements() ) {
439
String name = (String) stateNames.nextElement();
441
int num = scanner.states.getNumber(name).intValue();
444
println(" "+visibility+" static final int "+name+" = "+2*num+";");
446
println(" "+visibility+" static final int "+name+" = "+dfa.lexState[2*num]+";");
449
if (scanner.bolUsed) {
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");
457
println(" private static final int ZZ_LEXSTATE[] = { ");
462
for (i = 0; i < dfa.lexState.length-1; i++) {
463
print( dfa.lexState[i], 2 );
474
println( dfa.lexState[i] );
480
private void emitDynamicInit() {
482
int value = dfa.table[0][0];
485
println(" * The transition table of the DFA");
488
CountEmitter e = new CountEmitter("Trans");
489
e.setValTranslation(+1); // allow vals in [-1, 0xFFFE]
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) {
500
e.emit(count, value);
503
value = dfa.table[i][c];
510
e.emit(count, value);
513
println(e.toString());
517
private void emitCharMapInitFunction() {
519
CharClasses cl = parser.getCharClasses();
521
if ( cl.getMaxCharCode() < 256 ) return;
525
println(" * Unpacks the compressed character translation table.");
527
println(" * @param packed the packed character translation table");
528
println(" * @return the unpacked character translation table");
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);");
539
println(" return map;");
543
private void emitZZTrans() {
549
println(" * The transition table of the DFA");
551
println(" private static final int ZZ_TRANS [] = {"); //XXX
554
for (i = 0; i < dfa.numStates; i++) {
556
if ( !rowKilled[i] ) {
557
for (c = 0; c < dfa.numInput; c++) {
558
if ( !colKilled[c] ) {
564
print( dfa.table[i][c] );
565
if (i != dfa.numStates-1 || c != dfa.numInput-1)
577
private void emitCharMapArrayUnPacked() {
579
CharClasses cl = parser.getCharClasses();
580
intervalls = cl.getIntervalls();
584
println(" * Translates characters to character classes");
586
println(" private static final char [] ZZ_CMAP = {");
588
int n = 0; // numbers of entries in current line
591
int max = cl.getMaxCharCode();
593
while ( i < intervalls.length && intervalls[i].start <= max ) {
595
int end = Math.min(intervalls[i].end, max);
596
for (int c = intervalls[i].start; c <= end; c++) {
598
print(colMap[intervalls[i].charClass], 2);
618
private void emitCharMapArray() {
619
CharClasses cl = parser.getCharClasses();
621
if ( cl.getMaxCharCode() < 256 ) {
622
emitCharMapArrayUnPacked();
626
// ignores cl.getMaxCharCode(), emits all intervalls instead
628
intervalls = cl.getIntervalls();
632
println(" * Translates characters to character classes");
634
println(" private static final String ZZ_CMAP_PACKED = ");
636
int n = 0; // numbers of entries in current line
640
while ( i < intervalls.length-1 ) {
641
int count = intervalls[i].end-intervalls[i].start+1;
642
int value = colMap[intervalls[i].charClass];
656
printUC(intervalls[i].end-intervalls[i].start+1);
657
printUC(colMap[intervalls[i].charClass]);
663
println(" * Translates characters to character classes");
665
println(" private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);");
671
* Print number as octal/unicode escaped string character.
673
* @param c the value to print
674
* @prec 0 <= c <= 0xFFFF
676
private void printUC(int c) {
679
if (c < 0x1000) out.print("0");
680
out.print(Integer.toHexString(c));
684
out.print(Integer.toOctalString(c));
689
private void emitRowMapArray() {
692
println(" * Translates a state to a row index in the transition table");
695
HiLowEmitter e = new HiLowEmitter("RowMap");
697
for (int i = 0; i < dfa.numStates; i++) {
698
e.emit(rowMap[i]*numCols);
701
println(e.toString());
705
private void emitAttributes() {
707
println(" * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>");
710
CountEmitter e = new CountEmitter("Attribute");
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;
720
for (int i = 1; i < dfa.numStates; i++) {
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;
727
if (value == attribute) {
731
e.emit(count, value);
737
e.emit(count, value);
740
println(e.toString());
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;");
751
if ( scanner.classCode != null ) {
752
println(" /* user code: */");
753
println(scanner.classCode);
757
private void emitConstructorDecl() {
761
if ( scanner.isPublic ) print("public ");
762
print( scanner.className );
763
print("(java.io.Reader in)");
765
if ( scanner.initThrow != null ) {
767
print( scanner.initThrow );
772
if ( scanner.initCode != null ) {
774
print( scanner.initCode );
777
println(" this.zzReader = in;");
784
println(" * Creates a new scanner.");
785
println(" * There is also java.io.Reader version of this constructor.");
787
println(" * @param in the java.io.Inputstream to read input from.");
791
if ( scanner.isPublic ) print("public ");
792
print( scanner.className );
793
print("(java.io.InputStream in)");
795
if ( scanner.initThrow != null ) {
797
print( scanner.initThrow );
801
println(" this(new java.io.InputStreamReader(in));");
806
private void emitDoEOF() {
807
if ( scanner.eofCode == null ) return;
810
println(" * Contains user EOF-code, which will be executed exactly once,");
811
println(" * when the end of file is reached");
814
print(" private void zzDoEOF()");
816
if ( scanner.eofThrow != null ) {
818
print(scanner.eofThrow);
823
println(" if (!zzEOFDone) {");
824
println(" zzEOFDone = true;");
825
println(" "+scanner.eofCode );
832
private void emitLexFunctHeader() {
834
if (scanner.cupCompatible) {
835
// force public, because we have to implement java_cup.runtime.Symbol
839
print(" "+visibility+" ");
842
if ( scanner.tokenType == null ) {
843
if ( scanner.isInteger )
846
if ( scanner.isIntWrap )
852
print( scanner.tokenType );
856
print(scanner.functionName);
858
print("() throws java.io.IOException");
860
if ( scanner.lexThrow != null ) {
862
print(scanner.lexThrow);
865
if ( scanner.scanErrorException != null ) {
867
print(scanner.scanErrorException);
874
if ( scanner.useRowMap ) {
875
println(" int [] zzTransL = ZZ_TRANS;");
876
println(" int [] zzRowMapL = ZZ_ROWMAP;");
877
println(" int [] zzAttrL = ZZ_ATTRIBUTE;");
881
if ( scanner.lookAheadUsed ) {
882
println(" int zzPushbackPosL = zzPushbackPos = -1;");
883
println(" boolean zzWasPushback;");
888
if ( scanner.charCount ) {
889
println(" yychar+= zzMarkedPosL-zzStartRead;");
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;");
909
println(" case '\\r':");
910
if ( scanner.lineCount )
911
println(" yyline++;");
912
if ( scanner.columnCount )
913
println(" yycolumn = 0;");
914
println(" zzR = true;");
916
println(" case '\\n':");
917
println(" if (zzR)");
918
println(" zzR = false;");
920
if ( scanner.lineCount )
921
println(" yyline++;");
922
if ( scanner.columnCount )
923
println(" yycolumn = 0;");
926
println(" default:");
927
println(" zzR = false;");
928
if ( scanner.columnCount )
929
println(" yycolumn++;");
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;");
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;");
950
println(" zzPeek = zzBufferL[zzMarkedPosL] == '\\n';");
952
println(" if (zzPeek) yyline--;");
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;");
971
println(" case '\\r': ");
972
println(" if (zzMarkedPosL < zzEndReadL)");
973
println(" zzAtBOL = zzBufferL[zzMarkedPosL] != '\\n';");
974
println(" else if (zzAtEOF)");
975
println(" zzAtBOL = false;");
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;");
984
println(" zzAtBOL = zzBufferL[zzMarkedPosL] != '\\n';");
987
println(" default:");
988
println(" zzAtBOL = false;");
995
if (scanner.bolUsed) {
996
println(" if (zzAtBOL)");
997
println(" zzState = ZZ_LEXSTATE[zzLexicalState+1];");
999
println(" zzState = ZZ_LEXSTATE[zzLexicalState];");
1003
println(" zzState = zzLexicalState;");
1007
if (scanner.lookAheadUsed)
1008
println(" zzWasPushback = false;");
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;");
1020
println(" int zzAttributes = zzAttrL[zzState];");
1022
if ( scanner.lookAheadUsed ) {
1023
println(" if ( (zzAttributes & "+PUSHBACK+") == "+PUSHBACK+" )");
1024
println(" zzPushbackPosL = zzCurrentPosL;");
1028
println(" if ( (zzAttributes & "+FINAL+") == "+FINAL+" ) {");
1029
if ( scanner.lookAheadUsed )
1030
println(" zzWasPushback = (zzAttributes & "+LOOKEND+") == "+LOOKEND+";");
1034
println(" if ( (zzAttributes & "+NOLOOK+") == "+NOLOOK+" ) break zzForAction;");
1039
private void emitTransitionTable() {
1040
transformTransitionTable();
1042
println(" zzInput = zzCMapL[zzInput];");
1045
if ( scanner.lookAheadUsed )
1046
println(" boolean zzPushback = false;");
1048
println(" boolean zzIsFinal = false;");
1049
println(" boolean zzNoLookAhead = false;");
1052
println(" zzForNext: { switch (zzState) {");
1054
for (int state = 0; state < dfa.numStates; state++)
1055
if (isTransition[state]) emitState(state);
1057
println(" default:");
1058
println(" // if this is ever reached, there is a serious bug in JFlex");
1059
println(" zzScanError(ZZ_UNKNOWN_ERROR);");
1064
println(" if ( zzIsFinal ) {");
1066
if ( scanner.lookAheadUsed )
1067
println(" zzWasPushback = zzPushback;");
1071
println(" if ( zzNoLookAhead ) break zzForAction;");
1078
* Escapes all " ' \ tabs and newlines
1080
private String escapify(String s) {
1081
StringBuffer result = new StringBuffer(s.length()*2);
1083
for (int i = 0; i < s.length(); i++) {
1084
char c = s.charAt(i);
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+\"");
1092
case '\n': result.append("\"+ZZ_NL+\""); break;
1093
default: result.append(c);
1097
return result.toString();
1100
public void emitActionTable() {
1106
println(" * Translates DFA states to action switch labels.");
1108
CountEmitter e = new CountEmitter("Action");
1111
for (int i = 0; i < dfa.numStates; i++) {
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);
1120
newVal = stored.intValue();
1126
if (value == newVal) {
1130
if (count > 0) e.emit(count,value);
1136
if (count > 0) e.emit(count,value);
1139
println(e.toString());
1142
private void emitActions() {
1143
println(" switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {");
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();
1151
println(" case "+label+": ");
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));
1165
println(" { "+action.content);
1167
println(" case "+(i++)+": break;");
1171
private void emitEOFVal() {
1172
EOFActions eofActions = parser.getEOFActions();
1174
if ( scanner.eofCode != null )
1175
println(" zzDoEOF();");
1177
if ( eofActions.numActions() > 0 ) {
1178
println(" switch (zzLexicalState) {");
1180
Enumeration stateNames = scanner.states.names();
1182
// record lex states already emitted:
1183
Hashtable used = new Hashtable();
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;
1189
while ( stateNames.hasMoreElements() ) {
1190
String name = (String) stateNames.nextElement();
1191
int num = scanner.states.getNumber(name).intValue();
1192
Action action = eofActions.getAction(num);
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;
1206
Out.warning("Lexical states <"+name+"> and <"+used.get(key)+"> are equivalent.");
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));
1224
println(" "+action.content);
1226
println(" case "+(++last)+": break;");
1230
println(" default:");
1233
Action defaultAction = eofActions.getDefault();
1235
if (defaultAction != null) {
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));
1248
println(" " + defaultAction.content);
1251
else if ( scanner.eofVal != null )
1252
println(" { " + scanner.eofVal + " }");
1253
else if ( scanner.isInteger )
1254
println(" return YYEOF;");
1256
println(" return null;");
1258
if (eofActions.numActions() > 0)
1262
private void emitState(int state) {
1264
println(" case "+state+":");
1265
println(" switch (zzInput) {");
1267
int defaultTransition = getDefaultTransition(state);
1269
for (int next = 0; next < dfa.numStates; next++) {
1271
if ( next != defaultTransition && table[state][next] != null ) {
1272
emitTransition(state, next);
1276
if ( defaultTransition != DFA.NO_TARGET && noTarget[state] != null ) {
1277
emitTransition(state, DFA.NO_TARGET);
1280
emitDefaultTransition(state, defaultTransition);
1286
private void emitTransition(int state, int nextState) {
1288
CharSetEnumerator chars;
1290
if (nextState != DFA.NO_TARGET)
1291
chars = table[state][nextState].characters();
1293
chars = noTarget[state].characters();
1296
print((int)chars.nextElement());
1299
while ( chars.hasMoreElements() ) {
1302
print((int)chars.nextElement());
1306
if ( nextState != DFA.NO_TARGET ) {
1307
if ( dfa.isFinal[nextState] )
1308
print("zzIsFinal = true; ");
1310
if ( dfa.isPushback[nextState] )
1311
print("zzPushbackPosL = zzCurrentPosL; ");
1313
if ( dfa.isLookEnd[nextState] )
1314
print("zzPushback = true; ");
1316
if ( !isTransition[nextState] )
1317
print("zzNoLookAhead = true; ");
1319
if ( nextState == state )
1320
println("break zzForNext;");
1322
println("zzState = "+nextState+"; break zzForNext;");
1325
println("break zzForAction;");
1328
private void emitDefaultTransition(int state, int nextState) {
1329
print(" default: ");
1331
if ( nextState != DFA.NO_TARGET ) {
1332
if ( dfa.isFinal[nextState] )
1333
print("zzIsFinal = true; ");
1335
if ( dfa.isPushback[nextState] )
1336
print("zzPushbackPosL = zzCurrentPosL; ");
1338
if ( dfa.isLookEnd[nextState] )
1339
print("zzPushback = true; ");
1341
if ( !isTransition[nextState] )
1342
print("zzNoLookAhead = true; ");
1344
if ( nextState == state )
1345
println("break zzForNext;");
1347
println("zzState = "+nextState+"; break zzForNext;");
1350
println( "break zzForAction;" );
1353
private void emitPushback() {
1354
println(" if (zzWasPushback)");
1355
println(" zzMarkedPos = zzPushbackPosL;");
1358
private int getDefaultTransition(int state) {
1361
for (int i = 0; i < dfa.numStates; i++) {
1362
if ( table[state][max] == null )
1365
if ( table[state][i] != null && table[state][max].size() < table[state][i].size() )
1369
if ( table[state][max] == null ) return DFA.NO_TARGET;
1370
if ( noTarget[state] == null ) return max;
1372
if ( table[state][max].size() < noTarget[state].size() )
1373
max = DFA.NO_TARGET;
1378
// for switch statement:
1379
private void transformTransitionTable() {
1381
int numInput = parser.getCharClasses().getNumClasses()+1;
1386
table = new CharSet[dfa.numStates][dfa.numStates];
1387
noTarget = new CharSet[dfa.numStates];
1389
for (i = 0; i < dfa.numStates; i++)
1390
for (j = 0; j < dfa.numInput; j++) {
1392
int nextState = dfa.table[i][j];
1394
if ( nextState == DFA.NO_TARGET ) {
1395
if ( noTarget[i] == null )
1396
noTarget[i] = new CharSet(numInput, colMap[j]);
1398
noTarget[i].add(colMap[j]);
1401
if ( table[i][nextState] == null )
1402
table[i][nextState] = new CharSet(numInput, colMap[j]);
1404
table[i][nextState].add(colMap[j]);
1409
private void findActionStates() {
1410
isTransition = new boolean [dfa.numStates];
1412
for (int i = 0; i < dfa.numStates; i++) {
1414
while ( !isTransition[i] && j < dfa.numInput )
1415
isTransition[i] = dfa.table[i][j++] != DFA.NO_TARGET;
1420
private void reduceColumns() {
1421
colMap = new int [dfa.numInput];
1422
colKilled = new boolean [dfa.numInput];
1428
numCols = dfa.numInput;
1430
for (i = 0; i < dfa.numInput; i++) {
1432
colMap[i] = i-translate;
1434
for (j = 0; j < i; j++) {
1436
// test for equality:
1439
while (equal && ++k < dfa.numStates)
1440
equal = dfa.table[k][i] == dfa.table[k][j];
1444
colMap[i] = colMap[j];
1445
colKilled[i] = true;
1453
private void reduceRows() {
1454
rowMap = new int [dfa.numStates];
1455
rowKilled = new boolean [dfa.numStates];
1461
numRows = dfa.numStates;
1463
// i is the state to add to the new table
1464
for (i = 0; i < dfa.numStates; i++) {
1466
rowMap[i] = i-translate;
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++) {
1472
// test for equality:
1475
while (equal && ++k < dfa.numInput)
1476
equal = dfa.table[i][k] == dfa.table[j][k];
1480
rowMap[i] = rowMap[j];
1481
rowKilled[i] = true;
1492
* Set up EOF code sectioin according to scanner.eofcode
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");
1503
* Main Emitter method.
1505
public void emit() {
1509
if (scanner.functionName == null)
1510
scanner.functionName = "yylex";
1521
println(" private static final int ZZ_BUFFERSIZE = "+scanner.bufferSize+";");
1523
if (scanner.debugOption) {
1524
println(" private static final String ZZ_NL = System.getProperty(\"line.separator\");");
1529
emitLexicalStates();
1535
if (scanner.useRowMap) {
1548
if (scanner.useRowMap)
1557
emitConstructorDecl();
1559
emitCharMapInitFunction();
1571
emitLexFunctHeader();
1575
if (scanner.useRowMap)
1576
emitGetRowMapNext();
1578
emitTransitionTable();
1580
if (scanner.lookAheadUsed)