OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [gnu/] [classpath/] [tools/] [gjdoc/] [Parser.java] - Blame information for rev 779

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 779 jeremybenn
/* gnu.classpath.tools.gjdoc.Parser
2
   Copyright (C) 2001, 2005, 2008 Free Software Foundation, Inc.
3
 
4
   This file is part of GNU Classpath.
5
 
6
   GNU Classpath is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 2, or (at your option)
9
   any later version.
10
 
11
   GNU Classpath is distributed in the hope that it will be useful, but
12
   WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
   General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with GNU Classpath; see the file COPYING.  If not, write to the
18
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19
   02111-1307 USA.
20
 
21
   Linking this library statically or dynamically with other modules is
22
   making a combined work based on this library.  Thus, the terms and
23
   conditions of the GNU General Public License cover the whole
24
   combination.
25
 
26
   As a special exception, the copyright holders of this library give you
27
   permission to link this library with independent modules to produce an
28
   executable, regardless of the license terms of these independent
29
   modules, and to copy and distribute the resulting executable under
30
   terms of your choice, provided that you also meet, for each linked
31
   independent module, the terms and conditions of the license of that
32
   module.  An independent module is a module which is not derived from
33
   or based on this library.  If you modify this library, you may extend
34
   this exception to your version of the library, but you are not
35
   obligated to do so.  If you do not wish to do so, delete this
36
   exception statement from your version. */
37
 
38
package gnu.classpath.tools.gjdoc;
39
 
40
import java.io.*;
41
import java.nio.ByteBuffer;
42
import java.nio.CharBuffer;
43
import java.nio.charset.Charset;
44
import java.nio.charset.CharsetDecoder;
45
import java.nio.charset.CoderResult;
46
import java.nio.charset.CodingErrorAction;
47
import java.util.*;
48
 
49
import com.sun.javadoc.*;
50
 
51
import gnu.classpath.tools.IOToolkit;
52
import gnu.classpath.tools.NotifyingInputStreamReader;
53
import gnu.classpath.tools.MalformedInputListener;
54
import gnu.classpath.tools.MalformedInputEvent;
55
 
56
   class IgnoredFileParseException extends ParseException
57
   {
58
      // marker exception
59
   }
60
 
61
   abstract class SourceComponent {
62
 
63
      abstract int match(char[] source, int index) throws ParseException;
64
 
65
      int process(Parser parser, char[] source, int startIndex, int endIndex) throws ParseException, IOException {
66
         return endIndex;
67
      }
68
 
69
      int getEndIndex(char[] source, int endIndex) throws ParseException {
70
         return endIndex;
71
      }
72
   }
73
 
74
   abstract class BlockSourceComponent extends SourceComponent {
75
 
76
      int getEndIndex(char[] source, int endIndex) throws ParseException {
77
         return Parser.skipExpression(source, endIndex, 1, '\0');
78
      }
79
 
80
   }
81
 
82
   class Whitespace extends SourceComponent {
83
 
84
      int match(char[] source, int index) {
85
 
86
         int rc=index;
87
         int slen=source.length;
88
         while (rc<slen && Parser.WHITESPACE.indexOf(source[rc])>=0) ++rc;
89
 
90
         return (rc!=index) ? rc : -1;
91
      }
92
   }
93
 
94
   class BracketClose extends SourceComponent {
95
 
96
      int match(char[] source, int index) {
97
         if (source[index]=='}') {
98
            return index+1;
99
         }
100
         else {
101
            return -1;
102
         }
103
      }
104
 
105
     int process(Parser parser, char[] source, int startIndex, int endIndex)
106
       throws ParseException, IOException
107
     {
108
       parser.classClosed();
109
       return endIndex;
110
     }
111
   }
112
 
113
   class CommentComponent extends SourceComponent {
114
 
115
      int match(char[] source, int index) throws ParseException {
116
         if (index+1<source.length && source[index]=='/' && source[index+1]=='*') {
117
            for (index+=2; index+1<source.length; ++index) {
118
               if (source[index]=='*' && source[index+1]=='/')
119
                  return index+2;
120
            }
121
            throw new ParseException("unexpected end of input");
122
         }
123
         return -1;
124
      }
125
 
126
      int process(Parser parser, char[] source, int startIndex, int endIndex) {
127
 
128
         if (source[startIndex+0]=='/'
129
             && source[startIndex+1]=='*'
130
             && source[startIndex+2]=='*') {
131
 
132
            parser.setLastComment(new String(source, startIndex, endIndex-startIndex));
133
         }
134
         else if (null == parser.getBoilerplateComment() && Main.getInstance().isCopyLicenseText()) {
135
            String boilerplateComment = new String(source, startIndex + 2, endIndex-startIndex - 4);
136
            if (boilerplateComment.toLowerCase().indexOf("copyright") >= 0) {
137
               parser.setBoilerplateComment(boilerplateComment);
138
            }
139
         }
140
 
141
         return endIndex;
142
      }
143
   }
