KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > crosscuts > AspectJParser


1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the compiler and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  *
22  * Contributor(s):
23  */

24
25 package org.aspectj.compiler.crosscuts;
26 import org.aspectj.compiler.crosscuts.ast.*;
27 import org.aspectj.compiler.base.ast.*;
28 import org.aspectj.compiler.base.cst.*;
29 import org.aspectj.compiler.base.parser.*;
30 import org.aspectj.compiler.base.JavaCompiler;
31 import org.aspectj.compiler.base.TypeManager;
32
33 import java.util.*;
34 import java.io.*;
35
36 public class AspectJParser extends JavaParser {
37
38     public AspectJParser(JavaCompiler compiler) {
39         super(compiler);
40     }
41
42     // aspect, pointcut and privileged are virtually new keywords
43
// this is part of the implementation of ajc-1.0, not necessarily
44
// part of the language design of AspectJ-1.0
45
{
46         decParsers.put("aspect", new AspectDecParser());
47
48         decParsers.put("pointcut", new PointcutDecParser());
49
50         modifiers.put("privileged", new Integer JavaDoc(Modifiers.PRIVILEGED));
51     }
52
53
54     protected Map aspectDecParsers = new HashMap();
55     {
56         aspectDecParsers.put("declare", new DeclareParser());
57
58         aspectDecParsers.put("before", new BeforeDecParser());
59         aspectDecParsers.put("after", new AfterDecParser());
60         aspectDecParsers.put("around", new AroundDecParser());
61
62         // this is both in AspectOf and class/aspect
63
aspectDecParsers.put("pointcut", new PointcutDecParser());
64     }
65
66     protected void eatModifiersPattern() {
67         Token token;
68         while (true) {
69             token = peekToken();
70             if (!(token.kind == BANG || isModifier(token))) break;
71             eatTopToken();
72         }
73     }
74
75     public ModifiersPattern parseModifiersPattern(int legalModifiers) {
76         int trueValue = 0;
77         int falseValue = 0;
78         Token beginToken = peekToken();
79
80         while (true) {
81             boolean assertion = true;
82
83             if (peekToken().kind == BANG) {
84                 if (getModifier(peekToken(1)) == null) break;
85                 eatTopToken();
86                 assertion = false;
87             }
88
89             Integer JavaDoc ivalue = getModifier(peekToken());
90             if (ivalue == null) {
91                 if (!assertion) {
92                     throwError(null, "! in modifier pattern not followed by modifier");
93                 }
94                 break;
95             }
96
97             int value = ivalue.intValue();
98             if ((legalModifiers & value) != value) {
99                 throwError(null, "illegal modifier for this dec");
100             }
101             eatTopToken();
102             if (assertion) trueValue |= value;
103             else falseValue |= value;
104         }
105         ModifiersPattern modifiers = new ModifiersPattern(dummySource,trueValue, falseValue);
106         addContext(modifiers, beginToken);
107         return modifiers;
108     }
109
110     public NameTypeDsPattern parseNameTypeDsPattern() {
111         if (peekToken(0).kind != BANG && !(isIdentifier(peekToken(0)))) {
112             return null;
113         }
114
115         TypeDs trueNames = new TypeDs(dummySource);
116         TypeDs falseNames = new TypeDs(dummySource);
117
118         while (true) {
119             Token token = peekToken(0);
120             boolean assertion = true;
121             if (token.kind == BANG) {
122                 eatTopToken();
123                 token = peekToken(0);
124                 assertion = false;
125             }
126
127             TypeD nameTypeD = parseNameTypeD();
128             if (nameTypeD == null) {
129                 if (!assertion) throwError(token, "illegal name pattern");
130             }
131
132             if (assertion) {
133                 trueNames.add(nameTypeD);
134             } else {
135                 falseNames.add(nameTypeD);
136             }
137             if (peekToken(0).kind != COMMA) break;
138             eatTopToken();
139         }
140
141         return new NameTypeDsPattern(dummySource,trueNames, falseNames);
142     }
143
144     public NameTypeDsPattern parseThrowsPattern() {
145         if (maybeEatKeyword("throws")) {
146             return parseNameTypeDsPattern();
147         } else {
148             return null;
149         }
150     }
151
152     public GenTypeName parseFormalPattern() {
153         Token beginToken = peekToken();
154         if (beginToken.kind == DOT && peekToken(1).kind == DOT) {
155             eatTopToken(); eatTopToken();
156             // an arbitrary number of formals
157
return null;
158         } else {
159             GenTypeName genTypeName = parseGenTypeName();
160             addContext(genTypeName, beginToken);
161             return genTypeName;
162         }
163     }
164
165
166     public FormalsPattern parseFormalsPattern() {
167         Token beginToken = peekToken();
168         eatTopToken(LPAREN);
169
170         GenTypeNames names = new GenTypeNames(dummySource);
171         FormalsPattern formalsPattern = new FormalsPattern(dummySource,names); //, -1);
172

173         if (peekToken().kind != RPAREN) {
174             while (true) {
175                 GenTypeName pattern = parseFormalPattern();
176                 if (pattern == null) {
177                     pattern = new EllipsesFakeTypeName(dummySource);
178                     addContext(pattern, peekToken(-1));
179                 }
180                 names.add(pattern);
181                 
182                 Token t = popToken();
183                 if (t.kind == RPAREN) break;
184                 else if (t.kind == COMMA) continue;
185                 throwError(t, "expected ',' or ')'");
186             }
187         } else {
188             eatTopToken();
189         }
190
191         addContext(names, beginToken);
192         addContext(formalsPattern, beginToken);
193         return formalsPattern;
194     }
195
196
197     public Expr parseVarInitializer() {
198         if (peekToken(0).kind == ASSIGN) {
199             eatTopToken();
200             if (peekToken(0).kind == LBRACE) {
201                 return parseArrayInitializer();
202             } else {
203                 return parseExpr();
204             }
205         } else {
206             return null;
207         }
208     }
209
210     public TypeD parseOptionalReturnTypeD() {
211         if (!maybeEatKeyword("returns")) return null;
212
213         Token beginToken = peekToken();
214         return parseTypeD();
215     }
216
217     public boolean isAdjacent(Token t1, Token t2) {
218         //System.out.println("is adjacent? " + t1.endPosition + ", " + t2.startPosition);
219
return t1.endPosition == t2.startPosition;
220     }
221
222     String JavaDoc makeNamePatternPiece(Token t) {
223         if (t.isIdentifier()) return t.image;
224         else if (t.kind == STAR) return "*";
225         else if (t.kind == INTEGER_LITERAL) return t.image;
226         //??? probably need to do some tricky handling of float literals here
227
else return null;
228     }
229     
230     public NamePattern parseNamePattern(Token t1, String JavaDoc firstPiece) {
231         List pieces = new ArrayList();
232         pieces.add(firstPiece);
233         
234         Token previousToken = t1;
235         while (isAdjacent(previousToken, peekToken())) {
236             previousToken = peekToken();
237             String JavaDoc piece = makeNamePatternPiece(previousToken);
238
239             if (piece == null) break;
240             eatTopToken();
241             pieces.add(piece);
242         }
243         
244         if (pieces.size() == 1) {
245             String JavaDoc piece = (String JavaDoc)pieces.get(0);
246             if (piece == "*") {
247                 return new AnyName(makeSourceLocation(t1));
248             } else {
249                 return new SimpleName(makeSourceLocation(t1), piece);
250             }
251         } else {
252             return new WildName(makeSourceLocation(t1), pieces);
253         }
254     }
255     public NamePattern parseNamePattern() {
256         Token t1 = peekToken();
257         String JavaDoc firstPiece = makeNamePatternPiece(t1);
258         if (firstPiece == null) {
259             throwError(t1, "identifier pattern expected");
260             return null;
261         }
262         eatTopToken();
263         return parseNamePattern(t1, firstPiece);
264     }
265     
266     protected boolean inAspect() {
267         if (peekEnclosingTypeDec() != null && peekEnclosingTypeDec() instanceof AspectDec) {
268             return true;
269         }
270         return false;
271     }
272     
273     ///////////////////////////////////////////////////////////////////////////
274
///////////////////////////////////////////////////////////////////////////
275
///////////////////////////////////////////////////////////////////////////
276

277     //XXX dangerous use of this...
278
protected boolean eatIdentifier(boolean onlyDec) {
279         //System.out.println(peekToken() + ": " + inAspect() + ": " + onlyDec);
280
if (!inAspect() || !onlyDec) return super.eatIdentifier(onlyDec);
281         
282         if (eatGenTypeName()) {
283             if (peekToken().kind == DOT) {
284                 eatTopToken(); eatTopToken();
285             }
286             return true;
287         }
288         return false;
289     }
290     
291     
292     static class TypeNameAndId {
293         public GenTypeName typeName;
294         public NamePattern namePattern;
295         
296         public String JavaDoc getId() {
297             if (namePattern.getSimpleName() == null) {
298                 namePattern.showError("identifier expected");
299             }
300             return namePattern.getSimpleName();
301         }
302     }
303     
304 // public String parseIdOrNew() {
305
// if (maybeEatToken(NEW)) {
306
// return "new";
307
// } else {
308
// return parseId();
309
// }
310
// }
311

312     public TypeNameAndId parseTypeNameAndId() {
313         TypeNameAndId ret = new TypeNameAndId();
314         Token beginToken = peekToken();
315         
316         if (peekToken().kind == LPAREN || peekKeyword("subtypes")) {
317             ret.typeName = parseGenTypeName();
318             eatTopToken(DOT);
319             ret.namePattern = parseNamePattern();
320         } else {
321             NamePatterns namePatterns = parseDottedNamePatterns();
322             
323             //namePatterns.display(0);
324

325             //System.out.println("parsed: " + namePatterns);
326

327             boolean includeSubTypes = false;
328             if (peekToken().kind == PLUS || peekToken().kind == LBRACKET) {
329                 ret.typeName = finishParsingPatternTypeName(beginToken, namePatterns);
330                 eatTopToken(DOT);
331                 ret.namePattern = parseNamePattern();
332             } else {
333                 //XXX validate that is is a true simple name
334
ret.namePattern = namePatterns.pop(); //.getSimpleName();
335
if (namePatterns.size() > 0) {
336                     ret.typeName = new PatternTypeName(dummySource, namePatterns, false, 0);
337                     ret.typeName.setSource(namePatterns);
338                 }
339             }
340         }
341         
342         return ret;
343     }
344     
345     protected boolean eatGenTypeName() {
346         if (peekKeyword("import")) return false;
347         
348         //XXX very heuristic approach
349
if (peekToken(0).kind == LPAREN && !(peekToken(1).kind == RPAREN)) {
350             parseGenTypeName();
351             return true;
352         } else {
353             if (!eatTypeD()) return false;
354             maybeEatToken(PLUS);
355             return true;
356         }
357     }
358     
359
360     protected Dec noDecFound() {
361         Token beginToken = peekToken();
362         
363         if (inAspect()) {
364             if (lookaheadIntroducedSuperDec()) {
365                 return parseIntroducedSuperDec();
366             } else if (lookaheadIntroducedConstructorDec()) {
367                 return parseIntroducedConstructorDec();
368             }
369         }
370         
371         throwError(beginToken, "declaration or '}' expected");
372         return null;
373     }
374     
375     protected boolean lookaheadIntroducedSuperDec() {
376         pushCurrentIndex();
377         
378         if (eatGenTypeName()) {
379             if (maybeEatKeyword("implements") || maybeEatKeyword("extends")) {
380                 throwError(peekToken(-1), "expected +implements or +extends");
381                 return false;
382             } else if (this.maybeEatToken(PLUS) &&
383                 (maybeEatKeyword("implements") || maybeEatKeyword("extends")))
384             {
385                 popCurrentIndex();
386                 return true;
387             }
388         }
389         popCurrentIndex();
390         return false;
391     }
392     
393     public Dec parseIntroducedSuperDec() {
394         getCompiler().warnVersion("1.0alpha1", tokenToASTObject(peekToken()),
395                 "use declare parents instead");
396         
397         GenTypeName typeName = parseGenTypeName();
398         eatTopToken(PLUS);
399         boolean isImplements;
400         if (maybeEatKeyword("implements")) {
401             isImplements = true;
402         } else {
403             eatKeyword("extends");
404             isImplements = false;
405         }
406         TypeDs typeDs = parseTypeDs();
407         Dec ret = new IntroducedSuperDec(dummySource, typeName, typeDs, isImplements);
408         eatTopToken(SEMICOLON);
409         return ret;
410     }
411     
412     
413     protected boolean lookaheadIntroducedConstructorDec() {
414         pushCurrentIndex();
415     
416         this.eatModifiers();
417         //this.eatGenTypeName();
418
//System.out.println(peekToken(0) + ", " + peekToken(1) + ", " + peekToken(2));
419
if (this.eatGenTypeName() && maybeEatToken(DOT) && maybeEatToken(NEW)) {
420             popCurrentIndex();
421             return true;
422         }
423         
424         popCurrentIndex();
425         return false;
426     }
427     
428     
429     
430     /* Mostly cut from JavaParser, this also allows for introduced Decs */
431     public Dec parseIntroducedConstructorDec() {
432         int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE;
433
434         Token beginToken = peekToken();
435         Modifiers modifiers = parseModifiers(legalModifiers);
436         GenTypeName genTypeName = null;
437         if (inAspect()) {
438             TypeNameAndId gid = parseTypeNameAndId();
439             genTypeName = gid.typeName;
440             String JavaDoc id = gid.getId();
441             if (genTypeName != null) {
442                 if (!id.equals("new")) {
443                     throwError(beginToken, "bad introduced constructor syntax");
444                 }
445             } else {
446                 if (!id.equals(peekEnclosingTypeDec().getId())) {
447                     throwError(beginToken, "constructor name doesn't match enclosing type " +
448                             peekEnclosingTypeDec().getId());
449                 }
450             }
451         } else {
452             parseIdMatchingEnclosingTypeName("constructor name");
453         }
454         
455         
456         Formals formals = parseFormals();
457         TypeDs _throws = parseThrows();
458
459         Dec ret = new ConstructorDec(dummySource,modifiers, formals, _throws,
460                     parseConstructorBody());
461     
462         if (genTypeName != null) {
463             //System.out.println("making introduced constructor on " + genTypeName);
464
return new IntroducedDec(dummySource, genTypeName, ret);
465         } else {
466             return ret;
467         }
468     }
469     
470     public Dec parseConstructorDec() {
471         pushCurrentIndex();
472         eatModifiers();
473         if (peekKeyword("subtypes")) {
474             popCurrentIndex();
475             return parseIntroducedConstructorDec();
476         } else {
477             popCurrentIndex();
478             return super.parseConstructorDec();
479         }
480     }
481     
482     public Dec parseMethodDec() {
483         int legalModifiers;
484         if (inInterface) {
485             legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT;
486         } else {
487             legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE |
488                 Modifiers.ABSTRACT | Modifiers.STATIC | Modifiers.FINAL |
489                 Modifiers.SYNCHRONIZED | Modifiers.NATIVE | Modifiers.STRICT;
490         }
491
492         Modifiers modifiers = parseModifiers(legalModifiers);
493         if (inInterface) {
494             modifiers.setAbstract(true);
495             modifiers.setPublic(true);
496         }
497         
498         TypeD typeD = parseTypeD();
499         
500         GenTypeName genTypeName = null;
501         String JavaDoc id = null;
502         if (inAspect()) {
503             TypeNameAndId gid = parseTypeNameAndId();
504             genTypeName = gid.typeName;
505             id = gid.getId();
506             //XXX this is a horrible design
507
if (genTypeName == null && id.equals("around")) {
508                 return parseAroundAdviceDec(modifiers, typeD);
509             }
510         } else {
511             id = parseId();
512         }
513
514         Formals formals = parseFormals();
515
516         // handle funky "int foo()[] {" return type specifier
517
typeD = addBracketsToTypeD(typeD);
518
519         TypeDs _throws = parseThrows();
520
521         MethodDec ret = new MethodDec(dummySource, modifiers, typeD, id, formals, _throws,
522                                  parseOptionalCodeBody());
523         
524         if (genTypeName != null) {
525             //System.out.println("making introduced dec: " + id + " on " + genTypeName);
526
return new IntroducedDec(dummySource, genTypeName, ret);
527         } else {
528             return ret;
529         }
530     }
531     
532     
533     public Stmt parseFieldDec() {
534         int legalModifiers;
535
536         if (inInterface) {
537             legalModifiers = Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.FINAL;
538         } else {
539             legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE |
540                 Modifiers.STATIC | Modifiers.FINAL |
541                 Modifiers.TRANSIENT | Modifiers.VOLATILE;
542         }
543
544         Token beginToken = peekToken();
545         Modifiers modifiers = parseModifiers(legalModifiers);
546         
547         if (inInterface) {
548             modifiers.setPublic(true);
549             modifiers.setStatic(true);
550             modifiers.setFinal(true);
551         }
552         
553         TypeD baseTypeD = parseTypeD();
554
555         Decs decs = null;
556         Dec dec = null;
557
558         while (true) {
559             GenTypeName genTypeName = null;
560             String JavaDoc id = null;
561             if (inAspect()) {
562                 TypeNameAndId gid = parseTypeNameAndId();
563                 genTypeName = gid.typeName;
564                 id = gid.getId();
565             } else {
566                 id = parseId();
567             }
568             TypeD typeD = baseTypeD;
569
570             Expr initializer = null;
571             typeD = addBracketsToTypeD(typeD);
572             //VarDes des = new VarDes(modifiers, id, typeD);
573
//??? what should the context really be for a var des in a list
574
//addContext(des, beginToken);
575

576             Token endToken = popToken();
577             if (endToken.kind == ASSIGN) {
578                 if (typeD instanceof ArrayTypeD && peekToken().kind == LBRACE) {
579                     initializer = parseArrayInitializer();
580                 } else {
581                     initializer = parseExpr();
582                 }
583                 endToken = popToken();
584             }
585
586             dec = new FieldDec(dummySource,(Modifiers)modifiers.copy(), typeD, id, initializer);
587             addContext(dec, beginToken);
588             if (genTypeName != null) {
589                 dec = new IntroducedDec(dummySource, genTypeName, dec);
590             }
591
592             if (endToken.kind == SEMICOLON) {
593                 if (decs != null) decs.add(dec);
594                 break;
595             } else if (endToken.kind == COMMA) {
596                 if (decs == null) decs = new Decs(dummySource,dec);
597                 else decs.add(dec);
598
599                 // this copy is needed to keep the AST a tree and not a graph
600
baseTypeD = (TypeD)baseTypeD.copy();
601                 continue;
602             } else {
603                 throwError(endToken, "expected ',' or ';'");
604             }
605         }
606
607         if (decs != null) return decs;
608         else return dec;
609     }
610     
611     
612     
613     
614     
615     ///////////////////////////////////////////////////////////////////////////
616
///////////////////////////////////////////////////////////////////////////
617
///////////////////////////////////////////////////////////////////////////
618
public ConstructorPattern parseConstructorPattern() {
619         int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE
620             | Modifiers.STRICT; // constructor may be implicitly strictfp by class decl.
621

622         Token beginToken = peekToken();
623         Modifiers modifiers = parseModifiersPattern(legalModifiers);
624         
625         TypeNameAndId gid = parseTypeNameAndId();
626         GenTypeName declaringType = gid.typeName;
627         
628         //System.out.println(gid.getId());
629

630         if (!"new".equals(gid.namePattern.getSimpleName())) {
631             this.throwError(peekToken(-1), "expected new");
632         }
633         FormalsPattern formals = parseFormalsPattern();
634         NameTypeDsPattern _throws = parseThrowsPattern();
635
636         ConstructorPattern ret = new ConstructorPattern(dummySource,modifiers, declaringType, formals, _throws);
637         addContext(ret, beginToken);
638         return ret;
639     }
640
641     public MethodPattern parseMethodPattern() {
642         int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE |
643             Modifiers.ABSTRACT | Modifiers.STATIC | Modifiers.FINAL |
644             Modifiers.SYNCHRONIZED | Modifiers.NATIVE | Modifiers.STRICT;
645
646         Token beginToken = peekToken();
647         Modifiers modifiers = parseModifiersPattern(legalModifiers);
648         GenTypeName returnType = parseGenTypeName();
649         
650         TypeNameAndId gid = parseTypeNameAndId();
651         GenTypeName declaringType = gid.typeName;
652         NamePattern id = gid.namePattern;
653         if ("new".equals(id.getSimpleName())) {
654             this.tokenToASTObject(beginToken).showError("constructor patterns don't have a return type");
655         }
656
657         FormalsPattern formals = parseFormalsPattern();
658         NameTypeDsPattern _throws = parseThrowsPattern();
659
660         MethodPattern ret = new MethodPattern(dummySource,modifiers, declaringType, returnType, id, formals, _throws);
661         addContext(ret, beginToken);
662         return ret;
663     }
664
665     public CodePattern parseConstructorOrMethodPattern() {
666         //XXX this is clearly an inefficient design
667
//XXX is this the straw that broke the hand-written parser's back?
668
pushCurrentIndex();
669         try {
670             CodePattern ret = parseConstructorPattern();
671             //XXX don't really want this
672
//XXX popCurrentIndex();
673
return ret;
674         } catch (ParseException pe) {
675             popCurrentIndex();
676             return parseMethodPattern();
677         }
678     }
679
680     public FieldPattern parseFieldPattern() {
681         int legalModifiers = Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.PRIVATE |
682             Modifiers.STATIC | Modifiers.FINAL |
683             Modifiers.NATIVE | Modifiers.TRANSIENT;
684
685         Token beginToken = peekToken();
686         Modifiers modifiers = parseModifiersPattern(legalModifiers);
687         GenTypeName fieldType = parseGenTypeName();
688         
689         TypeNameAndId gid = parseTypeNameAndId();
690         GenTypeName declaringType = gid.typeName;
691         NamePattern id = gid.namePattern;
692 // if (declaringType == null) {
693
// throwError(peekToken(-1), "must include declaring type (or pattern)");
694
// }
695

696         FieldPattern ret = new FieldPattern(dummySource,modifiers, declaringType, fieldType, id);
697         addContext(ret, beginToken);
698         return ret;
699     }
700
701 // boolean peekComma() {
702
// int nesting = 0;
703
// final int MAX_LOOKAHEAD = 20;
704
// for (int i = 0; i < MAX_LOOKAHEAD; i++) {
705
// Token t = peekToken(i);
706
// if (t.kind == COMMA) {
707
// return true;
708
// }
709
// if (t.kind == RPAREN) {
710
// nesting -= 1;
711
// if (nesting < 0) return false;
712
// }
713
// if (t.kind == LPAREN) {
714
// nesting += 1;
715
// }
716
// }
717
// return false;
718
// }
719

720     public void skipToMatching(int lparen, int rparen, int depth) {
721         do {
722             Token t = popToken();
723             if (t.kind == lparen) depth++;
724             if (t.kind == rparen) depth--;
725         } while (depth > 0);
726     }
727     
728     
729     public void skipToMatchingParen() {
730         skipToMatching(LPAREN, RPAREN, 0);
731     }
732     
733     public void warnNameChange(String JavaDoc name, String JavaDoc newName) {
734         if (name.equals(newName)) return;
735         
736         getCompiler().warnVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
737             "change from " + name + " to " + newName + "");
738     }
739
740     public Pcd parseFunctionPcd() {
741         parseNoModifiers();
742         Token beginToken = peekToken();
743         String JavaDoc name = parseAnyId();
744
745         if (name.equals("receptions")) {
746             getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
747                 "replaced by call, see release notes");
748             skipToMatchingParen();
749             return new EmptyPcd(dummySource);
750         } else if (name.equals("calls") || name.equals("call")) {
751             warnNameChange(name, "call");
752             
753             eatTopToken(LPAREN);
754             CodePattern codePattern = parseConstructorOrMethodPattern();
755             eatTopToken(RPAREN);
756             return new CallPcd(dummySource, codePattern); //, null);
757
} else if (name.equals("gets") || name.equals("get")) {
758             warnNameChange(name, "get");
759             eatTopToken(LPAREN);
760             FieldPattern fieldPattern = parseFieldPattern();
761             eatTopToken(RPAREN);
762             if (maybeEatToken(LBRACKET)) {
763                 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
764                     "[oldValue] not supported use field access to get this value");
765                 skipToMatching(LBRACKET, RBRACKET, 1);
766             }
767             return new FieldGetPcd(dummySource,fieldPattern); //, oldVarTypeName);
768
} else if (name.equals("sets") || name.equals("set")) {
769             warnNameChange(name, "set");
770             eatTopToken(LPAREN);
771             FieldPattern fieldPattern = parseFieldPattern();
772             eatTopToken(RPAREN);
773
774             if (maybeEatToken(LBRACKET)) {
775                 getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
776                     "[oldValue][newValue] not supported use field access to get oldValue and args(newValue)");
777                 skipToMatching(LBRACKET, RBRACKET, 1);
778                 skipToMatching(LBRACKET, RBRACKET, 0);
779             }
780             return new FieldSetPcd(dummySource,fieldPattern); //, oldVarTypeName, newVarTypeName);
781
} else if (name.equals("executions") || name.equals("execution")) {
782             warnNameChange(name, "execution");
783             eatTopToken(LPAREN);
784             CodePattern codePattern = parseConstructorOrMethodPattern();
785             eatTopToken(RPAREN);
786             return new ExecutionPcd(dummySource,codePattern);
787         } else if (name.equals("initialization")) {
788             eatTopToken(LPAREN);
789             ConstructorPattern codePattern = parseConstructorPattern();
790             eatTopToken(RPAREN);
791             return new InitializerPcd(dummySource, codePattern);
792         } else if (name.equals("initializations")) {
793             getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
794                 "replaced by initialization with different meaning, see release notes");
795             skipToMatchingParen();
796             return new EmptyPcd(dummySource);
797         } else if (name.equals("staticinitializations") || name.equals("staticinitialization")) {
798             warnNameChange(name, "staticinitialization");
799             eatTopToken(LPAREN);
800             GenTypeName genTypeName = parseGenTypeName();
801             eatTopToken(RPAREN);
802             return new StaticInitializerPcd(dummySource,genTypeName);
803         } else if (name.equals("handlers") || name.equals("handler")) {
804             warnNameChange(name, "handler");
805             eatTopToken(LPAREN);
806             GenTypeName genTypeName = parseGenTypeName();
807             eatTopToken(RPAREN);
808             return new HandlerPcd(dummySource,genTypeName);
809         } else if (name.equals("hasaspect")) {
810             getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
811                 "change to if(A.hasAspect(o))");
812             eatTopToken(LPAREN);
813             GenTypeName genTypeName = parseGenTypeName();
814             eatTopToken(RPAREN);
815             return new EmptyPcd(dummySource);
816         } else if (name.equals("instanceof") || name.equals("this")) {
817             warnNameChange(name, "this");
818             eatTopToken(LPAREN);
819             GenTypeName genTypeName = parseGenTypeName();
820             eatTopToken(RPAREN);
821             return new ThisPcd(dummySource,genTypeName);
822         } else if (name.equals("within")) {
823             eatTopToken(LPAREN);
824             GenTypeName genTypeName = parseGenTypeName();
825             eatTopToken(RPAREN);
826             return new WithinPcd(dummySource,genTypeName);
827         } else if (name.equals("target")) {
828             eatTopToken(LPAREN);
829             GenTypeName genTypeName = parseGenTypeName();
830             eatTopToken(RPAREN);
831             return new TargetPcd(dummySource,genTypeName);
832         } else if (name.equals("args")) {
833             //eatTopToken(LPAREN);
834
FormalsPattern genTypeNames = parseFormalsPattern();
835             //eatTopToken(RPAREN);
836
return new ArgsPcd(dummySource,genTypeNames);
837         } else if (name.equals("withinall")) {
838             getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
839                 "replaced with with(T+)");
840             eatTopToken(LPAREN);
841             GenTypeName genTypeName = parseGenTypeName();
842             CodePattern codePattern = null;
843             eatTopToken(RPAREN);
844             return new EmptyPcd(dummySource);
845         } else if (name.equals("withincode")) {
846             eatTopToken(LPAREN);
847             CodePattern codePattern = parseConstructorOrMethodPattern();
848             eatTopToken(RPAREN);
849             return new WithinCodePcd(dummySource,codePattern);
850         } else if (name.equals("callsto")) {
851             getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
852                 "not supported any more due to the removal of reception join points");
853             skipToMatchingParen();
854             return new EmptyPcd(dummySource);
855         } else if (name.equals("cflow")) {
856             eatTopToken(LPAREN);
857             Pcd pointcut = parsePcd();
858             eatTopToken(RPAREN);
859             return new CFlowPcd(dummySource,pointcut, true);
860         } else if (name.equals("if")) {
861             eatTopToken(LPAREN);
862             Expr test = parseExpr();
863             eatTopToken(RPAREN);
864             return new IfPcd(dummySource, test);
865         } else if (name.equals("cflowbelow")) {
866             eatTopToken(LPAREN);
867             Pcd pointcut = parsePcd();
868             eatTopToken(RPAREN);
869             return new CFlowPcd(dummySource,pointcut, false);
870         } else if (name.equals("cflowtop")) {
871             getCompiler().warnVersion("0.8beta3", tokenToASTObject(peekToken(-1)),
872                                   "use common idiom cflow(P && !cflowbelow(P))");
873             return new EmptyPcd(dummySource);
874         } else {
875             return new NamePcd(dummySource,null, name, parseFormalsPattern(), null);
876         }
877     }
878
879     private TypeD typeDFromName(Name name) {
880         UnresolvedNameTypeD ret = new UnresolvedNameTypeD(dummySource,name);
881         ret.setSource(name);
882         return ret;
883     }
884     
885     
886     private NamePcd parseNamePcd() {
887         Token begin = peekToken();
888         Name name = parseExtendedName();
889         if (name == null) {
890             throwError(begin, "expected pcd here");
891         }
892         
893         String JavaDoc pointcutName = name.getId();
894
895         TypeD inTypeD = null;
896         if (name.getParentName() != null) {
897             inTypeD = typeDFromName(name.getParentName());
898         }
899         FormalsPattern formals = parseFormalsPattern();
900         return new NamePcd(dummySource,inTypeD, pointcutName, formals, null);
901     }
902
903     public Pcd parsePcdTerminal() {
904         if (peekToken(1).kind == DOT) {
905             return parseNamePcd();
906         } else {
907             return parseFunctionPcd();
908         }
909     }
910
911
912     class PcdOp extends PrefixOperator {
913         public PcdOp(int kind) {
914             super(kind, -1);
915         }
916
917         public Expr parse() {
918             return parsePcdTerminal();
919         }
920     }
921
922     class UnionPcdOperator extends InfixOperator {
923         public UnionPcdOperator(int precedence) {
924             super("||", precedence);
925         }
926
927         public Expr parse(Expr lhs) {
928             Pcd rhsCC = (Pcd)parentParse(precedence);
929             return new OrPcd(dummySource,(Pcd)lhs, rhsCC);
930         }
931     }
932
933     class IntersectPcdOperator extends InfixOperator {
934         public IntersectPcdOperator(int precedence) {
935             super("&&", precedence);
936         }
937
938         public Expr parse(Expr lhs) {
939             Pcd rhsCC = (Pcd)parentParse(precedence);
940             return new AndPcd(dummySource,(Pcd)lhs, rhsCC);
941         }
942     }
943
944     class ComplementPcdOperator extends PrefixOperator {
945         public ComplementPcdOperator(int precedence) {
946             super("!", precedence);
947         }
948
949         public Expr parse() {
950             // if this is a modifiers pattern, then treat it specially
951
// this is a hack for an ugly part of the syntax
952
if (isModifier(peekToken(1))) {
953                 return parsePcdTerminal();
954             }
955
956             eatTopToken(); // eats the '!'
957
return new NotPcd(dummySource,(Pcd)parentParse(precedence));
958         }
959     }
960
961     class ParenPcdOperator extends PrefixOperator {
962         public ParenPcdOperator(int precedence) {
963             super("(", precedence);
964         }
965
966         public Expr parse() {
967             eatTopToken(); // eats the '('
968
Pcd cc = (Pcd)parentParse(precedence);
969             eatTopToken(RPAREN);
970             return cc;
971         }
972     }
973
974     private InfixOperator[] infixPcdOperators = {
975         new UnionPcdOperator(500),
976         new IntersectPcdOperator(700),
977     };
978
979     private PrefixOperator[] prefixPcdOperators = {
980         new PcdOp(IDENTIFIER),
981         new PcdOp(STAR),
982         new PcdOp(NEW),
983         new ComplementPcdOperator(3000),
984         new ParenPcdOperator(1),
985     };
986
987
988     protected ExprParser pointcutParser =
989         new ExprParser(prefixPcdOperators, infixPcdOperators, false);
990
991     public Pcd parsePcd() {
992         Pcd ret;
993         ret = (Pcd)pointcutParser.parse();
994         if (ret == null) {
995             throwError(null, "pointcut designator required");
996         }
997         return ret;
998     }
999
1000
1001    class TypeNameOp extends PrefixOperator {
1002        public TypeNameOp(int kind) {
1003            super(kind, -1);
1004        }
1005
1006        public Expr parse() {
1007            return parseTypeNameTerminal();
1008        }
1009    }
1010
1011    class UnionTypeNameOperator extends InfixOperator {
1012        public UnionTypeNameOperator(int precedence) {
1013            super("||", precedence);
1014        }
1015
1016        public Expr parse(Expr lhs) {
1017            GenTypeName rhsCC = (GenTypeName)parentParse(precedence);
1018            return new UnionTypeName(dummySource,(GenTypeName)lhs, rhsCC);
1019        }
1020    }
1021
1022    class IntersectTypeNameOperator extends InfixOperator {
1023        public IntersectTypeNameOperator(int precedence) {
1024            super("&&", precedence);
1025        }
1026
1027        public Expr parse(Expr lhs) {
1028            GenTypeName rhsCC = (GenTypeName)parentParse(precedence);
1029            return new IntersectTypeName(dummySource,(GenTypeName)lhs, rhsCC);
1030        }
1031    }
1032
1033    class ComplementTypeNameOperator extends PrefixOperator {
1034        public ComplementTypeNameOperator(int precedence) {
1035            super("!", precedence);
1036        }
1037
1038        public Expr parse() {
1039            eatTopToken(); // eats the '!'
1040
return new ComplementTypeName(dummySource,(GenTypeName)parentParse(precedence));
1041        }
1042    }
1043
1044    class ParenTypeNameOperator extends PrefixOperator {
1045        public ParenTypeNameOperator(int precedence) {
1046            super("(", precedence);
1047        }
1048
1049        public Expr parse() {
1050            eatTopToken(); // eats the '('
1051
GenTypeName cc = (GenTypeName)parentParse(precedence);
1052            eatTopToken(RPAREN);
1053            return cc;
1054        }
1055    }
1056
1057    private InfixOperator[] infixTypeNameOperators = {
1058        new UnionTypeNameOperator(500),
1059        new IntersectTypeNameOperator(700),
1060    };
1061
1062    private PrefixOperator[] prefixTypeNameOperators = {
1063        new TypeNameOp(IDENTIFIER),
1064        new TypeNameOp(STAR),
1065        new ComplementTypeNameOperator(3000),
1066        new ParenTypeNameOperator(1),
1067    };
1068
1069
1070    protected ExprParser typeNameParser =
1071        new ExprParser(prefixTypeNameOperators, infixTypeNameOperators, false);
1072
1073
1074    public GenTypeName parseGenTypeName() {
1075        GenTypeName ret = (GenTypeName)typeNameParser.parse();
1076        if (ret == null) {
1077            throwError(peekToken(), "expected type name");
1078        }
1079        return ret;
1080    }
1081
1082    public GenTypeName parseTypeNameTerminal() {
1083        Token beginToken = peekToken();
1084
1085        if (maybeEatKeyword("subtypes")) {
1086            getCompiler().errorVersion("1.0alpha1", tokenToASTObject(peekToken(-1)),
1087                "subtypes(T) should be replaced by T+");
1088            skipToMatchingParen();
1089            return null;
1090        }
1091
1092        GenTypeName baseType = parsePatternTypeName();
1093// if (beginToken.isIdentifier()
1094
// && peekToken(1).kind != DOT && peekToken(1).kind != STAR
1095
// && peekToken(1).kind != PLUS)
1096
// {
1097
// String id = parseId();
1098
// TypeD typeD = lookupPrimitiveTypeD(id);
1099
// if (typeD == null) {
1100
// baseType = new VarTypeName(dummySource,id);
1101
// } else {
1102
// baseType = new SimpleTypeName(dummySource,typeD);
1103
// }
1104
// } else {
1105
// baseType = parsePatternTypeName();
1106
// }
1107

1108        //??? this is an ugly way to handle []s
1109
//baseType = addBracketsToTypeName(baseType);
1110
//addContext(baseType, beginToken);
1111
return baseType;
1112    }
1113
1114    public GenTypeName parsePatternTypeName() {
1115        Token beginToken = peekToken();
1116        NamePatterns names = parseDottedNamePatterns();
1117        
1118        return finishParsingPatternTypeName(beginToken, names);
1119    }
1120
1121    protected PatternTypeName finishParsingPatternTypeName(Token beginToken, NamePatterns names) {
1122        boolean includeSubTypes = false;
1123        if (maybeEatToken(PLUS)) includeSubTypes = true;
1124        
1125        int dimensions = 0;
1126        while (peekToken().kind == LBRACKET && peekToken(1).kind == RBRACKET) {
1127            eatTopToken(); eatTopToken();
1128            dimensions += 1;
1129        }
1130        
1131        PatternTypeName ret = new PatternTypeName(dummySource, names, includeSubTypes, dimensions);
1132        addContext(ret, beginToken);
1133        return ret;
1134    }
1135    
1136    /** We mess around with FLOATING_POINT_LITERAL in here in order to handle
1137     * *1.f() kinds of patterns
1138     */

