/plugins/JavaSideKick/tags/javasidekick-2-0-2/src/sidekick/java/parser/Tiger.jj

# · Unknown · 2651 lines · 2422 code · 229 blank · 0 comment · 0 complexity · d871d777ed9e997cb2a8bce67acb6c2a MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. Per Sreenivasa Viswanadha (as posted on the javacc user mailing list), the
  3. original java 1.5 grammar is licensed under the BSD license, so this modified
  4. grammar is also.
  5. Copyright (c) 2005, Dale Anson
  6. All rights reserved.
  7. Redistribution and use in source and binary forms, with or without modification,
  8. are permitted provided that the following conditions are met:
  9. * Redistributions of source code must retain the above copyright notice,
  10. this list of conditions and the following disclaimer.
  11. * Redistributions in binary form must reproduce the above copyright notice,
  12. this list of conditions and the following disclaimer in the documentation
  13. and/or other materials provided with the distribution.
  14. * Neither the name of the <ORGANIZATION> nor the names of its contributors
  15. may be used to endorse or promote products derived from this software without
  16. specific prior written permission.
  17. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  21. ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  24. ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. options {
  29. JAVA_UNICODE_ESCAPE = true;
  30. ERROR_REPORTING = false;
  31. STATIC = false;
  32. }
  33. PARSER_BEGIN(TigerParser)
  34. package sidekick.java.parser;
  35. import sidekick.java.node.*;
  36. import java.io.*;
  37. import java.util.*;
  38. /**
  39. * Based on grammar to parse Java version 1.5 written by Sreenivasa Viswanadha,
  40. * parses a java file for the JBrowse plugin to provide a java code
  41. * browser that works with java 1.5.
  42. * <p>
  43. * Example usage:<p>
  44. * <code>
  45. * TigerParser parser = new TigerParser(filename);<br>
  46. * CUNode root = parser.CompilationUnit();<br>
  47. * </code>
  48. * Calling <code>CompilationUnit()</code> causes the file to be parsed into
  49. * TigerNodes, of which, CUNode is the top-level. The TigerNodes have a parent/
  50. * child relastionship, which naturally forms a tree structure.
  51. * <p>
  52. * To turn this .jj file into a .java file, run <code>javacc Tiger.jj</code>
  53. * from the directory that contains this file. Javacc will produce a number of
  54. * .java files, Be careful -- not all files in the directory are produced by
  55. * javacc, in particular ModifierSet.java and Token.java are required files and
  56. * are NOT produced by javacc. So the sequence is:<br>
  57. * .jj -> javacc -> .java -> javac -> .class
  58. */
  59. public class TigerParser
  60. {
  61. // accumulates counts of classes, interfaces, methods and fields.
  62. private Results results = new Results();
  63. private InputStream inputStream = null;
  64. /**
  65. * Constructor for TigerParser. Note that JBrowse does not use this
  66. * constructor -- since the options for building the parser have both
  67. * USER_TOKEN_MANAGER and USER_CHAR_STREAM set to false (these are the
  68. * default values so are not explicitly set), javacc will create a
  69. * constructor "public TigerParser(InputStream)". It is that constructor
  70. * that JBrowse uses.
  71. * @param fileName name of the file to parse
  72. */
  73. public TigerParser(String filename)
  74. {
  75. this(System.in);
  76. try {
  77. inputStream = new FileInputStream(new File(filename));
  78. ReInit(inputStream);
  79. }
  80. catch(Exception e) {
  81. e.printStackTrace();
  82. }
  83. }
  84. /**
  85. * @return the accumulated counts of classes, interfaces, methods, and fields.
  86. */
  87. public Results getResults() {
  88. return results;
  89. }
  90. public Location getLocation(Token t) {
  91. if (t == null)
  92. return new Location(0, 0);
  93. return new Location(t.beginLine, t.beginColumn);
  94. }
  95. public Location getEndLocation(Token t) {
  96. if (t == null)
  97. return new Location(0, 0);
  98. return new Location(t.endLine, t.endColumn);
  99. }
  100. public Location getLocation(Modifier m) {
  101. if (m == null)
  102. return new Location(0, 0);
  103. if (m.beginLine == -1)
  104. m.beginLine = 0;
  105. return new Location(m.beginLine, m.beginColumn);
  106. }
  107. public void error_skipto(int kind) {
  108. ParseException e = generateParseException(); // generate the exception object.
  109. addException(e);
  110. Token t = null;
  111. int i = 0;
  112. do {
  113. i++;
  114. if (i > 100) {
  115. break;
  116. }
  117. t = getNextToken();
  118. } while (t != null && t.kind != kind);
  119. }
  120. private List exceptions = new ArrayList();
  121. private void addException(ParseException pe) {
  122. ErrorNode en = new ErrorNode(pe);
  123. exceptions.add(en);
  124. }
  125. public List getErrors() {
  126. return exceptions;
  127. }
  128. public void adjustModifier(Modifier m, Token t) {
  129. if (m.beginLine < t.beginLine) {
  130. m.beginLine = t.beginLine;
  131. }
  132. if (m.beginLine == t.beginLine && (t.beginColumn < m.beginColumn || m.beginColumn == -1)) {
  133. m.beginColumn = t.beginColumn;
  134. }
  135. if (m.endLine < t.endLine) {
  136. m.endLine = t.endLine;
  137. }
  138. if (m.endLine == t.endLine && m.endColumn < t.endColumn) {
  139. m.endColumn = t.endColumn;
  140. }
  141. }
  142. public void setTabSize(int size) {
  143. jj_input_stream.setTabSize(size);
  144. }
  145. }
  146. PARSER_END(TigerParser)
  147. /* **************** Parser Rules Follow ****************/
  148. /* WHITE SPACE */
  149. SKIP :
  150. {
  151. " "
  152. | "\t"
  153. | "\n"
  154. | "\r"
  155. | "\f"
  156. }
  157. /* COMMENTS */
  158. MORE :
  159. {
  160. "//" : IN_SINGLE_LINE_COMMENT
  161. |
  162. <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
  163. |
  164. "/*" : IN_MULTI_LINE_COMMENT
  165. }
  166. <IN_SINGLE_LINE_COMMENT>
  167. SPECIAL_TOKEN :
  168. {
  169. <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT
  170. }
  171. <IN_FORMAL_COMMENT>
  172. SPECIAL_TOKEN :
  173. {
  174. <FORMAL_COMMENT: "*/" > : DEFAULT
  175. }
  176. <IN_MULTI_LINE_COMMENT>
  177. SPECIAL_TOKEN :
  178. {
  179. <MULTI_LINE_COMMENT: "*/" > : DEFAULT
  180. }
  181. <IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
  182. MORE :
  183. {
  184. < ~[] >
  185. }
  186. /* RESERVED WORDS AND LITERALS */
  187. TOKEN :
  188. {
  189. < ABSTRACT: "abstract" >
  190. | < ASSERT: "assert" >
  191. | < BOOLEAN: "boolean" >
  192. | < BREAK: "break" >
  193. | < BYTE: "byte" >
  194. | < CASE: "case" >
  195. | < CATCH: "catch" >
  196. | < CHAR: "char" >
  197. | < CLASS: "class" >
  198. | < CONST: "const" >
  199. | < CONTINUE: "continue" >
  200. | < _DEFAULT: "default" >
  201. | < DO: "do" >
  202. | < DOUBLE: "double" >
  203. | < ELSE: "else" >
  204. | < ENUM: "enum" >
  205. | < EXTENDS: "extends" >
  206. | < FALSE: "false" >
  207. | < FINAL: "final" >
  208. | < FINALLY: "finally" >
  209. | < FLOAT: "float" >
  210. | < FOR: "for" >
  211. | < GOTO: "goto" >
  212. | < IF: "if" >
  213. | < IMPLEMENTS: "implements" >
  214. | < IMPORT: "import" >
  215. | < INSTANCEOF: "instanceof" >
  216. | < INT: "int" >
  217. | < INTERFACE: "interface" >
  218. | < LONG: "long" >
  219. | < NATIVE: "native" >
  220. | < NEW: "new" >
  221. | < NULL: "null" >
  222. | < PACKAGE: "package">
  223. | < PRIVATE: "private" >
  224. | < PROTECTED: "protected" >
  225. | < PUBLIC: "public" >
  226. | < RETURN: "return" >
  227. | < SHORT: "short" >
  228. | < STATIC: "static" >
  229. | < STRICTFP: "strictfp" >
  230. | < SUPER: "super" >
  231. | < SWITCH: "switch" >
  232. | < SYNCHRONIZED: "synchronized" >
  233. | < THIS: "this" >
  234. | < THROW: "throw" >
  235. | < THROWS: "throws" >
  236. | < TRANSIENT: "transient" >
  237. | < TRUE: "true" >
  238. | < TRY: "try" >
  239. | < VOID: "void" >
  240. | < VOLATILE: "volatile" >
  241. | < WHILE: "while" >
  242. }
  243. /* LITERALS */
  244. TOKEN :
  245. {
  246. < INTEGER_LITERAL:
  247. <DECIMAL_LITERAL> (["l","L"])?
  248. | <HEX_LITERAL> (["l","L"])?
  249. | <OCTAL_LITERAL> (["l","L"])?
  250. >
  251. |
  252. < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
  253. |
  254. < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
  255. |
  256. < #OCTAL_LITERAL: "0" (["0"-"7"])* >
  257. |
  258. < FLOATING_POINT_LITERAL:
  259. (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
  260. | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
  261. | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
  262. | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
  263. >
  264. |
  265. < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
  266. |
  267. < CHARACTER_LITERAL:
  268. "'"
  269. ( (~["'","\\","\n","\r"])
  270. | ("\\"
  271. ( ["n","t","b","r","f","\\","'","\""]
  272. | ["0"-"7"] ( ["0"-"7"] )?
  273. | ["0"-"3"] ["0"-"7"] ["0"-"7"]
  274. )
  275. )
  276. )
  277. "'"
  278. >
  279. |
  280. < STRING_LITERAL:
  281. "\""
  282. ( (~["\"","\\","\n","\r"])
  283. | ("\\"
  284. ( ["n","t","b","r","f","\\","'","\""]
  285. | ["0"-"7"] ( ["0"-"7"] )?
  286. | ["0"-"3"] ["0"-"7"] ["0"-"7"]
  287. )
  288. )
  289. )*
  290. "\""
  291. >
  292. }
  293. /* IDENTIFIERS */
  294. TOKEN :
  295. {
  296. < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
  297. |
  298. < #LETTER:
  299. [
  300. "\u0024",
  301. "\u0041"-"\u005a",
  302. "\u005f",
  303. "\u0061"-"\u007a",
  304. "\u00c0"-"\u00d6",
  305. "\u00d8"-"\u00f6",
  306. "\u00f8"-"\u00ff",
  307. "\u0100"-"\u1fff",
  308. "\u3040"-"\u318f",
  309. "\u3300"-"\u337f",
  310. "\u3400"-"\u3d2d",
  311. "\u4e00"-"\u9fff",
  312. "\uf900"-"\ufaff"
  313. ]
  314. >
  315. |
  316. < #DIGIT:
  317. [
  318. "\u0030"-"\u0039",
  319. "\u0660"-"\u0669",
  320. "\u06f0"-"\u06f9",
  321. "\u0966"-"\u096f",
  322. "\u09e6"-"\u09ef",
  323. "\u0a66"-"\u0a6f",
  324. "\u0ae6"-"\u0aef",
  325. "\u0b66"-"\u0b6f",
  326. "\u0be7"-"\u0bef",
  327. "\u0c66"-"\u0c6f",
  328. "\u0ce6"-"\u0cef",
  329. "\u0d66"-"\u0d6f",
  330. "\u0e50"-"\u0e59",
  331. "\u0ed0"-"\u0ed9",
  332. "\u1040"-"\u1049"
  333. ]
  334. >
  335. }
  336. /* SEPARATORS */
  337. TOKEN :
  338. {
  339. < LPAREN: "(" >
  340. | < RPAREN: ")" >
  341. | < LBRACE: "{" >
  342. | < RBRACE: "}" >
  343. | < LBRACKET: "[" >
  344. | < RBRACKET: "]" >
  345. | < SEMICOLON: ";" >
  346. | < COMMA: "," >
  347. | < DOT: "." >
  348. | < AT: "@" >
  349. }
  350. /* OPERATORS */
  351. TOKEN :
  352. {
  353. < ASSIGN: "=" >
  354. | < LT: "<" >
  355. | < BANG: "!" >
  356. | < TILDE: "~" >
  357. | < HOOK: "?" >
  358. | < COLON: ":" >
  359. | < EQ: "==" >
  360. | < LE: "<=" >
  361. | < GE: ">=" >
  362. | < NE: "!=" >
  363. | < SC_OR: "||" >
  364. | < SC_AND: "&&" >
  365. | < INCR: "++" >
  366. | < DECR: "--" >
  367. | < PLUS: "+" >
  368. | < MINUS: "-" >
  369. | < STAR: "*" >
  370. | < SLASH: "/" >
  371. | < BIT_AND: "&" >
  372. | < BIT_OR: "|" >
  373. | < XOR: "^" >
  374. | < REM: "%" >
  375. | < LSHIFT: "<<" >
  376. | < PLUSASSIGN: "+=" >
  377. | < MINUSASSIGN: "-=" >
  378. | < STARASSIGN: "*=" >
  379. | < SLASHASSIGN: "/=" >
  380. | < ANDASSIGN: "&=" >
  381. | < ORASSIGN: "|=" >
  382. | < XORASSIGN: "^=" >
  383. | < REMASSIGN: "%=" >
  384. | < LSHIFTASSIGN: "<<=" >
  385. | < RSIGNEDSHIFTASSIGN: ">>=" >
  386. | < RUNSIGNEDSHIFTASSIGN: ">>>=" >
  387. | < ELLIPSIS: "..." >
  388. }
  389. /* >'s need special attention due to generics syntax. */
  390. TOKEN :
  391. {
  392. < RUNSIGNEDSHIFT: ">>>" >
  393. {
  394. matchedToken.kind = GT;
  395. ((Token.GTToken)matchedToken).realKind = RUNSIGNEDSHIFT;
  396. input_stream.backup(2);
  397. }
  398. | < RSIGNEDSHIFT: ">>" >
  399. {
  400. matchedToken.kind = GT;
  401. ((Token.GTToken)matchedToken).realKind = RSIGNEDSHIFT;
  402. input_stream.backup(1);
  403. }
  404. | < GT: ">" >
  405. }
  406. /*****************************************
  407. * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
  408. *****************************************/
  409. /*
  410. * Program structuring syntax follows.
  411. */
  412. /**
  413. * Main entry point for parsing.
  414. * @return a CUNode, which is parent or root node of all other nodes.
  415. */
  416. CUNode CompilationUnit(int tab_size):
  417. {
  418. setTabSize(tab_size);
  419. CUNode n = new CUNode();
  420. TigerNode a;
  421. String packageName = "";
  422. ImportNode in = null;
  423. Token end_t = null;
  424. }
  425. {
  426. try {
  427. (
  428. // don't care about package or imports for JBrowse, but I do for JavaSideKick...
  429. [ packageName=PackageDeclaration() ]
  430. ( in=ImportDeclaration() { n.addImport(in); } )*
  431. // do care about TypeDeclaration, this will be one or more classes or
  432. // interfaces, add these as child nodes of the root node
  433. (
  434. a=TypeDeclaration()
  435. { n.addChild(a); }
  436. )*
  437. // read the whole file
  438. end_t=<EOF>
  439. )
  440. }
  441. catch(ParseException pe) {
  442. error_skipto(SEMICOLON);
  443. }
  444. {
  445. try {
  446. if (inputStream != null)
  447. inputStream.close();
  448. }
  449. catch(Exception e) {
  450. // not to worry
  451. }
  452. n.setPackageName(packageName);
  453. if (end_t != null) {
  454. n.setEndLocation(getLocation(end_t));
  455. }
  456. return n;
  457. }
  458. }
  459. String PackageDeclaration():
  460. {
  461. TigerNode name = null;
  462. }
  463. {
  464. try {
  465. "package" name=Name() ";"
  466. }
  467. catch(ParseException pe) {
  468. error_skipto(SEMICOLON);
  469. }
  470. {
  471. return name == null ? "" : name.getName();
  472. }
  473. }
  474. /**
  475. * @return just the package name, without the 'import' or 'static' or '.*', e.g.
  476. * "import java.util.*;" will return "java.util". A fully qualified import will
  477. * return the full classname, e.g. "import java.util.List;" will return
  478. * "java.util.List", this is also the case with static imports, e.g.
  479. * "import static java.lang.Math.PI;" will return "java.lang.Math.PI".
  480. */
  481. ImportNode ImportDeclaration():
  482. {
  483. TigerNode name = null;
  484. }
  485. {
  486. try {
  487. "import" [ "static" ] name=Name() [ "." "*" ] ";"
  488. }
  489. catch(ParseException pe) {
  490. error_skipto(SEMICOLON);
  491. }
  492. {
  493. if (name != null) {
  494. ImportNode in = new ImportNode(name.getName());
  495. in.setStartLocation(name.getStartLocation());
  496. in.setEndLocation(name.getEndLocation());
  497. return in;
  498. }
  499. return null;
  500. }
  501. }
  502. /*
  503. * Modifiers. We match all modifiers in a single rule to reduce the chances of
  504. * syntax errors for simple modifier mistakes. It will also enable us to give
  505. * better error messages.
  506. */
  507. Modifier Modifiers():
  508. {
  509. int modifiers = 0;
  510. Token t = null;
  511. Modifier m = new Modifier();
  512. }
  513. {
  514. (
  515. LOOKAHEAD(2)
  516. (
  517. t="public" { modifiers |= ModifierSet.PUBLIC; adjustModifier(m, t);}
  518. |
  519. t="static" { modifiers |= ModifierSet.STATIC; adjustModifier(m, t);}
  520. |
  521. t="protected" { modifiers |= ModifierSet.PROTECTED; adjustModifier(m, t);}
  522. |
  523. t="private" { modifiers |= ModifierSet.PRIVATE; adjustModifier(m, t);}
  524. |
  525. t="final" { modifiers |= ModifierSet.FINAL; adjustModifier(m, t);}
  526. |
  527. t="abstract" { modifiers |= ModifierSet.ABSTRACT; adjustModifier(m, t);}
  528. |
  529. t="synchronized" { modifiers |= ModifierSet.SYNCHRONIZED; adjustModifier(m, t);}
  530. |
  531. t="native" { modifiers |= ModifierSet.NATIVE; adjustModifier(m, t);}
  532. |
  533. t="transient" { modifiers |= ModifierSet.TRANSIENT; adjustModifier(m, t);}
  534. |
  535. t="volatile" { modifiers |= ModifierSet.VOLATILE; adjustModifier(m, t);}
  536. |
  537. t="strictfp" { modifiers |= ModifierSet.STRICTFP; adjustModifier(m, t);}
  538. |
  539. Annotation()
  540. )
  541. )*
  542. {
  543. m.modifiers = modifiers;
  544. return m;
  545. }
  546. }
  547. /*
  548. * Declaration syntax follows.
  549. */
  550. // Handle classes, interfaces, enums, and annotations.
  551. TigerNode TypeDeclaration():
  552. {
  553. Modifier modifier;
  554. TigerNode tn = null;
  555. }
  556. {
  557. try {
  558. ";" /// is this the semi-colon that I need to handle at the end of a class??
  559. |
  560. modifier = Modifiers()
  561. (
  562. tn=ClassOrInterfaceDeclaration(modifier)
  563. |
  564. tn=EnumDeclaration(modifier)
  565. |
  566. AnnotationTypeDeclaration(modifier) { tn = null; }
  567. )
  568. }
  569. catch(ParseException pe) {
  570. error_skipto(SEMICOLON);
  571. }
  572. {
  573. return tn;
  574. }
  575. }
  576. /**
  577. * @return a ClassNode or an InterfaceNode
  578. */
  579. TigerNode ClassOrInterfaceDeclaration(Modifier m):
  580. {
  581. boolean isInterface = false;
  582. Token t = null;
  583. TigerNode kids = null; // only need the children of this node
  584. String type_params = "";
  585. List extends_list = null;
  586. List implements_list = null;
  587. Token type = null;
  588. }
  589. {
  590. try {
  591. ( type="class" | type="interface" { isInterface = true; } )
  592. t=<IDENTIFIER>
  593. [ type_params = TypeParameters() ]
  594. [ extends_list=ExtendsList(isInterface) ]
  595. [ implements_list=ImplementsList(isInterface) ]
  596. kids=ClassOrInterfaceBody(isInterface)
  597. /* danson, added this check for trailing semi-colon. Apparently, this has been
  598. legal since the beginning of Java, some sort of a C hold-over. Sun's latest
  599. Java 1.5 compiler doesn't mind it, but this parser whined if the class has a
  600. semi-colon after the last }. The original Java1.5.jj file that this parser
  601. is based on does NOT whine, so I've done something to change the base behaviour.
  602. See below, I probably broke this in ClassOrInterfaceBody. */
  603. [ LOOKAHEAD(2) <SEMICOLON> ]
  604. }
  605. catch(ParseException pe) {
  606. error_skipto(SEMICOLON);
  607. }
  608. {
  609. ClassNode node = isInterface ? new InterfaceNode(t.image, m.modifiers) : new ClassNode(t.image, m.modifiers);
  610. if (isInterface)
  611. results.incInterfaceCount();
  612. else
  613. results.incClassCount();
  614. if (m.beginColumn > -1) {
  615. node.setStartLocation(getLocation(m) );
  616. }
  617. else {
  618. node.setStartLocation(getLocation(type));
  619. }
  620. if (kids != null)
  621. node.setEndLocation(kids.getEndLocation());
  622. // add the child nodes, don't need the 'kids' node itself, it's just a holder
  623. // for the nodes I want (although I do want the end location).
  624. if (kids != null && kids.getChildren() != null)
  625. node.addChildren(kids.getChildren());
  626. node.setTypeParams(type_params);
  627. node.setExtendsList(extends_list);
  628. node.setImplementsList(implements_list);
  629. return node;
  630. }
  631. }
  632. /**
  633. * @return a list of sidekick.java.node.Types representing items in an 'extends'
  634. * list, e.g. the "Bar" in "public class Foo extends Bar"
  635. */
  636. List ExtendsList(boolean isInterface):
  637. {
  638. boolean extendsMoreThanOne = false;
  639. List list = new ArrayList(); // a list of Types
  640. Type type_s = null;
  641. Type type_a = null;
  642. }
  643. {
  644. try {
  645. "extends" type_s=ClassOrInterfaceType() { list.add(type_s); }
  646. ( "," type_a=ClassOrInterfaceType() { extendsMoreThanOne = true; list.add(type_a); } )*
  647. }
  648. catch(ParseException pe) {
  649. error_skipto(SEMICOLON);
  650. }
  651. {
  652. if (extendsMoreThanOne && !isInterface)
  653. throw new ParseException("A class cannot extend more than one other class");
  654. return list;
  655. }
  656. }
  657. /**
  658. * @return a list of sidekick.java.node.Types representing items in an 'implements'
  659. * list, e.g. the "Bar" and "Serializable" in "public class Foo implements Bar, Serializable"
  660. */
  661. List ImplementsList(boolean isInterface):
  662. {
  663. List list = new ArrayList();
  664. Type type_s = null;
  665. Type type_a = null;
  666. }
  667. {
  668. try {
  669. "implements" type_s=ClassOrInterfaceType() { list.add(type_s); }
  670. ( "," type_a=ClassOrInterfaceType() { list.add(type_a); } )*
  671. }
  672. catch(ParseException pe) {
  673. error_skipto(SEMICOLON);
  674. }
  675. {
  676. if (isInterface)
  677. throw new ParseException("An interface cannot implement other interfaces");
  678. return list;
  679. }
  680. }
  681. /**
  682. * @return an EnumNode
  683. */
  684. TigerNode EnumDeclaration(Modifier m):
  685. {
  686. Token t = null;
  687. Token start_t = null;
  688. Location end_loc = null;
  689. }
  690. {
  691. try {
  692. start_t="enum" t=<IDENTIFIER>
  693. [ ImplementsList(false) ]
  694. end_loc=EnumBody()
  695. }
  696. catch(ParseException pe) {
  697. if (t == null) {
  698. // handle the case where old code used 'enum' as a variable name
  699. ParseException e = new ParseException("Parse error at line " + start_t.beginLine + ", column " + start_t.beginColumn + ". Encountered: 'enum' as an identifier, 'enum' is a keyword.");
  700. addException(e);
  701. return null;
  702. }
  703. else
  704. error_skipto(SEMICOLON);
  705. }
  706. {
  707. if (t == null) {
  708. // handle the case where old code used 'enum' as a variable name
  709. ParseException e = new ParseException("Parse error at line " + start_t.beginLine + ", column " + start_t.beginColumn + ". Encountered: 'enum' as an identifier, 'enum' is a keyword.");
  710. addException(e);
  711. return null;
  712. }
  713. EnumNode node = new EnumNode(t.image, m.modifiers);
  714. if (start_t != null) {
  715. if (m.beginColumn == -1)
  716. node.setStartLocation(getLocation(start_t));
  717. else
  718. node.setStartLocation(getLocation(m));
  719. }
  720. if (end_loc != null)
  721. node.setEndLocation(end_loc);
  722. return node;
  723. }
  724. }
  725. // returns the end location of the enum body
  726. Location EnumBody():
  727. {
  728. Token t = null;
  729. }
  730. {
  731. try {
  732. "{"
  733. EnumConstant() ( "," EnumConstant() )*
  734. [ ";" ( ClassOrInterfaceBodyDeclaration(false) )* ]
  735. t="}"
  736. }
  737. catch(ParseException pe) {
  738. error_skipto(SEMICOLON);
  739. }
  740. {
  741. return t == null ? null : getLocation(t);
  742. }
  743. }
  744. /// what is this? Should I be handling it?
  745. void EnumConstant():
  746. {}
  747. {
  748. try {
  749. <IDENTIFIER> [ Arguments() ] [ ClassOrInterfaceBody(false) ]
  750. }
  751. catch(ParseException pe) {
  752. error_skipto(SEMICOLON);
  753. }
  754. }
  755. /**
  756. * @return a string representing a generics type, e.g. the "<String>" in
  757. * "List<String> list = new List();", the string will contain the angle brackets.
  758. */
  759. String TypeParameters():
  760. {
  761. String s = "<";
  762. String a = "";
  763. }
  764. {
  765. try {
  766. (
  767. "<"
  768. a=TypeParameter()
  769. { s += a; }
  770. (
  771. ","
  772. { s += ","; }
  773. a=TypeParameter()
  774. { s += a; }
  775. )*
  776. ">"
  777. )
  778. }
  779. catch(ParseException pe) {
  780. error_skipto(SEMICOLON);
  781. }
  782. {
  783. return s + ">";
  784. }
  785. }
  786. String TypeParameter():
  787. {
  788. String s = "";
  789. Token t = null;
  790. }
  791. {
  792. try {
  793. (
  794. t=<IDENTIFIER> [ s=TypeBound() ]
  795. )
  796. }
  797. catch(ParseException pe) {
  798. error_skipto(SEMICOLON);
  799. }
  800. {
  801. StringBuffer sb = new StringBuffer();
  802. if (t.image != null)
  803. sb.append(t.image);
  804. if (s.length() > 0)
  805. sb.append(" ").append(s);
  806. return sb.toString();
  807. }
  808. }
  809. String TypeBound():
  810. {
  811. String s = "extends";
  812. Type type_s = null;
  813. Type type_a = null;
  814. }
  815. {
  816. try {
  817. (
  818. "extends"
  819. type_a=ClassOrInterfaceType()
  820. { s += " " + type_a.toString(); }
  821. (
  822. "&"
  823. { s += " & "; }
  824. type_a=ClassOrInterfaceType()
  825. { s += type_a.toString(); }
  826. )*
  827. )
  828. }
  829. catch(ParseException pe) {
  830. error_skipto(SEMICOLON);
  831. }
  832. {
  833. return s;
  834. }
  835. }
  836. /**
  837. * @return a node representing the contents of a Class or Interface body. The
  838. * returned node is simply a holder for the contents, it is the children of this
  839. * node that is useful as they are the methods and fields of the class or
  840. * interface.
  841. */
  842. TigerNode ClassOrInterfaceBody(boolean isInterface):
  843. {
  844. TigerNode parent = new TigerNode("", -1);
  845. TigerNode child;
  846. Token start_t = null;
  847. Token end_t = null;
  848. }
  849. {
  850. try {
  851. (
  852. start_t="{"
  853. (
  854. child=ClassOrInterfaceBodyDeclaration(isInterface)
  855. { if (child != null) parent.addChild(child); }
  856. )*
  857. end_t="}"
  858. )
  859. }
  860. catch(ParseException pe) {
  861. error_skipto(SEMICOLON);
  862. }
  863. {
  864. if (start_t != null)
  865. parent.setStartLocation(getLocation(start_t));
  866. if (end_t != null)
  867. parent.setEndLocation(getLocation(end_t));
  868. return parent.getChildren() != null ? parent : null;
  869. }
  870. }
  871. /**
  872. * @return one of several different nodes, could be a ClassNode, EnumNode,
  873. * ConstructorNode, FieldNode, MethodNode, or an InterfaceNode.
  874. */
  875. TigerNode ClassOrInterfaceBodyDeclaration(boolean isInterface):
  876. {
  877. // see note above (~ line 510), I think my changes here have broken the test for a
  878. // trailing ; after a class body.
  879. boolean isNestedInterface = false;
  880. Modifier m;
  881. TigerNode a = null;
  882. TigerNode initializer = null;
  883. String type_params = null;
  884. }
  885. {
  886. try {
  887. (
  888. LOOKAHEAD(2)
  889. initializer=Initializer()
  890. {
  891. if (isInterface)
  892. throw new ParseException("An interface cannot have initializers");
  893. if (initializer != null)
  894. return initializer;
  895. }
  896. |
  897. m = Modifiers() // Just get all the modifiers out of the way. If you want to do
  898. // more checks, pass the modifiers down to the member
  899. (
  900. a=ClassOrInterfaceDeclaration(m)
  901. |
  902. a=EnumDeclaration(m)
  903. |
  904. LOOKAHEAD( [ type_params=TypeParameters() ] <IDENTIFIER> "(" )
  905. a=ConstructorDeclaration()
  906. {
  907. ((ConstructorNode)a).setModifiers(m.modifiers);
  908. ((ConstructorNode)a).setTypeParams(type_params);
  909. ((ConstructorNode)a).setStartLocation(getLocation(m));
  910. }
  911. |
  912. LOOKAHEAD( Type() <IDENTIFIER> ( "[" "]" )* ( "," | "=" | ";" ) )
  913. a=FieldDeclaration(m)
  914. |
  915. a=MethodDeclaration(m)
  916. )
  917. |
  918. ";" /// is this the trailing semi-colon??
  919. )
  920. }
  921. catch(ParseException pe) {
  922. error_skipto(SEMICOLON);
  923. }
  924. {
  925. return a;
  926. }
  927. }
  928. /**
  929. * @return a FieldNode
  930. */
  931. TigerNode FieldDeclaration(Modifier m):
  932. {
  933. Type type = null;
  934. TigerNode name = null;
  935. TigerNode a;
  936. Token t = null;
  937. }
  938. {
  939. try {
  940. (
  941. // Modifiers are already matched in the caller
  942. /// might need to change this, I'm collecting multiple declarations into a single
  943. /// field, which seems to be okay, e.g. I'm putting "int x = 0, y = 6" into a
  944. /// field with Type "int" and name "x, y". It might be better to create individual
  945. /// nodes for each, so for this example, this method could return 2 fields, one
  946. /// for "int x" and one for "int y".
  947. type=Type() name=VariableDeclarator() ( "," a=VariableDeclarator() { name.setName(name.getName() + ", " + a.getName()); })* t=";"
  948. )
  949. }
  950. catch(ParseException pe) {
  951. error_skipto(SEMICOLON);
  952. }
  953. {
  954. FieldNode fn = new FieldNode(name.getName(), m.modifiers, type);
  955. if (fn.isPrimitive())
  956. results.incPrimitiveFieldCount();
  957. else
  958. results.incReferenceFieldCount();
  959. if (m.beginColumn == -1)
  960. fn.setStartLocation(type.getStartLocation());
  961. else
  962. fn.setStartLocation(getLocation(m)); //type.getStartLocation());
  963. fn.setEndLocation(getLocation(t));
  964. return fn;
  965. }
  966. }
  967. TigerNode VariableDeclarator():
  968. {
  969. TigerNode s = null;
  970. }
  971. {
  972. try {
  973. (
  974. s=VariableDeclaratorId() [ "=" VariableInitializer() ]
  975. )
  976. }
  977. catch(ParseException pe) {
  978. error_skipto(SEMICOLON);
  979. }
  980. {
  981. return s;
  982. }
  983. }
  984. TigerNode VariableDeclaratorId():
  985. {
  986. Token t = null;
  987. }
  988. {
  989. try {
  990. t=<IDENTIFIER> ( "[" "]" )*
  991. }
  992. catch(ParseException pe) {
  993. error_skipto(SEMICOLON);
  994. }
  995. {
  996. TigerNode tn = new TigerNode(t.image, 0);
  997. tn.setStartLocation(new Location(t.beginLine, t.beginColumn));
  998. tn.setEndLocation(new Location(t.beginLine, t.beginColumn + t.image.length()));
  999. return tn;
  1000. }
  1001. }
  1002. void VariableInitializer():
  1003. {}
  1004. {
  1005. try {
  1006. ArrayInitializer()
  1007. |
  1008. Expression()
  1009. }
  1010. catch(ParseException pe) {
  1011. error_skipto(SEMICOLON);
  1012. }
  1013. }
  1014. void ArrayInitializer():
  1015. {}
  1016. {
  1017. try {
  1018. "{" [ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"
  1019. }
  1020. catch(ParseException pe) {
  1021. error_skipto(SEMICOLON);
  1022. }
  1023. }
  1024. /**
  1025. * @return a MethodNode
  1026. */
  1027. TigerNode MethodDeclaration(Modifier m):
  1028. {
  1029. String type_params = "";
  1030. String return_type = "";
  1031. MethodNode m_node = null;
  1032. List name_list = null;
  1033. int line_number = -1;
  1034. BlockNode block = null;
  1035. Location endLoc = null;
  1036. Token t = null;
  1037. }
  1038. {
  1039. try {
  1040. (
  1041. // Modifiers already matched in the caller!
  1042. [ type_params = TypeParameters() ]
  1043. return_type = ResultType()
  1044. m_node = MethodDeclarator() [ "throws" name_list=NameList() ]
  1045. ( block = Block() | t=";" )
  1046. )
  1047. }
  1048. catch(ParseException pe) {
  1049. error_skipto(SEMICOLON);
  1050. }
  1051. {
  1052. if (m_node == null)
  1053. return null;
  1054. MethodNode node = new MethodNode();
  1055. node.setName(m_node.getName());
  1056. if (m.beginColumn == -1)
  1057. node.setStartLocation(new Location(m_node.getStartLocation().line, 0));
  1058. else
  1059. node.setStartLocation(getLocation(m));
  1060. node.setModifiers(m.modifiers);
  1061. node.setFormalParams(m_node.getFormalParams());
  1062. node.setReturnType(return_type);
  1063. node.setTypeParams(type_params);
  1064. node.setThrows(name_list);
  1065. if (block == null && t != null) {
  1066. node.setEndLocation(getLocation(t));
  1067. }
  1068. else {
  1069. node.addChildren(block.getChildren());
  1070. node.setEndLocation(block.getEndLocation());
  1071. }
  1072. results.incMethodCount();
  1073. return node;
  1074. }
  1075. }
  1076. MethodNode MethodDeclarator():
  1077. {
  1078. Token t = null;
  1079. String s = "";
  1080. List f = null;
  1081. }
  1082. {
  1083. try {
  1084. (
  1085. t=<IDENTIFIER> f=FormalParameters() ( "[" "]" )*
  1086. )
  1087. }
  1088. catch(ParseException pe) {
  1089. error_skipto(SEMICOLON);
  1090. }
  1091. {
  1092. if (t == null)
  1093. return null;
  1094. MethodNode node = new MethodNode();
  1095. node.setName(t.image);
  1096. node.setStartLocation(getLocation(t));
  1097. node.setFormalParams(f);
  1098. return node;
  1099. }
  1100. }
  1101. List FormalParameters():
  1102. {
  1103. ArrayList params = new ArrayList();
  1104. Parameter a = null;
  1105. }
  1106. {
  1107. try {
  1108. (
  1109. "("
  1110. [
  1111. a=FormalParameter()
  1112. { params.add(a); }
  1113. (
  1114. ","
  1115. a=FormalParameter()
  1116. { params.add(a); }
  1117. )*
  1118. ]
  1119. ")"
  1120. )
  1121. }
  1122. catch(ParseException pe) {
  1123. error_skipto(SEMICOLON);
  1124. }
  1125. {
  1126. return params;
  1127. }
  1128. }
  1129. Parameter FormalParameter():
  1130. {
  1131. Parameter param = new Parameter();
  1132. TigerNode n;
  1133. Type type_a = null;
  1134. Token t = null;
  1135. }
  1136. {
  1137. try {
  1138. (
  1139. [
  1140. t="final"
  1141. {
  1142. param.setFinal(true);
  1143. param.setStartLocation(getLocation(t));
  1144. }
  1145. ]
  1146. type_a=Type()
  1147. { param.setType(type_a); }
  1148. [
  1149. "..."
  1150. { param.setVarArg(true); }
  1151. ]
  1152. n=VariableDeclaratorId()
  1153. {
  1154. param.setName(n.getName());
  1155. if (t == null)
  1156. param.setStartLocation(n.getStartLocation());
  1157. param.setEndLocation(n.getEndLocation());
  1158. }
  1159. )
  1160. }
  1161. catch(ParseException pe) {
  1162. error_skipto(SEMICOLON);
  1163. }
  1164. {
  1165. return param;
  1166. }
  1167. }
  1168. ConstructorNode ConstructorDeclaration():
  1169. {
  1170. Token t = null;
  1171. List params = null;
  1172. List name_list = null;
  1173. String type_params = null;
  1174. Token end_t = null;
  1175. TigerNode child = null;
  1176. ConstructorNode cn = new ConstructorNode();
  1177. }
  1178. {
  1179. try {
  1180. (
  1181. [ type_params=TypeParameters() ]
  1182. // Modifiers matched in the caller
  1183. t=<IDENTIFIER> params=FormalParameters() [ "throws" name_list=NameList() ]
  1184. "{"
  1185. [ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ]
  1186. ( child=BlockStatement() { if (child != null) cn.addChildren(child.getChildren()); })*
  1187. end_t="}"
  1188. )
  1189. }
  1190. catch(ParseException pe) {
  1191. error_skipto(SEMICOLON);
  1192. }
  1193. {
  1194. cn.setName(t.image);
  1195. //cn.setStartLocation(new Location(t.beginLine, 0)); // start location set in calling method
  1196. cn.setEndLocation(getLocation(end_t));
  1197. cn.setFormalParams(params);
  1198. cn.setTypeParams(type_params);
  1199. cn.setThrows(name_list);
  1200. return cn;
  1201. }
  1202. }
  1203. void ExplicitConstructorInvocation():
  1204. {}
  1205. {
  1206. try {
  1207. LOOKAHEAD("this" Arguments() ";")
  1208. "this" Arguments() ";"
  1209. |
  1210. [ LOOKAHEAD(2) PrimaryExpression() "." ] "super" Arguments() ";"
  1211. }
  1212. catch(ParseException pe) {
  1213. error_skipto(SEMICOLON);
  1214. }
  1215. }
  1216. /**
  1217. * @return an InitializerNode, this handles static initializer blocks
  1218. */
  1219. TigerNode Initializer():
  1220. {
  1221. Token t = null;
  1222. BlockNode block = null;
  1223. }
  1224. {
  1225. try {
  1226. [ t="static" ] block=Block()
  1227. }
  1228. catch(ParseException pe) {
  1229. error_skipto(SEMICOLON);
  1230. }
  1231. {
  1232. if (t != null && block != null) {
  1233. TigerNode node = new InitializerNode(t.beginLine);
  1234. node.setStartLocation(block.getStartLocation());
  1235. node.setEndLocation(block.getEndLocation());
  1236. node.addChild(block);
  1237. return node;
  1238. }
  1239. return null;
  1240. }
  1241. }
  1242. /*
  1243. * Type, name and expression syntax follows.
  1244. */
  1245. Type Type():
  1246. {
  1247. Type s = null;
  1248. }
  1249. {
  1250. try {
  1251. (
  1252. LOOKAHEAD(2) s=ReferenceType()
  1253. |
  1254. s=PrimitiveType()
  1255. )
  1256. }
  1257. catch(ParseException pe) {
  1258. error_skipto(SEMICOLON);
  1259. }
  1260. {
  1261. return s;
  1262. }
  1263. }
  1264. Type ReferenceType():
  1265. {
  1266. Type s = null;
  1267. }
  1268. {
  1269. try {
  1270. (
  1271. s=PrimitiveType() ( LOOKAHEAD(2) "[" "]" )+
  1272. |
  1273. ( s=ClassOrInterfaceType() ) ( LOOKAHEAD(2) "[" "]" )*
  1274. )
  1275. }
  1276. catch(ParseException pe) {
  1277. error_skipto(SEMICOLON);
  1278. }
  1279. {
  1280. return s;
  1281. }
  1282. }
  1283. Type ClassOrInterfaceType():
  1284. {
  1285. Type s = new Type();
  1286. String type_arg = "";
  1287. Token t = null;
  1288. }
  1289. {
  1290. try {
  1291. (
  1292. t=<IDENTIFIER> [ LOOKAHEAD(2) type_arg=TypeArguments() ]
  1293. {
  1294. s.type = t.image;
  1295. s.typeArgs=type_arg;
  1296. s.setStartLocation(new Location(t.beginLine, t.beginColumn));
  1297. s.setEndLocation(new Location(t.endLine, t.endColumn));
  1298. }
  1299. ( LOOKAHEAD(2) "." t=<IDENTIFIER> [ LOOKAHEAD(2) type_arg=TypeArguments() ]
  1300. {
  1301. s.type += "." + t.image;
  1302. s.typeArgs += type_arg;
  1303. s.setEndLocation(new Location(t.endLine, t.endColumn));
  1304. }
  1305. )*
  1306. )
  1307. }
  1308. catch(ParseException pe) {
  1309. error_skipto(SEMICOLON);
  1310. }
  1311. {
  1312. return s;
  1313. }
  1314. }
  1315. String TypeArguments():
  1316. {
  1317. String s = "<";
  1318. String a = "";
  1319. }
  1320. {
  1321. try {
  1322. (
  1323. "<" a=TypeArgument() { s += a; }
  1324. ( "," a=TypeArgument() { s += "," + a; } )* ">"
  1325. )
  1326. }
  1327. catch(ParseException pe) {
  1328. error_skipto(SEMICOLON);
  1329. }
  1330. {
  1331. return s + ">";
  1332. }
  1333. }
  1334. String TypeArgument():
  1335. {
  1336. Type type = null;
  1337. String s = "";
  1338. String a = "";
  1339. }
  1340. {
  1341. try {
  1342. (
  1343. type=ReferenceType() { s=type.toString(); }
  1344. |
  1345. "?" [ a=WildcardBounds() { s = "?" + a; } ]
  1346. )
  1347. }
  1348. catch(ParseException pe) {
  1349. error_skipto(SEMICOLON);
  1350. }
  1351. {
  1352. return s;
  1353. }
  1354. }
  1355. String WildcardBounds():
  1356. {
  1357. Type type = null;
  1358. String s = "";
  1359. }
  1360. {
  1361. try {
  1362. (
  1363. "extends" type=ReferenceType() { s="extends " + type.toString(); }
  1364. |
  1365. "super" type=ReferenceType() { s="super " + type.toString(); }
  1366. )
  1367. }
  1368. catch(ParseException pe) {
  1369. error_skipto(SEMICOLON);
  1370. }
  1371. {
  1372. return s;
  1373. }
  1374. }
  1375. Type PrimitiveType():
  1376. {
  1377. Token t = null;
  1378. Type s = new Type();
  1379. }
  1380. {
  1381. try {
  1382. (
  1383. t="boolean" { s.type = "boolean"; }
  1384. |
  1385. t="char" { s.type = "char"; }
  1386. |
  1387. t="byte" { s.type = "byte"; }
  1388. |
  1389. t="short" { s.type = "short"; }
  1390. |
  1391. t="int" { s.type = "int"; }
  1392. |
  1393. t="long" { s.type = "long"; }
  1394. |
  1395. t="float" { s.type = "float"; }
  1396. |
  1397. t="double" { s.type = "double"; }
  1398. )
  1399. }
  1400. catch(ParseException pe) {
  1401. error_skipto(SEMICOLON);
  1402. }
  1403. {
  1404. if (t != null) {
  1405. s.setStartLocation(new Location(t.beginLine, t.beginColumn));
  1406. s.setEndLocation(new Location(t.endLine, t.endColumn));
  1407. }
  1408. s.isPrimitive = true;
  1409. return s;
  1410. }
  1411. }
  1412. String ResultType():
  1413. {
  1414. Token t;
  1415. Type s = new Type();
  1416. }
  1417. {
  1418. try {
  1419. (
  1420. t="void"
  1421. {
  1422. s.type = "void";
  1423. s.setStartLocation(new Location(t.beginLine, t.beginColumn));
  1424. s.setEndLocation(new Location(t.endLine, t.endColumn));
  1425. }
  1426. |
  1427. s = Type()
  1428. )
  1429. }
  1430. catch(ParseException pe) {
  1431. error_skipto(SEMICOLON);
  1432. }
  1433. {
  1434. return s.toString();
  1435. }
  1436. }
  1437. TigerNode Name():
  1438. /*
  1439. * A lookahead of 2 is required below since "Name" can be followed
  1440. * by a ".*" when used in the context of an "ImportDeclaration".
  1441. */
  1442. {
  1443. Token t = null;
  1444. String s = "";
  1445. TigerNode tn = new TigerNode();
  1446. Location startLocation = null;
  1447. Location endLocation = null;
  1448. }
  1449. {
  1450. try {
  1451. t=<IDENTIFIER> { s = t.image; startLocation = getLocation(t); endLocation = getEndLocation(t); }
  1452. ( LOOKAHEAD(2) "." t=<IDENTIFIER> { s += "." + t.image; endLocation = getEndLocation(t); }
  1453. )*
  1454. }
  1455. catch(ParseException pe) {
  1456. error_skipto(SEMICOLON);
  1457. }
  1458. {
  1459. tn.setName(s);
  1460. tn.setStartLocation(startLocation);
  1461. tn.setEndLocation(endLocation);
  1462. return tn;
  1463. }
  1464. }
  1465. List NameList():
  1466. {
  1467. List nameList = new ArrayList();
  1468. String s = "";
  1469. String a = "";
  1470. TigerNode tn;
  1471. }
  1472. {
  1473. try {
  1474. tn=Name() { nameList.add(tn); }
  1475. ( "," tn=Name() { nameList.add(tn); } )*
  1476. }
  1477. catch(ParseException pe) {
  1478. error_skipto(SEMICOLON);
  1479. }
  1480. {
  1481. return nameList;
  1482. }
  1483. }
  1484. /*
  1485. * Expression syntax follows.
  1486. */
  1487. void Expression():
  1488. /*
  1489. * This expansion has been written this way instead of:
  1490. * Assignment() | ConditionalExpression()
  1491. * for performance reasons.
  1492. * However, it is a weakening of the grammar for it allows the LHS of
  1493. * assignments to be any conditional expression whereas it can only be
  1494. * a primary expression. Consider adding a semantic predicate to work
  1495. * around this.
  1496. */
  1497. {}
  1498. {
  1499. try {
  1500. ConditionalExpression()
  1501. [
  1502. LOOKAHEAD(2)
  1503. AssignmentOperator() Expression()
  1504. ]
  1505. }
  1506. catch(ParseException pe) {
  1507. error_skipto(SEMICOLON);
  1508. }
  1509. }
  1510. void AssignmentOperator():
  1511. {}
  1512. {
  1513. "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|="
  1514. }
  1515. void ConditionalExpression():
  1516. {}
  1517. {
  1518. try {
  1519. ConditionalOrExpression() [ "?" Expression() ":" Expression() ]
  1520. }
  1521. catch(ParseException pe) {
  1522. error_skipto(SEMICOLON);
  1523. }
  1524. }
  1525. void ConditionalOrExpression():
  1526. {}
  1527. {
  1528. try {
  1529. ConditionalAndExpression() ( "||" ConditionalAndExpression() )*
  1530. }
  1531. catch(ParseException pe) {
  1532. error_skipto(SEMICOLON);
  1533. }
  1534. }
  1535. void ConditionalAndExpression():
  1536. {}
  1537. {
  1538. try {
  1539. InclusiveOrExpression() ( "&&" InclusiveOrExpression() )*
  1540. }
  1541. catch(ParseException pe) {
  1542. error_skipto(SEMICOLON);
  1543. }
  1544. }
  1545. void InclusiveOrExpression():
  1546. {}
  1547. {
  1548. try {
  1549. ExclusiveOrExpression() ( "|" ExclusiveOrExpression() )*
  1550. }
  1551. catch(ParseException pe) {
  1552. error_skipto(SEMICOLON);
  1553. }
  1554. }
  1555. void ExclusiveOrExpression():
  1556. {}
  1557. {
  1558. try {
  1559. AndExpression() ( "^" AndExpression() )*
  1560. }
  1561. catch(ParseException pe) {
  1562. error_skipto(SEMICOLON);
  1563. }
  1564. }
  1565. void AndExpression():
  1566. {}
  1567. {
  1568. try {
  1569. EqualityExpression() ( "&" EqualityExpression() )*
  1570. }
  1571. catch(ParseException pe) {
  1572. error_skipto(SEMICOLON);
  1573. }
  1574. }
  1575. void EqualityExpression():
  1576. {}
  1577. {
  1578. try {
  1579. InstanceOfExpression() ( ( "==" | "!=" ) InstanceOfExpression() )*
  1580. }
  1581. catch(ParseException pe) {
  1582. error_skipto(SEMICOLON);
  1583. }
  1584. }
  1585. void InstanceOfExpression():
  1586. {}
  1587. {
  1588. try {
  1589. RelationalExpression() [ "instanceof" Type() ]
  1590. }
  1591. catch(ParseException pe) {
  1592. error_skipto(SEMICOLON);
  1593. }
  1594. }
  1595. void RelationalExpression():
  1596. {}
  1597. {
  1598. try {
  1599. ShiftExpression() ( ( "<" | ">" | "<=" | ">=" ) ShiftExpression() )*
  1600. }
  1601. catch(ParseException pe) {
  1602. error_skipto(SEMICOLON);
  1603. }
  1604. }
  1605. void ShiftExpression():
  1606. {}
  1607. {
  1608. try {
  1609. AdditiveExpression() ( ( "<<" | RSIGNEDSHIFT() | RUNSIGNEDSHIFT() ) AdditiveExpression() )*
  1610. }
  1611. catch(ParseException pe) {
  1612. error_skipto(SEMICOLON);
  1613. }
  1614. }
  1615. void AdditiveExpression():
  1616. {}
  1617. {
  1618. try {
  1619. MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )*
  1620. }
  1621. catch(ParseException pe) {
  1622. error_skipto(SEMICOLON);
  1623. }
  1624. }
  1625. void MultiplicativeExpression():
  1626. {}
  1627. {
  1628. try {
  1629. UnaryExpression() ( ( "*" | "/" | "%" ) UnaryExpression() )*
  1630. }
  1631. catch(ParseException pe) {
  1632. error_skipto(SEMICOLON);
  1633. }
  1634. }
  1635. void UnaryExpression():
  1636. {}
  1637. {
  1638. try {
  1639. ( "+" | "-" ) UnaryExpression()
  1640. |
  1641. PreIncrementExpression()
  1642. |
  1643. PreDecrementExpression()
  1644. |
  1645. UnaryExpressionNotPlusMinus()
  1646. }
  1647. catch(ParseException pe) {
  1648. error_skipto(SEMICOLON);
  1649. }
  1650. }
  1651. void PreIncrementExpression():
  1652. {}
  1653. {
  1654. try {
  1655. "++" PrimaryExpression()
  1656. }
  1657. catch(ParseException pe) {
  1658. error_skipto(SEMICOLON);
  1659. }
  1660. }
  1661. void PreDecrementExpression():
  1662. {}
  1663. {
  1664. try {
  1665. "--" PrimaryExpression()
  1666. }
  1667. catch(ParseException pe) {
  1668. error_skipto(SEMICOLON);
  1669. }
  1670. }
  1671. void UnaryExpressionNotPlusMinus():
  1672. {}
  1673. {
  1674. try {
  1675. ( "~" | "!" ) UnaryExpression()
  1676. |
  1677. LOOKAHEAD( CastLookahead() )
  1678. CastExpression()
  1679. |
  1680. PostfixExpression()
  1681. }
  1682. catch(ParseException pe) {
  1683. error_skipto(SEMICOLON);
  1684. }
  1685. }
  1686. // This production is to determine lookahead only. The LOOKAHEAD specifications
  1687. // below are not used, but they are there just to indicate that we know about
  1688. // this.
  1689. void CastLookahead():
  1690. {
  1691. Type type = null;
  1692. }
  1693. {
  1694. try {
  1695. LOOKAHEAD(2)
  1696. "(" PrimitiveType()
  1697. |
  1698. LOOKAHEAD("(" Type() "[")
  1699. "(" Type() "[" "]"
  1700. |
  1701. "(" Type() ")" ( "~" | "!" | "(" | <IDENTIFIER> | "this" | "super" | "new" | Literal() )
  1702. }
  1703. catch(ParseException pe) {
  1704. error_skipto(SEMICOLON);
  1705. }
  1706. }
  1707. void PostfixExpression():
  1708. {}
  1709. {
  1710. try {
  1711. PrimaryExpression() [ "++" | "--" ]
  1712. }
  1713. catch(ParseException pe) {
  1714. error_skipto(SEMICOLON);
  1715. }
  1716. }
  1717. void CastExpression():
  1718. {}
  1719. {
  1720. try {
  1721. LOOKAHEAD("(" PrimitiveType())
  1722. "(" Type() ")" UnaryExpression()
  1723. |
  1724. "(" Type() ")" UnaryExpressionNotPlusMinus()
  1725. }
  1726. catch(ParseException pe) {
  1727. error_skipto(SEMICOLON);
  1728. }
  1729. }
  1730. void PrimaryExpression():
  1731. {}
  1732. {
  1733. try {
  1734. PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )*
  1735. }
  1736. catch(ParseException pe) {
  1737. error_skipto(SEMICOLON);
  1738. }
  1739. }
  1740. void MemberSelector():
  1741. {}
  1742. {
  1743. try {
  1744. "." TypeArguments() <IDENTIFIER>
  1745. }
  1746. catch(ParseException pe) {
  1747. error_skipto(SEMICOLON);
  1748. }
  1749. }
  1750. void PrimaryPrefix():
  1751. {}
  1752. {
  1753. try {
  1754. Literal()
  1755. |
  1756. "this"
  1757. |
  1758. "super" "." <IDENTIFIER>
  1759. |
  1760. "(" Expression() ")"
  1761. |
  1762. AllocationExpression()
  1763. |
  1764. LOOKAHEAD( ResultType() "." "class" )
  1765. ResultType() "." "class"
  1766. |
  1767. Name()
  1768. }
  1769. catch(ParseException pe) {
  1770. error_skipto(SEMICOLON);
  1771. }
  1772. }
  1773. void PrimarySuffix():
  1774. {}
  1775. {
  1776. try {
  1777. LOOKAHEAD(2)
  1778. "." "this"
  1779. |
  1780. LOOKAHEAD(2)
  1781. "." AllocationExpression()
  1782. |
  1783. LOOKAHEAD(3)
  1784. MemberSelector()
  1785. |
  1786. "[" Expression() "]"
  1787. |
  1788. "." <IDENTIFIER>
  1789. |
  1790. Arguments()
  1791. }
  1792. catch(ParseException pe) {
  1793. error_skipto(SEMICOLON);
  1794. }
  1795. }
  1796. void Literal():
  1797. {}
  1798. {
  1799. try {
  1800. <INTEGER_LITERAL>
  1801. |
  1802. <FLOATING_POINT_LITERAL>
  1803. |
  1804. <CHARACTER_LITERAL>
  1805. |
  1806. <STRING_LITERAL>
  1807. |
  1808. BooleanLiteral()
  1809. |
  1810. NullLiteral()
  1811. }
  1812. catch(ParseException pe) {
  1813. error_skipto(SEMICOLON);
  1814. }
  1815. }
  1816. void BooleanLiteral():
  1817. {}
  1818. {
  1819. "true"
  1820. |
  1821. "false"
  1822. }
  1823. void NullLiteral():
  1824. {}
  1825. {
  1826. "null"
  1827. }
  1828. void Arguments():
  1829. {}
  1830. {
  1831. try {
  1832. "(" [ ArgumentList() ] ")"
  1833. }
  1834. catch(ParseException pe) {
  1835. error_skipto(SEMICOLON);
  1836. }
  1837. }
  1838. void ArgumentList():
  1839. {}
  1840. {
  1841. try {
  1842. Expression() ( "," Expression() )*
  1843. }
  1844. catch(ParseException pe) {
  1845. error_skipto(SEMICOLON);
  1846. }
  1847. }
  1848. void AllocationExpression():
  1849. {}
  1850. {
  1851. try {
  1852. LOOKAHEAD(2)
  1853. "new" PrimitiveType() ArrayDimsAndInits()
  1854. |
  1855. "new" ClassOrInterfaceType() [ TypeArguments() ]
  1856. (
  1857. ArrayDimsAndInits()
  1858. |
  1859. Arguments() [ ClassOrInterfaceBody(false) ]
  1860. )
  1861. }
  1862. catch(ParseException pe) {
  1863. error_skipto(SEMICOLON);
  1864. }
  1865. }
  1866. /*
  1867. * The third LOOKAHEAD specification below is to parse to PrimarySuffix
  1868. * if there is an expression between the "[...]".
  1869. */
  1870. void ArrayDimsAndInits():
  1871. {}
  1872. {
  1873. try {
  1874. LOOKAHEAD(2)
  1875. ( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )*
  1876. |
  1877. ( "[" "]" )+ ArrayInitializer()
  1878. }
  1879. catch(ParseException pe) {
  1880. error_skipto(SEMICOLON);
  1881. }
  1882. }
  1883. /*
  1884. * Statement syntax follows.
  1885. */
  1886. BlockNode Statement():
  1887. {
  1888. BlockNode bn = null;
  1889. }
  1890. {
  1891. try {
  1892. (
  1893. LOOKAHEAD(2)
  1894. LabeledStatement()
  1895. |
  1896. AssertStatement()
  1897. |
  1898. bn=Block()
  1899. |
  1900. EmptyStatement()
  1901. |
  1902. StatementExpression() ";"
  1903. |
  1904. bn=SwitchStatement()
  1905. |
  1906. bn=IfStatement()
  1907. |
  1908. bn=WhileStatement()
  1909. |
  1910. bn=DoStatement()
  1911. |
  1912. bn=ForStatement()
  1913. |
  1914. BreakStatement()
  1915. |
  1916. ContinueStatement()
  1917. |
  1918. ReturnStatement()
  1919. |
  1920. ThrowStatement()
  1921. |
  1922. bn=SynchronizedStatement()
  1923. |
  1924. bn=TryStatement()
  1925. )
  1926. }
  1927. catch(ParseException pe) {
  1928. error_skipto(SEMICOLON);
  1929. }
  1930. {
  1931. return bn;
  1932. }
  1933. }
  1934. void AssertStatement():
  1935. {}
  1936. {
  1937. try {
  1938. "assert" Expression() [ ":" Expression() ] ";"
  1939. }
  1940. catch(ParseException pe) {
  1941. error_skipto(SEMICOLON);
  1942. }
  1943. }
  1944. void LabeledStatement():
  1945. {}
  1946. {
  1947. try {
  1948. <IDENTIFIER> ":" Statement()
  1949. }
  1950. catch(ParseException pe) {
  1951. error_skipto(SEMICOLON);
  1952. }
  1953. }
  1954. BlockNode Block():
  1955. {
  1956. // an un-named block of code
  1957. Token start_t = null;
  1958. Token end_t = null;
  1959. BlockNode bn = new BlockNode();
  1960. TigerNode child = null;
  1961. }
  1962. {
  1963. try {
  1964. start_t="{" ( child=BlockStatement() { bn.addChild(child); })* end_t="}"
  1965. }
  1966. catch(ParseException pe) {
  1967. error_skipto(SEMICOLON);
  1968. }
  1969. {
  1970. bn.setName("block_" + start_t.beginLine + ":" + start_t.beginColumn);
  1971. bn.setStartLocation(getLocation(start_t));
  1972. bn.setEndLocation(getLocation(end_t));
  1973. return bn;
  1974. }
  1975. }
  1976. TigerNode BlockStatement():
  1977. {
  1978. TigerNode tn = null;
  1979. }
  1980. {
  1981. try {
  1982. (
  1983. LOOKAHEAD([ "final" ] Type() <IDENTIFIER>)
  1984. tn=LocalVariableDeclaration() ";"
  1985. |
  1986. tn=Statement()
  1987. |
  1988. tn=ClassOrInterfaceDeclaration(new Modifier())
  1989. )
  1990. }
  1991. catch(ParseException pe) {
  1992. error_skipto(SEMICOLON);
  1993. }
  1994. {
  1995. return tn;
  1996. }
  1997. }
  1998. LocalVariableNode LocalVariableDeclaration():
  1999. {
  2000. Type type = null;
  2001. TigerNode name = null ;
  2002. TigerNode a = null;
  2003. Token t = null;
  2004. }
  2005. {
  2006. try {
  2007. //[ "final" ] Type() VariableDeclarator() ( "," VariableDeclarator() )*
  2008. [ t="final" ] type=Type() name=VariableDeclarator() ( "," a=VariableDeclarator() { name.setName(name.getName() + ", " + a.getName()); name.setEndLocation(a.getEndLocation()); })*
  2009. }
  2010. catch(ParseException pe) {
  2011. error_skipto(SEMICOLON);
  2012. }
  2013. {
  2014. LocalVariableNode lvn = new LocalVariableNode(name.getName(), type);
  2015. if (lvn.isPrimitive())
  2016. results.incPrimitiveFieldCount();
  2017. else
  2018. results.incReferenceFieldCount();
  2019. lvn.setStartLocation(name.getStartLocation());
  2020. lvn.setEndLocation(name.getEndLocation());
  2021. lvn.setFinal(t != null);
  2022. return lvn;
  2023. }
  2024. }
  2025. void EmptyStatement():
  2026. {}
  2027. {
  2028. ";"
  2029. }
  2030. void StatementExpression():
  2031. /*
  2032. * The last expansion of this production accepts more than the legal
  2033. * Java expansions for StatementExpression. This expansion does not
  2034. * use PostfixExpression for performance reasons.
  2035. */
  2036. {}
  2037. {
  2038. try {
  2039. PreIncrementExpression()
  2040. |
  2041. PreDecrementExpression()
  2042. |
  2043. PrimaryExpression()
  2044. [
  2045. "++"
  2046. |
  2047. "--"
  2048. |
  2049. AssignmentOperator() Expression()
  2050. ]
  2051. }
  2052. catch(ParseException pe) {
  2053. error_skipto(SEMICOLON);
  2054. }
  2055. }
  2056. BlockNode SwitchStatement():
  2057. {
  2058. BlockNode bn = new BlockNode("switch");
  2059. TigerNode child = null;
  2060. Token start_t = null;
  2061. Token end_t = null;
  2062. }
  2063. {
  2064. try {
  2065. start_t="switch" "(" Expression() "…