144
 
145
   class SlashSlashCommentComponent extends SourceComponent {
146
 
147
      int match(char[] source, int index) {
148
         if (index+1<source.length && source[index]=='/' && source[index+1]=='/') {
149
            index+=2;
150
            while (index<source.length && source[index]!='\n')
151
               ++index;
152
            return index;
153
         }
154
         else {
155
            return -1;
156
         }
157
      }
158
   }
159
 
160
   class EmptyStatementComponent extends SourceComponent {
161
 
162
      int match(char[] source, int index) {
163
         while (index < source.length
164
                && Parser.isWhitespace(source[index])) {
165
            ++ index;
166
         }
167
         if (index < source.length && source[index] == ';') {
168
            return index+1;
169
         }
170
         else {
171
            return -1;
172
         }
173
      }
174
   }
175
 
176
   class ImportComponent extends SourceComponent {
177
 
178
      int match(char[] source, int index) {
179
         if (index+7<source.length) {
180
            if (source[index+0]=='i'
181
                && source[index+1]=='m'
182
                && source[index+2]=='p'
183
                && source[index+3]=='o'
184
                && source[index+4]=='r'
185
                && source[index+5]=='t'
186
                && Parser.WHITESPACE.indexOf(source[index+6])>=0) {
187
 
188
               for (index+=7; index<source.length && source[index]!=';'; ++index)
189
                  ;
190
 
191
               return index+1;
192
            }
193
         }
194
         return -1;
195
      }
196
 
197
      int process(Parser parser, char[] source, int startIndex, int endIndex) throws ParseException, IOException {
198
         String importString=new String(source,startIndex+7,endIndex-startIndex-7-1).trim();
199
         parser.importEncountered(importString);
200
         return endIndex;
201
      }
202
   }
203
 
204
   class PackageComponent extends SourceComponent {
205
 
206
      int match(char[] source, int index) {
207
         if (index+10<source.length) {
208
            if (source[index+0]=='p'
209
                && source[index+1]=='a'
210
                && source[index+2]=='c'
211
                && source[index+3]=='k'
212
                && source[index+4]=='a'
213
                && source[index+5]=='g'
214
                && source[index+6]=='e'
215
                && Parser.WHITESPACE.indexOf(source[index+7])>=0) {
216
 
217
               for (index+=7; index<source.length && source[index]!=';'; ++index)
218
                  ;
219
 
220
               return index+1;
221
            }
222
         }
223
         return -1;
224
      }
225
 
226
      int process(Parser parser, char[] source, int startIndex, int endIndex) {
227
         String packageName=new String(source,startIndex+8,endIndex-startIndex-8-1).trim();
228
         parser.packageOpened(packageName);
229
         return endIndex;
230
      }
231
   }
232
 
