PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

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

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