You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PatternParser.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import java.util.*;
  14. import org.aspectj.weaver.*;
  15. //XXX doesn't handle errors for extra tokens very well (sometimes ignores)
  16. public class PatternParser {
  17. private ITokenSource tokenSource;
  18. private ISourceContext sourceContext;
  19. /**
  20. * Constructor for PatternParser.
  21. */
  22. public PatternParser(ITokenSource tokenSource) {
  23. super();
  24. this.tokenSource = tokenSource;
  25. this.sourceContext = tokenSource.getSourceContext();
  26. }
  27. public PerClause maybeParsePerClause() {
  28. IToken tok = tokenSource.peek();
  29. if (tok == IToken.EOF) return null;
  30. if (tok.isIdentifier()) {
  31. String name = tok.getString();
  32. if (name.equals("issingleton")) {
  33. return parsePerSingleton();
  34. } else if (name.equals("perthis")) {
  35. return parsePerObject(true);
  36. } else if (name.equals("pertarget")) {
  37. return parsePerObject(false);
  38. } else if (name.equals("percflow")) {
  39. return parsePerCflow(false);
  40. } else if (name.equals("percflowbelow")) {
  41. return parsePerCflow(true);
  42. } else {
  43. return null;
  44. }
  45. }
  46. return null;
  47. }
  48. private PerClause parsePerCflow(boolean isBelow) {
  49. parseIdentifier();
  50. eat("(");
  51. Pointcut entry = parsePointcut();
  52. eat(")");
  53. return new PerCflow(entry, isBelow);
  54. }
  55. private PerClause parsePerObject(boolean isThis) {
  56. parseIdentifier();
  57. eat("(");
  58. Pointcut entry = parsePointcut();
  59. eat(")");
  60. return new PerObject(entry, isThis);
  61. }
  62. private PerClause parsePerSingleton() {
  63. parseIdentifier();
  64. eat("(");
  65. eat(")");
  66. return new PerSingleton();
  67. }
  68. public Declare parseDeclare() {
  69. int startPos = tokenSource.peek().getStart();
  70. eatIdentifier("declare");
  71. String kind = parseIdentifier();
  72. eat(":");
  73. Declare ret;
  74. //XXX beta add soft, dominates
  75. if (kind.equals("error")) {
  76. ret = parseErrorOrWarning(true);
  77. } else if (kind.equals("warning")) {
  78. ret = parseErrorOrWarning(false);
  79. } else if (kind.equals("precedence")) {
  80. ret = parseDominates();
  81. } else if (kind.equals("dominates")) {
  82. throw new ParserException("name changed to declare precedence", tokenSource.peek(-2));
  83. } else if (kind.equals("parents")) {
  84. ret = parseParents();
  85. } else if (kind.equals("soft")) {
  86. ret = parseSoft();
  87. } else {
  88. throw new ParserException("expected one of error, warning, parents, soft, dominates",
  89. tokenSource.peek(-1));
  90. }
  91. int endPos = tokenSource.peek(-1).getEnd();
  92. ret.setLocation(sourceContext, startPos, endPos);
  93. return ret;
  94. }
  95. public DeclarePrecedence parseDominates() {
  96. List l = new ArrayList();
  97. do {
  98. l.add(parseTypePattern());
  99. } while (maybeEat(","));
  100. return new DeclarePrecedence(l);
  101. }
  102. private Declare parseParents() {
  103. TypePattern p = parseTypePattern();
  104. IToken t = tokenSource.next();
  105. if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
  106. throw new ParserException("extends or implements", t);
  107. }
  108. List l = new ArrayList();
  109. do {
  110. l.add(parseTypePattern());
  111. } while (maybeEat(","));
  112. //XXX somewhere in the chain we need to enforce that we have only ExactTypePatterns
  113. return new DeclareParents(p, l);
  114. }
  115. private Declare parseSoft() {
  116. TypePattern p = parseTypePattern();
  117. eat(":");
  118. Pointcut pointcut = parsePointcut();
  119. return new DeclareSoft(p, pointcut);
  120. }
  121. private Declare parseErrorOrWarning(boolean isError) {
  122. Pointcut pointcut = parsePointcut();
  123. eat(":");
  124. String message = parseStringLiteral();
  125. return new DeclareErrorOrWarning(isError, pointcut, message);
  126. }
  127. public Pointcut parsePointcut() {
  128. Pointcut p = parseAtomicPointcut();
  129. if (maybeEat("&&")) {
  130. p = new AndPointcut(p, parseNotOrPointcut());
  131. }
  132. if (maybeEat("||")) {
  133. p = new OrPointcut(p, parsePointcut());
  134. }
  135. return p;
  136. }
  137. private Pointcut parseNotOrPointcut() {
  138. Pointcut p = parseAtomicPointcut();
  139. if (maybeEat("&&")) {
  140. p = new AndPointcut(p, parsePointcut());
  141. }
  142. return p;
  143. }
  144. private Pointcut parseAtomicPointcut() {
  145. if (maybeEat("!")) {
  146. int startPos = tokenSource.peek(-1).getStart();
  147. Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos);
  148. return p;
  149. }
  150. if (maybeEat("(")) {
  151. Pointcut p = parsePointcut();
  152. eat(")");
  153. return p;
  154. }
  155. int startPos = tokenSource.peek().getStart();
  156. Pointcut p = parseSinglePointcut();
  157. int endPos = tokenSource.peek(-1).getEnd();
  158. p.setLocation(sourceContext, startPos, endPos);
  159. return p;
  160. }
  161. public Pointcut parseSinglePointcut() {
  162. int start = tokenSource.getIndex();
  163. IToken t = tokenSource.peek();
  164. Pointcut p = t.maybeGetParsedPointcut();
  165. if (p != null) {
  166. tokenSource.next();
  167. return p;
  168. }
  169. String kind = parseIdentifier();
  170. tokenSource.setIndex(start);
  171. if (kind.equals("execution") || kind.equals("call") ||
  172. kind.equals("get") || kind.equals("set")) {
  173. return parseKindedPointcut();
  174. } else if (kind.equals("args")) {
  175. return parseArgsPointcut();
  176. } else if (kind.equals("this") || kind.equals("target")) {
  177. return parseThisOrTargetPointcut();
  178. } else if (kind.equals("within")) {
  179. return parseWithinPointcut();
  180. } else if (kind.equals("withincode")) {
  181. return parseWithinCodePointcut();
  182. } else if (kind.equals("cflow")) {
  183. return parseCflowPointcut(false);
  184. } else if (kind.equals("cflowbelow")) {
  185. return parseCflowPointcut(true);
  186. } else if (kind.equals("adviceexecution")) {
  187. parseIdentifier(); eat("(");
  188. eat(")");
  189. return new KindedPointcut(Shadow.AdviceExecution,
  190. new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY,
  191. TypePattern.ANY, TypePattern.ANY, NamePattern.ANY,
  192. TypePatternList.ANY,
  193. ThrowsPattern.ANY));
  194. } else if (kind.equals("handler")) {
  195. parseIdentifier(); eat("(");
  196. TypePattern typePat = parseTypePattern();
  197. eat(")");
  198. return new HandlerPointcut(typePat);
  199. } else if (kind.equals("initialization")) {
  200. parseIdentifier(); eat("(");
  201. SignaturePattern sig = parseConstructorSignaturePattern();
  202. eat(")");
  203. return new KindedPointcut(Shadow.Initialization, sig);
  204. } else if (kind.equals("staticinitialization")) {
  205. parseIdentifier(); eat("(");
  206. TypePattern typePat = parseTypePattern();
  207. eat(")");
  208. return new KindedPointcut(Shadow.StaticInitialization,
  209. new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY,
  210. TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY,
  211. ThrowsPattern.ANY));
  212. } else if (kind.equals("preinitialization")) {
  213. parseIdentifier(); eat("(");
  214. SignaturePattern sig = parseConstructorSignaturePattern();
  215. eat(")");
  216. return new KindedPointcut(Shadow.PreInitialization, sig);
  217. } else {
  218. return parseReferencePointcut();
  219. }
  220. }
  221. private SignaturePattern parseConstructorSignaturePattern() {
  222. SignaturePattern ret = parseMethodOrConstructorSignaturePattern();
  223. if (ret.getKind() == Member.CONSTRUCTOR) return ret;
  224. throw new ParserException("constructor pattern required, found method pattern",
  225. ret);
  226. }
  227. private Pointcut parseWithinCodePointcut() {
  228. parseIdentifier();
  229. eat("(");
  230. SignaturePattern sig = parseMethodOrConstructorSignaturePattern();
  231. eat(")");
  232. return new WithincodePointcut(sig);
  233. }
  234. private Pointcut parseCflowPointcut(boolean isBelow) {
  235. parseIdentifier();
  236. eat("(");
  237. Pointcut entry = parsePointcut();
  238. eat(")");
  239. return new CflowPointcut(entry, isBelow, null);
  240. }
  241. /**
  242. * Method parseWithinPointcut.
  243. * @return Pointcut
  244. */
  245. private Pointcut parseWithinPointcut() {
  246. parseIdentifier();
  247. eat("(");
  248. TypePattern type = parseTypePattern();
  249. eat(")");
  250. return new WithinPointcut(type);
  251. }
  252. /**
  253. * Method parseThisOrTargetPointcut.
  254. * @return Pointcut
  255. */
  256. private Pointcut parseThisOrTargetPointcut() {
  257. String kind = parseIdentifier();
  258. eat("(");
  259. TypePattern type = parseTypePattern();
  260. eat(")");
  261. return new ThisOrTargetPointcut(kind.equals("this"), type);
  262. }
  263. /**
  264. * Method parseArgsPointcut.
  265. * @return Pointcut
  266. */
  267. private Pointcut parseArgsPointcut() {
  268. parseIdentifier();
  269. TypePatternList arguments = parseArgumentsPattern();
  270. return new ArgsPointcut(arguments);
  271. }
  272. private Pointcut parseReferencePointcut() {
  273. TypePattern onType = parseTypePattern();
  274. NamePattern name = tryToExtractName(onType);
  275. if (name == null) {
  276. throw new ParserException("name pattern", tokenSource.peek());
  277. }
  278. if (onType.toString().equals("")) {
  279. onType = null;
  280. }
  281. TypePatternList arguments = parseArgumentsPattern();
  282. return new ReferencePointcut(onType, name.maybeGetSimpleName(), arguments);
  283. }
  284. public List parseDottedIdentifier() {
  285. List ret = new ArrayList();
  286. ret.add(parseIdentifier());
  287. while (maybeEat(".")) {
  288. ret.add(parseIdentifier());
  289. }
  290. return ret;
  291. }
  292. private KindedPointcut parseKindedPointcut() {
  293. String kind = parseIdentifier();
  294. eat("(");
  295. SignaturePattern sig;
  296. Shadow.Kind shadowKind = null;
  297. if (kind.equals("execution")) {
  298. sig = parseMethodOrConstructorSignaturePattern();
  299. if (sig.getKind() == Member.METHOD) {
  300. shadowKind = Shadow.MethodExecution;
  301. } else if (sig.getKind() == Member.CONSTRUCTOR) {
  302. shadowKind = Shadow.ConstructorExecution;
  303. }
  304. } else if (kind.equals("call")) {
  305. sig = parseMethodOrConstructorSignaturePattern();
  306. if (sig.getKind() == Member.METHOD) {
  307. shadowKind = Shadow.MethodCall;
  308. } else if (sig.getKind() == Member.CONSTRUCTOR) {
  309. shadowKind = Shadow.ConstructorCall;
  310. }
  311. } else if (kind.equals("get")) {
  312. sig = parseFieldSignaturePattern();
  313. shadowKind = Shadow.FieldGet;
  314. } else if (kind.equals("set")) {
  315. sig = parseFieldSignaturePattern();
  316. shadowKind = Shadow.FieldSet;
  317. } else {
  318. throw new ParserException("bad kind: " + kind, tokenSource.peek());
  319. }
  320. eat(")");
  321. return new KindedPointcut(shadowKind, sig);
  322. }
  323. public TypePattern parseTypePattern() {
  324. TypePattern p = parseAtomicTypePattern();
  325. if (maybeEat("&&")) {
  326. p = new AndTypePattern(p, parseNotOrTypePattern());
  327. }
  328. if (maybeEat("||")) {
  329. p = new OrTypePattern(p, parseTypePattern());
  330. }
  331. return p;
  332. }
  333. private TypePattern parseNotOrTypePattern() {
  334. TypePattern p = parseAtomicTypePattern();
  335. if (maybeEat("&&")) {
  336. p = new AndTypePattern(p, parseTypePattern());
  337. }
  338. return p;
  339. }
  340. private TypePattern parseAtomicTypePattern() {
  341. if (maybeEat("!")) {
  342. int startPos = tokenSource.peek(-1).getStart();
  343. //??? we lose source location for true start of !type
  344. TypePattern p = new NotTypePattern(parseAtomicTypePattern());
  345. return p;
  346. }
  347. if (maybeEat("(")) {
  348. TypePattern p = parseTypePattern();
  349. eat(")");
  350. return p;
  351. }
  352. int startPos = tokenSource.peek().getStart();
  353. TypePattern p = parseSingleTypePattern();
  354. int endPos = tokenSource.peek(-1).getEnd();
  355. p.setLocation(sourceContext, startPos, endPos);
  356. return p;
  357. }
  358. public TypePattern parseSingleTypePattern() {
  359. List names = parseDottedNamePattern();
  360. // new ArrayList();
  361. // NamePattern p1 = parseNamePattern();
  362. // names.add(p1);
  363. // while (maybeEat(".")) {
  364. // if (maybeEat(".")) {
  365. // names.add(NamePattern.ELLIPSIS);
  366. // }
  367. // NamePattern p2 = parseNamePattern();
  368. // names.add(p2);
  369. // }
  370. int dim = 0;
  371. while (maybeEat("[")) {
  372. eat("]");
  373. dim++;
  374. }
  375. boolean includeSubtypes = maybeEat("+");
  376. int endPos = tokenSource.peek(-1).getEnd();
  377. //??? what about the source location of any's????
  378. if (names.size() == 1 && ((NamePattern)names.get(0)).isAny() && dim == 0) return TypePattern.ANY;
  379. return new WildTypePattern(names, includeSubtypes, dim, endPos);
  380. }
  381. public List parseDottedNamePattern() {
  382. List names = new ArrayList();
  383. StringBuffer buf = new StringBuffer();
  384. IToken previous = null;
  385. while (true) {
  386. IToken tok;
  387. int startPos = tokenSource.peek().getStart();
  388. String afterDot = null;
  389. while (true) {
  390. tok = tokenSource.peek();
  391. if (previous != null) {
  392. if (!isAdjacent(previous, tok)) break;
  393. }
  394. if (tok.getString() == "*" || tok.isIdentifier()) {
  395. buf.append(tok.getString());
  396. } else if (tok.getLiteralKind() != null) {
  397. //System.err.println("literal kind: " + tok.getString());
  398. String s = tok.getString();
  399. int dot = s.indexOf('.');
  400. if (dot != -1) {
  401. buf.append(s.substring(0, dot));
  402. afterDot = s.substring(dot+1);
  403. previous = tokenSource.next();
  404. break;
  405. }
  406. buf.append(s); // ??? so-so
  407. } else {
  408. break;
  409. }
  410. previous = tokenSource.next();
  411. //XXX need to handle floats and other fun stuff
  412. }
  413. int endPos = tokenSource.peek(-1).getEnd();
  414. if (buf.length() == 0 && names.isEmpty()) {
  415. throw new ParserException("expected name pattern", tok);
  416. }
  417. if (buf.length() == 0) {
  418. names.add(NamePattern.ELLIPSIS);
  419. } else {
  420. checkLegalName(buf.toString(), previous);
  421. NamePattern ret = new NamePattern(buf.toString());
  422. ret.setLocation(sourceContext, startPos, endPos);
  423. names.add(ret);
  424. }
  425. if (afterDot == null) {
  426. buf.setLength(0);
  427. if (!maybeEat(".")) break;
  428. else previous = tokenSource.peek(-1);
  429. } else {
  430. buf.setLength(0);
  431. buf.append(afterDot);
  432. afterDot = null;
  433. }
  434. }
  435. //System.err.println("parsed: " + names);
  436. return names;
  437. }
  438. public NamePattern parseNamePattern() {
  439. StringBuffer buf = new StringBuffer();
  440. IToken previous = null;
  441. IToken tok;
  442. int startPos = tokenSource.peek().getStart();
  443. while (true) {
  444. tok = tokenSource.peek();
  445. if (previous != null) {
  446. if (!isAdjacent(previous, tok)) break;
  447. }
  448. if (tok.getString() == "*" || tok.isIdentifier()) {
  449. buf.append(tok.getString());
  450. } else if (tok.getLiteralKind() != null) {
  451. //System.err.println("literal kind: " + tok.getString());
  452. String s = tok.getString();
  453. if (s.indexOf('.') != -1) break;
  454. buf.append(s); // ??? so-so
  455. } else {
  456. break;
  457. }
  458. previous = tokenSource.next();
  459. //XXX need to handle floats and other fun stuff
  460. }
  461. int endPos = tokenSource.peek(-1).getEnd();
  462. if (buf.length() == 0) {
  463. throw new ParserException("expected name pattern", tok);
  464. }
  465. checkLegalName(buf.toString(), previous);
  466. NamePattern ret = new NamePattern(buf.toString());
  467. ret.setLocation(sourceContext, startPos, endPos);
  468. return ret;
  469. }
  470. private void checkLegalName(String s, IToken tok) {
  471. char ch = s.charAt(0);
  472. if (!(ch == '*' || Character.isJavaIdentifierStart(ch))) {
  473. throw new ParserException("illegal identifier start (" + ch + ")", tok);
  474. }
  475. for (int i=1, len=s.length(); i < len; i++) {
  476. ch = s.charAt(i);
  477. if (!(ch == '*' || Character.isJavaIdentifierPart(ch))) {
  478. throw new ParserException("illegal identifier character (" + ch + ")", tok);
  479. }
  480. }
  481. }
  482. private boolean isAdjacent(IToken first, IToken second) {
  483. return first.getEnd() == second.getStart()-1;
  484. }
  485. public ModifiersPattern parseModifiersPattern() {
  486. int requiredFlags = 0;
  487. int forbiddenFlags = 0;
  488. int start;
  489. while (true) {
  490. start = tokenSource.getIndex();
  491. boolean isForbidden = false;
  492. isForbidden = maybeEat("!");
  493. IToken t = tokenSource.next();
  494. int flag = ModifiersPattern.getModifierFlag(t.getString());
  495. if (flag == -1) break;
  496. if (isForbidden) forbiddenFlags |= flag;
  497. else requiredFlags |= flag;
  498. }
  499. tokenSource.setIndex(start);
  500. if (requiredFlags == 0 && forbiddenFlags == 0) {
  501. return ModifiersPattern.ANY;
  502. } else {
  503. return new ModifiersPattern(requiredFlags, forbiddenFlags);
  504. }
  505. }
  506. public TypePatternList parseArgumentsPattern() {
  507. List patterns = new ArrayList();
  508. eat("(");
  509. if (maybeEat(")")) {
  510. return new TypePatternList();
  511. }
  512. do {
  513. if (maybeEat(".")) {
  514. eat(".");
  515. patterns.add(TypePattern.ELLIPSIS);
  516. } else {
  517. patterns.add(parseTypePattern());
  518. }
  519. } while (maybeEat(","));
  520. eat(")");
  521. return new TypePatternList(patterns);
  522. }
  523. public ThrowsPattern parseOptionalThrowsPattern() {
  524. IToken t = tokenSource.peek();
  525. if (t.isIdentifier() && t.getString().equals("throws")) {
  526. tokenSource.next();
  527. List required = new ArrayList();
  528. List forbidden = new ArrayList();
  529. do {
  530. boolean isForbidden = maybeEat("!");
  531. //???might want an error for a second ! without a paren
  532. TypePattern p = parseTypePattern();
  533. if (isForbidden) forbidden.add(p);
  534. else required.add(p);
  535. } while (maybeEat(","));
  536. return new ThrowsPattern(new TypePatternList(required), new TypePatternList(forbidden));
  537. }
  538. return ThrowsPattern.ANY;
  539. }
  540. public SignaturePattern parseMethodOrConstructorSignaturePattern() {
  541. int startPos = tokenSource.peek().getStart();
  542. ModifiersPattern modifiers = parseModifiersPattern();
  543. TypePattern returnType = parseTypePattern();
  544. TypePattern declaringType;
  545. NamePattern name = null;
  546. Member.Kind kind;
  547. // here we can check for 'new'
  548. if (maybeEatNew(returnType)) {
  549. kind = Member.CONSTRUCTOR;
  550. if (returnType.toString().length() == 0) {
  551. declaringType = TypePattern.ANY;
  552. } else {
  553. declaringType = returnType;
  554. }
  555. returnType = TypePattern.ANY;
  556. name = NamePattern.ANY;
  557. } else {
  558. kind = Member.METHOD;
  559. declaringType = parseTypePattern();
  560. if (maybeEat(".")) {
  561. name = parseNamePattern();
  562. } else {
  563. name = tryToExtractName(declaringType);
  564. if (name == null) {
  565. throw new ParserException("name pattern", tokenSource.peek());
  566. }
  567. String simpleName = name.maybeGetSimpleName();
  568. //XXX should add check for any Java keywords
  569. if (simpleName != null && simpleName.equals("new")) {
  570. throw new ParserException("constructor patterns have no return type",
  571. tokenSource.peek());
  572. }
  573. if (declaringType.toString().equals("")) {
  574. declaringType = declaringType.ANY;
  575. }
  576. }
  577. }
  578. TypePatternList parameterTypes = parseArgumentsPattern();
  579. ThrowsPattern throwsPattern = parseOptionalThrowsPattern();
  580. SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, throwsPattern);
  581. int endPos = tokenSource.peek(-1).getEnd();
  582. ret.setLocation(sourceContext, startPos, endPos);
  583. return ret;
  584. }
  585. private boolean maybeEatNew(TypePattern returnType) {
  586. if (returnType instanceof WildTypePattern) {
  587. WildTypePattern p = (WildTypePattern)returnType;
  588. if (p.maybeExtractName("new")) return true;
  589. }
  590. int start = tokenSource.getIndex();
  591. if (maybeEat(".")) {
  592. String id = maybeEatIdentifier();
  593. if (id != null && id.equals("new")) return true;
  594. tokenSource.setIndex(start);
  595. }
  596. return false;
  597. }
  598. public SignaturePattern parseFieldSignaturePattern() {
  599. int startPos = tokenSource.peek().getStart();
  600. ModifiersPattern modifiers = parseModifiersPattern();
  601. TypePattern returnType = parseTypePattern();
  602. TypePattern declaringType = parseTypePattern();
  603. NamePattern name;
  604. //System.err.println("parsed field: " + declaringType.toString());
  605. if (maybeEat(".")) {
  606. name = parseNamePattern();
  607. } else {
  608. name = tryToExtractName(declaringType);
  609. if (declaringType.toString().equals("")) {
  610. declaringType = declaringType.ANY;
  611. }
  612. }
  613. SignaturePattern ret = new SignaturePattern(Member.FIELD, modifiers, returnType,
  614. declaringType, name, TypePatternList.ANY, ThrowsPattern.ANY);
  615. int endPos = tokenSource.peek(-1).getEnd();
  616. ret.setLocation(sourceContext, startPos, endPos);
  617. return ret;
  618. }
  619. private NamePattern tryToExtractName(TypePattern nextType) {
  620. if (nextType == TypePattern.ANY) {
  621. return NamePattern.ANY;
  622. } else if (nextType instanceof WildTypePattern) {
  623. WildTypePattern p = (WildTypePattern)nextType;
  624. return p.extractName();
  625. } else {
  626. return null;
  627. }
  628. }
  629. public String parseStringLiteral() {
  630. IToken token = tokenSource.next();
  631. String literalKind = token.getLiteralKind();
  632. if (literalKind == "string") {
  633. return token.getString();
  634. }
  635. throw new ParserException("string", token);
  636. }
  637. public String parseIdentifier() {
  638. IToken token = tokenSource.next();
  639. if (token.isIdentifier()) return token.getString();
  640. throw new ParserException("identifier", token);
  641. }
  642. public void eatIdentifier(String expectedValue) {
  643. IToken next = tokenSource.next();
  644. if (!next.getString().equals(expectedValue)) {
  645. throw new ParserException(expectedValue, next);
  646. }
  647. }
  648. public boolean maybeEatIdentifier(String expectedValue) {
  649. IToken next = tokenSource.peek();
  650. if (next.getString().equals(expectedValue)) {
  651. tokenSource.next();
  652. return true;
  653. } else {
  654. return false;
  655. }
  656. }
  657. public void eat(String expectedValue) {
  658. IToken next = tokenSource.next();
  659. if (next.getString() != expectedValue) {
  660. throw new ParserException(expectedValue, next);
  661. }
  662. }
  663. public boolean maybeEat(String token) {
  664. IToken next = tokenSource.peek();
  665. if (next.getString() == token) {
  666. tokenSource.next();
  667. return true;
  668. } else {
  669. return false;
  670. }
  671. }
  672. public String maybeEatIdentifier() {
  673. IToken next = tokenSource.peek();
  674. if (next.isIdentifier()) {
  675. tokenSource.next();
  676. return next.getString();
  677. } else {
  678. return null;
  679. }
  680. }
  681. public boolean peek(String token) {
  682. IToken next = tokenSource.peek();
  683. return next.getString() == token;
  684. }
  685. public PatternParser(String data) {
  686. this(BasicTokenSource.makeTokenSource(data));
  687. }
  688. }