233
   class FieldComponent extends SourceComponent {
234
 
235
      int match(char[] source, int index) throws ParseException {
236
         boolean isField=false;
237
         final int STATE_NORMAL=1;
238
         final int STATE_SLASHC=2;
239
         final int STATE_STARC=3;
240
         final int STATE_FIELDVAL=4;
241
         final int STATE_STRING=5;
242
         final int STATE_SINGLEQUOTED=6;
243
         final int STATE_STRING_BS=7;
244
         final int STATE_SINGLEQUOTED_BS=8;
245
 
246
         int state=STATE_NORMAL;
247
         int prevState=STATE_NORMAL;
248
 
249
         int fieldValueLevel = 0;
250
 
251
         for (; index<source.length && !isField; ++index) {
252
            if (state==STATE_STARC) {
253
               if (index<source.length-1 && source[index]=='*' && source[index+1]=='/') {
254
                  ++index;
255
                  state=prevState;
256
               }
257
            }
258
            else if (state==STATE_SLASHC) {
259
               if (source[index]=='\n') {
260
                  state=prevState;
261
               }
262
            }
263
            else if (state==STATE_STRING) {
264
               if (source[index]=='\\') {
265
                  state=STATE_STRING_BS;
266
               }
267
               else if (source[index]=='\"') {
268
                  state=prevState;
269
               }
270
            }
271
            else if (state==STATE_STRING_BS) {
272
               state=STATE_STRING;
273
            }
274
            else if (state==STATE_SINGLEQUOTED) {
275
               if (source[index]=='\\') {
276
                  state=STATE_SINGLEQUOTED_BS;
277
               }
278
               else if (source[index]=='\'') {
279
                  state=prevState;
280
               }
281
            }
282
            else if (state==STATE_SINGLEQUOTED_BS) {
283
               state=STATE_SINGLEQUOTED;
284
            }
285
            else if (state==STATE_FIELDVAL) {
286
               if (source[index]=='/') {
287
                  if (index<source.length-1 && source[index+1]=='*') {
288
                     state=STATE_STARC;
289
                     ++index;
290
                  }
291
                  else if (index<source.length-1 && source[index+1]=='/') {
292
                     state=STATE_SLASHC;
293
                     ++index;
294
                  }
295
               }
296
               else if (source[index]=='{') {
297
                  ++ fieldValueLevel;
298
               }
299
               else if (source[index]=='}') {
300
                  -- fieldValueLevel;
301
               }
302
               else if (source[index]=='\"') {
303
                  state=STATE_STRING;
304
               }
305
               else if (source[index]=='\'') {
306
                  state=STATE_SINGLEQUOTED;
307
               }
308
               else if (source[index]==';' && 0 == fieldValueLevel) {
309
                  isField=true;
310
                  break;
311
               }
312
            }
313
            else switch (source[index]) {
314
            case '/':
315
               if (index<source.length-1 && source[index+1]=='*') {
316
                  state=STATE_STARC;
317
                  ++index;
318
               }
319
               else if (index<source.length-1 && source[index+1]=='/') {
320
                  state=STATE_SLASHC;
321
                  ++index;
322
               }
323
               break;
324
            case '{':  // class
325
            case '(':  // method
326
               return -1;
327
            case '=':  // field
328
               state=STATE_FIELDVAL;
329
               prevState=state;
330
               continue;
331
            case ';':  // field
332
               isField=true;
333
               break;
334
            }
335
            if (isField) break;
336
         }
337
         if (!isField || index==source.length) {
338
            return -1;
339
         }
340
 
341
         //System.err.println("char is "+source[index]);
342
 
343
         if (source[index]!=';') {
344
            index=Parser.skipExpression(source, index, 0, ';');
345
         }
346
         return index+1;
347
      }
348
 
349
      int process(Parser parser, char[] source, int startIndex, int endIndex) {
350
 
351
         //Debug.log(9,"found package statement: \""+str+"\"");
352
         //Debug.log(9,"found function component: '"+str+"'");
353
         //xxx(new FieldDocImpl(ctx.classDoc, ctx.classDoc.containingPackage(), 0, false, false));
354
 
355
         // Ignore superfluous semicoli after class definition
356
         if (endIndex-startIndex<=1) return endIndex;
357
 
358
         //assert (parser.ctx!=null);
359
         Collection fields=FieldDocImpl.createFromSource(parser.ctx.classDoc,
360
                                                         parser.ctx.classDoc.containingPackage(),
361
                                                         source, startIndex, endIndex);
362
 
363
         for (Iterator it=fields.iterator(); it.hasNext(); ) {
364
            FieldDocImpl field=(FieldDocImpl)it.next();
365
            boolean fieldHasSerialTag=!field.isTransient() && !field.isStatic(); //field.hasSerialTag();
366
            if ((field.isIncluded() || fieldHasSerialTag) && parser.getAddComments()) {
367
               field.setRawCommentText(parser.getLastComment());
368
            }
369
            parser.ctx.fieldList.add(field);
370
            if (field.isIncluded()) {
371
               parser.ctx.filteredFieldList.add(field);
372
            }
373
            if (fieldHasSerialTag) {
374
               parser.ctx.sfieldList.add(field);
375
            }
376
         }
377
 
378
         parser.setLastComment(null);
379
         return endIndex;
380
      }
381
 
382
 
383
   }
384
 
