PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-0-pre5/bsh/bsh.jjt

#
Unknown | 1195 lines | 1089 code | 106 blank | 0 comment | 0 complexity | cb41e2878bc3dc093a926d24cf66fd82 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. /* Print detailed lookahead debugging info
  51. DEBUG_LOOKAHEAD=true; */
  52. }
  53. PARSER_BEGIN(Parser)
  54. package bsh;
  55. import java.io.Reader;
  56. class Parser {
  57. void jjtreeOpenNodeScope(Node n) {
  58. ((SimpleNode)n).firstToken = getToken(1);
  59. }
  60. void jjtreeCloseNodeScope(Node n) {
  61. ((SimpleNode)n).lastToken = getToken(0);
  62. }
  63. /**
  64. Re-initialize the input stream and token source.
  65. */
  66. void reInitInput( Reader in ) {
  67. ReInit(in);
  68. }
  69. /**
  70. Explicitly re-initialize just the token reader.
  71. This seems to be necessary to avoid certain looping errors when
  72. reading bogus input. See Interpreter.
  73. */
  74. void reInitTokenInput( Reader in ) {
  75. jj_input_stream.ReInit( in,
  76. jj_input_stream.getEndLine(),
  77. jj_input_stream.getEndColumn() );
  78. }
  79. }
  80. PARSER_END(Parser)
  81. SKIP : /* WHITE SPACE */
  82. {
  83. " " | "\t" | "\r" | "\f"
  84. | "\n"
  85. | < NONPRINTABLE: (["\u0000"-"\u0020", "\u0080"-"\u00ff"])+ >
  86. }
  87. SPECIAL_TOKEN : /* COMMENTS */
  88. {
  89. /*
  90. Single line comments fail on the last line of a file with no terminating
  91. linefeed. I thought the <EOF> would fix that, but no...
  92. <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* "<EOF>"|("\n"|"\r"|"\r\n")>
  93. */
  94. <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
  95. | <HASH_BANG_COMMENT: "#!" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
  96. | <FORMAL_COMMENT: "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
  97. | <MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
  98. }
  99. TOKEN : /* RESERVED WORDS AND LITERALS */
  100. {
  101. < BOOLEAN: "boolean" >
  102. | < BREAK: "break" >
  103. | < CLASS: "class" >
  104. | < BYTE: "byte" >
  105. | < CASE: "case" >
  106. | < CATCH: "catch" >
  107. | < CHAR: "char" >
  108. | < CONST: "const" >
  109. | < CONTINUE: "continue" >
  110. | < _DEFAULT: "default" >
  111. | < DO: "do" >
  112. | < DOUBLE: "double" >
  113. | < ELSE: "else" >
  114. | < FALSE: "false" >
  115. | < FINAL: "final" >
  116. | < FINALLY: "finally" >
  117. | < FLOAT: "float" >
  118. | < FOR: "for" >
  119. | < GOTO: "goto" >
  120. | < IF: "if" >
  121. | < IMPORT: "import" >
  122. | < INSTANCEOF: "instanceof" >
  123. | < INT: "int" >
  124. | < INTERFACE: "interface" >
  125. | < LONG: "long" >
  126. | < NEW: "new" >
  127. | < NULL: "null" >
  128. | < PRIVATE: "private" >
  129. | < PROTECTED: "protected" >
  130. | < PUBLIC: "public" >
  131. | < RETURN: "return" >
  132. | < SHORT: "short" >
  133. | < STATIC: "static" >
  134. | < SWITCH: "switch" >
  135. | < THROW: "throw" >
  136. | < TRUE: "true" >
  137. | < TRY: "try" >
  138. | < VOID: "void" >
  139. | < WHILE: "while" >
  140. }
  141. TOKEN : /* LITERALS */
  142. {
  143. < INTEGER_LITERAL:
  144. <DECIMAL_LITERAL> (["l","L"])?
  145. | <HEX_LITERAL> (["l","L"])?
  146. | <OCTAL_LITERAL> (["l","L"])?
  147. >
  148. |
  149. < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
  150. |
  151. < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
  152. |
  153. < #OCTAL_LITERAL: "0" (["0"-"7"])* >
  154. |
  155. < FLOATING_POINT_LITERAL:
  156. (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
  157. | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
  158. | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
  159. | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
  160. >
  161. |
  162. < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
  163. |
  164. < CHARACTER_LITERAL:
  165. "'"
  166. ( (~["'","\\","\n","\r"])
  167. | ("\\"
  168. ( ["n","t","b","r","f","\\","'","\""]
  169. | ["0"-"7"] ( ["0"-"7"] )?
  170. | ["0"-"3"] ["0"-"7"] ["0"-"7"]
  171. )
  172. )
  173. )
  174. "'"
  175. >
  176. |
  177. < STRING_LITERAL:
  178. "\""
  179. ( (~["\"","\\","\n","\r"])
  180. | ("\\"
  181. ( ["n","t","b","r","f","\\","'","\""]
  182. | ["0"-"7"] ( ["0"-"7"] )?
  183. | ["0"-"3"] ["0"-"7"] ["0"-"7"]
  184. )
  185. )
  186. )*
  187. "\""
  188. >
  189. }
  190. TOKEN : /* IDENTIFIERS */
  191. {
  192. < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
  193. |
  194. < #LETTER:
  195. [
  196. "\u0024",
  197. "\u0041"-"\u005a",
  198. "\u005f",
  199. "\u0061"-"\u007a",
  200. "\u00c0"-"\u00d6",
  201. "\u00d8"-"\u00f6",
  202. "\u00f8"-"\u00ff",
  203. "\u0100"-"\u1fff",
  204. "\u3040"-"\u318f",
  205. "\u3300"-"\u337f",
  206. "\u3400"-"\u3d2d",
  207. "\u4e00"-"\u9fff",
  208. "\uf900"-"\ufaff"
  209. ]
  210. >
  211. |
  212. < #DIGIT:
  213. [
  214. "\u0030"-"\u0039",
  215. "\u0660"-"\u0669",
  216. "\u06f0"-"\u06f9",
  217. "\u0966"-"\u096f",
  218. "\u09e6"-"\u09ef",
  219. "\u0a66"-"\u0a6f",
  220. "\u0ae6"-"\u0aef",
  221. "\u0b66"-"\u0b6f",
  222. "\u0be7"-"\u0bef",
  223. "\u0c66"-"\u0c6f",
  224. "\u0ce6"-"\u0cef",
  225. "\u0d66"-"\u0d6f",
  226. "\u0e50"-"\u0e59",
  227. "\u0ed0"-"\u0ed9",
  228. "\u1040"-"\u1049"
  229. ]
  230. >
  231. }
  232. TOKEN : /* SEPARATORS */
  233. {
  234. < LPAREN: "(" >
  235. | < RPAREN: ")" >
  236. | < LBRACE: "{" >
  237. | < RBRACE: "}" >
  238. | < LBRACKET: "[" >
  239. | < RBRACKET: "]" >
  240. | < SEMICOLON: ";" >
  241. | < COMMA: "," >
  242. | < DOT: "." >
  243. }
  244. TOKEN : /* OPERATORS */
  245. {
  246. < ASSIGN: "=" >
  247. | < GT: ">" >
  248. | < GTX: "@gt" >
  249. | < LT: "<" >
  250. | < LTX: "@lt" >
  251. | < BANG: "!" >
  252. | < TILDE: "~" >
  253. | < HOOK: "?" >
  254. | < COLON: ":" >
  255. | < EQ: "==" >
  256. | < LE: "<=" >
  257. | < LEX: "@lteq" >
  258. | < GE: ">=" >
  259. | < GEX: "@gteq" >
  260. | < NE: "!=" >
  261. | < BOOL_OR: "||" >
  262. | < BOOL_ORX: "@or" >
  263. | < BOOL_AND: "&&" >
  264. | < BOOL_ANDX: "@and" >
  265. | < INCR: "++" >
  266. | < DECR: "--" >
  267. | < PLUS: "+" >
  268. | < MINUS: "-" >
  269. | < STAR: "*" >
  270. | < SLASH: "/" >
  271. | < BIT_AND: "&" >
  272. | < BIT_ANDX: "@bitwise_and" >
  273. | < BIT_OR: "|" >
  274. | < BIT_ORX: "@bitwise_or" >
  275. | < XOR: "^" >
  276. | < MOD: "%" >
  277. | < LSHIFT: "<<" >
  278. | < LSHIFTX: "@left_shift" >
  279. | < RSIGNEDSHIFT: ">>" >
  280. | < RSIGNEDSHIFTX: "@right_shift" >
  281. | < RUNSIGNEDSHIFT: ">>>" >
  282. | < RUNSIGNEDSHIFTX: "@right_unsigned_shift" >
  283. | < PLUSASSIGN: "+=" >
  284. | < MINUSASSIGN: "-=" >
  285. | < STARASSIGN: "*=" >
  286. | < SLASHASSIGN: "/=" >
  287. | < ANDASSIGN: "&=" >
  288. | < ANDASSIGNX: "@and_assign" >
  289. | < ORASSIGN: "|=" >
  290. | < ORASSIGNX: "@or_assign" >
  291. | < XORASSIGN: "^=" >
  292. | < MODASSIGN: "%=" >
  293. | < LSHIFTASSIGN: "<<=" >
  294. | < LSHIFTASSIGNX: "@left_shift_assign" >
  295. | < RSIGNEDSHIFTASSIGN: ">>=" >
  296. | < RSIGNEDSHIFTASSIGNX: "@right_shift_assign" >
  297. | < RUNSIGNEDSHIFTASSIGN: ">>>=" >
  298. | < RUNSIGNEDSHIFTASSIGNX: "@right_unsigned_shift_assign" >
  299. }
  300. boolean Line() :
  301. {}
  302. {
  303. <EOF> {
  304. Interpreter.debug("End of File!");
  305. return true;
  306. }
  307. |
  308. (
  309. /*
  310. SYNTACTIC_LOOKAHEAD
  311. I'm guessing this is expensive, but I don't know how to work around
  312. it... Is there another syntactic indication that we are working
  313. through an expression as opposed to a statement?
  314. What is the difference? Well, some statements don't require a
  315. semicolon and they don't return vlues... We could probably broaden
  316. bsh to allow everything to return a value, but the semi-colon thing
  317. is tougher. You don't want to have to say if ( foo ) { } ;
  318. Maybe we can invert ths and enumerate all of those types of
  319. statements in a special lookahead that's cheaper??
  320. */
  321. LOOKAHEAD( Expression() ";" )
  322. Expression() ";"
  323. |
  324. BlockStatement()
  325. )
  326. {
  327. return false;
  328. }
  329. }
  330. /*****************************************
  331. * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
  332. *****************************************/
  333. void MethodDeclaration() #MethodDeclaration :
  334. { Token t = null; }
  335. {
  336. // SYNTACTIC_LOOKAHEAD
  337. // this one seems cheap enough
  338. LOOKAHEAD( MethodDeclarationTypeLookahead() )
  339. ReturnType() t = <IDENTIFIER> { jjtThis.name = t.image; }
  340. FormalParameters() Block()
  341. |
  342. t = <IDENTIFIER> { jjtThis.name = t.image; }
  343. FormalParameters() Block()
  344. }
  345. void MethodDeclarationLookahead() : { }
  346. {
  347. // SYNTACTIC_LOOKAHEAD
  348. // this one seems cheap enough
  349. LOOKAHEAD( MethodDeclarationTypeLookahead() )
  350. ReturnType() <IDENTIFIER> FormalParameters() "{"
  351. |
  352. <IDENTIFIER> FormalParameters() "{"
  353. }
  354. void MethodDeclarationTypeLookahead() : { }
  355. {
  356. ReturnType() <IDENTIFIER> "("
  357. }
  358. void ImportDeclaration() #ImportDeclaration :
  359. {
  360. Token t = null;
  361. }
  362. {
  363. LOOKAHEAD( 2 )
  364. "import" AmbiguousName() [ t = "." "*" ] ";" {
  365. if ( t != null )
  366. jjtThis.importPackage = true;
  367. }
  368. |
  369. // bsh super import statement
  370. "import" "*" ";" {
  371. jjtThis.superImport = true;
  372. }
  373. }
  374. void VariableDeclarator() #VariableDeclarator :
  375. { Token t; }
  376. {
  377. t=<IDENTIFIER> [ "=" VariableInitializer() ] { jjtThis.name = t.image; }
  378. }
  379. /*
  380. Can get rid of this if we ignore postfix array dimensions in declarations.
  381. I don't like them and I don't want to deal with them right now.
  382. void VariableDeclaratorId() #VariableDeclaratorId :
  383. { Token t; }
  384. {
  385. t=<IDENTIFIER> { jjtThis.name = t.image; }
  386. ( "[" "]" { jjtThis.addArrayDimension(); } )*
  387. }
  388. */
  389. void VariableInitializer() :
  390. {}
  391. {
  392. ArrayInitializer()
  393. |
  394. Expression()
  395. }
  396. void ArrayInitializer() #ArrayInitializer :
  397. {}
  398. {
  399. "{" [ VariableInitializer()
  400. ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"
  401. }
  402. void FormalParameters() #FormalParameters :
  403. {}
  404. {
  405. "(" [ FormalParameter() ( "," FormalParameter() )* ] ")"
  406. }
  407. /*
  408. void FormalParameter() #FormalParameter :
  409. { Token t; }
  410. {
  411. // added [] to Type for bsh. Removed [ final ] - is that legal?
  412. [ LOOKAHEAD(2) Type() ] t=<IDENTIFIER> { jjtThis.name = t.image; }
  413. }
  414. */
  415. void FormalParameter() #FormalParameter :
  416. { Token t; }
  417. {
  418. // added [] to Type for bsh. Removed [ final ] - is that legal?
  419. LOOKAHEAD(2) Type() t=<IDENTIFIER> { jjtThis.name = t.image; }
  420. |
  421. t=<IDENTIFIER> { jjtThis.name = t.image; }
  422. }
  423. /*
  424. Type, name and expression syntax follows.
  425. */
  426. void Type() #Type :
  427. { }
  428. {
  429. /*
  430. The embedded lookahead is (was?) necessary to disambiguate for
  431. PrimaryPrefix. ( )* is a choice point. It took me a while to
  432. figure out where to put that. This stuff is annoying.
  433. */
  434. ( PrimitiveType() | AmbiguousName() )
  435. ( LOOKAHEAD(2) "[" "]" { jjtThis.addArrayDimension(); } )*
  436. }
  437. /*
  438. Originally called ResultType in the grammar
  439. */
  440. void ReturnType() #ReturnType :
  441. { }
  442. {
  443. "void" { jjtThis.isVoid = true; }
  444. |
  445. Type()
  446. }
  447. void PrimitiveType() #PrimitiveType :
  448. { } {
  449. "boolean" { jjtThis.type = Boolean.TYPE; }
  450. | "char" { jjtThis.type = Character.TYPE; }
  451. | "byte" { jjtThis.type = Byte.TYPE; }
  452. | "short" { jjtThis.type = Short.TYPE; }
  453. | "int" { jjtThis.type = Integer.TYPE; }
  454. | "long" { jjtThis.type = Long.TYPE; }
  455. | "float" { jjtThis.type = Float.TYPE; }
  456. | "double" { jjtThis.type = Double.TYPE; }
  457. }
  458. void AmbiguousName() #AmbiguousName :
  459. /*
  460. * A lookahead of 2 is required below since "Name" can be followed
  461. * by a ".*" when used in the context of an "ImportDeclaration".
  462. */
  463. {
  464. Token t;
  465. StringBuffer s;
  466. }
  467. {
  468. t = <IDENTIFIER> {
  469. s = new StringBuffer(t.image);
  470. }
  471. ( LOOKAHEAD(2) "." t = <IDENTIFIER> {
  472. s.append("."+t.image);
  473. }
  474. )* {
  475. jjtThis.text = s.toString();
  476. }
  477. }
  478. /*
  479. * Expression syntax follows.
  480. */
  481. void Expression() :
  482. { }
  483. {
  484. /**
  485. SYNTACTIC_LOOKAHEAD
  486. This is probably expensive. Can we simplify it somehow?
  487. */
  488. LOOKAHEAD( LHSPrimaryExpression() AssignmentOperator() )
  489. Assignment()
  490. |
  491. ConditionalExpression()
  492. }
  493. void Assignment() #Assignment :
  494. { int op ; }
  495. {
  496. LHSPrimaryExpression()
  497. op = AssignmentOperator() {
  498. jjtThis.operator = op;
  499. }
  500. Expression()
  501. }
  502. int AssignmentOperator() :
  503. { Token t; }
  504. {
  505. ( "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "&=" | "^=" | "|=" |
  506. "<<=" | "@left_shift_assign" | ">>=" | "@right_shift_assign" |
  507. ">>>=" | "@right_unsigned_shift_assign" )
  508. {
  509. t = getToken(0);
  510. return t.kind;
  511. }
  512. }
  513. void ConditionalExpression() :
  514. { }
  515. {
  516. ConditionalOrExpression() [ "?" Expression() ":" ConditionalExpression()
  517. #TernaryExpression(3) ]
  518. }
  519. void ConditionalOrExpression() :
  520. { Token t=null; }
  521. {
  522. ConditionalAndExpression()
  523. ( ( t = "||" | t = "@or" )
  524. ConditionalAndExpression()
  525. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  526. }
  527. void ConditionalAndExpression() :
  528. { Token t=null; }
  529. {
  530. InclusiveOrExpression()
  531. ( ( t = "&&" | t = "@and" )
  532. InclusiveOrExpression()
  533. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  534. }
  535. void InclusiveOrExpression() :
  536. { Token t=null; }
  537. {
  538. ExclusiveOrExpression()
  539. ( ( t = "|" | t = "@bitwise_or" )
  540. ExclusiveOrExpression()
  541. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  542. }
  543. void ExclusiveOrExpression() :
  544. { Token t=null; }
  545. {
  546. AndExpression() ( t="^" AndExpression()
  547. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  548. }
  549. void AndExpression() :
  550. { Token t=null; }
  551. {
  552. EqualityExpression()
  553. ( ( t = "&" | t = "@bitwise_and" )
  554. EqualityExpression()
  555. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  556. }
  557. void EqualityExpression() :
  558. { Token t = null; }
  559. {
  560. InstanceOfExpression() ( ( t= "==" | t= "!=" ) InstanceOfExpression()
  561. { jjtThis.kind = t.kind; } #BinaryExpression(2)
  562. )*
  563. }
  564. void InstanceOfExpression() :
  565. { Token t = null; }
  566. {
  567. RelationalExpression()
  568. [ t = "instanceof" Type() { jjtThis.kind = t.kind; } #BinaryExpression(2) ]
  569. }
  570. void RelationalExpression() :
  571. { Token t = null; }
  572. {
  573. ShiftExpression()
  574. ( ( t = "<" | t = "@lt" | t = ">" | t = "@gt" |
  575. t = "<=" | t = "@lteq" | t = ">=" | t = "@gteq" )
  576. ShiftExpression()
  577. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  578. }
  579. void ShiftExpression() :
  580. { Token t = null; }
  581. {
  582. AdditiveExpression()
  583. ( ( t = "<<" | t = "@left_shift" | t = ">>" | t = "@right_shift" |
  584. t = ">>>" | t = "@right_unsigned_shift" )
  585. AdditiveExpression()
  586. { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  587. }
  588. void AdditiveExpression() :
  589. { Token t = null; }
  590. {
  591. MultiplicativeExpression()
  592. ( ( t= "+" | t= "-" ) MultiplicativeExpression() { jjtThis.kind = t.kind; }
  593. #BinaryExpression(2)
  594. )*
  595. }
  596. void MultiplicativeExpression() :
  597. { Token t = null; }
  598. {
  599. UnaryExpression() ( ( t= "*" | t= "/" | t= "%" )
  600. UnaryExpression() { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
  601. }
  602. void UnaryExpression() :
  603. { Token t = null; }
  604. {
  605. ( t="+" | t="-" ) UnaryExpression()
  606. { jjtThis.kind = t.kind; } #UnaryExpression(1)
  607. |
  608. PreIncrementExpression()
  609. |
  610. PreDecrementExpression()
  611. |
  612. UnaryExpressionNotPlusMinus()
  613. }
  614. void PreIncrementExpression() :
  615. { Token t = null; }
  616. {
  617. t="++" LHSPrimaryExpression()
  618. { jjtThis.kind = t.kind; } #UnaryExpression(1)
  619. }
  620. void PreDecrementExpression() :
  621. { Token t = null; }
  622. {
  623. t="--" LHSPrimaryExpression()
  624. { jjtThis.kind = t.kind; } #UnaryExpression(1)
  625. }
  626. void UnaryExpressionNotPlusMinus() :
  627. { Token t = null; }
  628. {
  629. ( t="~" | t="!" ) UnaryExpression()
  630. { jjtThis.kind = t.kind; } #UnaryExpression(1)
  631. |
  632. // SYNTACTIC_LOOKAHEAD
  633. LOOKAHEAD( CastLookahead() ) CastExpression()
  634. |
  635. PostfixExpression()
  636. }
  637. // This production is to determine lookahead only.
  638. void CastLookahead() : { }
  639. {
  640. LOOKAHEAD(2) "(" PrimitiveType()
  641. |
  642. // SYNTACTIC_LOOKAHEAD
  643. LOOKAHEAD( "(" AmbiguousName() "[" ) "(" AmbiguousName() "[" "]"
  644. |
  645. "(" AmbiguousName() ")" ( "~" | "!" | "(" | <IDENTIFIER> | /* "this" | "super" | */ "new" | Literal() )
  646. }
  647. void PostfixExpression() :
  648. { Token t = null; }
  649. {
  650. (
  651. // SYNTACTIC_LOOKAHEAD
  652. LOOKAHEAD( LHSPrimaryExpression() ("++"|"--") )
  653. LHSPrimaryExpression()
  654. [ ( t="++" | t="--" ) {
  655. jjtThis.kind = t.kind; jjtThis.postfix = true; } #UnaryExpression(1) ]
  656. |
  657. PrimaryExpression()
  658. )
  659. }
  660. void CastExpression() #CastExpression :
  661. { }
  662. {
  663. // SYNTACTIC_LOOKAHEAD
  664. LOOKAHEAD( "(" PrimitiveType() ) "(" Type() ")" UnaryExpression()
  665. |
  666. "(" Type() ")" UnaryExpressionNotPlusMinus()
  667. }
  668. void PrimaryExpression() #PrimaryExpression : { }
  669. {
  670. PrimaryPrefix() ( PrimarySuffix() )*
  671. }
  672. // The MethodInvocation node here simplifies the prefix/suffix parsing a bit
  673. // by forcing the prefix to an object.
  674. void PrimaryPrefix() : { }
  675. {
  676. Literal()
  677. |
  678. "(" Expression() ")"
  679. |
  680. AllocationExpression()
  681. |
  682. // SYNTACTIC_LOOKAHEAD
  683. LOOKAHEAD( Type() "." "class" )
  684. Type()
  685. |
  686. /*
  687. Handle method invocation OR straight ambigous name...
  688. (probably should just write this as two rules more clearly)
  689. */
  690. ( AmbiguousName() [ Arguments() ] ) #MethodInvocation(>1)
  691. /*
  692. |
  693. LOOKAHEAD( "void" "." "class" )
  694. */
  695. }
  696. void PrimarySuffix() #PrimarySuffix :
  697. {
  698. Token t = null;
  699. }
  700. {
  701. LOOKAHEAD(2)
  702. "." "class" {
  703. jjtThis.operation = BSHPrimarySuffix.CLASS;
  704. }
  705. |
  706. "[" Expression() "]" {
  707. jjtThis.operation = BSHPrimarySuffix.INDEX;
  708. }
  709. |
  710. // Field access or method invocation
  711. "." t = <IDENTIFIER> [ Arguments() ] {
  712. jjtThis.operation = BSHPrimarySuffix.NAME;
  713. jjtThis.field = t.image;
  714. }
  715. |
  716. "{" Expression() "}" {
  717. jjtThis.operation = BSHPrimarySuffix.PROPERTY;
  718. }
  719. /*
  720. For inner classes
  721. |
  722. LOOKAHEAD(2)
  723. "." AllocationExpression()
  724. */
  725. }
  726. /*
  727. Begin LHS part of the grammar --
  728. The reason this stuff is duplicated (e.g. LHSPrimaryPrefix and
  729. PrimaryPrefix) is that the whole grammar splits based on whether we
  730. are preparig to do an assignment or not. This is an important issue
  731. to revisit in the future.
  732. */
  733. /**
  734. The method invocation is here to force this to an object type in order
  735. to simplify the suffix processing.
  736. */
  737. void LHSPrimaryPrefix() : { }
  738. {
  739. /*
  740. Method invocation or simple ambiguous name.
  741. (probably should just write this as two rules more clearly)
  742. */
  743. ( AmbiguousName() [ Arguments() ] ) #MethodInvocation(>1)
  744. }
  745. void LHSPrimaryExpression() #LHSPrimaryExpression : { }
  746. {
  747. LHSPrimaryPrefix() ( LHSPrimarySuffix( ) )*
  748. }
  749. void LHSPrimarySuffix() #LHSPrimarySuffix :
  750. {
  751. Token t=null, t1, t2 = null;
  752. }
  753. {
  754. // Indexed to a field
  755. "[" Expression() "]" {
  756. jjtThis.operation = BSHLHSPrimarySuffix.INDEX;
  757. }
  758. |
  759. // Field access or method invocation followed by field access
  760. "." t1 = <IDENTIFIER> [ Arguments() "." t2 = <IDENTIFIER> ] {
  761. jjtThis.operation = BSHLHSPrimarySuffix.NAME;
  762. if ( t2 == null )
  763. jjtThis.field = t1.image;
  764. else {
  765. jjtThis.method = t1.image;
  766. jjtThis.field = t2.image;
  767. }
  768. }
  769. |
  770. "{" Expression() "}" {
  771. jjtThis.operation = BSHLHSPrimarySuffix.PROPERTY;
  772. }
  773. }
  774. /*
  775. -- End LHS part of the grammar
  776. */
  777. void Literal() #Literal :
  778. {
  779. Token x;
  780. boolean b;
  781. String literal;
  782. char ch;
  783. }
  784. {
  785. x = <INTEGER_LITERAL>
  786. {
  787. literal = x.image;
  788. ch = literal.charAt(literal.length()-1);
  789. if(ch == 'l' || ch == 'L')
  790. {
  791. literal = literal.substring(0,literal.length()-1);
  792. // This really should be Long.decode, but there isn't one. As a result,
  793. // hex and octal literals ending in 'l' or 'L' don't work.
  794. jjtThis.value = new Primitive( new Long( literal ) );
  795. }
  796. else
  797. jjtThis.value = new Primitive( Integer.decode( literal ) );
  798. }
  799. |
  800. x = <FLOATING_POINT_LITERAL>
  801. {
  802. literal = x.image;
  803. ch = literal.charAt(literal.length()-1);
  804. if(ch == 'f' || ch == 'F')
  805. {
  806. literal = literal.substring(0,literal.length()-1);
  807. jjtThis.value = new Primitive( new Float( literal ) );
  808. }
  809. else
  810. {
  811. if(ch == 'd' || ch == 'D')
  812. literal = literal.substring(0,literal.length()-1);
  813. jjtThis.value = new Primitive( new Double( literal ) );
  814. }
  815. }
  816. |
  817. x = <CHARACTER_LITERAL> {
  818. try {
  819. jjtThis.charSetup( x.image.substring(1, x.image.length() - 1) );
  820. } catch ( Exception e ) {
  821. throw new ParseException("Error parsing character: "+x.image);
  822. }
  823. }
  824. |
  825. x = <STRING_LITERAL> {
  826. try {
  827. jjtThis.stringSetup( x.image.substring(1, x.image.length() - 1) );
  828. } catch ( Exception e ) {
  829. throw new ParseException("Error parsing string: "+x.image);
  830. }
  831. }
  832. |
  833. b = BooleanLiteral() {
  834. jjtThis.value = new Primitive( new Boolean(b) ); }
  835. |
  836. NullLiteral() {
  837. jjtThis.value = Primitive.NULL;
  838. }
  839. |
  840. VoidLiteral() {
  841. jjtThis.value = Primitive.VOID; }
  842. }
  843. boolean BooleanLiteral() :
  844. {}
  845. {
  846. "true" { return true; }
  847. |
  848. "false" { return false; }
  849. }
  850. void NullLiteral() :
  851. {}
  852. {
  853. "null"
  854. }
  855. void VoidLiteral() :
  856. {}
  857. {
  858. "void"
  859. }
  860. void Arguments() #Arguments :
  861. { }
  862. {
  863. "(" [ ArgumentList() ] ")"
  864. }
  865. // leave these on the stack for Arguments() to handle
  866. void ArgumentList() :
  867. { }
  868. {
  869. Expression()
  870. ( "," Expression() )*
  871. }
  872. void AllocationExpression() #AllocationExpression :
  873. { }
  874. {
  875. LOOKAHEAD(2)
  876. "new" PrimitiveType() ArrayDimensions()
  877. |
  878. "new" AmbiguousName()
  879. (
  880. ArrayDimensions()
  881. |
  882. // SYNTACTIC_LOOKAHEAD
  883. Arguments() [ LOOKAHEAD(2) Block() ]
  884. )
  885. }
  886. void ArrayDimensions() #ArrayDimensions :
  887. {}
  888. {
  889. LOOKAHEAD(2)
  890. ( LOOKAHEAD(2) "[" Expression() "]" { jjtThis.addArrayDimension(); } )+
  891. // Removed trailing "[]" identifiers. Specify array dims fully.
  892. |
  893. ( "[" "]" { jjtThis.addArrayDimension(); } )+ ArrayInitializer()
  894. }
  895. /*
  896. * Statement syntax follows.
  897. */
  898. void Statement() : { }
  899. {
  900. LOOKAHEAD(2)
  901. LabeledStatement()
  902. |
  903. Block()
  904. |
  905. EmptyStatement()
  906. |
  907. StatementExpression() ";"
  908. |
  909. SwitchStatement()
  910. |
  911. IfStatement()
  912. |
  913. WhileStatement()
  914. |
  915. DoStatement()
  916. |
  917. ForStatement()
  918. |
  919. BreakStatement()
  920. |
  921. ContinueStatement()
  922. |
  923. ReturnStatement()
  924. |
  925. ThrowStatement()
  926. |
  927. TryStatement()
  928. }
  929. void LabeledStatement() :
  930. {}
  931. {
  932. <IDENTIFIER> ":" Statement()
  933. }
  934. void Block() #Block :
  935. {}
  936. {
  937. "{" ( BlockStatement() )* "}"
  938. }
  939. void BlockStatement() :
  940. {}
  941. {
  942. // SYNTACTIC_LOOKAHEAD
  943. LOOKAHEAD( MethodDeclarationLookahead() ) MethodDeclaration()
  944. |
  945. // SYNTACTIC_LOOKAHEAD
  946. LOOKAHEAD([ "final" ] Type() <IDENTIFIER>)
  947. TypedVariableDeclaration() ";"
  948. |
  949. Statement()
  950. /* end */
  951. |
  952. // Allow BeanShell imports in any block
  953. ImportDeclaration()
  954. }
  955. void EmptyStatement() :
  956. {}
  957. {
  958. ";"
  959. }
  960. void StatementExpression() :
  961. /*
  962. * The last expansion of this production accepts more than the legal
  963. * Java expansions for StatementExpression.
  964. */
  965. { }
  966. {
  967. PreIncrementExpression()
  968. |
  969. PreDecrementExpression()
  970. |
  971. // SYNTACTIC_LOOKAHEAD
  972. LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
  973. Assignment() { }
  974. |
  975. PostfixExpression()
  976. }
  977. void SwitchStatement() #SwitchStatement :
  978. {}
  979. {
  980. "switch" "(" Expression() ")" "{"
  981. ( SwitchLabel() ( BlockStatement() )* )*
  982. "}"
  983. }
  984. void SwitchLabel() #SwitchLabel :
  985. {}
  986. {
  987. "case" Expression() ":"
  988. |
  989. "default" ":" { jjtThis.isDefault = true; }
  990. }
  991. void IfStatement() #IfStatement :
  992. /*
  993. * The disambiguating algorithm of JavaCC automatically binds dangling
  994. * else's to the innermost if statement. The LOOKAHEAD specification
  995. * is to tell JavaCC that we know what we are doing.
  996. */
  997. {}
  998. {
  999. "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ]
  1000. }
  1001. void WhileStatement() #WhileStatement :
  1002. {}
  1003. {
  1004. "while" "(" Expression() ")" Statement()
  1005. }
  1006. /*
  1007. Do statement is just a While statement with a special hook to execute
  1008. at least once.
  1009. */
  1010. void DoStatement() #WhileStatement :
  1011. {}
  1012. {
  1013. "do" Statement() "while" "(" Expression() ")" ";"
  1014. { jjtThis.isDoStatement=true; }
  1015. }
  1016. void ForStatement() #ForStatement :
  1017. {}
  1018. {
  1019. "for" "(" [ ForInit() { jjtThis.hasForInit=true; } ]
  1020. ";" [ Expression() { jjtThis.hasExpression=true; } ]
  1021. ";" [ ForUpdate() { jjtThis.hasForUpdate=true; } ] ")"
  1022. Statement()
  1023. }
  1024. void ForInit() :
  1025. { Token t = null; }
  1026. {
  1027. // SYNTACTIC_LOOKAHEAD
  1028. LOOKAHEAD( [ t="final" ] Type() <IDENTIFIER> )
  1029. TypedVariableDeclaration()
  1030. |
  1031. StatementExpressionList()
  1032. }
  1033. /**
  1034. Declared a typed variable.
  1035. Untyped variables are not declared per-se but are handled by the part
  1036. of the grammar that deals with assignments.
  1037. */
  1038. void TypedVariableDeclaration() #TypedVariableDeclaration :
  1039. {
  1040. Token t = null;
  1041. }
  1042. {
  1043. [ t="final" ] Type()
  1044. VariableDeclarator() ( "," VariableDeclarator() )*
  1045. {
  1046. jjtThis.isFinal = (t!=null);
  1047. }
  1048. }
  1049. void StatementExpressionList() #StatementExpressionList :
  1050. {}
  1051. {
  1052. StatementExpression() ( "," StatementExpression() )*
  1053. }
  1054. void ForUpdate() :
  1055. {}
  1056. {
  1057. StatementExpressionList()
  1058. }
  1059. void BreakStatement() #ReturnStatement :
  1060. {}
  1061. {
  1062. "break" [ <IDENTIFIER> ] ";" { jjtThis.kind = BREAK; }
  1063. }
  1064. void ContinueStatement() #ReturnStatement :
  1065. {}
  1066. {
  1067. "continue" [ <IDENTIFIER> ] ";" { jjtThis.kind = CONTINUE; }
  1068. }
  1069. void ReturnStatement() #ReturnStatement :
  1070. {}
  1071. {
  1072. "return" [ Expression() ] ";" { jjtThis.kind = RETURN; }
  1073. }
  1074. void ThrowStatement() #ThrowStatement :
  1075. {}
  1076. {
  1077. "throw" Expression() ";"
  1078. }
  1079. void TryStatement() #TryStatement:
  1080. /*
  1081. * Semantic check required here to make sure that at least one
  1082. * finally/catch is present.
  1083. */
  1084. {}
  1085. {
  1086. "try" Block()
  1087. ( "catch" "(" FormalParameter() ")" Block() )*
  1088. [ "finally" Block() ]
  1089. }