1139    public NamePatterns parseDottedNamePatterns() {
1140        Token beginToken = peekToken();
1141
1142        NamePatterns ret = new NamePatterns(dummySource,parseNamePattern());
1143
1144        String JavaDoc extraName = null;
1145        while (peekToken().kind == DOT || peekToken().kind == FLOATING_POINT_LITERAL) {
1146            Token t = popToken();
1147            if (t.kind == FLOATING_POINT_LITERAL) {
1148                String JavaDoc i = t.image;
1149                int dot = i.indexOf('.');
1150                NamePattern p = ret.get(ret.size()-1);
1151                if (p instanceof AnyName) {
1152                    List pieces = new ArrayList();
1153                    pieces.add("*");
1154                    pieces.add(i.substring(0, dot));
1155                    p.replaceWith(new WildName(dummySource, pieces));
1156                } else {
1157                    ((WildName)p).getPieces().add(i.substring(0, dot));
1158                }
1159                if (dot != i.length()-1) {
1160                    extraName = i.substring(dot+1);
1161                }
1162            }
1163            if (extraName == null && maybeEatToken(DOT)) {
1164                ret.add(new EllipsesFakeNamePattern(dummySource));
1165            }
1166            if (extraName != null) {
1167                ret.add(parseNamePattern(t, extraName));
1168                extraName = null;
1169            } else {
1170                ret.add(parseNamePattern());
1171            }
1172        }
1173
1174        addContext(ret, beginToken);
1175        return ret;
1176    }
1177
1178
1179
1180    public PerClause parsePerClause() {
1181        PerClause ret = null;
1182        Token beginToken = peekToken();
1183        
1184        if (!beginToken.isIdentifier()) return null;
1185        
1186        String JavaDoc name = parseAnyId();
1187        if (name.equals("perthis")) {
1188            eatTopToken(LPAREN);
1189            Pcd pointcut = parsePcd();
1190            eatTopToken(RPAREN);
1191            //ret = new PerObject(dummySource,pointcut, true);
1192
ret = new PerThisOrTarget(dummySource,pointcut, true);
1193        } else if (name.equals("pertarget")) {
1194            eatTopToken(LPAREN);
1195            Pcd pointcut = parsePcd();
1196            eatTopToken(RPAREN);
1197            //ret = new PerObject(dummySource,pointcut, false);
1198
ret = new PerThisOrTarget(dummySource,pointcut, false);
1199        } else if (name.equals("percflow")) {
1200            eatTopToken(LPAREN);
1201            Pcd pointcut = parsePcd();
1202            eatTopToken(RPAREN);
1203            ret = new PerCFlow(dummySource,pointcut, true);
1204        } else if (name.equals("percflowbelow")) {
1205            eatTopToken(LPAREN);
1206            Pcd pointcut = parsePcd();
1207            eatTopToken(RPAREN);
1208            ret = new PerCFlow(dummySource,pointcut, false);
1209        } else if (name.equals("issingleton")) {
1210            eatTopToken(LPAREN);
1211            eatTopToken(RPAREN);
1212            ret = new PerSingleton(dummySource);
1213        } else {
1214            throwError(beginToken,
1215                "expected issingleton, pertarget, perthis, percflow or percflowbelow");
1216        }
1217
1218        addContext(ret, beginToken);
1219        return ret;
1220    }
1221    
1222    public PerClause parseOldOfClause() {
1223        PerClause ret = null;
1224        Token beginToken = peekToken(-1);
1225        
1226        String JavaDoc name = parseAnyId();
1227        if (name.equals("eachobject")) {
1228            getCompiler().errorVersion("1.0alpha1", tokenToASTObject(beginToken),
1229                "change to perthis or pertarget as appropriate");
1230            eatTopToken(LPAREN);
1231            Pcd pointcut = parsePcd();
1232            eatTopToken(RPAREN);
1233            return null;
1234        } else if (name.equals("eachcflow")) {
1235            getCompiler().warnVersion("1.0alpha1", tokenToASTObject(beginToken),
1236                "change 'of eachcflow' to 'percflow'");
1237            eatTopToken(LPAREN);
1238            Pcd pointcut = parsePcd();
1239            eatTopToken(RPAREN);
1240            ret = new PerCFlow(dummySource,pointcut, true);
1241        } else if (name.equals("eachcflowbelow")) {
1242            getCompiler().warnVersion("1.0alpha1", tokenToASTObject(beginToken),
1243                "change 'of eachcflowbelow' to 'percflowbelow'");
1244            eatTopToken(LPAREN);
1245            Pcd pointcut = parsePcd();
1246            eatTopToken(RPAREN);
1247            ret = new PerCFlow(dummySource,pointcut, false);
1248        } else if (name.equals("eachJVM")) {
1249            getCompiler().warnVersion("1.0alpha1", tokenToASTObject(beginToken),
1250                "change 'of eachJVM' to 'issingleton'");
1251            eatTopToken(LPAREN);
1252            eatTopToken(RPAREN);
1253            ret = new PerSingleton(dummySource);
1254        } else {
1255            throwError(beginToken,
1256                "expected issingleton, pertarget, perthis, percflow or percflowbelow");
1257        }
1258
1259        addContext(ret, beginToken);
1260        return ret;
1261    }
1262
1263    class PointcutDecParser extends DecParser {
1264        public Dec parse() {
1265            final int legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT |
1266                Modifiers.FINAL | Modifiers.STATIC |
1267                Modifiers.PRIVATE | Modifiers.PROTECTED;
1268
1269            Modifiers modifiers = parseModifiers(legalModifiers);
1270            eatKeyword("pointcut");
1271
1272            String JavaDoc name = parseId();
1273            Formals formals = parseFormals();
1274            TypeD resultTypeD = parseOptionalReturnTypeD();
1275
1276            if (modifiers.isAbstract()) {
1277                if (peekToken().kind == COLON) {
1278                    throwError(null, "abstract pointcut can't have body");
1279                }
1280                eatTopToken(SEMICOLON);
1281                return new PointcutDec(dummySource,modifiers, name, resultTypeD, formals, new EmptyPcd(dummySource));
1282            } else {
1283                Pcd pointcut;
1284                
1285                if (maybeEatToken(COLON)) {
1286                    pointcut = parsePcd();
1287                    eatTopToken(SEMICOLON);
1288                } else {
1289                    pointcut = new EmptyPcd(dummySource);
1290                }
1291
1292                return new PointcutDec(dummySource,modifiers, name, resultTypeD, formals, pointcut);
1293            }
1294        }
1295    }
1296
1297
1298    class AspectDecParser extends DecParser {
1299        public Dec parse() {
1300            // not used, we override parse(boolean)
1301
throw new RuntimeException JavaDoc();
1302        }
1303        public Dec parse(boolean isNotMethodLocal) {
1304            int legalModifiers;
1305            if (peekEnclosingTypeDec() == null) {
1306                legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL |
1307                    Modifiers.STRICT | Modifiers.PRIVILEGED;
1308            } else if (inInterface) {
1309                legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL |
1310                    Modifiers.STRICT | Modifiers.PRIVILEGED | Modifiers.STATIC;
1311
1312            } else {
1313                legalModifiers = Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.FINAL |
1314                    Modifiers.STRICT | Modifiers.PRIVILEGED |
1315                    Modifiers.PRIVATE | Modifiers.PROTECTED | Modifiers.STATIC;
1316            }
1317
1318            Modifiers modifiers = parseModifiers(legalModifiers);
1319            if (inInterface) modifiers.setPublic(true);
1320
1321            eatKeyword("aspect");
1322            String JavaDoc id = parseId();
1323
1324            TypeD superClass = null;
1325            if (maybeEatKeyword("extends")) {
1326                superClass = parseTypeD();
1327            }
1328            TypeDs _implements = null;
1329            if (maybeEatKeyword("implements")) {
1330                _implements = parseTypeDs();
1331            }
1332            GenTypeName _dominates = null;
1333            if (maybeEatKeyword("dominates")) {
1334                _dominates = parseGenTypeName();
1335            }
1336
1337            // the of clause is optional but it must go at the end of the list
1338
PerClause perClause = null;
1339            if (maybeEatKeyword("of")) {
1340                //XXX show version error
1341
perClause = parseOldOfClause();
1342            } else {
1343                perClause = parsePerClause();
1344            }
1345
1346            TypeDec ret =
1347                new AspectDec(dummySource, modifiers, id, superClass, _implements,
1348                               _dominates, perClause, null);
1349
1350            ret.setEnclosingTypeDec(peekEnclosingTypeDec());
1351            pushEnclosingTypeDec(ret);
1352            Decs body = null;
1353            boolean oldInInterface = inInterface;
1354            boolean oldParseInterfaceOnly = parseInterfaceOnly;
1355            try {
1356                inInterface = false;
1357                parseInterfaceOnly = false;
1358                body = parseDecs(aspectDecParsers);
1359            } finally {
1360                inInterface = oldInInterface;
1361                parseInterfaceOnly = oldParseInterfaceOnly;
1362            }
1363            popEnclosingTypeDec();
1364
1365            ret.setBody(body);
1366            if (peekEnclosingTypeDec() == null) currentCompilationUnit.addDefinedType(ret);
1367            return ret;
1368        }
1369    }
1370
1371    class DeclareParser extends DecParser {
1372        public Dec parse() {
1373            parseNoModifiers();
1374            eatKeyword("declare");
1375            
1376            String JavaDoc kind = parseId();
1377            
1378            if (kind.equals("parents")) {
1379                eatTopToken(COLON);
1380                
1381                GenTypeName typeName = parseGenTypeName();
1382                boolean isImplements;
1383                if (maybeEatKeyword("implements")) {
1384                    isImplements = true;
1385                } else {
1386                    eatKeyword("extends");
1387                    isImplements = false;
1388                }
1389                TypeDs typeDs = parseTypeDs();
1390                Dec ret = new IntroducedSuperDec(dummySource, typeName, typeDs, isImplements);
1391                eatTopToken(SEMICOLON);
1392                return ret;
1393            } else if (kind.equals("error") || kind.equals("warning")) {
1394                boolean isWarning = kind.equals("warning");
1395                eatTopToken(COLON);
1396                Pcd pointcut = parsePcd();
1397                eatTopToken(COLON);
1398                Expr message = parseExpr();
1399                return new ShowErrorDec(dummySource, pointcut, message, isWarning);
1400            } else if (kind.equals("soft")) {
1401                eatTopToken(COLON);
1402                GenTypeName typeName = parseGenTypeName();
1403                eatTopToken(COLON);
1404                Pcd pointcut = parsePcd();
1405                return new SoftThrowableDec(dummySource, typeName, pointcut);
1406            } else {
1407                throwError(peekToken(-1), "no declare " + kind + " is defined");
1408                return null;
1409            }
1410        }
1411    }
1412    
1413    class BeforeDecParser extends DecParser {
1414        public Dec parse() {
1415            Modifiers modifiers = parseModifiers(Modifiers.STATIC | Modifiers.STRICT);
1416            eatKeyword("before");
1417
1418            Formals formals = parseFormals();
1419            TypeDs _throws = parseThrows();
1420            //TypeD resultTypeD = parseOptionalReturnTypeD();
1421
eatTopToken(COLON);
1422
1423            Pcd pointcut = parsePcd();
1424
1425            return new BeforeAdviceDec(dummySource,modifiers, formals, _throws, pointcut, parseCodeBodyFully());
1426        }
1427    }
1428
1429    //XXX used by parseMethodDec to deal with some ambiguities
1430
public AroundAdviceDec parseAroundAdviceDec(Modifiers modifiers, TypeD resultTypeD) {
1431        // would be nice to verify that modifiers are appropriate
1432

1433        Formals formals = parseFormals();
1434        TypeDs _throws = parseThrows();
1435        eatTopToken(COLON);
1436        
1437        Pcd pointcut = parsePcd();
1438        
1439        return new AroundAdviceDec(dummySource,modifiers, resultTypeD, formals, _throws, pointcut, parseCodeBodyFully());
1440    }
1441    
1442    class AroundDecParser extends DecParser {
1443        public Dec parse() {
1444            Modifiers modifiers = parseModifiers(Modifiers.STATIC | Modifiers.STRICT);
1445            
1446            boolean needReturns = false;
1447            TypeD resultTypeD = null;
1448            if (maybeEatKeyword("around")) {
1449                needReturns = true;
1450                getCompiler().warnVersion("1.0alpha1",
1451                        tokenToASTObject(peekToken(-1)),
1452                        "the return type now goes before the around keyword,\n" +
1453                        "i.e. Object around() instead of around() returns Object");
1454            } else {
1455                resultTypeD = parseTypeD();
1456                eatKeyword("around");
1457            }
1458
1459            Formals formals = parseFormals();
1460            // I believe this is always required for around advice
1461

1462
1463            if (needReturns) {
1464                if (!maybeEatKeyword("returns") ) {
1465                    getCompiler().showError(formals, "return type required for around");
1466                } else {
1467                    resultTypeD = parseTypeD();
1468                }
1469            }
1470            TypeDs _throws = parseThrows();
1471            eatTopToken(COLON);
1472
1473            Pcd pointcut = parsePcd();
1474
1475            return new AroundAdviceDec(dummySource,modifiers, resultTypeD, formals, _throws, pointcut, parseCodeBodyFully());
1476        }
1477    }
1478
1479    class AfterDecParser extends DecParser {
1480        public Dec parse() {
1481            Modifiers modifiers = parseModifiers(Modifiers.STATIC | Modifiers.STRICT);
1482            eatKeyword("after");
1483
1484            Formals formals = parseFormals();
1485
1486            if (maybeEatKeyword("returning")) {
1487                FormalDec formal = null;
1488                if (maybeEatToken(LPAREN)) {
1489                    if (peekToken().kind != RPAREN) {
1490                        formal = parseFormal();
1491                    }
1492                    eatTopToken(RPAREN);
1493                }
1494
1495                TypeDs _throws = parseThrows();
1496                eatTopToken(COLON);
1497                
1498                Pcd pointcut = parsePcd();
1499                return new AfterReturningAdviceDec(dummySource,modifiers, formals, formal, _throws, pointcut, parseCodeBodyFully());
1500            } else if (maybeEatKeyword("throwing")) {
1501                FormalDec formal = null;
1502                if (maybeEatToken(LPAREN)) {
1503                    if (peekToken().kind != RPAREN) {
1504                        formal = parseFormal();
1505                    }
1506                    eatTopToken(RPAREN);
1507                }
1508                TypeDs _throws = parseThrows();
1509                eatTopToken(COLON);
1510                Pcd pointcut = parsePcd();
1511                return new AfterThrowingAdviceDec(dummySource,modifiers, formals, formal, _throws, pointcut, parseCodeBodyFully());
1512            } else {
1513                TypeDs _throws = parseThrows();
1514                eatTopToken(COLON);
1515                Pcd pointcut = parsePcd();
1516                return new AfterAdviceDec(dummySource,modifiers, formals, _throws, pointcut, parseCodeBodyFully());
1517            }
1518        }
1519    }
1520}
1521
Popular Tags