385
   class FunctionComponent extends BlockSourceComponent {
386
 
387
      int getEndIndex(char[] source, int endIndex) throws ParseException {
388
         if (source[endIndex-1]==';') {
389
            return endIndex;
390
         }
391
         else {
392
            return super.getEndIndex(source, endIndex);
393
         }
394
      }
395
 
396
      int process(Parser parser, char[] source, int startIndex, int endIndex) throws IOException, ParseException {
397
 
398
         //ctx.fieldList.add(FieldDocImpl.createFromSource(source, startIndex, endIndex));
399
 
400
         //System.out.println("function match '"+new String(source,startIndex,endIndex-startIndex)+"'");
401
         ExecutableMemberDocImpl execDoc=MethodDocImpl.createFromSource(parser.ctx.classDoc,
402
                                                                        parser.ctx.classDoc.containingPackage(),
403
                                                                        source, startIndex, endIndex);
404
 
405
         if (parser.getAddComments())
406
            execDoc.setRawCommentText(parser.getLastComment());
407
 
408
         parser.setLastComment(null);
409
 
410
         if (execDoc.isMethod()) {
411
            parser.ctx.methodList.add(execDoc);
412
            if (execDoc.isIncluded()) {
413
               parser.ctx.filteredMethodList.add(execDoc);
414
            }
415
         }
416
         else {
417
            parser.ctx.constructorList.add(execDoc);
418
            if (execDoc.isIncluded()) {
419
               parser.ctx.filteredConstructorList.add(execDoc);
420
            }
421
         }
422
 
423
         if (execDoc.isMethod()
424
                  && (execDoc.name().equals("readObject")
425
                      || execDoc.name().equals("writeObject")
426
                      || execDoc.name().equals("readExternal")
427
                      || execDoc.name().equals("writeExternal")
428
                      || execDoc.name().equals("readResolve"))) {
429
           // FIXME: add readExternal here?
430
 
431
            parser.ctx.maybeSerMethodList.add(execDoc);
432
         }
433
 
434
         return endIndex;
435
      }
436
 
437
      int match(char[] source, int index) {
438
         boolean isFunc=false;
439
         final int STATE_NORMAL=1;
440
         final int STATE_SLASHC=2;
441
         final int STATE_STARC=3;
442
         int state=STATE_NORMAL;
443
         for (; index<source.length && !isFunc; ++index) {
444
            if (state==STATE_STARC) {
445
               if (source[index]=='*' && source[index+1]=='/') {
446
                  ++index;
447
                  state=STATE_NORMAL;
448
               }
449
            }
450
            else if (state==STATE_SLASHC) {
451
               if (source[index]=='\n') {
452
                  state=STATE_NORMAL;
453
               }
454
            }
455
            else switch (source[index]) {
456
            case '/':
457
               if (source[index+1]=='*') {
458
                  state=STATE_STARC;
459
                  ++index;
460
               }
461
               else if (source[index+1]=='/') {
462
                  state=STATE_SLASHC;
463
                  ++index;
464
               }
465
               break;
466
            case '=':  // field
467
            case ';':  // field
468
            case '{':  // class
469
               return -1;
470
            case '(':
471
               isFunc=true;
472
               break;
473
            }
474
            if (isFunc) break;
475
         }
476
         if (!isFunc || index==source.length)
477
            return -1;
478
 
479
         for (; index<source.length && (state!=STATE_NORMAL || (source[index]!='{' && source[index]!=';')); ++index)
480
            if (state==STATE_SLASHC && source[index]=='\n') {
481
               state=STATE_NORMAL;
482
            }
483
            else if (index<source.length-1) {
484
               if (state==STATE_STARC) {
485
                  if (source[index]=='*' && source[index+1]=='/') {
486
                     state=STATE_NORMAL;
487
                  }
488
               }
489
               else {
490
                  if (source[index]=='/' && source[index+1]=='*') {
491
                     state=STATE_STARC;
492
                  }
493
                  else if (source[index]=='/' && source[index+1]=='/') {
494
                     state=STATE_SLASHC;
495
                  }
496
               }
497
            }
498
         return index+1;
499
      }
500
 
501
 
502
   }
503
 
504
   class StaticBlockComponent extends BlockSourceComponent {
505
 
506
      int process(Parser parser, char[] source, int startIndex, int endIndex) {
507
         //Debug.log(9,"found package statement: \""+str+"\"");
508
         //Debug.log(9,"found function component: '"+str+"'");
509
         parser.setLastComment(null);
510
         return endIndex;
511
      }
512
 
513
      int match(char[] source, int index) {
514
         if (source[index]=='{') return index+1;
515
 
516
         if (index+7<source.length) {
517
            if (source[index+0]=='s'
518
                && source[index+1]=='t'
519
                && source[index+2]=='a'
520
                && source[index+3]=='t'
521
                && source[index+4]=='i'
522
                && source[index+5]=='c') {
523
 
524
               for (index+=6; index<source.length && Parser.WHITESPACE.indexOf(source[index])>=0; ++index)
525
                  ;
526
 
527
               if (index<source.length && source[index]=='{')
528
                  return index+1;
529
               else
530
                  return -1;
531
            }
532
         }
533
         return -1;
534
      }
535
 
536
   }
537
 
