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.

пре 21 година
пре 21 година
пре 21 година
пре 21 година
пре 21 година
пре 21 година
пре 21 година
пре 21 година
пре 21 година
пре 21 година
пре 21 година
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. }