PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/bsh/bsh.jjt

#
Unknown | 1432 lines | 1304 code | 128 blank | 0 comment | 0 complexity | 845544ad4a72d3a5289a0a1977ec4529 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*****************************************************************************
  2. * *
  3. * This file is part of the BeanShell Java Scripting distribution. *
  4. * Documentation and updates may be found at http://www.beanshell.org/ *
  5. * *
  6. * Sun Public License Notice: *
  7. * *
  8. * The contents of this file are subject to the Sun Public License Version *
  9. * 1.0 (the "License"); you may not use this file except in compliance with *
  10. * the License. A copy of the License is available at http://www.sun.com *
  11. * *
  12. * The Original Code is BeanShell. The Initial Developer of the Original *
  13. * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
  14. * (C) 2000. All Rights Reserved. *
  15. * *
  16. * GNU Public License Notice: *
  17. * *
  18. * Alternatively, the contents of this file may be used under the terms of *
  19. * the GNU Lesser General Public License (the "LGPL"), in which case the *
  20. * provisions of LGPL are applicable instead of those above. If you wish to *
  21. * allow use of your version of this file only under the terms of the LGPL *
  22. * and not to allow others to use your version of this file under the SPL, *
  23. * indicate your decision by deleting the provisions above and replace *
  24. * them with the notice and other provisions required by the LGPL. If you *
  25. * do not delete the provisions above, a recipient may use your version of *
  26. * this file under either the SPL or the LGPL. *
  27. * *
  28. * Patrick Niemeyer (pat@pat.net) *
  29. * Author of Learning Java, O'Reilly & Associates *
  30. * http://www.pat.net/~pat/ *
  31. * *
  32. *****************************************************************************/
  33. /*
  34. Notes:
  35. There is probably a lot of room for improvement in here.
  36. All of the syntactic lookaheads have been commented with:
  37. SYNTACTIC_LOOKAHEAD
  38. These are probably expensive and we may want to start weeding them out
  39. where possible.
  40. */
  41. options {
  42. JAVA_UNICODE_ESCAPE=true;
  43. STATIC=false;
  44. MULTI=true;
  45. NODE_DEFAULT_VOID=true;
  46. NODE_SCOPE_HOOK=true;
  47. NODE_PREFIX="BSH";
  48. /* Print grammar debugging info as we parse
  49. DEBUG_PARSER=true;
  50. */
  51. /* Print detailed lookahead debugging info
  52. DEBUG_LOOKAHEAD=true;
  53. */
  54. // Not sure exactly what this does
  55. ERROR_REPORTING=false;
  56. // This breaks something for interactive use on the command line,
  57. // but may be useful in non-interactive use.
  58. //CACHE_TOKENS=true;
  59. }
  60. PARSER_BEGIN(Parser)
  61. package bsh;
  62. import java.io.*;
  63. import java.util.Vector;
  64. /**
  65. This is the BeanShell parser. It is used internally by the Interpreter
  66. class (which is probably what you are looking for). The parser knows
  67. only how to parse the structure of the language, it does not understand
  68. names, commands, etc.
  69. <p>
  70. You can use the Parser from the command line to do basic structural
  71. validation of BeanShell files without actually executing them. e.g.
  72. <code><pre>
  73. java bsh.Parser [ -p ] file [ file ] [ ... ]
  74. </pre></code>
  75. <p>
  76. The -p option causes the abstract syntax to be printed.
  77. <p>
  78. From code you'd use the Parser like this:
  79. <p
  80. <code><pre>
  81. Parser parser = new Parser(in);
  82. while( !(eof=parser.Line()) ) {
  83. SimpleNode node = parser.popNode();
  84. // use the node, etc. (See bsh.BSH* classes)
  85. }
  86. </pre></code>
  87. */
  88. public class Parser
  89. {
  90. boolean retainComments = false;
  91. public void setRetainComments( boolean b ) {
  92. retainComments = b;
  93. }
  94. void jjtreeOpenNodeScope(Node n) {
  95. ((SimpleNode)n).firstToken = getToken(1);
  96. }
  97. void jjtreeCloseNodeScope(Node n) {
  98. ((SimpleNode)n).lastToken = getToken(0);
  99. }
  100. /**
  101. Re-initialize the input stream and token source.
  102. */
  103. void reInitInput( Reader in ) {
  104. ReInit(in);
  105. }
  106. public SimpleNode popNode()
  107. {
  108. if ( jjtree.nodeArity() > 0) // number of child nodes
  109. return (SimpleNode)jjtree.popNode();
  110. else
  111. return null;
  112. }
  113. /**
  114. Explicitly re-initialize just the token reader.
  115. This seems to be necessary to avoid certain looping errors when
  116. reading bogus input. See Interpreter.
  117. */
  118. void reInitTokenInput( Reader in ) {
  119. jj_input_stream.ReInit( in,
  120. jj_input_stream.getEndLine(),
  121. jj_input_stream.getEndColumn() );
  122. }
  123. public static void main( String [] args )
  124. throws IOException, ParseException
  125. {
  126. boolean print = false;
  127. int i=0;
  128. if ( args[0].equals("-p") ) {
  129. i++;
  130. print=true;
  131. }
  132. for(; i< args.length; i++) {
  133. Reader in = new FileReader(args[i]);
  134. Parser parser = new Parser(in);
  135. parser.setRetainComments(true);
  136. while( !parser.Line()/*eof*/ )
  137. if ( print )
  138. System.out.println( parser.popNode() );
  139. }
  140. }
  141. /**
  142. Lookahead for the enhanced for statement.
  143. Expect "for" "(" and then see whether we hit ":" or a ";" first.
  144. */
  145. boolean isRegularForStatement()
  146. {
  147. int curTok = 1;
  148. Token tok;
  149. tok = getToken(curTok++);
  150. if ( tok.kind != FOR ) return false;
  151. tok = getToken(curTok++);
  152. if ( tok.kind != LPAREN ) return false;
  153. while (true)
  154. {
  155. tok = getToken(curTok++);
  156. switch (tok.kind) {
  157. case COLON:
  158. return false;
  159. case SEMICOLON:
  160. return true;
  161. case EOF:
  162. return false;
  163. }
  164. }
  165. }
  166. /**
  167. Lookahead to determine whether a method has a return type.
  168. // Case 1 - primitive or void
  169. [ void, boolean, char, ... ] foo() { }
  170. byte [] foo() { }
  171. // Case 2 - simple type name
  172. Foo foo () { }
  173. Foo [] foo () { }
  174. // Case 3 - compound type name
  175. foo.Foo foo () { }
  176. foo.Foo [] foo () { }
  177. // Case 4 - Parameterized return type?
  178. // ??
  179. // Case N - no type
  180. foo () { }
  181. */
  182. /*
  183. Note: it's important not to read ahead tokens (e.g. tok2) unless
  184. previous ones match. We're used in lookaheads and if we have to wait
  185. for tokens that couldn't match it messes up interactivity on the
  186. command line.
  187. */
  188. boolean methodHasReturnType()
  189. {
  190. Token tok1 = getToken(1), tok2=null;
  191. // Case 1
  192. if ( tok1.kind == VOID || tok1.kind == BOOLEAN || tok1.kind == CHAR
  193. || tok1.kind == BYTE || tok1.kind == SHORT || tok1.kind == INT
  194. || tok1.kind == LONG || tok1.kind == FLOAT || tok1.kind == DOUBLE
  195. )
  196. return true;
  197. // Case 2
  198. if ( tok1.kind == IDENTIFIER && (tok2=getToken(2)).kind == LBRACKET )
  199. return true;
  200. if ( tok1.kind == IDENTIFIER && tok2.kind == IDENTIFIER
  201. && getToken(3).kind == LPAREN )
  202. return true;
  203. // Case 3
  204. if ( tok1.kind == IDENTIFIER && tok2.kind == DOT )
  205. return true;
  206. // Case N
  207. return false;
  208. }
  209. /**
  210. Generate a ParseException with the specified message, pointing to the
  211. current token.
  212. The auto-generated Parser.generateParseException() method does not
  213. provide line number info, therefore we do this.
  214. */
  215. ParseException createParseException( String message )
  216. {
  217. Token errortok = token;
  218. int line = errortok.beginLine, column = errortok.beginColumn;
  219. String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image;
  220. return new ParseException( "Parse error at line " + line
  221. + ", column " + column + " : " + message );
  222. }
  223. }
  224. PARSER_END(Parser)
  225. SKIP : /* WHITE SPACE */
  226. {
  227. " " | "\t" | "\r" | "\f"
  228. | "\n"
  229. | < NONPRINTABLE: (["\u0000"-"\u0020", "\u0080"-"\u00ff"])+ >
  230. }
  231. SPECIAL_TOKEN : /* COMMENTS */
  232. {
  233. /*
  234. SINGLE_LINE_COMMENT includes a hack to accept SLC at the end of a file
  235. with no terminanting linefeed. This is actually illegal according to
  236. spec, but comes up often enough to warrant it... (especially in eval()).
  237. */
  238. <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")? >
  239. | <HASH_BANG_COMMENT: "#!" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
  240. /* Moved FORMAL_COMMENT to a real token. Modified MULTI_LINE_COMMENT to not
  241. catch formal comments (require no star after star) */
  242. | <MULTI_LINE_COMMENT:
  243. "/*" (~["*"])+ "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
  244. }
  245. TOKEN : /* RESERVED WORDS AND LITERALS */
  246. {
  247. < ABSTRACT : "abstract" >
  248. | < BOOLEAN: "boolean" >
  249. | < BREAK: "break" >
  250. | < CLASS: "class" >
  251. | < BYTE: "byte" >
  252. | < CASE: "case" >
  253. | < CATCH: "catch" >
  254. | < CHAR: "char" >
  255. | < CONST: "const" >
  256. | < CONTINUE: "continue" >
  257. | < _DEFAULT: "default" >
  258. | < DO: "do" >
  259. | < DOUBLE: "double" >
  260. | < ELSE: "else" >
  261. | < ENUM: "enum" >
  262. | < EXTENDS: "extends" >
  263. | < FALSE: "false" >
  264. | < FINAL: "final" >
  265. | < FINALLY: "finally" >
  266. | < FLOAT: "float" >
  267. | < FOR: "for" >
  268. | < GOTO: "goto" >
  269. | < IF: "if" >
  270. | < IMPLEMENTS: "implements" >
  271. | < IMPORT: "import" >
  272. | < INSTANCEOF: "instanceof" >
  273. | < INT: "int" >
  274. | < INTERFACE: "interface" >
  275. | < LONG: "long" >
  276. | < NATIVE: "native" >
  277. | < NEW: "new" >
  278. | < NULL: "null" >
  279. | < PACKAGE: "package" >
  280. | < PRIVATE: "private" >
  281. | < PROTECTED: "protected" >
  282. | < PUBLIC: "public" >
  283. | < RETURN: "return" >
  284. | < SHORT: "short" >
  285. | < STATIC: "static" >
  286. | < STRICTFP : "strictfp" >
  287. | < SWITCH: "switch" >
  288. | < SYNCHRONIZED: "synchronized" >
  289. | < TRANSIENT: "transient" >
  290. | < THROW: "throw" >
  291. | < THROWS: "throws" >
  292. | < TRUE: "true" >
  293. | < TRY: "try" >
  294. | < VOID: "void" >
  295. | < VOLATILE: "volatile" >
  296. | < WHILE: "while" >
  297. }
  298. TOKEN : /* LITERALS */
  299. {
  300. < INTEGER_LITERAL:
  301. <DECIMAL_LITERAL> (["l","L"])?
  302. | <HEX_LITERAL> (["l","L"])?
  303. | <OCTAL_LITERAL> (["l","L"])?
  304. >
  305. |
  306. < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
  307. |
  308. < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
  309. |
  310. < #OCTAL_LITERAL: "0" (["0"-"7"])* >
  311. |
  312. < FLOATING_POINT_LITERAL:
  313. (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
  314. | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
  315. | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
  316. | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
  317. >
  318. |
  319. < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
  320. |
  321. < CHARACTER_LITERAL:
  322. "'"
  323. ( (~["'","\\","\n","\r"])
  324. | ("\\"
  325. ( ["n","t","b","r","f","\\","'","\""]
  326. | ["0"-"7"] ( ["0"-"7"] )?
  327. | ["0"-"3"] ["0"-"7"] ["0"-"7"]
  328. )
  329. )
  330. )
  331. "'"
  332. >
  333. |
  334. < STRING_LITERAL:
  335. "\""
  336. ( (~["\"","\\","\n","\r"])
  337. | ("\\"
  338. ( ["n","t","b","r","f","\\","'","\""]
  339. | ["0"-"7"] ( ["0"-"7"] )?
  340. | ["0"-"3"] ["0"-"7"] ["0"-"7"]
  341. )
  342. )
  343. )*
  344. "\""
  345. >
  346. |
  347. < FORMAL_COMMENT:
  348. "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/"
  349. >
  350. }
  351. TOKEN : /* IDENTIFIERS */
  352. {
  353. < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
  354. |
  355. < #LETTER:
  356. [
  357. "\u0024",
  358. "\u0041"-"\u005a",
  359. "\u005f",
  360. "\u0061"-"\u007a",
  361. "\u00c0"-"\u00d6",
  362. "\u00d8"-"\u00f6",
  363. "\u00f8"-"\u00ff",
  364. "\u0100"-"\u1fff",
  365. "\u3040"-"\u318f",
  366. "\u3300"-"\u337f",
  367. "\u3400"-"\u3d2d",
  368. "\u4e00"-"\u9fff",
  369. "\uf900"-"\ufaff"
  370. ]
  371. >
  372. |
  373. < #DIGIT:
  374. [
  375. "\u0030"-"\u0039",
  376. "\u0660"-"\u0669",
  377. "\u06f0"-"\u06f9",
  378. "\u0966"-"\u096f",
  379. "\u09e6"-"\u09ef",
  380. "\u0a66"-"\u0a6f",
  381. "\u0ae6"-"\u0aef",
  382. "\u0b66"-"\u0b6f",
  383. "\u0be7"-"\u0bef",
  384. "\u0c66"-"\u0c6f",
  385. "\u0ce6"-"\u0cef",
  386. "\u0d66"-"\u0d6f",
  387. "\u0e50"-"\u0e59",
  388. "\u0ed0"-"\u0ed9",
  389. "\u1040"-"\u1049"
  390. ]
  391. >
  392. }
  393. TOKEN : /* SEPARATORS */
  394. {
  395. < LPAREN: "(" >
  396. | < RPAREN: ")" >
  397. | < LBRACE: "{" >
  398. | < RBRACE: "}" >
  399. | < LBRACKET: "[" >
  400. | < RBRACKET: "]" >
  401. | < SEMICOLON: ";" >
  402. | < COMMA: "," >
  403. | < DOT: "." >
  404. }
  405. TOKEN : /* OPERATORS */
  406. {
  407. < ASSIGN: "=" >
  408. | < GT: ">" >
  409. | < GTX: "@gt" >
  410. | < LT: "<" >
  411. | < LTX: "@lt" >
  412. | < BANG: "!" >
  413. | < TILDE: "~" >
  414. | < HOOK: "?" >
  415. | < COLON: ":" >
  416. | < EQ: "==" >
  417. | < LE: "<=" >
  418. | < LEX: "@lteq" >
  419. | < GE: ">=" >
  420. | < GEX: "@gteq" >
  421. | < NE: "!=" >
  422. | < BOOL_OR: "||" >
  423. | < BOOL_ORX: "@or" >
  424. | < BOOL_AND: "&&" >
  425. | < BOOL_ANDX: "@and" >
  426. | < INCR: "++" >
  427. | < DECR: "--" >
  428. | < PLUS: "+" >
  429. | < MINUS: "-" >
  430. | < STAR: "*" >
  431. | < SLASH: "/" >
  432. | < BIT_AND: "&" >
  433. | < BIT_ANDX: "@bitwise_and" >
  434. | < BIT_OR: "|" >
  435. | < BIT_ORX: "@bitwise_or" >
  436. | < XOR: "^" >
  437. | < MOD: "%" >
  438. | < LSHIFT: "<<" >
  439. | < LSHIFTX: "@left_shift" >
  440. | < RSIGNEDSHIFT: ">>" >
  441. | < RSIGNEDSHIFTX: "@right_shift" >
  442. | < RUNSIGNEDSHIFT: ">>>" >
  443. | < RUNSIGNEDSHIFTX: "@right_unsigned_shift" >
  444. | < PLUSASSIGN: "+=" >
  445. | < MINUSASSIGN: "-=" >
  446. | < STARASSIGN: "*=" >
  447. | < SLASHASSIGN: "/=" >
  448. | < ANDASSIGN: "&=" >
  449. | < ANDASSIGNX: "@and_assign" >
  450. | < ORASSIGN: "|=" >
  451. | < ORASSIGNX: "@or_assign" >
  452. | < XORASSIGN: "^=" >
  453. | < MODASSIGN: "%=" >
  454. | < LSHIFTASSIGN: "<<=" >
  455. | < LSHIFTASSIGNX: "@left_shift_assign" >
  456. | < RSIGNEDSHIFTASSIGN: ">>=" >
  457. | < RSIGNEDSHIFTASSIGNX: "@right_shift_assign" >
  458. | < RUNSIGNEDSHIFTASSIGN: ">>>=" >
  459. | < RUNSIGNEDSHIFTASSIGNX: "@right_unsigned_shift_assign" >
  460. }
  461. /*
  462. Thanks to Sreenivasa Viswanadha for suggesting how to get rid of expensive
  463. lookahead here.
  464. */
  465. boolean Line() :
  466. {}
  467. {
  468. <EOF> {
  469. Interpreter.debug("End of File!");
  470. return true;
  471. }
  472. |
  473. BlockStatement() {
  474. return false;
  475. }
  476. }
  477. /*****************************************
  478. * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
  479. *****************************************/
  480. /*
  481. Gather modifiers for a class, method, or field.
  482. I lookahead is true then we are being called as part of a lookahead and we
  483. should not enforce any rules. Otherwise we validate based on context
  484. (field, method, class)
  485. */
  486. Modifiers Modifiers( int context, boolean lookahead ) :
  487. {
  488. Modifiers mods = null;
  489. }
  490. {
  491. (
  492. (
  493. "private" | "protected" | "public" | "synchronized" | "final"
  494. | "native" | "transient" | "volatile" | "abstract" | "static"
  495. | "strictfp"
  496. ) {
  497. if ( !lookahead )
  498. try {
  499. if ( mods == null ) mods = new Modifiers();
  500. mods.addModifier( context, getToken(0).image );
  501. } catch ( IllegalStateException e ) {
  502. throw createParseException( e.getMessage() );
  503. }
  504. }
  505. )* {
  506. return mods;
  507. }
  508. }
  509. /**
  510. */
  511. void ClassDeclaration() #ClassDeclaration :
  512. {
  513. Modifiers mods;
  514. Token t;
  515. int numInterfaces;
  516. }
  517. {
  518. mods = Modifiers( Modifiers.CLASS, false )
  519. "class" t=<IDENTIFIER>
  520. [ "extends" AmbiguousName() { jjtThis.extend = true; } ]
  521. [ "implements" numInterfaces=NameList()
  522. { jjtThis.numInterfaces=numInterfaces; } ]
  523. Block() {
  524. jjtThis.modifiers = mods;
  525. jjtThis.name = t.image;
  526. }
  527. }
  528. void MethodDeclaration() #MethodDeclaration :
  529. {
  530. Token t = null;
  531. Modifiers mods;
  532. int count;
  533. }
  534. {
  535. mods = Modifiers( Modifiers.METHOD, false ) { jjtThis.modifiers = mods; }
  536. [ LOOKAHEAD( { methodHasReturnType() } ) ReturnType() ]
  537. t = <IDENTIFIER> { jjtThis.name = t.image; }
  538. FormalParameters()
  539. [ "throws" count=NameList() { jjtThis.numThrows=count; } ]
  540. Block()
  541. }
  542. /**
  543. It's tempting to collapse this to one like like so:
  544. [ LOOKAHEAD( { methodHasReturnType() } ) ReturnType() ]
  545. <IDENTIFIER> FormalParameters() "{"
  546. However this doesn't work because nested lookaheads are not evaluated
  547. during lookahead!
  548. http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq.htm#tth_sEc4.9
  549. */
  550. void MethodDeclarationLookahead() : { }
  551. {
  552. Modifiers( Modifiers.METHOD, true )
  553. (
  554. LOOKAHEAD( { methodHasReturnType() } ) ReturnType()
  555. <IDENTIFIER> FormalParameters() [ "throws" NameList() ] "{"
  556. |
  557. <IDENTIFIER> FormalParameters() [ "throws" NameList() ] "{"
  558. )
  559. }
  560. void ImportDeclaration() #ImportDeclaration :
  561. {
  562. Token t = null;
  563. }
  564. {
  565. LOOKAHEAD( 2 )
  566. "import" AmbiguousName() [ t = "." "*" ] ";" {
  567. if ( t != null )
  568. jjtThis.importPackage = true;
  569. }
  570. |
  571. // bsh super import statement
  572. "import" "*" ";" {
  573. jjtThis.superImport = true;
  574. }
  575. }
  576. void VariableDeclarator() #VariableDeclarator :
  577. {
  578. Token t;
  579. Modifiers mods;
  580. }
  581. {
  582. t=<IDENTIFIER> [ "=" VariableInitializer() ]
  583. {
  584. jjtThis.name = t.image;
  585. }
  586. }
  587. /*
  588. Can get rid of this if we ignore postfix array dimensions in declarations.
  589. I don't like them and I don't want to deal with them right now.
  590. void VariableDeclaratorId() #VariableDeclaratorId :
  591. { Token t; }
  592. {
  593. t=<IDENTIFIER> { jjtThis.name = t.image; }
  594. ( "[" "]" { jjtThis.addUndefinedDimension(); } )*
  595. }
  596. */
  597. void VariableInitializer() :
  598. {}
  599. {
  600. ArrayInitializer()
  601. |
  602. Expression()
  603. }
  604. void ArrayInitializer() #ArrayInitializer :
  605. {}
  606. {
  607. "{" [ VariableInitializer()
  608. ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"
  609. }
  610. void FormalParameters() #FormalParameters :
  611. {}
  612. {
  613. "(" [ FormalParameter() ( "," FormalParameter() )* ] ")"
  614. }
  615. void FormalParameter() #FormalParameter :
  616. { Token t; }
  617. {
  618. // added [] to Type for bsh. Removed [ final ] - is that legal?
  619. LOOKAHEAD(2) Type() t=<IDENTIFIER> { jjtThis.name = t.image; }
  620. |
  621. t=<IDENTIFIER> { jjtThis.name = t.image; }
  622. }
  623. /*
  624. Type, name and expression syntax follows.
  625. */
  626. void Type() #Type :
  627. { }
  628. {
  629. /*
  630. The embedded lookahead is (was?) necessary to disambiguate for
  631. PrimaryPrefix. ( )* is a choice point. It took me a while to
  632. figure out where to put that. This stuff is annoying.
  633. */
  634. ( PrimitiveType() | AmbiguousName() )
  635. ( LOOKAHEAD(2) "[" "]" { jjtThis.addArrayDimension(); } )*
  636. }
  637. /*
  638. Originally called ResultType in the grammar
  639. */
  640. void ReturnType() #ReturnType :
  641. { }
  642. {
  643. "void" { jjtThis.isVoid = true; }
  644. |
  645. Type()
  646. }
  647. void PrimitiveType() #PrimitiveType :
  648. { } {
  649. "boolean" { jjtThis.type = Boolean.TYPE; }
  650. | "char" { jjtThis.type = Character.TYPE; }
  651. | "byte" { jjtThis.type = Byte.TYPE; }
  652. | "short" { jjtThis.type = Short.TYPE; }
  653. | "int" { jjtThis.type = Integer.TYPE; }
  654. | "long" { jjtThis.type = Long.TYPE; }
  655. | "float" { jjtThis.type = Float.TYPE; }
  656. | "double" { jjtThis.type = Double.TYPE; }
  657. }
  658. void AmbiguousName() #AmbiguousName :
  659. /*
  660. A lookahead of 2 is required below since "Name" can be followed by a ".*"
  661. when used in the context of an "ImportDeclaration".
  662. */
  663. {
  664. Token t;
  665. StringBuffer s;
  666. }
  667. {
  668. t = <IDENTIFIER> {
  669. s = new StringBuffer(t.image);
  670. }
  671. ( LOOKAHEAD(2) "." t = <IDENTIFIER> { s.append("."+t.image); } )* {
  672. jjtThis.text = s.toString();
  673. }
  674. }
  675. int NameList() :
  676. { int count = 0; }
  677. {
  678. AmbiguousName() { ++count; } ( "," AmbiguousName() { ++count; } )*
  679. { return count; }
  680. }
  681. /*
  682. * Expression syntax follows.
  683. */
  684. void Expression() :
  685. { }
  686. {
  687. /**
  688. SYNTACTIC_LOOKAHEAD
  689. Note: the original grammar was cheating here and we've fixed that,
  690. but at the expense of another syntactic lookahead.
  691. */
  692. LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
  693. Assignment()
  694. |
  695. ConditionalExpression()
  696. }
  697. void Assignment() #Assignment :
  698. { int op ; }
  699. {
  700. PrimaryExpression()
  701. op = AssignmentOperator() { jjtThis.operator = op; }
  702. // Add this for blocks, e.g. foo = { };
  703. //( Expression() | Block() )
  704. Expression()
  705. }
  706. int AssignmentOperator() :
  707. { Token t; }
  708. {
  709. ( "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "&=" | "^=" | "|=" |
  710. "<<=" | "@left_shift_assign" | ">>=" | "@right_shift_assign" |
  711. ">>>=" | "@right_unsigned_shift_assign" )
  712. {
  713. t = getToken(0);
  714. return t.kind;
  715. }
  716. }
  717. void ConditionalExpression() :
  718. { }
  719. {
  720. ConditionalOrExpression() [ "?" Expression() ":" ConditionalExpression()
  721. #TernaryExpression(3) ]
  722. }
  723. void ConditionalOrExpression() :
  724. { Token t=null; }
  725. {
  726. ConditionalAndExpression()
  727. ( ( t = "||" | t = "@or" )
  728. ConditionalAndExpression()
  729. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  730. }
  731. void ConditionalAndExpression() :
  732. { Token t=null; }
  733. {
  734. InclusiveOrExpression()
  735. ( ( t = "&&" | t = "@and" )
  736. InclusiveOrExpression()
  737. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  738. }
  739. void InclusiveOrExpression() :
  740. { Token t=null; }
  741. {
  742. ExclusiveOrExpression()
  743. ( ( t = "|" | t = "@bitwise_or" )
  744. ExclusiveOrExpression()
  745. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  746. }
  747. void ExclusiveOrExpression() :
  748. { Token t=null; }
  749. {
  750. AndExpression() ( t="^" AndExpression()
  751. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  752. }
  753. void AndExpression() :
  754. { Token t=null; }
  755. {
  756. EqualityExpression()
  757. ( ( t = "&" | t = "@bitwise_and" )
  758. EqualityExpression()
  759. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  760. }
  761. void EqualityExpression() :
  762. { Token t = null; }
  763. {
  764. InstanceOfExpression() ( ( t= "==" | t= "!=" ) InstanceOfExpression()
  765. { jjtThis.kind = t.kind; } #BinaryExpression(2)
  766. )*
  767. }
  768. void InstanceOfExpression() :
  769. { Token t = null; }
  770. {
  771. RelationalExpression()
  772. [ t = "instanceof" Type() { jjtThis.kind = t.kind; } #BinaryExpression(2) ]
  773. }
  774. void RelationalExpression() :
  775. { Token t = null; }
  776. {
  777. ShiftExpression()
  778. ( ( t = "<" | t = "@lt" | t = ">" | t = "@gt" |
  779. t = "<=" | t = "@lteq" | t = ">=" | t = "@gteq" )
  780. ShiftExpression()
  781. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  782. }
  783. void ShiftExpression() :
  784. { Token t = null; }
  785. {
  786. AdditiveExpression()
  787. ( ( t = "<<" | t = "@left_shift" | t = ">>" | t = "@right_shift" |
  788. t = ">>>" | t = "@right_unsigned_shift" )
  789. AdditiveExpression()
  790. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  791. }
  792. void AdditiveExpression() :
  793. { Token t = null; }
  794. {
  795. MultiplicativeExpression()
  796. ( ( t= "+" | t= "-" ) MultiplicativeExpression() { jjtThis.kind = t.kind; }
  797. #BinaryExpression(2)
  798. )*
  799. }
  800. void MultiplicativeExpression() :
  801. { Token t = null; }
  802. {
  803. UnaryExpression() ( ( t= "*" | t= "/" | t= "%" )
  804. UnaryExpression() { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  805. }
  806. void UnaryExpression() :
  807. { Token t = null; }
  808. {
  809. ( t="+" | t="-" ) UnaryExpression()
  810. { jjtThis.kind = t.kind; } #UnaryExpression(1)
  811. |
  812. PreIncrementExpression()
  813. |
  814. PreDecrementExpression()
  815. |
  816. UnaryExpressionNotPlusMinus()
  817. }
  818. void PreIncrementExpression() :
  819. { Token t = null; }
  820. {
  821. t="++" PrimaryExpression()
  822. { jjtThis.kind = t.kind; } #UnaryExpression(1)
  823. }
  824. void PreDecrementExpression() :
  825. { Token t = null; }
  826. {
  827. t="--" PrimaryExpression()
  828. { jjtThis.kind = t.kind; } #UnaryExpression(1)
  829. }
  830. void UnaryExpressionNotPlusMinus() :
  831. { Token t = null; }
  832. {
  833. ( t="~" | t="!" ) UnaryExpression()
  834. { jjtThis.kind = t.kind; } #UnaryExpression(1)
  835. |
  836. // SYNTACTIC_LOOKAHEAD
  837. LOOKAHEAD( CastLookahead() ) CastExpression()
  838. |
  839. PostfixExpression()
  840. }
  841. // This production is to determine lookahead only.
  842. void CastLookahead() : { }
  843. {
  844. LOOKAHEAD(2) "(" PrimitiveType()
  845. |
  846. // SYNTACTIC_LOOKAHEAD
  847. LOOKAHEAD( "(" AmbiguousName() "[" ) "(" AmbiguousName() "[" "]"
  848. |
  849. "(" AmbiguousName() ")" ( "~" | "!" | "(" | <IDENTIFIER> | /* "this" | "super" | */ "new" | Literal() )
  850. }
  851. void PostfixExpression() :
  852. { Token t = null; }
  853. {
  854. // SYNTACTIC_LOOKAHEAD
  855. LOOKAHEAD( PrimaryExpression() ("++"|"--") )
  856. PrimaryExpression()
  857. ( t="++" | t="--" ) {
  858. jjtThis.kind = t.kind; jjtThis.postfix = true; } #UnaryExpression(1)
  859. |
  860. PrimaryExpression()
  861. }
  862. void CastExpression() #CastExpression :
  863. { }
  864. {
  865. // SYNTACTIC_LOOKAHEAD
  866. LOOKAHEAD( "(" PrimitiveType() ) "(" Type() ")" UnaryExpression()
  867. |
  868. "(" Type() ")" UnaryExpressionNotPlusMinus()
  869. }
  870. void PrimaryExpression() #PrimaryExpression : { }
  871. {
  872. PrimaryPrefix() ( PrimarySuffix() )*
  873. }
  874. void MethodInvocation() #MethodInvocation : { }
  875. {
  876. AmbiguousName() Arguments()
  877. }
  878. void PrimaryPrefix() : { }
  879. {
  880. Literal()
  881. |
  882. "(" Expression() ")"
  883. |
  884. AllocationExpression()
  885. |
  886. // SYNTACTIC_LOOKAHEAD
  887. LOOKAHEAD( MethodInvocation() )
  888. MethodInvocation()
  889. |
  890. LOOKAHEAD( Type() "." "class" )
  891. Type()
  892. |
  893. AmbiguousName()
  894. /*
  895. |
  896. LOOKAHEAD( "void" "." "class" )
  897. */
  898. }
  899. void PrimarySuffix() #PrimarySuffix :
  900. {
  901. Token t = null;
  902. }
  903. {
  904. LOOKAHEAD(2)
  905. "." "class" {
  906. jjtThis.operation = BSHPrimarySuffix.CLASS;
  907. }
  908. |
  909. "[" Expression() "]" {
  910. jjtThis.operation = BSHPrimarySuffix.INDEX;
  911. }
  912. |
  913. // Field access or method invocation
  914. "." t = <IDENTIFIER> [ Arguments() ] {
  915. jjtThis.operation = BSHPrimarySuffix.NAME;
  916. jjtThis.field = t.image;
  917. }
  918. |
  919. "{" Expression() "}" {
  920. jjtThis.operation = BSHPrimarySuffix.PROPERTY;
  921. }
  922. /*
  923. For inner classes
  924. |
  925. LOOKAHEAD(2)
  926. "." AllocationExpression()
  927. */
  928. }
  929. void Literal() #Literal :
  930. {
  931. Token x;
  932. boolean b;
  933. String literal;
  934. char ch;
  935. }
  936. {
  937. x = <INTEGER_LITERAL>
  938. {
  939. literal = x.image;
  940. ch = literal.charAt(literal.length()-1);
  941. if(ch == 'l' || ch == 'L')
  942. {
  943. literal = literal.substring(0,literal.length()-1);
  944. // This really should be Long.decode, but there isn't one. As a result,
  945. // hex and octal literals ending in 'l' or 'L' don't work.
  946. jjtThis.value = new Primitive( new Long( literal ) );
  947. }
  948. else
  949. try {
  950. jjtThis.value = new Primitive( Integer.decode( literal ) );
  951. } catch ( NumberFormatException e ) {
  952. throw createParseException(
  953. "Error or number too big for integer type: "+ literal );
  954. }
  955. }
  956. |
  957. x = <FLOATING_POINT_LITERAL>
  958. {
  959. literal = x.image;
  960. ch = literal.charAt(literal.length()-1);
  961. if(ch == 'f' || ch == 'F')
  962. {
  963. literal = literal.substring(0,literal.length()-1);
  964. jjtThis.value = new Primitive( new Float( literal ) );
  965. }
  966. else
  967. {
  968. if(ch == 'd' || ch == 'D')
  969. literal = literal.substring(0,literal.length()-1);
  970. jjtThis.value = new Primitive( new Double( literal ) );
  971. }
  972. }
  973. |
  974. x = <CHARACTER_LITERAL> {
  975. try {
  976. jjtThis.charSetup( x.image.substring(1, x.image.length() - 1) );
  977. } catch ( Exception e ) {
  978. throw createParseException("Error parsing character: "+x.image);
  979. }
  980. }
  981. |
  982. x = <STRING_LITERAL> {
  983. try {
  984. jjtThis.stringSetup( x.image.substring(1, x.image.length() - 1) );
  985. } catch ( Exception e ) {
  986. throw createParseException("Error parsing string: "+x.image);
  987. }
  988. }
  989. |
  990. b = BooleanLiteral() {
  991. jjtThis.value = new Primitive( new Boolean(b) ); }
  992. |
  993. NullLiteral() {
  994. jjtThis.value = Primitive.NULL;
  995. }
  996. |
  997. VoidLiteral() {
  998. jjtThis.value = Primitive.VOID; }
  999. }
  1000. boolean BooleanLiteral() :
  1001. {}
  1002. {
  1003. "true" { return true; }
  1004. |
  1005. "false" { return false; }
  1006. }
  1007. void NullLiteral() :
  1008. {}
  1009. {
  1010. "null"
  1011. }
  1012. void VoidLiteral() :
  1013. {}
  1014. {
  1015. "void"
  1016. }
  1017. void Arguments() #Arguments :
  1018. { }
  1019. {
  1020. "(" [ ArgumentList() ] ")"
  1021. }
  1022. // leave these on the stack for Arguments() to handle
  1023. void ArgumentList() :
  1024. { }
  1025. {
  1026. Expression()
  1027. ( "," Expression() )*
  1028. }
  1029. void AllocationExpression() #AllocationExpression :
  1030. { }
  1031. {
  1032. LOOKAHEAD(2)
  1033. "new" PrimitiveType() ArrayDimensions()
  1034. |
  1035. "new" AmbiguousName()
  1036. (
  1037. ArrayDimensions()
  1038. |
  1039. // SYNTACTIC_LOOKAHEAD
  1040. Arguments() [ LOOKAHEAD(2) Block() ]
  1041. )
  1042. }
  1043. void ArrayDimensions() #ArrayDimensions :
  1044. {}
  1045. {
  1046. // e.g. int [4][3][][];
  1047. LOOKAHEAD(2)
  1048. ( LOOKAHEAD(2) "[" Expression() "]" { jjtThis.addDefinedDimension(); } )+
  1049. ( LOOKAHEAD(2) "[" "]" { jjtThis.addUndefinedDimension(); } )*
  1050. |
  1051. // e.g. int [][] { {1,2}, {3,4} };
  1052. ( "[" "]" { jjtThis.addUndefinedDimension(); } )+ ArrayInitializer()
  1053. }
  1054. /*
  1055. * Statement syntax follows.
  1056. */
  1057. void Statement() : { }
  1058. {
  1059. LOOKAHEAD(2)
  1060. LabeledStatement()
  1061. |
  1062. Block()
  1063. |
  1064. EmptyStatement()
  1065. |
  1066. StatementExpression() ";"
  1067. |
  1068. SwitchStatement()
  1069. |
  1070. IfStatement()
  1071. |
  1072. WhileStatement()
  1073. |
  1074. DoStatement()
  1075. |
  1076. LOOKAHEAD ( { isRegularForStatement() } )
  1077. ForStatement()
  1078. |
  1079. EnhancedForStatement()
  1080. |
  1081. BreakStatement()
  1082. |
  1083. ContinueStatement()
  1084. |
  1085. ReturnStatement()
  1086. |
  1087. SynchronizedStatement()
  1088. |
  1089. ThrowStatement()
  1090. |
  1091. TryStatement()
  1092. }
  1093. void LabeledStatement() :
  1094. {}
  1095. {
  1096. <IDENTIFIER> ":" Statement()
  1097. }
  1098. void Block() #Block :
  1099. {}
  1100. {
  1101. "{" ( BlockStatement() )* "}"
  1102. }
  1103. void BlockStatement() :
  1104. {
  1105. }
  1106. {
  1107. // SYNTACTIC_LOOKAHEAD
  1108. LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) "class" )
  1109. ClassDeclaration()
  1110. |
  1111. // SYNTACTIC_LOOKAHEAD
  1112. LOOKAHEAD( MethodDeclarationLookahead() ) MethodDeclaration()
  1113. |
  1114. // SYNTACTIC_LOOKAHEAD
  1115. LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) Type() <IDENTIFIER> )
  1116. TypedVariableDeclaration() ";"
  1117. |
  1118. Statement()
  1119. |
  1120. // Allow BeanShell imports in any block
  1121. ImportDeclaration()
  1122. |
  1123. FormalComment()
  1124. }
  1125. void FormalComment() #FormalComment( retainComments ) :
  1126. {
  1127. Token t;
  1128. }
  1129. {
  1130. t=<FORMAL_COMMENT> {
  1131. jjtThis.text=t.image;
  1132. }
  1133. }
  1134. void EmptyStatement() :
  1135. {}
  1136. {
  1137. ";"
  1138. }
  1139. void StatementExpression() :
  1140. { }
  1141. {
  1142. /*
  1143. This is looser than normal Java to simplify the grammar. This allows
  1144. us to type arbitrary expressions on the command line, e.g. "1+1;"
  1145. We should turn this off in the implementation in strict java mode.
  1146. */
  1147. Expression()
  1148. /*
  1149. // This was the original Java grammar.
  1150. // Original comment:
  1151. // The last expansion of this production accepts more than the legal
  1152. // Java expansions for StatementExpression.
  1153. PreIncrementExpression()
  1154. |
  1155. PreDecrementExpression()
  1156. |
  1157. // SYNTACTIC_LOOKAHEAD
  1158. LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
  1159. Assignment() { }
  1160. |
  1161. PostfixExpression()
  1162. */
  1163. }
  1164. void SwitchStatement() #SwitchStatement :
  1165. {}
  1166. {
  1167. "switch" "(" Expression() ")" "{"
  1168. ( SwitchLabel() ( BlockStatement() )* )*
  1169. "}"
  1170. }
  1171. void SwitchLabel() #SwitchLabel :
  1172. {}
  1173. {
  1174. "case" Expression() ":"
  1175. |
  1176. "default" ":" { jjtThis.isDefault = true; }
  1177. }
  1178. void IfStatement() #IfStatement :
  1179. /*
  1180. * The disambiguating algorithm of JavaCC automatically binds dangling
  1181. * else's to the innermost if statement. The LOOKAHEAD specification
  1182. * is to tell JavaCC that we know what we are doing.
  1183. */
  1184. {}
  1185. {
  1186. "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ]
  1187. }
  1188. void WhileStatement() #WhileStatement :
  1189. {}
  1190. {
  1191. "while" "(" Expression() ")" Statement()
  1192. }
  1193. /*
  1194. Do statement is just a While statement with a special hook to execute
  1195. at least once.
  1196. */
  1197. void DoStatement() #WhileStatement :
  1198. {}
  1199. {
  1200. "do" Statement() "while" "(" Expression() ")" ";"
  1201. { jjtThis.isDoStatement=true; }
  1202. }
  1203. void ForStatement() #ForStatement :
  1204. { Token t = null; }
  1205. {
  1206. "for" "(" [ ForInit() { jjtThis.hasForInit=true; } ]
  1207. ";" [ Expression() { jjtThis.hasExpression=true; } ]
  1208. ";" [ ForUpdate() { jjtThis.hasForUpdate=true; } ] ")"
  1209. Statement()
  1210. }
  1211. /*
  1212. The new JDK1.5 enhanced for statement.
  1213. e.g. for( int a : arrayOfInts ) { }
  1214. We also support loose typing of the iterator var for BeanShell
  1215. e.g. for( a : arrayOfInts ) { }
  1216. */
  1217. void EnhancedForStatement() #EnhancedForStatement :
  1218. { Token t = null; }
  1219. {
  1220. LOOKAHEAD( 4 ) // look ahead for the ":" before deciding
  1221. "for" "(" t=<IDENTIFIER> ":" Expression() ")"
  1222. Statement() { jjtThis.varName = t.image; }
  1223. |
  1224. "for" "(" Type() t=<IDENTIFIER> ":" Expression() ")"
  1225. Statement() { jjtThis.varName = t.image; }
  1226. }
  1227. void ForInit() :
  1228. { Token t = null; }
  1229. {
  1230. // SYNTACTIC_LOOKAHEAD
  1231. LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) Type() <IDENTIFIER> )
  1232. TypedVariableDeclaration()
  1233. |
  1234. StatementExpressionList()
  1235. }
  1236. /**
  1237. Declared a typed variable.
  1238. Untyped variables are not declared per-se but are handled by the part
  1239. of the grammar that deals with assignments.
  1240. */
  1241. void TypedVariableDeclaration() #TypedVariableDeclaration :
  1242. {
  1243. Token t = null;
  1244. Modifiers mods;
  1245. }
  1246. {
  1247. mods = Modifiers( Modifiers.FIELD, false )
  1248. Type() VariableDeclarator() ( "," VariableDeclarator() )*
  1249. {
  1250. jjtThis.modifiers = mods;
  1251. }
  1252. }
  1253. void StatementExpressionList() #StatementExpressionList :
  1254. {}
  1255. {
  1256. StatementExpression() ( "," StatementExpression() )*
  1257. }
  1258. void ForUpdate() :
  1259. {}
  1260. {
  1261. StatementExpressionList()
  1262. }
  1263. void BreakStatement() #ReturnStatement :
  1264. {}
  1265. {
  1266. "break" [ <IDENTIFIER> ] ";" { jjtThis.kind = BREAK; }
  1267. }
  1268. void ContinueStatement() #ReturnStatement :
  1269. {}
  1270. {
  1271. "continue" [ <IDENTIFIER> ] ";" { jjtThis.kind = CONTINUE; }
  1272. }
  1273. void ReturnStatement() #ReturnStatement :
  1274. {}
  1275. {
  1276. "return" [ Expression() ] ";" { jjtThis.kind = RETURN; }
  1277. }
  1278. void SynchronizedStatement() #Block :
  1279. {
  1280. }
  1281. {
  1282. "synchronized" "(" Expression() ")" Block() {
  1283. jjtThis.isSynchronized=true;
  1284. }
  1285. }
  1286. void ThrowStatement() #ThrowStatement :
  1287. {}
  1288. {
  1289. "throw" Expression() ";"
  1290. }
  1291. void TryStatement() #TryStatement:
  1292. /*
  1293. Semantic check required here to make sure that at least one
  1294. finally/catch is present. (You can have a try with finally and no catch).
  1295. */
  1296. { boolean closed = false; }
  1297. {
  1298. "try" Block()
  1299. ( "catch" "(" FormalParameter() ")" Block() { closed = true; } )*
  1300. [ "finally" Block() { closed = true; } ]
  1301. {
  1302. if ( !closed ) throw generateParseException();
  1303. }
  1304. }