538
   class ClassComponent extends SourceComponent {
539
 
540
      int match(char[] source, int index) {
541
         boolean isClass=false;
542
         for (; index<source.length && !isClass; ++index) {
543
            switch (source[index]) {
544
            case '/':  // possible comment
545
               if (index<source.length-1) {
546
                  char c = source[index+1];
547
                  if ('/' == c) {
548
                     index += 2;
549
                     while (index<source.length && source[index]!=10) {
550
                        ++ index;
551
                     }
552
                  }
553
                  else if ('*' == c) {
554
                     index += 3;
555
                     while (index<source.length && (source[index-1] != '*' || source[index]!='/')) {
556
                        ++ index;
557
                     }
558
                  }
559
               }
560
               break;
561
            case '@':  // annotation
562
               index += 1;
563
               while(index<source.length &&  Character.isJavaIdentifierPart(source[index])) {
564
                   ++ index;
565
               }
566
               if (index<source.length && source[index]=='(') {
567
                   int parLevel = 1;
568
                   index += 1;
569
                   while (index<source.length && parLevel>0) {
570
                       if (source[index] == '(')
571
                          ++ parLevel;
572
                       if (source[index] == ')')
573
                          -- parLevel;
574
                       ++ index;
575
                       if (parLevel==0)
576
                           break;
577
                   }
578
               }
579
               break;
580
            case '=':  // field
581
            case ';':  // field
582
            case '(':  // function
583
               return -1;
584
            case '{':
585
               isClass=true;
586
               break;
587
            }
588
            if (isClass) break;
589
         }
590
         if (!isClass || index>=source.length)
591
            return -1;
592
 
593
         return index+1;
594
      }
595
 
596
      int process(Parser parser, char[] source, int startIndex, int endIndex) throws ParseException, IOException {
597
 
598
         parser.classOpened(source, startIndex, endIndex);
599
         if (parser.getAddComments())
600
            parser.ctx.classDoc.setRawCommentText(parser.getLastComment());
601
         parser.setLastComment(null);
602
         if (parser.ctx.classDoc.isEnum())
603
           {
604
             int depth = 0;
605
             for (int a = endIndex; a < source.length; ++a)
606
             {
607
               Debug.log(9, "Enum skipping " + a);
608
               if (source[a] == '{')
609
                 {
610
                   Debug.log(1, "Found inner { in enum");
611
                   ++depth;
612
                 }
613
               if (source[a] == '}')
614
                 {
615
                   if (depth > 0)
616
                     {
617
                       Debug.log(1, "Found inner } in enum");
618
                       --depth;
619
                     }
620
                   else
621
                     {
622
                       Debug.log(1, "Found enum }");
623
                       parser.classClosed();
624
                       return a + 1;
625
                     }
626
                 }
627
             }
628
           }
629
         int rc=parser.parse(source, endIndex, parser.getClassLevelComponents());
630
         return rc;
631
      }
632
 
633
   }
634
 
635
 
636
public class Parser {
637
 
638
 
639
   static int skipExpression(char[] source, int endIndex, int level, char delimiter) throws ParseException {
640
 
641
      int orgEndIndex=endIndex;
642
 
643
      final int STATE_NORMAL=1;
644
      final int STATE_STARC=2;
645
      final int STATE_SLASHC=3;
646
      final int STATE_CHAR=4;
647
      final int STATE_STRING=5;
648
 
649
      int state=STATE_NORMAL;
650
      int prev=0;
651
      for (; !((level==0 && state==STATE_NORMAL && (delimiter=='\0' || source[endIndex]==delimiter))) && endIndex<source.length; ++endIndex) {
652
         int c=source[endIndex];
653
         if (state==STATE_NORMAL) {
654
            if (c=='}') --level;
655
            else if (c=='{') ++level;
656
            else if (c=='/' && prev=='/') { state=STATE_SLASHC; c=0; }
657
            else if (c=='*' && prev=='/') { state=STATE_STARC; c=0; }
658
            else if (c=='\'' && prev!='\\') { state=STATE_CHAR; c=0; }
659
            else if (c=='\"' && prev!='\\') { state=STATE_STRING; c=0; }
660
         }
661
         else if (state==STATE_SLASHC) {
662
            if (c=='\n') state=STATE_NORMAL;
663
         }
664
         else if (state==STATE_CHAR) {
665
            if (c=='\'' && prev!='\\') state=STATE_NORMAL;
666
            else if (c=='\\' && prev=='\\') c=0;
667
         }
668
         else if (state==STATE_STRING) {
669
            if (c=='\"' && prev!='\\') state=STATE_NORMAL;
670
            else if (c=='\\' && prev=='\\') c=0;
671
         }
672
         else {
673
            if (c=='/' && prev=='*') { state=STATE_NORMAL; c=0; }
674
         }
675
         prev=c;
676
      }
677
      if (level>0)
678
         throw new ParseException("Unexpected end of source.");
679
      else {
680
         String rc=new String(source, orgEndIndex, endIndex-orgEndIndex);
681
         return endIndex;
682
      }
683
   }
684
 
685
   private boolean addComments = false;
686
 
687
   public boolean getAddComments()
688
   {
689
      return this.addComments;
690
   }
691
 
692
   public static final String WHITESPACE=" \t\r\n";
693
 
694
   public static final boolean isWhitespace(char c) {
695
      return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '');
696
      //return WHITESPACE.indexOf(c)>=0;
697
   }
698
 
699
   private int currentLine;
700
 
701
   static char[] loadFile(final File file, String encoding)
702
      throws IOException
703
   {
704
      InputStream in = new FileInputStream(file);
705
      NotifyingInputStreamReader notifyingInput
706
         = new NotifyingInputStreamReader(in, encoding);
707
      notifyingInput.addMalformedInputListener(new MalformedInputListener() {
708
            public void malformedInputEncountered(MalformedInputEvent event) {
709
               Main.getRootDoc().printWarning("Illegal character in file " + file + ", line " + event.getLineNumber() + ", column " + event.getColumnNumber());
710
               try {
711
                  Main.getRootDoc().printWarning(IOToolkit.getLineFromFile(file, event.getLineNumber()));
712
                  Main.getRootDoc().printWarning(IOToolkit.getColumnDisplayLine(event.getColumnNumber()));
713
               }
714
               catch (IOException ignore) {
715
               }
716
            }
717
         });
718
      Reader reader
719
         = new BufferedReader(notifyingInput);
720
      char[] result = IOToolkit.readFully(reader);
721
      reader.close();
722
      return result;
723
   }
724
 
725
   private SourceComponent[] sourceLevelComponents;
726
   private SourceComponent[] classLevelComponents;
727
 
728
   public SourceComponent[] getClassLevelComponents()
729
   {
730
      return this.classLevelComponents;
731
   }
732
 
733
   public Parser() {
734
      try {
735
 
736
         sourceLevelComponents=new SourceComponent[] {
737
            new Whitespace(),
738
            new CommentComponent(),
739
            new SlashSlashCommentComponent(),
740
            new PackageComponent(),
741
            new EmptyStatementComponent(),
742
            new ImportComponent(),
743
            new ClassComponent(),
744
         };
745
 
746
         classLevelComponents=new SourceComponent[] {
747
            new Whitespace(),
748
            new BracketClose(),
749
            new CommentComponent(),
750
            new SlashSlashCommentComponent(),
751
            new FunctionComponent(),
752
            new StaticBlockComponent(),
753
            new ImportComponent(),
754
            new ClassComponent(),
755
            new FieldComponent(),
756
         };
757
      }
758
      catch (Exception e) {
759
         e.printStackTrace();
760
      }
761
   }
762
 
763
   public int getNumberOfProcessedFiles() {
764
      return processedFiles.size();
765
   }
766
 
767
   static Set processedFiles = new HashSet();
768
 
769
   ClassDocImpl processSourceFile(File file, boolean addComments,
770
                                  String encoding, String expectedPackageName)
771
      throws IOException, ParseException
772
   {
773
     //System.err.println("Processing " + file + "...");
774
      this.currentFile = file;
775
      this.currentPackage = null;
776
      this.currentPackageName = null;
777
      this.expectedPackageName = expectedPackageName;
778
      this.outerClass = null;
779
      this.boilerplateComment = null;
780
 
781
      this.addComments=addComments;
782
 
783
      if (processedFiles.contains(file)) {
784
         return null;
785
      }
786
 
787
      processedFiles.add(file);
788
 
789
      Debug.log(1,"Processing file "+file);
790
 
791
      contextStack.clear();
792
      ctx=null;
793
 
794
      importedClassesList.clear();
795
      importedStringList.clear();
796
      importedPackagesList.clear();
797
      importedStatementList.clear();
798
 
799
      currentLine = 1;
800
 
801
      char[] source = loadFile(file, encoding);
802
 
803
      try {
804
         parse(source, 0, sourceLevelComponents);
805
 
806
         ClassDoc[] importedClasses=(ClassDoc[])importedClassesList.toArray(new ClassDoc[0]);
807
         PackageDoc[] importedPackages=(PackageDoc[])importedPackagesList.toArray(new PackageDoc[0]);
808
 
809
         if (Main.DESCEND_IMPORTED) {
810
            for (int i=0; i<importedClasses.length; ++i) {
811
               Main.getRootDoc().scheduleClass(currentClass, importedClasses[i].qualifiedName());
812
            }
813
         }
814
 
815
 
816
           if (contextStack.size()>0) {
817
             Debug.log(1,"-->contextStack not empty! size is "+contextStack.size());
818
           }
819
 
820
         return outerClass;
821
      }
822
      catch (IgnoredFileParseException ignore) {
823
        Debug.log(1, "File ignored: " + ignore);
824
         return null;
825
      }
826
   }
827
 
828
   int parse(char[] source, int index, SourceComponent[] componentTypes) throws ParseException, IOException {
829
 
830
      while (index<source.length) {
831
 
832
         int match=-1;
833
         int i=0;
834
         for (; i<componentTypes.length; ++i) {
835
            if ((match=componentTypes[i].match(source, index))>=0) {
836
              //Debug.log(1,componentTypes[i].getClass().getName()+" ("+match+"/"+source.length+")");
837
               break;
838
            }
839
         }
840
 
841
         if (i<componentTypes.length) {
842
            int endIndex=componentTypes[i].getEndIndex(source, match);
843
            Debug.log(9, "Processing " + new String(source,index,endIndex-index) + " with " + componentTypes[i]);
844
            index=componentTypes[i].process(this, source, index, endIndex);
845
            if (index<0) {
846
              //Debug.log(9,"exiting parse because of "+componentTypes[i].getClass().getName()+" (\""+new String(source, index, endIndex-index)+"\")");
847
               return endIndex;
848
            }
849
         }
850
         else {
851
           //Debug.log(9,"index="+index+", source.length()="+source.length);
852
            throw new ParseException("unmatched input in line "+currentLine+": "+new String(source, index, Math.min(50,source.length-index)));
853
         }
854
 
855
      }
856
      //Debug.log(9,"exiting parse normally, index="+index+" source.length="+source.length);
857
      return index;
858
   }
859
 
860
   private static int countNewLines(String source) {
861
      int i=0;
862
      int rc=0;
863
      while ((i=source.indexOf('\n',i)+1)>0)
864
         ++rc;
865
      return rc;
866
   }
867
 
868
   public void processSourceDir(File dir, String encoding, String expectedPackageName)
869
      throws IOException, ParseException
870
   {
871
      Debug.log(9,"Processing "+dir.getParentFile().getName()+"."+dir.getName());
872
      File[] files=dir.listFiles();
873
      if (null!=files) {
874
         for (int i=0; i<files.length; ++i) {
875
            if (files[i].getName().toLowerCase().endsWith(".java")) {
876
               processSourceFile(files[i], true, encoding, expectedPackageName);
877
            }
878
         }
879
      }
880
   }
881
 
882
   void classOpened(char[] source, int startIndex, int endIndex) throws ParseException, IOException {
883
 
884
      referencedClassesList.clear();
885
 
886
      if (null == currentPackage) {
887
 
888
         if (expectedPackageName != null) {
889
            if (null == currentPackageName ||
890
                !currentPackageName.equals(expectedPackageName)) {
891
 
892
               Main.getRootDoc().printWarning("Ignoring file " + currentFile + ": (wrong package, " + currentPackageName + "!=" + expectedPackageName + ")");
893
               throw new IgnoredFileParseException();
894
            }
895
         }
896
 
897
         if (null != currentPackageName) {
898
            currentPackage = Main.getRootDoc().findOrCreatePackageDoc(currentPackageName);
899
         }
900
         else {
901
            currentPackage = Main.getRootDoc().findOrCreatePackageDoc("");
902
         }
903
      }
904
 
905
      if (currentPackageName != null)
906
         importedStatementList.add(currentPackageName + ".*");
907
      importedStatementList.add("java.lang.*");
908
 
909
      ClassDocImpl classDoc
910
         = ClassDocImpl.createInstance((ctx!=null)?(ctx.classDoc):null, currentPackage,
911
                                       null,
912
                                       (PackageDoc[])importedPackagesList.toArray(new PackageDoc[0]),
913
                                       source, startIndex, endIndex,
914
                                       importedStatementList);
915
 
916
      if (ctx != null) {
917
         ctx.innerClassesList.add(classDoc);
918
         if (classDoc.isIncluded()) {
919
            ctx.filteredInnerClassesList.add(classDoc);
920
         }
921
      }
922
 
923
      if (importedClassesList.isEmpty()) {
924
         for (Iterator it=importedStringList.iterator(); it.hasNext(); ) {
925
            importedClassesList.add(new ClassDocProxy((String)it.next(), classDoc));
926
         }
927
      }
928
      classDoc.setImportedClasses((ClassDoc[])importedClassesList.toArray(new ClassDoc[0]));
929
 
930
      currentPackage.addClass(classDoc);
931
 
932
      currentClass = classDoc;
933
 
934
      if (null == outerClass) {
935
         outerClass = classDoc;
936
      }
937
 
938
      if (classDoc.superclass()!=null)
939
         referencedClassesList.add(classDoc.superclass());
940
 
941
      Debug.log(1,"classOpened "+classDoc+", adding superclass "+classDoc.superclass());
942
      Debug.log(1,"Pushing " + ctx);
943
      contextStack.push(ctx);
944
      ctx=new Context(classDoc);
945
      //Debug.log(9,"ctx="+ctx);
946
   }
947
 
948
   private Doc[] toArray(List list, Doc[] template)
949
   {
950
      Doc[] result = (Doc[])list.toArray(template);
951
      return result;
952
   }
953
 
954
   void classClosed() throws ParseException, IOException {
955
      ctx.classDoc.setFields((FieldDoc[])toArray(ctx.fieldList,
956
                                                             new FieldDoc[0]));
957
      ctx.classDoc.setFilteredFields((FieldDoc[])toArray(ctx.filteredFieldList,
958
                                                                     new FieldDoc[0]));
959
      ctx.classDoc.setSerializableFields((FieldDoc[])toArray(ctx.sfieldList, new FieldDoc[0]));
960
      ctx.classDoc.setMethods((MethodDoc[])toArray(ctx.methodList, new MethodDoc[0]));
961
      ctx.classDoc.setFilteredMethods((MethodDoc[])toArray(ctx.filteredMethodList, new MethodDoc[0]));
962
      ctx.classDoc.setMaybeSerMethodList(ctx.maybeSerMethodList);
963
      ctx.classDoc.setConstructors((ConstructorDoc[])toArray(ctx.constructorList, new ConstructorDoc[0]));
964
      ctx.classDoc.setFilteredConstructors((ConstructorDoc[])toArray(ctx.filteredConstructorList, new ConstructorDoc[0]));
965
 
966
      ctx.classDoc.setInnerClasses((ClassDocImpl[])toArray(ctx.innerClassesList, new ClassDocImpl[0]));
967
      ctx.classDoc.setFilteredInnerClasses((ClassDocImpl[])toArray(ctx.filteredInnerClassesList, new ClassDocImpl[0]));
968
      ctx.classDoc.setBoilerplateComment(boilerplateComment);
969
 
970
      Main.getRootDoc().addClassDoc(ctx.classDoc);
971
 
972
      if (Main.DESCEND_INTERFACES) {
973
         for (int i=0; i<ctx.classDoc.interfaces().length; ++i) {
974
            Main.getRootDoc().scheduleClass(ctx.classDoc, ctx.classDoc.interfaces()[i].qualifiedName());
975
         }
976
      }
977
 
978
      Debug.log(1,"classClosed: "+ctx.classDoc);
979
 
980
      ctx=(Context)contextStack.pop();
981
      Debug.log(1, "Popping " + ctx);
982
      ClassDoc[] referencedClasses=(ClassDoc[])referencedClassesList.toArray(new ClassDoc[0]);
983
 
984
      if (Main.DESCEND_SUPERCLASS) {
985
         for (int i=0; i<referencedClasses.length; ++i) {
986
            Main.getRootDoc().scheduleClass(currentClass, referencedClasses[i].qualifiedName());
987
         }
988
      }
989
   }
990
 
991
   Context      ctx             = null;
992
   Stack        contextStack    = new Stack();
993
   class Context {
994
      Context(ClassDocImpl classDoc) { this.classDoc=classDoc; }
995
      ClassDocImpl      classDoc                 = null;
996
      List              fieldList                = new LinkedList();
997
      List              filteredFieldList        = new LinkedList();
998
      List              sfieldList               = new LinkedList();
999
      List              methodList               = new LinkedList();
1000
      List              filteredMethodList       = new LinkedList();
1001
      List              maybeSerMethodList       = new LinkedList();
1002
      List              constructorList          = new LinkedList();
1003
      List              filteredConstructorList  = new LinkedList();
1004
      List              innerClassesList         = new LinkedList();
1005
      List              filteredInnerClassesList = new LinkedList();
1006
   }
1007
 
1008
   File currentFile = null;
1009
   String lastComment = null;
1010
   String expectedPackageName = null;
1011
   String currentPackageName = null;
1012
   PackageDocImpl currentPackage = null;
1013
   ClassDocImpl currentClass = null;
1014
   ClassDocImpl outerClass   = null;
1015
   List ordinaryClassesList  = new LinkedList();
1016
   List allClassesList       = new LinkedList();
1017
   List interfacesList       = new LinkedList();
1018
 
1019
   List importedClassesList  = new LinkedList();
1020
   List importedStringList   = new LinkedList();
1021
   List importedPackagesList = new LinkedList();
1022
   List importedStatementList = new LinkedList();
1023
 
1024
   List referencedClassesList = new LinkedList();
1025
 
1026
   String boilerplateComment = null;
1027
 
1028
   void packageOpened(String packageName) {
1029
      currentPackageName = packageName;
1030
   }
1031
 
1032
   void importEncountered(String importString) throws ParseException, IOException {
1033
      //Debug.log(9,"importing '"+importString+"'");
1034
 
1035
      importedStatementList.add(importString);
1036
 
1037
      if (importString.endsWith(".*")) {
1038
         importedPackagesList.add(Main.getRootDoc().findOrCreatePackageDoc(importString.substring(0,importString.length()-2)));
1039
      }
1040
      else {
1041
         importedStringList.add(importString);
1042
      }
1043
   }
1044
 
1045
 
1046
   void setLastComment(String lastComment) {
1047
      this.lastComment=lastComment;
1048
   }
1049
 
1050
   String getLastComment() {
1051
      return this.lastComment;
1052
   }
1053
 
1054
   void setBoilerplateComment(String boilerplateComment)
1055
   {
1056
      this.boilerplateComment = boilerplateComment;
1057
   }
1058
 
1059
   String getBoilerplateComment()
1060
   {
1061
      return boilerplateComment;
1062
   }
1063
 
1064
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.