PageRenderTime 79ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/ext/melbourne/grammar18.y

https://github.com/ethansr/rubinius
Happy | 6098 lines | 5552 code | 546 blank | 0 comment | 0 complexity | a7866c79593b354f3ddbf3672e93d778 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1
  1. /**********************************************************************
  2. parse.y -
  3. $Author: matz $
  4. $Date: 2004/11/29 06:13:51 $
  5. created at: Fri May 28 18:02:42 JST 1993
  6. Copyright (C) 1993-2003 Yukihiro Matsumoto
  7. **********************************************************************/
  8. %{
  9. #define YYDEBUG 1
  10. #define YYERROR_VERBOSE 1
  11. #include <stdio.h>
  12. #include <errno.h>
  13. #include <ctype.h>
  14. #include <string.h>
  15. #include <stdbool.h>
  16. #include <stdint.h>
  17. #include <assert.h>
  18. #include "ruby.h"
  19. #include "grammar18.hpp"
  20. #include "parser_state18.hpp"
  21. #include "visitor18.hpp"
  22. #include "symbols.hpp"
  23. namespace melbourne {
  24. namespace grammar18 {
  25. #ifndef isnumber
  26. #define isnumber isdigit
  27. #endif
  28. /* Defined at least in mach/boolean.h on OS X. */
  29. #ifdef TRUE
  30. #undef TRUE
  31. #endif
  32. #ifdef FALSE
  33. #undef FALSE
  34. #endif
  35. #define TRUE true
  36. #define FALSE false
  37. /*
  38. #define ISALPHA isalpha
  39. #define ISSPACE isspace
  40. #define ISALNUM(x) (isalpha(x) || isnumber(x))
  41. #define ISDIGIT isdigit
  42. #define ISXDIGIT isxdigit
  43. #define ISUPPER isupper
  44. */
  45. #define ismbchar(c) (0)
  46. #define mbclen(c) (1)
  47. #define string_new(ptr, len) blk2bstr(ptr, len)
  48. #define string_new2(ptr) cstr2bstr(ptr)
  49. static int
  50. mel_yyerror(const char *, rb_parser_state*);
  51. #define yyparse mel_yyparse
  52. #define yylex mel_yylex
  53. #define yyerror(str) mel_yyerror(str, (rb_parser_state*)parser_state)
  54. #define yylval mel_yylval
  55. #define yychar mel_yychar
  56. #define yydebug mel_yydebug
  57. #define YYPARSE_PARAM parser_state
  58. #define YYLEX_PARAM parser_state
  59. #define ID_SCOPE_SHIFT 3
  60. #define ID_SCOPE_MASK 0x07
  61. #define ID_LOCAL 0x01
  62. #define ID_INSTANCE 0x02
  63. #define ID_GLOBAL 0x03
  64. #define ID_ATTRSET 0x04
  65. #define ID_CONST 0x05
  66. #define ID_CLASS 0x06
  67. #define ID_JUNK 0x07
  68. #define ID_INTERNAL ID_JUNK
  69. #define is_notop_id(id) ((id)>tLAST_TOKEN)
  70. #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
  71. #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
  72. #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
  73. #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
  74. #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
  75. #define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
  76. #define is_junk_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_JUNK)
  77. #define is_asgn_or_id(id) ((is_notop_id(id)) && \
  78. (((id)&ID_SCOPE_MASK) == ID_GLOBAL || \
  79. ((id)&ID_SCOPE_MASK) == ID_INSTANCE || \
  80. ((id)&ID_SCOPE_MASK) == ID_CLASS))
  81. /* FIXME these went into the ruby_state instead of parser_state
  82. because a ton of other crap depends on it
  83. char *ruby_sourcefile; current source file
  84. int ruby_sourceline; current line no.
  85. */
  86. static int yylex(void*, void *);
  87. #define BITSTACK_PUSH(stack, n) (stack = (stack<<1)|((n)&1))
  88. #define BITSTACK_POP(stack) (stack >>= 1)
  89. #define BITSTACK_LEXPOP(stack) (stack = (stack >> 1) | (stack & 1))
  90. #define BITSTACK_SET_P(stack) (stack&1)
  91. #define COND_PUSH(n) BITSTACK_PUSH(cond_stack, n)
  92. #define COND_POP() BITSTACK_POP(cond_stack)
  93. #define COND_LEXPOP() BITSTACK_LEXPOP(cond_stack)
  94. #define COND_P() BITSTACK_SET_P(cond_stack)
  95. #define CMDARG_PUSH(n) BITSTACK_PUSH(cmdarg_stack, n)
  96. #define CMDARG_POP() BITSTACK_POP(cmdarg_stack)
  97. #define CMDARG_LEXPOP() BITSTACK_LEXPOP(cmdarg_stack)
  98. #define CMDARG_P() BITSTACK_SET_P(cmdarg_stack)
  99. static NODE *cond(NODE*,rb_parser_state*);
  100. static NODE *logop(enum node_type,NODE*,NODE*,rb_parser_state*);
  101. static int cond_negative(NODE**);
  102. static NODE *newline_node(rb_parser_state*,NODE*);
  103. static void fixpos(NODE*,NODE*);
  104. static int value_expr0(NODE*,rb_parser_state*);
  105. static void void_expr0(NODE*,rb_parser_state*);
  106. static void void_stmts(NODE*,rb_parser_state*);
  107. static NODE *remove_begin(NODE*,rb_parser_state*);
  108. #define value_expr(node) value_expr0((node) = \
  109. remove_begin(node, (rb_parser_state*)parser_state), \
  110. (rb_parser_state*)parser_state)
  111. #define void_expr(node) void_expr0((node) = \
  112. remove_begin(node, (rb_parser_state*)parser_state), \
  113. (rb_parser_state*)parser_state)
  114. static NODE *block_append(rb_parser_state*,NODE*,NODE*);
  115. static NODE *list_append(rb_parser_state*,NODE*,NODE*);
  116. static NODE *list_concat(NODE*,NODE*);
  117. static NODE *arg_concat(rb_parser_state*,NODE*,NODE*);
  118. static NODE *arg_prepend(rb_parser_state*,NODE*,NODE*);
  119. static NODE *literal_concat(rb_parser_state*,NODE*,NODE*);
  120. static NODE *new_evstr(rb_parser_state*,NODE*);
  121. static NODE *evstr2dstr(rb_parser_state*,NODE*);
  122. static NODE *call_op(NODE*,QUID,int,NODE*,rb_parser_state*);
  123. /* static NODE *negate_lit(NODE*); */
  124. static NODE *ret_args(rb_parser_state*,NODE*);
  125. static NODE *arg_blk_pass(NODE*,NODE*);
  126. static NODE *new_call(rb_parser_state*,NODE*,QUID,NODE*);
  127. static NODE *new_fcall(rb_parser_state*,QUID,NODE*);
  128. static NODE *new_super(rb_parser_state*,NODE*);
  129. static NODE *new_yield(rb_parser_state*,NODE*);
  130. static NODE *mel_gettable(rb_parser_state*,QUID);
  131. #define gettable(i) mel_gettable((rb_parser_state*)parser_state, i)
  132. static NODE *assignable(QUID,NODE*,rb_parser_state*);
  133. static NODE *aryset(NODE*,NODE*,rb_parser_state*);
  134. static NODE *attrset(NODE*,QUID,rb_parser_state*);
  135. static void rb_backref_error(NODE*,rb_parser_state*);
  136. static NODE *node_assign(NODE*,NODE*,rb_parser_state*);
  137. static NODE *match_gen(NODE*,NODE*,rb_parser_state*);
  138. static void mel_local_push(rb_parser_state*, int cnt);
  139. #define local_push(cnt) mel_local_push(vps, cnt)
  140. static void mel_local_pop(rb_parser_state*);
  141. #define local_pop() mel_local_pop(vps)
  142. static intptr_t mel_local_cnt(rb_parser_state*,QUID);
  143. #define local_cnt(i) mel_local_cnt(vps, i)
  144. static int mel_local_id(rb_parser_state*,QUID);
  145. #define local_id(i) mel_local_id(vps, i)
  146. static QUID *mel_local_tbl(rb_parser_state *st);
  147. static QUID convert_op(rb_parser_state *st, QUID id);
  148. #define QUID2SYM(x) (x)
  149. static void tokadd(char c, rb_parser_state *parser_state);
  150. static int tokadd_string(int, int, int, QUID*, rb_parser_state*);
  151. rb_parser_state *parser_alloc_state() {
  152. rb_parser_state *parser_state;
  153. parser_state = (rb_parser_state*)calloc(1, sizeof(rb_parser_state));
  154. lex_pbeg = 0;
  155. lex_p = 0;
  156. lex_pend = 0;
  157. parse_error = false;
  158. eofp = false;
  159. command_start = true;
  160. class_nest = 0;
  161. in_single = 0;
  162. in_def = 0;
  163. compile_for_eval = 0;
  164. cur_mid = 0;
  165. tokenbuf = NULL;
  166. tokidx = 0;
  167. toksiz = 0;
  168. memory_cur = NULL;
  169. memory_last_addr = NULL;
  170. current_pool = 0;
  171. pool_size = 0;
  172. memory_size = 204800;
  173. memory_pools = NULL;
  174. emit_warnings = 0;
  175. verbose = RTEST(ruby_verbose);
  176. magic_comments = new std::vector<bstring>;
  177. start_lines = new std::list<StartPosition>;
  178. quark_indexes = new quark_map();
  179. quarks = new quark_vector();
  180. return parser_state;
  181. }
  182. void *pt_allocate(rb_parser_state *parser_state, int size) {
  183. void *cur;
  184. if(!memory_cur || ((memory_cur + size) >= memory_last_addr)) {
  185. if(memory_cur) current_pool++;
  186. if(current_pool == pool_size) {
  187. pool_size += 10;
  188. if(memory_pools) {
  189. memory_pools = (void**)realloc(memory_pools, sizeof(void*) * pool_size);
  190. } else {
  191. memory_pools = (void**)malloc(sizeof(void*) * pool_size);
  192. }
  193. }
  194. memory_pools[current_pool] = malloc(memory_size);
  195. memory_cur = (char*)memory_pools[current_pool];
  196. memory_last_addr = memory_cur + memory_size - 1;
  197. }
  198. cur = (void*)memory_cur;
  199. memory_cur = memory_cur + size;
  200. return cur;
  201. }
  202. void pt_free(rb_parser_state *parser_state) {
  203. int i;
  204. if(line_buffer) {
  205. bdestroy(line_buffer);
  206. }
  207. if(lex_lastline) {
  208. bdestroy(lex_lastline);
  209. }
  210. free(tokenbuf);
  211. delete variables;
  212. for(std::vector<bstring>::iterator i = magic_comments->begin();
  213. i != magic_comments->end();
  214. i++) {
  215. bdestroy(*i);
  216. }
  217. delete magic_comments;
  218. delete start_lines;
  219. if(memory_pools) {
  220. for(i = 0; i <= current_pool; i++) {
  221. free(memory_pools[i]);
  222. }
  223. free(memory_pools);
  224. }
  225. quark_cleanup(parser_state);
  226. }
  227. #define SHOW_PARSER_WARNS 0
  228. static int rb_compile_error(rb_parser_state *st, const char *fmt, ...) {
  229. va_list ar;
  230. char msg[256];
  231. int count;
  232. va_start(ar, fmt);
  233. count = vsnprintf(msg, 256, fmt, ar);
  234. va_end(ar);
  235. mel_yyerror(msg, st);
  236. return count;
  237. }
  238. static int _debug_print(const char *fmt, ...) {
  239. #if SHOW_PARSER_WARNS
  240. va_list ar;
  241. int i;
  242. va_start(ar, fmt);
  243. i = vprintf(fmt, ar);
  244. va_end(ar);
  245. return i;
  246. #else
  247. return 0;
  248. #endif
  249. }
  250. #define rb_warn _debug_print
  251. #define rb_warning _debug_print
  252. void push_start_line(rb_parser_state* parser_state, int line, const char* which) {
  253. start_lines->push_back(StartPosition(line, which));
  254. }
  255. #define PUSH_LINE(which) push_start_line((rb_parser_state*)parser_state, ruby_sourceline, which)
  256. void pop_start_line(rb_parser_state* parser_state) {
  257. start_lines->pop_back();
  258. }
  259. #define POP_LINE() pop_start_line((rb_parser_state*)parser_state)
  260. static QUID rb_parser_sym(rb_parser_state *parser_state, const char *name);
  261. static QUID rb_id_attrset(rb_parser_state *parser_state, QUID);
  262. static int scan_oct(const char *start, int len, int *retlen);
  263. static int scan_hex(const char *start, int len, int *retlen);
  264. static void reset_block(rb_parser_state *parser_state);
  265. static NODE *extract_block_vars(rb_parser_state *parser_state, NODE* node, var_table vars);
  266. #ifndef RE_OPTION_IGNORECASE
  267. #define RE_OPTION_IGNORECASE (1)
  268. #endif
  269. #ifndef RE_OPTION_EXTENDED
  270. #define RE_OPTION_EXTENDED (2)
  271. #endif
  272. #ifndef RE_OPTION_MULTILINE
  273. #define RE_OPTION_MULTILINE (4)
  274. #endif
  275. #define RE_OPTION_DONT_CAPTURE_GROUP (128)
  276. #define RE_OPTION_CAPTURE_GROUP (256)
  277. #define RE_OPTION_ONCE (8192)
  278. #define NODE_STRTERM NODE_ZARRAY /* nothing to gc */
  279. #define NODE_HEREDOC NODE_ARRAY /* 1, 3 to gc */
  280. #define SIGN_EXTEND(x,n) (((1<<((n)-1))^((x)&~(~0<<(n))))-(1<<((n)-1)))
  281. #define nd_func u1.id
  282. #if SIZEOF_SHORT != 2
  283. #define nd_term(node) SIGN_EXTEND((node)->u2.id, (CHAR_BIT*2))
  284. #else
  285. #define nd_term(node) ((signed short)(node)->u2.id)
  286. #endif
  287. #define nd_paren(node) (char)((node)->u2.id >> (CHAR_BIT*2))
  288. #define nd_nest u3.id
  289. #define NEW_BLOCK_VAR(b, v) NEW_NODE(NODE_BLOCK_PASS, 0, b, v)
  290. /* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
  291. for instance). This is too low for Ruby to parse some files, such as
  292. date/format.rb, therefore bump the value up to at least Bison's default. */
  293. #ifdef OLD_YACC
  294. #ifndef YYMAXDEPTH
  295. #define YYMAXDEPTH 10000
  296. #endif
  297. #endif
  298. #define vps ((rb_parser_state*)parser_state)
  299. %}
  300. %pure-parser
  301. %union {
  302. VALUE val;
  303. NODE *node;
  304. QUID id;
  305. int num;
  306. var_table vars;
  307. }
  308. %token kCLASS
  309. kMODULE
  310. kDEF
  311. kUNDEF
  312. kBEGIN
  313. kRESCUE
  314. kENSURE
  315. kEND
  316. kIF
  317. kUNLESS
  318. kTHEN
  319. kELSIF
  320. kELSE
  321. kCASE
  322. kWHEN
  323. kWHILE
  324. kUNTIL
  325. kFOR
  326. kBREAK
  327. kNEXT
  328. kREDO
  329. kRETRY
  330. kIN
  331. kDO
  332. kDO_COND
  333. kDO_BLOCK
  334. kRETURN
  335. kYIELD
  336. kSUPER
  337. kSELF
  338. kNIL
  339. kTRUE
  340. kFALSE
  341. kAND
  342. kOR
  343. kNOT
  344. kIF_MOD
  345. kUNLESS_MOD
  346. kWHILE_MOD
  347. kUNTIL_MOD
  348. kRESCUE_MOD
  349. kALIAS
  350. kDEFINED
  351. klBEGIN
  352. klEND
  353. k__LINE__
  354. k__FILE__
  355. %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tXSTRING_BEG
  356. %token <node> tINTEGER tFLOAT tSTRING_CONTENT
  357. %token <node> tNTH_REF tBACK_REF
  358. %token <num> tREGEXP_END
  359. %type <node> singleton strings string string1 xstring regexp
  360. %type <node> string_contents xstring_contents string_content
  361. %type <node> words qwords word_list qword_list word
  362. %type <node> literal numeric dsym cpath
  363. %type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
  364. %type <node> expr_value arg_value primary_value
  365. %type <node> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
  366. %type <node> args when_args call_args call_args2 open_args paren_args opt_paren_args
  367. %type <node> command_args aref_args opt_block_arg block_arg var_ref var_lhs
  368. %type <node> mrhs superclass block_call block_command
  369. %type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
  370. %type <node> assoc_list assocs assoc undef_list backref string_dvar
  371. %type <node> for_var block_var opt_block_var block_par
  372. %type <node> brace_block cmd_brace_block do_block lhs none fitem
  373. %type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
  374. %type <id> fsym variable sym symbol operation operation2 operation3
  375. %type <id> cname fname op f_rest_arg
  376. %type <num> f_norm_arg f_arg
  377. %token tUPLUS /* unary+ */
  378. %token tUMINUS /* unary- */
  379. %token tUBS /* unary\ */
  380. %token tPOW /* ** */
  381. %token tCMP /* <=> */
  382. %token tEQ /* == */
  383. %token tEQQ /* === */
  384. %token tNEQ /* != */
  385. %token tGEQ /* >= */
  386. %token tLEQ /* <= */
  387. %token tANDOP tOROP /* && and || */
  388. %token tMATCH tNMATCH /* =~ and !~ */
  389. %token tDOT2 tDOT3 /* .. and ... */
  390. %token tAREF tASET /* [] and []= */
  391. %token tLSHFT tRSHFT /* << and >> */
  392. %token tCOLON2 /* :: */
  393. %token tCOLON3 /* :: at EXPR_BEG */
  394. %token <id> tOP_ASGN /* +=, -= etc. */
  395. %token tASSOC /* => */
  396. %token tLPAREN /* ( */
  397. %token tLPAREN_ARG /* ( */
  398. %token tRPAREN /* ) */
  399. %token tLBRACK /* [ */
  400. %token tLBRACE /* { */
  401. %token tLBRACE_ARG /* { */
  402. %token tSTAR /* * */
  403. %token tAMPER /* & */
  404. %token tSYMBEG tSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
  405. %token tSTRING_DBEG tSTRING_DVAR tSTRING_END
  406. /*
  407. * precedence table
  408. */
  409. %nonassoc tLOWEST
  410. %nonassoc tLBRACE_ARG
  411. %nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
  412. %left kOR kAND
  413. %right kNOT
  414. %nonassoc kDEFINED
  415. %right '=' tOP_ASGN
  416. %left kRESCUE_MOD
  417. %right '?' ':'
  418. %nonassoc tDOT2 tDOT3
  419. %left tOROP
  420. %left tANDOP
  421. %nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
  422. %left '>' tGEQ '<' tLEQ
  423. %left '|' '^'
  424. %left '&'
  425. %left tLSHFT tRSHFT
  426. %left '+' '-'
  427. %left '*' '/' '%'
  428. %right tUMINUS_NUM tUMINUS
  429. %right tPOW
  430. %right '!' '~' tUPLUS
  431. %token tLAST_TOKEN
  432. %%
  433. program : {
  434. lex_state = EXPR_BEG;
  435. variables = new LocalState(0);
  436. class_nest = 0;
  437. }
  438. compstmt
  439. {
  440. if ($2 && !compile_for_eval) {
  441. /* last expression should not be void */
  442. if (nd_type($2) != NODE_BLOCK) void_expr($2);
  443. else {
  444. NODE *node = $2;
  445. while (node->nd_next) {
  446. node = node->nd_next;
  447. }
  448. void_expr(node->nd_head);
  449. }
  450. }
  451. top_node = block_append(vps, top_node, $2);
  452. class_nest = 0;
  453. }
  454. ;
  455. bodystmt : compstmt
  456. opt_rescue
  457. opt_else
  458. opt_ensure
  459. {
  460. $$ = $1;
  461. if ($2) {
  462. $$ = NEW_RESCUE($1, $2, $3);
  463. }
  464. else if ($3) {
  465. rb_warn("else without rescue is useless");
  466. $$ = block_append(vps, $$, $3);
  467. }
  468. if ($4) {
  469. $$ = NEW_ENSURE($$, $4);
  470. }
  471. fixpos($$, $1);
  472. }
  473. ;
  474. compstmt : stmts opt_terms
  475. {
  476. void_stmts($1, vps);
  477. $$ = $1;
  478. }
  479. ;
  480. stmts : none
  481. | stmt
  482. {
  483. $$ = newline_node(vps, $1);
  484. }
  485. | stmts terms stmt
  486. {
  487. $$ = block_append(vps, $1, newline_node(vps, $3));
  488. }
  489. | error stmt
  490. {
  491. $$ = remove_begin($2, vps);
  492. }
  493. ;
  494. stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
  495. {
  496. $$ = NEW_ALIAS($2, $4);
  497. }
  498. | kALIAS tGVAR tGVAR
  499. {
  500. $$ = NEW_VALIAS($2, $3);
  501. }
  502. | kALIAS tGVAR tBACK_REF
  503. {
  504. char buf[3];
  505. snprintf(buf, sizeof(buf), "$%c", (char)$3->nd_nth);
  506. $$ = NEW_VALIAS($2, rb_parser_sym((rb_parser_state*)parser_state, buf));
  507. }
  508. | kALIAS tGVAR tNTH_REF
  509. {
  510. yyerror("can't make alias for the number variables");
  511. $$ = 0;
  512. }
  513. | kUNDEF undef_list
  514. {
  515. $$ = $2;
  516. }
  517. | stmt kIF_MOD expr_value
  518. {
  519. $$ = NEW_IF(cond($3, vps), remove_begin($1, vps), 0);
  520. fixpos($$, $3);
  521. if (cond_negative(&$$->nd_cond)) {
  522. $$->nd_else = $$->nd_body;
  523. $$->nd_body = 0;
  524. }
  525. }
  526. | stmt kUNLESS_MOD expr_value
  527. {
  528. $$ = NEW_UNLESS(cond($3, vps), remove_begin($1, vps), 0);
  529. fixpos($$, $3);
  530. if (cond_negative(&$$->nd_cond)) {
  531. $$->nd_body = $$->nd_else;
  532. $$->nd_else = 0;
  533. }
  534. }
  535. | stmt kWHILE_MOD expr_value
  536. {
  537. if ($1 && nd_type($1) == NODE_BEGIN) {
  538. $$ = NEW_WHILE(cond($3, vps), $1->nd_body, 0);
  539. }
  540. else {
  541. $$ = NEW_WHILE(cond($3, vps), $1, 1);
  542. }
  543. if (cond_negative(&$$->nd_cond)) {
  544. nd_set_type($$, NODE_UNTIL);
  545. }
  546. }
  547. | stmt kUNTIL_MOD expr_value
  548. {
  549. if ($1 && nd_type($1) == NODE_BEGIN) {
  550. $$ = NEW_UNTIL(cond($3, vps), $1->nd_body, 0);
  551. }
  552. else {
  553. $$ = NEW_UNTIL(cond($3, vps), $1, 1);
  554. }
  555. if (cond_negative(&$$->nd_cond)) {
  556. nd_set_type($$, NODE_WHILE);
  557. }
  558. }
  559. | stmt kRESCUE_MOD stmt
  560. {
  561. NODE *resq = NEW_RESBODY(0, remove_begin($3, vps), 0);
  562. $$ = NEW_RESCUE(remove_begin($1, vps), resq, 0);
  563. }
  564. | klBEGIN
  565. {
  566. if (in_def || in_single) {
  567. yyerror("BEGIN in method");
  568. }
  569. local_push(0);
  570. }
  571. '{' compstmt '}'
  572. {
  573. /*
  574. ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
  575. NEW_PREEXE($4));
  576. */
  577. local_pop();
  578. $$ = 0;
  579. }
  580. | klEND '{' compstmt '}'
  581. {
  582. if (in_def || in_single) {
  583. rb_warn("END in method; use at_exit");
  584. }
  585. $$ = NEW_ITER(0, NEW_POSTEXE(), $3);
  586. }
  587. | lhs '=' command_call
  588. {
  589. $$ = node_assign($1, $3, vps);
  590. }
  591. | mlhs '=' command_call
  592. {
  593. value_expr($3);
  594. $1->nd_value = ($1->nd_head) ? NEW_TO_ARY($3) : NEW_ARRAY($3);
  595. $$ = $1;
  596. }
  597. | var_lhs tOP_ASGN command_call
  598. {
  599. value_expr($3);
  600. if ($1) {
  601. QUID vid = $1->nd_vid;
  602. if ($2 == tOROP) {
  603. $1->nd_value = $3;
  604. $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
  605. if (is_asgn_or_id(vid)) {
  606. $$->nd_aid = vid;
  607. }
  608. }
  609. else if ($2 == tANDOP) {
  610. $1->nd_value = $3;
  611. $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
  612. }
  613. else {
  614. $$ = $1;
  615. $$->nd_value = call_op(gettable(vid),$2,1,$3, vps);
  616. }
  617. }
  618. else {
  619. $$ = 0;
  620. }
  621. }
  622. | primary_value '[' aref_args ']' tOP_ASGN command_call
  623. {
  624. NODE *args;
  625. value_expr($6);
  626. if (!$3) $3 = NEW_ZARRAY();
  627. args = arg_concat(vps, $6, $3);
  628. if ($5 == tOROP) {
  629. $5 = 0;
  630. }
  631. else if ($5 == tANDOP) {
  632. $5 = 1;
  633. }
  634. $$ = NEW_OP_ASGN1($1, $5, args);
  635. fixpos($$, $1);
  636. }
  637. | primary_value '.' tIDENTIFIER tOP_ASGN command_call
  638. {
  639. value_expr($5);
  640. if ($4 == tOROP) {
  641. $4 = 0;
  642. }
  643. else if ($4 == tANDOP) {
  644. $4 = 1;
  645. }
  646. $$ = NEW_OP_ASGN2($1, $3, $4, $5);
  647. fixpos($$, $1);
  648. }
  649. | primary_value '.' tCONSTANT tOP_ASGN command_call
  650. {
  651. value_expr($5);
  652. if ($4 == tOROP) {
  653. $4 = 0;
  654. }
  655. else if ($4 == tANDOP) {
  656. $4 = 1;
  657. }
  658. $$ = NEW_OP_ASGN2($1, $3, $4, $5);
  659. fixpos($$, $1);
  660. }
  661. | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
  662. {
  663. value_expr($5);
  664. if ($4 == tOROP) {
  665. $4 = 0;
  666. }
  667. else if ($4 == tANDOP) {
  668. $4 = 1;
  669. }
  670. $$ = NEW_OP_ASGN2($1, $3, $4, $5);
  671. fixpos($$, $1);
  672. }
  673. | backref tOP_ASGN command_call
  674. {
  675. rb_backref_error($1, vps);
  676. $$ = 0;
  677. }
  678. | lhs '=' mrhs
  679. {
  680. $$ = node_assign($1, NEW_SVALUE($3), vps);
  681. }
  682. | mlhs '=' arg_value
  683. {
  684. $1->nd_value = ($1->nd_head) ? NEW_TO_ARY($3) : NEW_ARRAY($3);
  685. $$ = $1;
  686. }
  687. | mlhs '=' mrhs
  688. {
  689. $1->nd_value = $3;
  690. $$ = $1;
  691. }
  692. | expr
  693. ;
  694. expr : command_call
  695. | expr kAND expr
  696. {
  697. $$ = logop(NODE_AND, $1, $3, vps);
  698. }
  699. | expr kOR expr
  700. {
  701. $$ = logop(NODE_OR, $1, $3, vps);
  702. }
  703. | kNOT expr
  704. {
  705. $$ = NEW_NOT(cond($2, vps));
  706. }
  707. | '!' command_call
  708. {
  709. $$ = NEW_NOT(cond($2, vps));
  710. }
  711. | arg
  712. ;
  713. expr_value : expr
  714. {
  715. value_expr($$);
  716. $$ = $1;
  717. }
  718. ;
  719. command_call : command
  720. | block_command
  721. | kRETURN call_args
  722. {
  723. $$ = NEW_RETURN(ret_args(vps, $2));
  724. }
  725. | kBREAK call_args
  726. {
  727. $$ = NEW_BREAK(ret_args(vps, $2));
  728. }
  729. | kNEXT call_args
  730. {
  731. $$ = NEW_NEXT(ret_args(vps, $2));
  732. }
  733. ;
  734. block_command : block_call
  735. | block_call '.' operation2 command_args
  736. {
  737. $$ = new_call(vps, $1, $3, $4);
  738. }
  739. | block_call tCOLON2 operation2 command_args
  740. {
  741. $$ = new_call(vps, $1, $3, $4);
  742. }
  743. ;
  744. cmd_brace_block : tLBRACE_ARG
  745. {
  746. $<num>1 = ruby_sourceline;
  747. reset_block(vps);
  748. }
  749. opt_block_var { $<vars>$ = variables->block_vars; }
  750. compstmt
  751. '}'
  752. {
  753. $$ = NEW_ITER($3, 0, extract_block_vars(vps, $5, $<vars>4));
  754. nd_set_line($$, $<num>1);
  755. }
  756. ;
  757. command : operation command_args %prec tLOWEST
  758. {
  759. $$ = new_fcall(vps, $1, $2);
  760. fixpos($$, $2);
  761. }
  762. | operation command_args cmd_brace_block
  763. {
  764. $$ = new_fcall(vps, $1, $2);
  765. if ($3) {
  766. if (nd_type($$) == NODE_BLOCK_PASS) {
  767. rb_compile_error(vps, "both block arg and actual block given");
  768. }
  769. $3->nd_iter = $$;
  770. $$ = $3;
  771. }
  772. fixpos($$, $2);
  773. }
  774. | primary_value '.' operation2 command_args %prec tLOWEST
  775. {
  776. $$ = new_call(vps, $1, $3, $4);
  777. fixpos($$, $1);
  778. }
  779. | primary_value '.' operation2 command_args cmd_brace_block
  780. {
  781. $$ = new_call(vps, $1, $3, $4);
  782. if ($5) {
  783. if (nd_type($$) == NODE_BLOCK_PASS) {
  784. rb_compile_error(vps, "both block arg and actual block given");
  785. }
  786. $5->nd_iter = $$;
  787. $$ = $5;
  788. }
  789. fixpos($$, $1);
  790. }
  791. | primary_value tCOLON2 operation2 command_args %prec tLOWEST
  792. {
  793. $$ = new_call(vps, $1, $3, $4);
  794. fixpos($$, $1);
  795. }
  796. | primary_value tCOLON2 operation2 command_args cmd_brace_block
  797. {
  798. $$ = new_call(vps, $1, $3, $4);
  799. if ($5) {
  800. if (nd_type($$) == NODE_BLOCK_PASS) {
  801. rb_compile_error(vps, "both block arg and actual block given");
  802. }
  803. $5->nd_iter = $$;
  804. $$ = $5;
  805. }
  806. fixpos($$, $1);
  807. }
  808. | kSUPER command_args
  809. {
  810. $$ = new_super(vps, $2);
  811. fixpos($$, $2);
  812. }
  813. | kYIELD command_args
  814. {
  815. $$ = new_yield(vps, $2);
  816. fixpos($$, $2);
  817. }
  818. ;
  819. mlhs : mlhs_basic
  820. | tLPAREN mlhs_entry ')'
  821. {
  822. $$ = $2;
  823. }
  824. ;
  825. mlhs_entry : mlhs_basic
  826. | tLPAREN mlhs_entry ')'
  827. {
  828. $$ = NEW_MASGN(NEW_LIST($2), 0);
  829. }
  830. ;
  831. mlhs_basic : mlhs_head
  832. {
  833. $$ = NEW_MASGN($1, 0);
  834. }
  835. | mlhs_head mlhs_item
  836. {
  837. $$ = NEW_MASGN(list_append(vps, $1,$2), 0);
  838. }
  839. | mlhs_head tSTAR mlhs_node
  840. {
  841. $$ = NEW_MASGN($1, $3);
  842. }
  843. | mlhs_head tSTAR
  844. {
  845. $$ = NEW_MASGN($1, -1);
  846. }
  847. | tSTAR mlhs_node
  848. {
  849. $$ = NEW_MASGN(0, $2);
  850. }
  851. | tSTAR
  852. {
  853. $$ = NEW_MASGN(0, -1);
  854. }
  855. ;
  856. mlhs_item : mlhs_node
  857. | tLPAREN mlhs_entry ')'
  858. {
  859. $$ = $2;
  860. }
  861. ;
  862. mlhs_head : mlhs_item ','
  863. {
  864. $$ = NEW_LIST($1);
  865. }
  866. | mlhs_head mlhs_item ','
  867. {
  868. $$ = list_append(vps, $1, $2);
  869. }
  870. ;
  871. mlhs_node : variable
  872. {
  873. $$ = assignable($1, 0, vps);
  874. }
  875. | primary_value '[' aref_args ']'
  876. {
  877. $$ = aryset($1, $3, vps);
  878. }
  879. | primary_value '.' tIDENTIFIER
  880. {
  881. $$ = attrset($1, $3, vps);
  882. }
  883. | primary_value tCOLON2 tIDENTIFIER
  884. {
  885. $$ = attrset($1, $3, vps);
  886. }
  887. | primary_value '.' tCONSTANT
  888. {
  889. $$ = attrset($1, $3, vps);
  890. }
  891. | primary_value tCOLON2 tCONSTANT
  892. {
  893. if (in_def || in_single)
  894. yyerror("dynamic constant assignment");
  895. $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
  896. }
  897. | tCOLON3 tCONSTANT
  898. {
  899. if (in_def || in_single)
  900. yyerror("dynamic constant assignment");
  901. $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
  902. }
  903. | backref
  904. {
  905. rb_backref_error($1, vps);
  906. $$ = 0;
  907. }
  908. ;
  909. lhs : variable
  910. {
  911. $$ = assignable($1, 0, vps);
  912. }
  913. | primary_value '[' aref_args ']'
  914. {
  915. $$ = aryset($1, $3, vps);
  916. }
  917. | primary_value '.' tIDENTIFIER
  918. {
  919. $$ = attrset($1, $3, vps);
  920. }
  921. | primary_value tCOLON2 tIDENTIFIER
  922. {
  923. $$ = attrset($1, $3, vps);
  924. }
  925. | primary_value '.' tCONSTANT
  926. {
  927. $$ = attrset($1, $3, vps);
  928. }
  929. | primary_value tCOLON2 tCONSTANT
  930. {
  931. if (in_def || in_single)
  932. yyerror("dynamic constant assignment");
  933. $$ = NEW_CDECL(0, 0, NEW_COLON2($1, $3));
  934. }
  935. | tCOLON3 tCONSTANT
  936. {
  937. if (in_def || in_single)
  938. yyerror("dynamic constant assignment");
  939. $$ = NEW_CDECL(0, 0, NEW_COLON3($2));
  940. }
  941. | backref
  942. {
  943. rb_backref_error($1, vps);
  944. $$ = 0;
  945. }
  946. ;
  947. cname : tIDENTIFIER
  948. {
  949. yyerror("class/module name must be CONSTANT");
  950. }
  951. | tCONSTANT
  952. ;
  953. cpath : tCOLON3 cname
  954. {
  955. $$ = NEW_COLON3($2);
  956. }
  957. | cname
  958. {
  959. $$ = NEW_COLON2(0, $$);
  960. }
  961. | primary_value tCOLON2 cname
  962. {
  963. $$ = NEW_COLON2($1, $3);
  964. }
  965. ;
  966. fname : tIDENTIFIER
  967. | tCONSTANT
  968. | tFID
  969. | op
  970. {
  971. lex_state = EXPR_END;
  972. $$ = convert_op((rb_parser_state*)parser_state, $1);
  973. }
  974. | reswords
  975. {
  976. lex_state = EXPR_END;
  977. $$ = $<id>1;
  978. }
  979. ;
  980. fsym : fname
  981. | symbol
  982. ;
  983. fitem : fsym
  984. {
  985. $$ = NEW_LIT(QUID2SYM($1));
  986. }
  987. | dsym
  988. ;
  989. undef_list : fitem
  990. {
  991. $$ = NEW_UNDEF($1);
  992. }
  993. | undef_list ',' {lex_state = EXPR_FNAME;} fitem
  994. {
  995. $$ = block_append(vps, $1, NEW_UNDEF($4));
  996. }
  997. ;
  998. op : '|' { $$ = '|'; }
  999. | '^' { $$ = '^'; }
  1000. | '&' { $$ = '&'; }
  1001. | tCMP { $$ = tCMP; }
  1002. | tEQ { $$ = tEQ; }
  1003. | tEQQ { $$ = tEQQ; }
  1004. | tMATCH { $$ = tMATCH; }
  1005. | '>' { $$ = '>'; }
  1006. | tGEQ { $$ = tGEQ; }
  1007. | '<' { $$ = '<'; }
  1008. | tLEQ { $$ = tLEQ; }
  1009. | tLSHFT { $$ = tLSHFT; }
  1010. | tRSHFT { $$ = tRSHFT; }
  1011. | '+' { $$ = '+'; }
  1012. | '-' { $$ = '-'; }
  1013. | '*' { $$ = '*'; }
  1014. | tSTAR { $$ = '*'; }
  1015. | '/' { $$ = '/'; }
  1016. | '%' { $$ = '%'; }
  1017. | tPOW { $$ = tPOW; }
  1018. | '~' { $$ = '~'; }
  1019. | tUPLUS { $$ = tUPLUS; }
  1020. | tUMINUS { $$ = tUMINUS; }
  1021. | tAREF { $$ = tAREF; }
  1022. | tASET { $$ = tASET; }
  1023. | '`' { $$ = '`'; }
  1024. ;
  1025. reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
  1026. | kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF
  1027. | kDEFINED | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
  1028. | kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
  1029. | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER
  1030. | kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
  1031. | kIF_MOD | kUNLESS_MOD | kWHILE_MOD | kUNTIL_MOD | kRESCUE_MOD
  1032. ;
  1033. arg : lhs '=' arg
  1034. {
  1035. $$ = node_assign($1, $3, vps);
  1036. }
  1037. | lhs '=' arg kRESCUE_MOD arg
  1038. {
  1039. $$ = node_assign($1, NEW_RESCUE($3, NEW_RESBODY(0,$5,0), 0), vps);
  1040. }
  1041. | var_lhs tOP_ASGN arg
  1042. {
  1043. value_expr($3);
  1044. if ($1) {
  1045. QUID vid = $1->nd_vid;
  1046. if ($2 == tOROP) {
  1047. $1->nd_value = $3;
  1048. $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
  1049. if (is_asgn_or_id(vid)) {
  1050. $$->nd_aid = vid;
  1051. }
  1052. }
  1053. else if ($2 == tANDOP) {
  1054. $1->nd_value = $3;
  1055. $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
  1056. }
  1057. else {
  1058. $$ = $1;
  1059. $$->nd_value = call_op(gettable(vid),$2,1,$3, vps);
  1060. }
  1061. }
  1062. else {
  1063. $$ = 0;
  1064. }
  1065. }
  1066. | primary_value '[' aref_args ']' tOP_ASGN arg
  1067. {
  1068. NODE *args;
  1069. value_expr($6);
  1070. if (!$3) $3 = NEW_ZARRAY();
  1071. args = arg_concat(vps, $6, $3);
  1072. if ($5 == tOROP) {
  1073. $5 = 0;
  1074. }
  1075. else if ($5 == tANDOP) {
  1076. $5 = 1;
  1077. }
  1078. $$ = NEW_OP_ASGN1($1, $5, args);
  1079. fixpos($$, $1);
  1080. }
  1081. | primary_value '.' tIDENTIFIER tOP_ASGN arg
  1082. {
  1083. value_expr($5);
  1084. if ($4 == tOROP) {
  1085. $4 = 0;
  1086. }
  1087. else if ($4 == tANDOP) {
  1088. $4 = 1;
  1089. }
  1090. $$ = NEW_OP_ASGN2($1, $3, $4, $5);
  1091. fixpos($$, $1);
  1092. }
  1093. | primary_value '.' tCONSTANT tOP_ASGN arg
  1094. {
  1095. value_expr($5);
  1096. if ($4 == tOROP) {
  1097. $4 = 0;
  1098. }
  1099. else if ($4 == tANDOP) {
  1100. $4 = 1;
  1101. }
  1102. $$ = NEW_OP_ASGN2($1, $3, $4, $5);
  1103. fixpos($$, $1);
  1104. }
  1105. | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
  1106. {
  1107. value_expr($5);
  1108. if ($4 == tOROP) {
  1109. $4 = 0;
  1110. }
  1111. else if ($4 == tANDOP) {
  1112. $4 = 1;
  1113. }
  1114. $$ = NEW_OP_ASGN2($1, $3, $4, $5);
  1115. fixpos($$, $1);
  1116. }
  1117. | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
  1118. {
  1119. yyerror("constant re-assignment");
  1120. $$ = 0;
  1121. }
  1122. | tCOLON3 tCONSTANT tOP_ASGN arg
  1123. {
  1124. yyerror("constant re-assignment");
  1125. $$ = 0;
  1126. }
  1127. | backref tOP_ASGN arg
  1128. {
  1129. rb_backref_error($1, vps);
  1130. $$ = 0;
  1131. }
  1132. | arg tDOT2 arg
  1133. {
  1134. value_expr($1);
  1135. value_expr($3);
  1136. $$ = NEW_DOT2($1, $3);
  1137. }
  1138. | arg tDOT3 arg
  1139. {
  1140. value_expr($1);
  1141. value_expr($3);
  1142. $$ = NEW_DOT3($1, $3);
  1143. }
  1144. | arg '+' arg
  1145. {
  1146. $$ = call_op($1, '+', 1, $3, vps);
  1147. }
  1148. | arg '-' arg
  1149. {
  1150. $$ = call_op($1, '-', 1, $3, vps);
  1151. }
  1152. | arg '*' arg
  1153. {
  1154. $$ = call_op($1, '*', 1, $3, vps);
  1155. }
  1156. | arg '/' arg
  1157. {
  1158. $$ = call_op($1, '/', 1, $3, vps);
  1159. }
  1160. | arg '%' arg
  1161. {
  1162. $$ = call_op($1, '%', 1, $3, vps);
  1163. }
  1164. | arg tPOW arg
  1165. {
  1166. $$ = call_op($1, tPOW, 1, $3, vps);
  1167. }
  1168. | tUMINUS_NUM tINTEGER tPOW arg
  1169. {
  1170. $$ = call_op(call_op($2, tPOW, 1, $4, vps), tUMINUS, 0, 0, vps);
  1171. }
  1172. | tUMINUS_NUM tFLOAT tPOW arg
  1173. {
  1174. $$ = call_op(call_op($2, tPOW, 1, $4, vps), tUMINUS, 0, 0, vps);
  1175. }
  1176. | tUPLUS arg
  1177. {
  1178. if ($2 && nd_type($2) == NODE_LIT) {
  1179. $$ = $2;
  1180. }
  1181. else {
  1182. $$ = call_op($2, tUPLUS, 0, 0, vps);
  1183. }
  1184. }
  1185. | tUMINUS arg
  1186. {
  1187. $$ = call_op($2, tUMINUS, 0, 0, vps);
  1188. }
  1189. | arg '|' arg
  1190. {
  1191. $$ = call_op($1, '|', 1, $3, vps);
  1192. }
  1193. | arg '^' arg
  1194. {
  1195. $$ = call_op($1, '^', 1, $3, vps);
  1196. }
  1197. | arg '&' arg
  1198. {
  1199. $$ = call_op($1, '&', 1, $3, vps);
  1200. }
  1201. | arg tCMP arg
  1202. {
  1203. $$ = call_op($1, tCMP, 1, $3, vps);
  1204. }
  1205. | arg '>' arg
  1206. {
  1207. $$ = call_op($1, '>', 1, $3, vps);
  1208. }
  1209. | arg tGEQ arg
  1210. {
  1211. $$ = call_op($1, tGEQ, 1, $3, vps);
  1212. }
  1213. | arg '<' arg
  1214. {
  1215. $$ = call_op($1, '<', 1, $3, vps);
  1216. }
  1217. | arg tLEQ arg
  1218. {
  1219. $$ = call_op($1, tLEQ, 1, $3, vps);
  1220. }
  1221. | arg tEQ arg
  1222. {
  1223. $$ = call_op($1, tEQ, 1, $3, vps);
  1224. }
  1225. | arg tEQQ arg
  1226. {
  1227. $$ = call_op($1, tEQQ, 1, $3, vps);
  1228. }
  1229. | arg tNEQ arg
  1230. {
  1231. $$ = NEW_NOT(call_op($1, tEQ, 1, $3, vps));
  1232. }
  1233. | arg tMATCH arg
  1234. {
  1235. $$ = match_gen($1, $3, vps);
  1236. }
  1237. | arg tNMATCH arg
  1238. {
  1239. $$ = NEW_NOT(match_gen($1, $3, vps));
  1240. }
  1241. | '!' arg
  1242. {
  1243. $$ = NEW_NOT(cond($2, vps));
  1244. }
  1245. | '~' arg
  1246. {
  1247. $$ = call_op($2, '~', 0, 0, vps);
  1248. }
  1249. | arg tLSHFT arg
  1250. {
  1251. $$ = call_op($1, tLSHFT, 1, $3, vps);
  1252. }
  1253. | arg tRSHFT arg
  1254. {
  1255. $$ = call_op($1, tRSHFT, 1, $3, vps);
  1256. }
  1257. | arg tANDOP arg
  1258. {
  1259. $$ = logop(NODE_AND, $1, $3, vps);
  1260. }
  1261. | arg tOROP arg
  1262. {
  1263. $$ = logop(NODE_OR, $1, $3, vps);
  1264. }
  1265. | kDEFINED opt_nl {in_defined = 1;} arg
  1266. {
  1267. in_defined = 0;
  1268. $$ = NEW_DEFINED($4);
  1269. }
  1270. | arg '?' {ternary_colon++;} arg ':' arg
  1271. {
  1272. $$ = NEW_IF(cond($1, vps), $4, $6);
  1273. fixpos($$, $1);
  1274. ternary_colon--;
  1275. }
  1276. | primary
  1277. {
  1278. $$ = $1;
  1279. }
  1280. ;
  1281. arg_value : arg
  1282. {
  1283. value_expr($1);
  1284. $$ = $1;
  1285. }
  1286. ;
  1287. aref_args : none
  1288. | command opt_nl
  1289. {
  1290. rb_warn("parenthesize argument(s) for future version");
  1291. $$ = NEW_LIST($1);
  1292. }
  1293. | args trailer
  1294. {
  1295. $$ = $1;
  1296. }
  1297. | args ',' tSTAR arg opt_nl
  1298. {
  1299. value_expr($4);
  1300. $$ = arg_concat(vps, $1, $4);
  1301. }
  1302. | assocs trailer
  1303. {
  1304. $$ = NEW_LIST(NEW_HASH($1));
  1305. }
  1306. | tSTAR arg opt_nl
  1307. {
  1308. value_expr($2);
  1309. $$ = NEW_NEWLINE(NEW_SPLAT($2));
  1310. }
  1311. ;
  1312. paren_args : '(' none ')'
  1313. {
  1314. $$ = $2;
  1315. }
  1316. | '(' call_args opt_nl ')'
  1317. {
  1318. $$ = $2;
  1319. }
  1320. | '(' block_call opt_nl ')'
  1321. {
  1322. rb_warn("parenthesize argument for future version");
  1323. $$ = NEW_LIST($2);
  1324. }
  1325. | '(' args ',' block_call opt_nl ')'
  1326. {
  1327. rb_warn("parenthesize argument for future version");
  1328. $$ = list_append(vps, $2, $4);
  1329. }
  1330. ;
  1331. opt_paren_args : none
  1332. | paren_args
  1333. ;
  1334. call_args : command
  1335. {
  1336. rb_warn("parenthesize argument(s) for future version");
  1337. $$ = NEW_LIST($1);
  1338. }
  1339. | args opt_block_arg
  1340. {
  1341. $$ = arg_blk_pass($1, $2);
  1342. }
  1343. | args ',' tSTAR arg_value opt_block_arg
  1344. {
  1345. $$ = arg_concat(vps, $1, $4);
  1346. $$ = arg_blk_pass($$, $5);
  1347. }
  1348. | assocs opt_block_arg
  1349. {
  1350. $$ = NEW_LIST(NEW_HASH($1));
  1351. $$ = arg_blk_pass($$, $2);
  1352. }
  1353. | assocs ',' tSTAR arg_value opt_block_arg
  1354. {
  1355. $$ = arg_concat(vps, NEW_LIST(NEW_HASH($1)), $4);
  1356. $$ = arg_blk_pass($$, $5);
  1357. }
  1358. | args ',' assocs opt_block_arg
  1359. {
  1360. $$ = list_append(vps, $1, NEW_HASH($3));
  1361. $$ = arg_blk_pass($$, $4);
  1362. }
  1363. | args ',' assocs ',' tSTAR arg opt_block_arg
  1364. {
  1365. value_expr($6);
  1366. $$ = arg_concat(vps, list_append(vps, $1, NEW_HASH($3)), $6);
  1367. $$ = arg_blk_pass($$, $7);
  1368. }
  1369. | tSTAR arg_value opt_block_arg
  1370. {
  1371. $$ = arg_blk_pass(NEW_SPLAT($2), $3);
  1372. }
  1373. | block_arg
  1374. ;
  1375. call_args2 : arg_value ',' args opt_block_arg
  1376. {
  1377. $$ = arg_blk_pass(list_concat(NEW_LIST($1),$3), $4);
  1378. }
  1379. | arg_value ',' block_arg
  1380. {
  1381. $$ = arg_blk_pass($1, $3);
  1382. }
  1383. | arg_value ',' tSTAR arg_value opt_block_arg
  1384. {
  1385. $$ = arg_concat(vps, NEW_LIST($1), $4);
  1386. $$ = arg_blk_pass($$, $5);
  1387. }
  1388. | arg_value ',' args ',' tSTAR arg_value opt_block_arg
  1389. {
  1390. $$ = arg_concat(vps, list_concat(NEW_LIST($1),$3), $6);
  1391. $$ = arg_blk_pass($$, $7);
  1392. }
  1393. | assocs opt_block_arg
  1394. {
  1395. $$ = NEW_LIST(NEW_HASH($1));
  1396. $$ = arg_blk_pass($$, $2);
  1397. }
  1398. | assocs ',' tSTAR arg_value opt_block_arg
  1399. {
  1400. $$ = arg_concat(vps, NEW_LIST(NEW_HASH($1)), $4);
  1401. $$ = arg_blk_pass($$, $5);
  1402. }
  1403. | arg_value ',' assocs opt_block_arg
  1404. {
  1405. $$ = list_append(vps, NEW_LIST($1), NEW_HASH($3));
  1406. $$ = arg_blk_pass($$, $4);
  1407. }
  1408. | arg_value ',' args ',' assocs opt_block_arg
  1409. {
  1410. $$ = list_append(vps, list_concat(NEW_LIST($1),$3), NEW_HASH($5));
  1411. $$ = arg_blk_pass($$, $6);
  1412. }
  1413. | arg_value ',' assocs ',' tSTAR arg_value opt_block_arg
  1414. {
  1415. $$ = arg_concat(vps, list_append(vps, NEW_LIST($1), NEW_HASH($3)), $6);
  1416. $$ = arg_blk_pass($$, $7);
  1417. }
  1418. | arg_value ',' args ',' assocs ',' tSTAR arg_value opt_block_arg
  1419. {
  1420. $$ = arg_concat(vps, list_append(vps,
  1421. list_concat(NEW_LIST($1), $3), NEW_HASH($5)), $8);
  1422. $$ = arg_blk_pass($$, $9);
  1423. }
  1424. | tSTAR arg_value opt_block_arg
  1425. {
  1426. $$ = arg_blk_pass(NEW_SPLAT($2), $3);
  1427. }
  1428. | block_arg
  1429. ;
  1430. command_args : {
  1431. $<val>$ = cmdarg_stack;
  1432. CMDARG_PUSH(1);
  1433. }
  1434. open_args
  1435. {
  1436. /* CMDARG_POP() */
  1437. cmdarg_stack = $<val>1;
  1438. $$ = $2;
  1439. }
  1440. ;
  1441. open_args : call_args
  1442. | tLPAREN_ARG {lex_state = EXPR_ENDARG;} ')'
  1443. {
  1444. rb_warn("don't put space before argument parentheses");
  1445. $$ = 0;
  1446. }
  1447. | tLPAREN_ARG call_args2 {lex_state = EXPR_ENDARG;} ')'
  1448. {
  1449. rb_warn("don't put space before argument parentheses");
  1450. $$ = $2;
  1451. }
  1452. ;
  1453. block_arg : tAMPER arg_value
  1454. {
  1455. $$ = NEW_BLOCK_PASS($2);
  1456. }
  1457. ;
  1458. opt_block_arg : ',' block_arg
  1459. {
  1460. $$ = $2;
  1461. }
  1462. | none
  1463. ;
  1464. args : arg_value
  1465. {
  1466. $$ = NEW_LIST($1);
  1467. }
  1468. | args ',' arg_value
  1469. {
  1470. $$ = list_append(vps, $1, $3);
  1471. }
  1472. ;
  1473. mrhs : args ',' arg_value
  1474. {
  1475. $$ = list_append(vps, $1, $3);
  1476. }
  1477. | args ',' tSTAR arg_value
  1478. {
  1479. $$ = arg_concat(vps, $1, $4);
  1480. }
  1481. | tSTAR arg_value
  1482. {
  1483. $$ = NEW_SPLAT($2);
  1484. }
  1485. ;
  1486. primary : literal
  1487. | strings
  1488. | xstring
  1489. | regexp
  1490. | words
  1491. | qwords
  1492. | var_ref
  1493. | backref
  1494. | tFID
  1495. {
  1496. $$ = NEW_FCALL($1, 0);
  1497. }
  1498. | kBEGIN
  1499. {
  1500. $<num>1 = ruby_sourceline;
  1501. PUSH_LINE("begin");
  1502. }
  1503. bodystmt
  1504. kEND
  1505. {
  1506. POP_LINE();
  1507. if ($3 == NULL)
  1508. $$ = NEW_NIL();
  1509. else
  1510. $$ = NEW_BEGIN($3);
  1511. nd_set_line($$, $<num>1);
  1512. }
  1513. | tLPAREN_ARG expr {lex_state = EXPR_ENDARG;} opt_nl ')'
  1514. {
  1515. rb_warning("(...) interpreted as grouped expression");
  1516. $$ = $2;
  1517. }
  1518. | tLPAREN compstmt ')'
  1519. {
  1520. if (!$2) $$ = NEW_NIL();
  1521. else $$ = $2;
  1522. }
  1523. | primary_value tCOLON2 tCONSTANT
  1524. {
  1525. $$ = NEW_COLON2($1, $3);
  1526. }
  1527. | tCOLON3 tCONSTANT
  1528. {
  1529. $$ = NEW_COLON3($2);
  1530. }
  1531. | primary_value '[' aref_args ']'
  1532. {
  1533. if ($1 && nd_type($1) == NODE_SELF) {
  1534. $$ = NEW_FCALL(convert_op((rb_parser_state*) parser_state, tAREF), $3);
  1535. } else {
  1536. $$ = NEW_CALL($1, convert_op((rb_parser_state*) parser_state, tAREF), $3);
  1537. }
  1538. fixpos($$, $1);
  1539. }
  1540. | tLBRACK aref_args ']'
  1541. {
  1542. if ($2 == 0) {
  1543. $$ = NEW_ZARRAY(); /* zero length array*/
  1544. }
  1545. else {
  1546. $$ = $2;
  1547. }
  1548. }
  1549. | tLBRACE assoc_list '}'
  1550. {
  1551. $$ = NEW_HASH($2);
  1552. }
  1553. | kRETURN
  1554. {
  1555. $$ = NEW_RETURN(0);
  1556. }
  1557. | kYIELD '(' call_args ')'
  1558. {
  1559. $$ = new_yield(vps, $3);
  1560. }
  1561. | kYIELD '(' ')'
  1562. {
  1563. $$ = NEW_YIELD(0, Qfalse);
  1564. }
  1565. | kYIELD
  1566. {
  1567. $$ = NEW_YIELD(0, Qfalse);
  1568. }
  1569. | kDEFINED opt_nl '(' {in_defined = 1;} expr ')'
  1570. {
  1571. in_defined = 0;
  1572. $$ = NEW_DEFINED($5);
  1573. }
  1574. | operation brace_block
  1575. {
  1576. $2->nd_iter = NEW_FCALL($1, 0);
  1577. $$ = $2;
  1578. fixpos($2->nd_iter, $2);
  1579. }
  1580. | method_call
  1581. | method_call brace_block
  1582. {
  1583. if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
  1584. rb_compile_error(vps, "both block arg and actual block given");
  1585. }
  1586. $2->nd_iter = $1;
  1587. $$ = $2;
  1588. fixpos($$, $1);
  1589. }
  1590. | kIF {
  1591. PUSH_LINE("if");
  1592. } expr_value then
  1593. compstmt
  1594. if_tail
  1595. kEND
  1596. {
  1597. POP_LINE();
  1598. $$ = NEW_IF(cond($3, vps), $5, $6);
  1599. fixpos($$, $3);
  1600. if (cond_negative(&$$->nd_cond)) {
  1601. NODE *tmp = $$->nd_body;
  1602. $$->nd_body = $$->nd_else;
  1603. $$->nd_else = tmp;
  1604. }
  1605. }
  1606. | kUNLESS {
  1607. PUSH_LINE("unless");
  1608. } expr_value then
  1609. compstmt
  1610. opt_else
  1611. kEND
  1612. {
  1613. POP_LINE();
  1614. $$ = NEW_UNLESS(cond($3, vps), $5, $6);
  1615. fixpos($$, $3);
  1616. if (cond_negative(&$$->nd_cond)) {
  1617. NODE *tmp = $$->nd_body;
  1618. $$->nd_body = $$->nd_else;
  1619. $$->nd_else = tmp;
  1620. }
  1621. }
  1622. | kWHILE {
  1623. PUSH_LINE("while");
  1624. COND_PUSH(1);
  1625. } expr_value do {COND_POP();}
  1626. compstmt
  1627. kEND
  1628. {
  1629. POP_LINE();
  1630. $$ = NEW_WHILE(cond($3, vps), $6, 1);
  1631. fixpos($$, $3);
  1632. if (cond_negative(&$$->nd_cond)) {
  1633. nd_set_type($$, NODE_UNTIL);
  1634. }
  1635. }
  1636. | kUNTIL {
  1637. PUSH_LINE("until");
  1638. COND_PUSH(1);
  1639. } expr_value do {COND_POP();}
  1640. compstmt
  1641. kEND
  1642. {
  1643. POP_LINE();
  1644. $$ = NEW_UNTIL(cond($3, vps), $6, 1);
  1645. fixpos($$, $3);
  1646. if (cond_negative(&$$->nd_cond)) {
  1647. nd_set_type($$, NODE_WHILE);
  1648. }
  1649. }
  1650. | kCASE {
  1651. PUSH_LINE("case");
  1652. } expr_value opt_terms
  1653. case_body
  1654. kEND
  1655. {
  1656. POP_LINE();
  1657. $$ = NEW_CASE($3, $5);
  1658. fixpos($$, $3);
  1659. }
  1660. | kCASE opt_terms {
  1661. push_start_line((rb_parser_state*)parser_state, ruby_sourceline - 1, "case");
  1662. } case_body kEND
  1663. {
  1664. POP_LINE();
  1665. $$ = $4;
  1666. }
  1667. | kCASE opt_terms {
  1668. push_start_line((rb_parser_state*)parser_state, ruby_sourceline - 1, "case");
  1669. } kELSE compstmt kEND
  1670. {
  1671. POP_LINE();
  1672. $$ = $5;
  1673. }
  1674. | kFOR {
  1675. PUSH_LINE("for");
  1676. } for_var kIN {COND_PUSH(1);} expr_value do {COND_POP();}
  1677. compstmt
  1678. kEND
  1679. {
  1680. POP_LINE();
  1681. $$ = NEW_FOR($3, $6, $9);
  1682. fixpos($$, $3);
  1683. }
  1684. | kCLASS cpath superclass
  1685. {
  1686. PUSH_LINE("class");
  1687. if (in_def || in_single)
  1688. yyerror("class definition in method body");
  1689. class_nest++;
  1690. local_push(0);
  1691. $<num>$ = ruby_sourceline;
  1692. }
  1693. bodystmt
  1694. kEND
  1695. {
  1696. POP_LINE();
  1697. $$ = NEW_CLASS($2, $5, $3);
  1698. nd_set_line($$, $<num>4);
  1699. local_pop();
  1700. class_nest--;
  1701. }
  1702. | kCLASS tLSHFT expr
  1703. {
  1704. PUSH_LINE("class");
  1705. $<num>$ = in_def;
  1706. in_def = 0;
  1707. }
  1708. term
  1709. {
  1710. $<num>$ = in_single;
  1711. in_single = 0;
  1712. class_nest++;
  1713. local_push(0);
  1714. }
  1715. bodystmt
  1716. kEND
  1717. {
  1718. POP_LINE();
  1719. $$ = NEW_SCLASS($3, $7);
  1720. fixpos($$, $3);
  1721. local_pop();
  1722. class_nest--;
  1723. in_def = $<num>4;
  1724. in_single = $<num>6;
  1725. }
  1726. | kMODULE cpath
  1727. {
  1728. PUSH_LINE("module");
  1729. if (in_def || in_single)
  1730. yyerror("module definition in method body");
  1731. class_nest++;
  1732. local_push(0);
  1733. $<num>$ = ruby_sourceline;
  1734. }
  1735. bodystmt
  1736. kEND
  1737. {
  1738. POP_LINE();
  1739. $$ = NEW_MODULE($2, $4);
  1740. nd_set_line($$, $<num>3);
  1741. local_pop();
  1742. class_nest--;
  1743. }
  1744. | kDEF fname
  1745. {
  1746. PUSH_LINE("def");
  1747. $<id>$ = cur_mid;
  1748. cur_mid = $2;
  1749. in_def++;
  1750. local_push(0);
  1751. }
  1752. f_arglist
  1753. bodystmt
  1754. kEND
  1755. {
  1756. POP_LINE();
  1757. if (!$5) $5 = NEW_NIL();
  1758. $$ = NEW_DEFN($2, $4, $5, NOEX_PRIVATE);
  1759. fixpos($$, $4);
  1760. local_pop();
  1761. in_def--;
  1762. cur_mid = $<id>3;
  1763. }
  1764. | kDEF singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
  1765. {
  1766. PUSH_LINE("def");
  1767. in_single++;
  1768. local_push(0);
  1769. lex_state = EXPR_END; /* force for args */
  1770. }
  1771. f_arglist
  1772. bodystmt
  1773. kEND
  1774. {
  1775. POP_LINE();
  1776. $$ = NEW_DEFS($2, $5, $7, $8);
  1777. fixpos($$, $2);
  1778. local_pop();
  1779. in_single--;
  1780. }
  1781. | kBREAK
  1782. {
  1783. $$ = NEW_BREAK(0);
  1784. }
  1785. | kNEXT
  1786. {
  1787. $$ = NEW_NEXT(0);
  1788. }
  1789. | kREDO
  1790. {
  1791. $$ = NEW_REDO();
  1792. }
  1793. | kRETRY
  1794. {
  1795. $$ = NEW_RETRY();
  1796. }
  1797. ;
  1798. primary_value : primary
  1799. {
  1800. value_expr($1);
  1801. $$ = $1;
  1802. }
  1803. ;
  1804. then : term
  1805. | ':'
  1806. | kTHEN
  1807. | term kTHEN
  1808. ;
  1809. do : term
  1810. | ':'
  1811. | kDO_COND
  1812. ;
  1813. if_tail : opt_else
  1814. | kELSIF expr_value then
  1815. compstmt
  1816. if_tail
  1817. {
  1818. $$ = NEW_IF(cond($2, vps), $4, $5);
  1819. fixpos($$, $2);
  1820. }
  1821. ;
  1822. opt_else : none
  1823. | kELSE compstmt
  1824. {
  1825. $$ = $2;
  1826. }
  1827. ;
  1828. for_var : lhs
  1829. | mlhs
  1830. ;
  1831. block_par : mlhs_item
  1832. {
  1833. $$ = NEW_LIST($1);
  1834. }
  1835. | block_par ',' mlhs_item
  1836. {
  1837. $$ = list_append(vps, $1, $3);
  1838. }
  1839. ;
  1840. block_var : block_par
  1841. {
  1842. if ($1->nd_alen == 1) {
  1843. $$ = $1->nd_head;
  1844. }
  1845. else {
  1846. $$ = NEW_MASGN($1, 0);
  1847. }
  1848. }
  1849. | block_par ','
  1850. {
  1851. $$ = NEW_MASGN($1, 0);
  1852. }
  1853. | block_par ',' tAMPER lhs
  1854. {
  1855. $$ = NEW_BLOCK_VAR($4, NEW_MASGN($1, 0));
  1856. }
  1857. | block_par ',' tSTAR lhs ',' tAMPER lhs
  1858. {
  1859. $$ = NEW_BLOCK_VAR($7, NEW_MASGN($1, $4));
  1860. }
  1861. | block_par ',' tSTAR ',' tAMPER lhs
  1862. {
  1863. $$ = NEW_BLOCK_VAR($6, NEW_MASGN($1, -1));
  1864. }
  1865. | block_par ',' tSTAR lhs
  1866. {
  1867. $$ = NEW_MASGN($1, $4);
  1868. }
  1869. | block_par ',' tSTAR
  1870. {
  1871. $$ = NEW_MASGN($1, -1);
  1872. }
  1873. | tSTAR lhs ',' tAMPER lhs
  1874. {
  1875. $$ = NEW_BLOCK_VAR($5, NEW_MASGN(0, $2));
  1876. }
  1877. | tSTAR ',' tAMPER lhs
  1878. {
  1879. $$ = NEW_BLOCK_VAR($4, NEW_MASGN(0, -1));
  1880. }
  1881. | tSTAR lhs
  1882. {
  1883. $$ = NEW_MASGN(0, $2);
  1884. }
  1885. | tSTAR
  1886. {
  1887. $$ = NEW_MASGN(0, -1);
  1888. }
  1889. | tAMPER lhs
  1890. {
  1891. $$ = NEW_BLOCK_VAR($2, (NODE*)1);
  1892. }
  1893. ;
  1894. opt_block_var : none
  1895. | '|' /* none */ '|'
  1896. {
  1897. $$ = (NODE*)1;
  1898. }
  1899. | tOROP
  1900. {
  1901. $$ = (NODE*)1;
  1902. }
  1903. | '|' block_var '|'
  1904. {
  1905. $$ = $2;
  1906. }
  1907. ;
  1908. do_block : kDO_BLOCK
  1909. {
  1910. PUSH_LINE("do");
  1911. $<num>1 = ruby_sourceline;
  1912. reset_block(vps);
  1913. }
  1914. opt_block_var
  1915. {
  1916. $<vars>$ = variables->block_vars;
  1917. }
  1918. compstmt
  1919. kEND
  1920. {
  1921. POP_LINE();
  1922. $$ = NEW_ITER($3, 0, extract_block_vars(vps, $5, $<vars>4));
  1923. nd_set_line($$, $<num>1);
  1924. }
  1925. ;
  1926. block_call : command do_block
  1927. {
  1928. if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
  1929. rb_compile_error(vps, "both block arg and actual block given");
  1930. }
  1931. $2->nd_iter = $1;
  1932. $$ = $2;
  1933. fixpos($$, $1);
  1934. }
  1935. | block_call '.' operation2 opt_paren_args
  1936. {
  1937. $$ = new_call(vps, $1, $3, $4);
  1938. }
  1939. | block_call tCOLON2 operation2 opt_paren_args
  1940. {
  1941. $$ = new_call(vps, $1, $3, $4);
  1942. }
  1943. ;
  1944. method_call : operation paren_args
  1945. {
  1946. $$ = new_fcall(vps, $1, $2);
  1947. fixpos($$, $2);
  1948. }
  1949. | primary_value '.' operation2 opt_paren_args
  1950. {
  1951. $$ = new_call(vps, $1, $3, $4);
  1952. fixpos($$, $1);
  1953. }
  1954. | primary_value tCOLON2 operation2 paren_args
  1955. {
  1956. $$ = new_call(vps, $1, $3, $4);
  1957. fixpos($$, $1);
  1958. }
  1959. | primary_value tCOLON2 operation3
  1960. {
  1961. $$ = new_call(vps, $1, $3, 0);
  1962. }
  1963. | primary_value '\\' operation2
  1964. {
  1965. $$ = NEW_CALL($1, rb_parser_sym((rb_parser_state*) parser_state, "get_reference"),
  1966. NEW_LIST(NEW_LIT(QUID2SYM($3))));
  1967. }
  1968. | tUBS operation2
  1969. {
  1970. $$ = NEW_FCALL(rb_parser_sym((rb_parser_state*) parser_state, "get_reference"),
  1971. NEW_LIST(NEW_LIT(QUID2SYM($2))));
  1972. }
  1973. | kSUPER paren_args
  1974. {
  1975. $$ = new_super(vps, $2);
  1976. }
  1977. | kSUPER
  1978. {
  1979. $$ = NEW_ZSUPER();
  1980. }
  1981. ;
  1982. brace_block : '{'
  1983. {
  1984. $<num>1 = ruby_sourceline;
  1985. reset_block(vps);
  1986. }
  1987. opt_block_var { $<vars>$ = variables->block_vars; }
  1988. compstmt '}'
  1989. {
  1990. $$ = NEW_ITER($3, 0, extract_block_vars(vps, $5, $<vars>4));
  1991. nd_set_line($$, $<num>1);
  1992. }
  1993. | kDO
  1994. {
  1995. PUSH_LINE("do");
  1996. $<num>1 = ruby_sourceline;
  1997. reset_block(vps);
  1998. }
  1999. opt_block_var { $<vars>$ = variables->block_vars; }
  2000. compstmt kEND
  2001. {
  2002. POP_LINE();
  2003. $$ = NEW_ITER($3, 0, extract_block_vars(vps, $5, $<vars>4));
  2004. nd_set_line($$, $<num>1);
  2005. }
  2006. ;
  2007. case_body : kWHEN when_args then
  2008. compstmt
  2009. cases
  2010. {
  2011. $$ = NEW_WHEN($2, $4, $5);
  2012. }
  2013. ;
  2014. when_args : args
  2015. | args ',' tSTAR arg_value
  2016. {
  2017. $$ = list_append(vps, $1, NEW_WHEN($4, 0, 0));
  2018. }
  2019. | tSTAR arg_value
  2020. {
  2021. $$ = NEW_LIST(NEW_WHEN($2, 0, 0));
  2022. }
  2023. ;
  2024. cases : opt_else
  2025. | case_body
  2026. ;
  2027. opt_rescue : kRESCUE exc_list exc_var then
  2028. compstmt
  2029. opt_rescue
  2030. {
  2031. if ($3) {
  2032. $3 = node_assign($3, NEW_GVAR(rb_parser_sym((rb_parser_state*) parser_state, "$!")), vps);
  2033. $5 = block_append(vps, $3, $5);
  2034. }
  2035. $$ = NEW_RESBODY($2, $5, $6);
  2036. fixpos($$, $2?$2:$5);
  2037. }
  2038. | none
  2039. ;
  2040. exc_list : arg_value
  2041. {
  2042. $$ = NEW_LIST($1);
  2043. }
  2044. | mrhs
  2045. | none
  2046. ;
  2047. exc_var : tASSOC lhs
  2048. {
  2049. $$ = $2;
  2050. }
  2051. | none
  2052. ;
  2053. opt_ensure : kENSURE compstmt
  2054. {
  2055. if ($2)
  2056. $$ = $2;
  2057. else
  2058. /* place holder */
  2059. $$ = NEW_NIL();
  2060. }
  2061. | none
  2062. ;
  2063. literal : numeric
  2064. | symbol
  2065. {
  2066. $$ = NEW_LIT(QUID2SYM($1));
  2067. }
  2068. | dsym
  2069. ;
  2070. strings : string
  2071. {
  2072. NODE *node = $1;
  2073. if (!node) {
  2074. node = NEW_STR(string_new(0, 0));
  2075. }
  2076. else {
  2077. node = evstr2dstr(vps, node);
  2078. }
  2079. $$ = node;
  2080. }
  2081. ;
  2082. string : string1
  2083. | string string1
  2084. {
  2085. $$ = literal_concat(vps, $1, $2);
  2086. }
  2087. ;
  2088. string1 : tSTRING_BEG string_contents tSTRING_END
  2089. {
  2090. $$ = $2;
  2091. }
  2092. ;
  2093. xstring : tXSTRING_BEG xstring_contents tSTRING_END
  2094. {
  2095. NODE *node = $2;
  2096. if (!node) {
  2097. node = NEW_XSTR(string_new(0, 0));
  2098. }
  2099. else {
  2100. switch (nd_type(node)) {
  2101. case NODE_STR:
  2102. nd_set_type(node, NODE_XSTR);
  2103. break;
  2104. case NODE_DSTR:
  2105. nd_set_type(node, NODE_DXSTR);
  2106. break;
  2107. default:
  2108. node = NEW_NODE(NODE_DXSTR, string_new(0, 0), 1, NEW_LIST(node));
  2109. break;
  2110. }
  2111. }
  2112. $$ = node;
  2113. }
  2114. ;
  2115. regexp : tREGEXP_BEG xstring_contents tREGEXP_END
  2116. {
  2117. intptr_t options = $3;
  2118. NODE *node = $2;
  2119. if (!node) {
  2120. node = NEW_REGEX(string_new2(""), options & ~RE_OPTION_ONCE);
  2121. }
  2122. else switch (nd_type(node)) {
  2123. case NODE_STR:
  2124. {
  2125. nd_set_type(node, NODE_REGEX);
  2126. node->nd_cnt = options & ~RE_OPTION_ONCE;
  2127. }
  2128. break;
  2129. default:
  2130. node = NEW_NODE(NODE_DSTR, string_new(0, 0), 1, NEW_LIST(node));
  2131. case NODE_DSTR:
  2132. if (options & RE_OPTION_ONCE) {
  2133. nd_set_type(node, NODE_DREGX_ONCE);
  2134. }
  2135. else {
  2136. nd_set_type(node, NODE_DREGX);
  2137. }
  2138. node->nd_cflag = options & ~RE_OPTION_ONCE;
  2139. break;
  2140. }
  2141. $$ = node;
  2142. }
  2143. ;
  2144. words : tWORDS_BEG ' ' tSTRING_END
  2145. {
  2146. $$ = NEW_ZARRAY();
  2147. }
  2148. | tWORDS_BEG word_list tSTRING_END
  2149. {
  2150. $$ = $2;
  2151. }
  2152. ;
  2153. word_list : /* none */
  2154. {
  2155. $$ = 0;
  2156. }
  2157. | word_list word ' '
  2158. {
  2159. $$ = list_append(vps, $1, evstr2dstr(vps, $2));
  2160. }
  2161. ;
  2162. word : string_content
  2163. | word string_content
  2164. {
  2165. $$ = literal_concat(vps, $1, $2);
  2166. }
  2167. ;
  2168. qwords : tQWORDS_BEG ' ' tSTRING_END
  2169. {
  2170. $$ = NEW_ZARRAY();
  2171. }
  2172. | tQWORDS_BEG qword_list tSTRING_END
  2173. {
  2174. $$ = $2;
  2175. }
  2176. ;
  2177. qword_list : /* none */
  2178. {
  2179. $$ = 0;
  2180. }
  2181. | qword_list tSTRING_CONTENT ' '
  2182. {
  2183. $$ = list_append(vps, $1, $2);
  2184. }
  2185. ;
  2186. string_contents : /* none */
  2187. {
  2188. $$ = 0;
  2189. }
  2190. | string_contents string_content
  2191. {
  2192. $$ = literal_concat(vps, $1, $2);
  2193. }
  2194. ;
  2195. xstring_contents: /* none */
  2196. {
  2197. $$ = 0;
  2198. }
  2199. | xstring_contents string_content
  2200. {
  2201. $$ = literal_concat(vps, $1, $2);
  2202. }
  2203. ;
  2204. string_content : tSTRING_CONTENT
  2205. | tSTRING_DVAR
  2206. {
  2207. $<node>$ = lex_strterm;
  2208. lex_strterm = 0;
  2209. lex_state = EXPR_BEG;
  2210. }
  2211. string_dvar
  2212. {
  2213. lex_strterm = $<node>2;
  2214. $$ = NEW_EVSTR($3);
  2215. }
  2216. | tSTRING_DBEG
  2217. {
  2218. $<node>$ = lex_strterm;
  2219. lex_strterm = 0;
  2220. lex_state = EXPR_BEG;
  2221. COND_PUSH(0);
  2222. CMDARG_PUSH(0);
  2223. }
  2224. compstmt '}'
  2225. {
  2226. lex_strterm = $<node>2;
  2227. COND_LEXPOP();
  2228. CMDARG_LEXPOP();
  2229. if (($$ = $3) && nd_type($$) == NODE_NEWLINE) {
  2230. $$ = $$->nd_next;
  2231. }
  2232. $$ = new_evstr(vps, $$);
  2233. }
  2234. ;
  2235. string_dvar : tGVAR {$$ = NEW_GVAR($1);}
  2236. | tIVAR {$$ = NEW_IVAR($1);}
  2237. | tCVAR {$$ = NEW_CVAR($1);}
  2238. | backref
  2239. ;
  2240. symbol : tSYMBEG sym
  2241. {
  2242. lex_state = EXPR_END;
  2243. $$ = $2;
  2244. }
  2245. ;
  2246. sym : fname
  2247. | tIVAR
  2248. | tGVAR
  2249. | tCVAR
  2250. ;
  2251. dsym : tSYMBEG xstring_contents tSTRING_END
  2252. {
  2253. lex_state = EXPR_END;
  2254. if (!($$ = $2)) {
  2255. yyerror("empty symbol literal");
  2256. }
  2257. else {
  2258. switch (nd_type($$)) {
  2259. case NODE_DSTR:
  2260. nd_set_type($$, NODE_DSYM);
  2261. break;
  2262. case NODE_STR:
  2263. /* TODO: this line should never fail unless nd_str is binary */
  2264. if (strlen(bdatae($$->nd_str,"")) == (size_t)blength($$->nd_str)) {
  2265. QUID tmp = rb_parser_sym((rb_parser_state*) parser_state, bdata($$->nd_str));
  2266. bdestroy($$->nd_str);
  2267. $$->nd_lit = QUID2SYM(tmp);
  2268. nd_set_type($$, NODE_LIT);
  2269. break;
  2270. } else {
  2271. bdestroy($$->nd_str);
  2272. }
  2273. /* fall through */
  2274. default:
  2275. $$ = NEW_NODE(NODE_DSYM, string_new(0, 0), 1, NEW_LIST($$));
  2276. break;
  2277. }
  2278. }
  2279. }
  2280. ;
  2281. numeric : tINTEGER
  2282. | tFLOAT
  2283. | tUMINUS_NUM tINTEGER %prec tLOWEST
  2284. {
  2285. $$ = NEW_NEGATE($2);
  2286. }
  2287. | tUMINUS_NUM tFLOAT %prec tLOWEST
  2288. {
  2289. $$ = NEW_NEGATE($2);
  2290. }
  2291. ;
  2292. variable : tIDENTIFIER
  2293. | tIVAR
  2294. | tGVAR
  2295. | tCONSTANT
  2296. | tCVAR
  2297. | kNIL {$$ = kNIL;}
  2298. | kSELF {$$ = kSELF;}
  2299. | kTRUE {$$ = kTRUE;}
  2300. | kFALSE {$$ = kFALSE;}
  2301. | k__FILE__ {$$ = k__FILE__;}
  2302. | k__LINE__ {$$ = k__LINE__;}
  2303. ;
  2304. var_ref : variable
  2305. {
  2306. $$ = gettable($1);
  2307. }
  2308. ;
  2309. var_lhs : variable
  2310. {
  2311. $$ = assignable($1, 0, vps);
  2312. }
  2313. ;
  2314. backref : tNTH_REF
  2315. | tBACK_REF
  2316. ;
  2317. superclass : term
  2318. {
  2319. $$ = 0;
  2320. }
  2321. | '<'
  2322. {
  2323. lex_state = EXPR_BEG;
  2324. }
  2325. expr_value term
  2326. {
  2327. $$ = $3;
  2328. }
  2329. | error term {yyerrok; $$ = 0;}
  2330. ;
  2331. f_arglist : '(' f_args opt_nl ')'
  2332. {
  2333. $$ = $2;
  2334. lex_state = EXPR_BEG;
  2335. command_start = TRUE;
  2336. }
  2337. | f_args term
  2338. {
  2339. $$ = $1;
  2340. }
  2341. ;
  2342. f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
  2343. {
  2344. $$ = block_append(vps, NEW_ARGS((intptr_t)$1, $3, $5), $6);
  2345. }
  2346. | f_arg ',' f_optarg opt_f_block_arg
  2347. {
  2348. $$ = block_append(vps, NEW_ARGS((intptr_t)$1, $3, 0), $4);
  2349. }
  2350. | f_arg ',' f_rest_arg opt_f_block_arg
  2351. {
  2352. $$ = block_append(vps, NEW_ARGS((intptr_t)$1, 0, $3), $4);
  2353. }
  2354. | f_arg opt_f_block_arg
  2355. {
  2356. $$ = block_append(vps, NEW_ARGS((intptr_t)$1, 0, 0), $2);
  2357. }
  2358. | f_optarg ',' f_rest_arg opt_f_block_arg
  2359. {
  2360. $$ = block_append(vps, NEW_ARGS(0, $1, $3), $4);
  2361. }
  2362. | f_optarg opt_f_block_arg
  2363. {
  2364. $$ = block_append(vps, NEW_ARGS(0, $1, 0), $2);
  2365. }
  2366. | f_rest_arg opt_f_block_arg
  2367. {
  2368. $$ = block_append(vps, NEW_ARGS(0, 0, $1), $2);
  2369. }
  2370. | f_block_arg
  2371. {
  2372. $$ = block_append(vps, NEW_ARGS(0, 0, 0), $1);
  2373. }
  2374. | /* none */
  2375. {
  2376. $$ = NEW_ARGS(0, 0, 0);
  2377. }
  2378. ;
  2379. f_norm_arg : tCONSTANT
  2380. {
  2381. yyerror("formal argument cannot be a constant");
  2382. }
  2383. | tIVAR
  2384. {
  2385. yyerror("formal argument cannot be an instance variable");
  2386. }
  2387. | tGVAR
  2388. {
  2389. yyerror("formal argument cannot be a global variable");
  2390. }
  2391. | tCVAR
  2392. {
  2393. yyerror("formal argument cannot be a class variable");
  2394. }
  2395. | tIDENTIFIER
  2396. {
  2397. if (!is_local_id($1))
  2398. yyerror("formal argument must be local variable");
  2399. else if (local_id($1))
  2400. yyerror("duplicate argument name");
  2401. local_cnt($1);
  2402. $$ = 1;
  2403. }
  2404. ;
  2405. f_arg : f_norm_arg
  2406. | f_arg ',' f_norm_arg
  2407. {
  2408. $$ += 1;
  2409. }
  2410. ;
  2411. f_opt : tIDENTIFIER '=' arg_value
  2412. {
  2413. if (!is_local_id($1))
  2414. yyerror("formal argument must be local variable");
  2415. else if (local_id($1))
  2416. yyerror("duplicate optional argument name");
  2417. $$ = assignable($1, $3, vps);
  2418. }
  2419. ;
  2420. f_optarg : f_opt
  2421. {
  2422. $$ = NEW_BLOCK($1);
  2423. $$->nd_end = $$;
  2424. }
  2425. | f_optarg ',' f_opt
  2426. {
  2427. $$ = block_append(vps, $1, $3);
  2428. }
  2429. ;
  2430. restarg_mark : '*'
  2431. | tSTAR
  2432. ;
  2433. f_rest_arg : restarg_mark tIDENTIFIER
  2434. {
  2435. if (!is_local_id($2))
  2436. yyerror("rest argument must be local variable");
  2437. else if (local_id($2))
  2438. yyerror("duplicate rest argument name");
  2439. $$ = local_cnt($2) + 1;
  2440. }
  2441. | restarg_mark
  2442. {
  2443. $$ = -2;
  2444. }
  2445. ;
  2446. blkarg_mark : '&'
  2447. | tAMPER
  2448. ;
  2449. f_block_arg : blkarg_mark tIDENTIFIER
  2450. {
  2451. if (!is_local_id($2))
  2452. yyerror("block argument must be local variable");
  2453. else if (local_id($2))
  2454. yyerror("duplicate block argument name");
  2455. $$ = NEW_BLOCK_ARG($2);
  2456. }
  2457. ;
  2458. opt_f_block_arg : ',' f_block_arg
  2459. {
  2460. $$ = $2;
  2461. }
  2462. | none
  2463. ;
  2464. singleton : var_ref
  2465. {
  2466. $$ = $1;
  2467. value_expr($$);
  2468. }
  2469. | '(' {lex_state = EXPR_BEG;} expr opt_nl ')'
  2470. {
  2471. if ($3 == 0) {
  2472. yyerror("can't define singleton method for ().");
  2473. }
  2474. else {
  2475. switch (nd_type($3)) {
  2476. case NODE_STR:
  2477. case NODE_DSTR:
  2478. case NODE_XSTR:
  2479. case NODE_DXSTR:
  2480. case NODE_DREGX:
  2481. case NODE_LIT:
  2482. case NODE_ARRAY:
  2483. case NODE_ZARRAY:
  2484. yyerror("can't define singleton method for literals");
  2485. default:
  2486. value_expr($3);
  2487. break;
  2488. }
  2489. }
  2490. $$ = $3;
  2491. }
  2492. ;
  2493. assoc_list : none
  2494. | assocs trailer
  2495. {
  2496. $$ = $1;
  2497. }
  2498. | args trailer
  2499. {
  2500. if ($1->nd_alen%2 != 0) {
  2501. yyerror("odd number list for Hash");
  2502. }
  2503. $$ = $1;
  2504. }
  2505. ;
  2506. assocs : assoc
  2507. | assocs ',' assoc
  2508. {
  2509. $$ = list_concat($1, $3);
  2510. }
  2511. ;
  2512. assoc : arg_value tASSOC arg_value
  2513. {
  2514. $$ = list_append(vps, NEW_LIST($1), $3);
  2515. }
  2516. ;
  2517. operation : tIDENTIFIER
  2518. | tCONSTANT
  2519. | tFID
  2520. ;
  2521. operation2 : tIDENTIFIER
  2522. | tCONSTANT
  2523. | tFID
  2524. | op
  2525. ;
  2526. operation3 : tIDENTIFIER
  2527. | tFID
  2528. | op
  2529. ;
  2530. dot_or_colon : '.'
  2531. | tCOLON2
  2532. ;
  2533. opt_terms : /* none */
  2534. | terms
  2535. ;
  2536. opt_nl : /* none */
  2537. | '\n'
  2538. ;
  2539. trailer : /* none */
  2540. | '\n'
  2541. | ','
  2542. ;
  2543. term : ';' {yyerrok;}
  2544. | '\n'
  2545. ;
  2546. terms : term
  2547. | terms ';' {yyerrok;}
  2548. ;
  2549. none : /* none */ {$$ = 0;}
  2550. ;
  2551. %%
  2552. /* We remove any previous definition of `SIGN_EXTEND_CHAR',
  2553. since ours (we hope) works properly with all combinations of
  2554. machines, compilers, `char' and `unsigned char' argument types.
  2555. (Per Bothner suggested the basic approach.) */
  2556. #undef SIGN_EXTEND_CHAR
  2557. #if __STDC__
  2558. # define SIGN_EXTEND_CHAR(c) ((signed char)(c))
  2559. #else /* not __STDC__ */
  2560. /* As in Harbison and Steele. */
  2561. # define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
  2562. #endif
  2563. #define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_' || ismbchar(c)))
  2564. #define LEAVE_BS 1
  2565. static int
  2566. mel_yyerror(const char *msg, rb_parser_state *parser_state)
  2567. {
  2568. create_error(parser_state, (char *)msg);
  2569. return 1;
  2570. }
  2571. static int
  2572. yycompile(rb_parser_state *parser_state, char *f, int line)
  2573. {
  2574. int n;
  2575. /* Setup an initial empty scope. */
  2576. heredoc_end = 0;
  2577. lex_strterm = 0;
  2578. end_seen = 0;
  2579. ruby_sourcefile = f;
  2580. command_start = TRUE;
  2581. n = yyparse(parser_state);
  2582. ruby_debug_lines = 0;
  2583. compile_for_eval = 0;
  2584. cond_stack = 0;
  2585. cmdarg_stack = 0;
  2586. command_start = TRUE;
  2587. class_nest = 0;
  2588. in_single = 0;
  2589. in_def = 0;
  2590. cur_mid = 0;
  2591. lex_strterm = 0;
  2592. return n;
  2593. }
  2594. static bool
  2595. lex_get_str(rb_parser_state *parser_state)
  2596. {
  2597. const char *str;
  2598. const char *beg, *end, *pend;
  2599. int sz;
  2600. str = bdata(lex_string);
  2601. beg = str;
  2602. if (lex_str_used) {
  2603. if (blength(lex_string) == lex_str_used) {
  2604. return false;
  2605. }
  2606. beg += lex_str_used;
  2607. }
  2608. pend = str + blength(lex_string);
  2609. end = beg;
  2610. while(end < pend) {
  2611. if(*end++ == '\n') break;
  2612. }
  2613. sz = (int)(end - beg);
  2614. bcatblk(line_buffer, beg, sz);
  2615. lex_str_used += sz;
  2616. return TRUE;
  2617. }
  2618. static bool
  2619. lex_getline(rb_parser_state *parser_state)
  2620. {
  2621. if(!line_buffer) {
  2622. line_buffer = cstr2bstr("");
  2623. } else {
  2624. btrunc(line_buffer, 0);
  2625. }
  2626. return lex_gets(parser_state);
  2627. }
  2628. VALUE
  2629. string_to_ast(VALUE ptp, const char *f, bstring s, int line)
  2630. {
  2631. int n;
  2632. VALUE ret;
  2633. rb_parser_state *parser_state = parser_alloc_state();
  2634. lex_string = s;
  2635. lex_gets = lex_get_str;
  2636. processor = ptp;
  2637. ruby_sourceline = line - 1;
  2638. compile_for_eval = 1;
  2639. n = yycompile(parser_state, (char*)f, line);
  2640. if(!parse_error) {
  2641. for(std::vector<bstring>::iterator i = magic_comments->begin();
  2642. i != magic_comments->end();
  2643. i++) {
  2644. rb_funcall(ptp, rb_intern("add_magic_comment"), 1,
  2645. rb_str_new((const char*)(*i)->data, (*i)->slen));
  2646. }
  2647. ret = process_parse_tree(parser_state, ptp, top_node, NULL);
  2648. } else {
  2649. ret = Qnil;
  2650. }
  2651. pt_free(parser_state);
  2652. free(parser_state);
  2653. return ret;
  2654. }
  2655. static bool parse_io_gets(rb_parser_state *parser_state) {
  2656. if(feof(lex_io)) {
  2657. return false;
  2658. }
  2659. while(TRUE) {
  2660. char *ptr, buf[1024];
  2661. int read;
  2662. ptr = fgets(buf, sizeof(buf), lex_io);
  2663. if(!ptr) {
  2664. return false;
  2665. }
  2666. read = (int)strlen(ptr);
  2667. bcatblk(line_buffer, ptr, read);
  2668. /* check whether we read a full line */
  2669. if(!(read == (sizeof(buf) - 1) && ptr[read] != '\n')) {
  2670. break;
  2671. }
  2672. }
  2673. return TRUE;
  2674. }
  2675. VALUE
  2676. file_to_ast(VALUE ptp, const char *f, FILE *file, int start)
  2677. {
  2678. int n;
  2679. VALUE ret;
  2680. rb_parser_state *parser_state = parser_alloc_state();
  2681. lex_io = file;
  2682. lex_gets = parse_io_gets;
  2683. processor = ptp;
  2684. ruby_sourceline = start - 1;
  2685. n = yycompile(parser_state, (char*)f, start);
  2686. if(!parse_error) {
  2687. for(std::vector<bstring>::iterator i = magic_comments->begin();
  2688. i != magic_comments->end();
  2689. i++) {
  2690. rb_funcall(ptp, rb_intern("add_magic_comment"), 1,
  2691. rb_str_new((const char*)(*i)->data, (*i)->slen));
  2692. }
  2693. ret = process_parse_tree(parser_state, ptp, top_node, NULL);
  2694. if (end_seen && lex_io) {
  2695. rb_funcall(ptp, rb_sData, 1, ULONG2NUM(ftell(lex_io)));
  2696. }
  2697. } else {
  2698. ret = Qnil;
  2699. }
  2700. pt_free(parser_state);
  2701. free(parser_state);
  2702. return ret;
  2703. }
  2704. #define nextc() ps_nextc(parser_state)
  2705. static inline int
  2706. ps_nextc(rb_parser_state *parser_state)
  2707. {
  2708. int c;
  2709. if (lex_p == lex_pend) {
  2710. bstring v;
  2711. if (!lex_getline(parser_state)) return -1;
  2712. v = line_buffer;
  2713. if (heredoc_end > 0) {
  2714. ruby_sourceline = heredoc_end;
  2715. heredoc_end = 0;
  2716. }
  2717. ruby_sourceline++;
  2718. /* This code is setup so that lex_pend can be compared to
  2719. the data in lex_lastline. Thats important, otherwise
  2720. the heredoc code breaks. */
  2721. if(lex_lastline) {
  2722. bassign(lex_lastline, v);
  2723. } else {
  2724. lex_lastline = bstrcpy(v);
  2725. }
  2726. v = lex_lastline;
  2727. lex_pbeg = lex_p = bdata(v);
  2728. lex_pend = lex_p + blength(v);
  2729. }
  2730. c = (unsigned char)*(lex_p++);
  2731. if (c == '\r' && lex_p < lex_pend && *(lex_p) == '\n') {
  2732. lex_p++;
  2733. c = '\n';
  2734. column = 0;
  2735. } else if(c == '\n') {
  2736. column = 0;
  2737. } else {
  2738. column++;
  2739. }
  2740. return c;
  2741. }
  2742. static void
  2743. pushback(int c, rb_parser_state *parser_state)
  2744. {
  2745. if (c == -1) return;
  2746. lex_p--;
  2747. }
  2748. /* Indicates if we're currently at the beginning of a line. */
  2749. #define was_bol() (lex_p == lex_pbeg + 1)
  2750. #define peek(c) (lex_p != lex_pend && (c) == *(lex_p))
  2751. /* The token buffer. It's just a global string that has
  2752. functions to build up the string easily. */
  2753. #define tokfix() (tokenbuf[tokidx]='\0')
  2754. #define tok() tokenbuf
  2755. #define toklen() tokidx
  2756. #define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
  2757. static char*
  2758. newtok(rb_parser_state *parser_state)
  2759. {
  2760. tokidx = 0;
  2761. if (!tokenbuf) {
  2762. toksiz = 60;
  2763. tokenbuf = ALLOC_N(char, 60);
  2764. }
  2765. if (toksiz > 4096) {
  2766. toksiz = 60;
  2767. REALLOC_N(tokenbuf, char, 60);
  2768. }
  2769. return tokenbuf;
  2770. }
  2771. static void tokadd(char c, rb_parser_state *parser_state)
  2772. {
  2773. assert(tokidx < toksiz && tokidx >= 0);
  2774. tokenbuf[tokidx++] = c;
  2775. if (tokidx >= toksiz) {
  2776. toksiz *= 2;
  2777. REALLOC_N(tokenbuf, char, toksiz);
  2778. }
  2779. }
  2780. static int
  2781. read_escape(rb_parser_state *parser_state)
  2782. {
  2783. int c;
  2784. switch (c = nextc()) {
  2785. case '\\': /* Backslash */
  2786. return c;
  2787. case 'n': /* newline */
  2788. return '\n';
  2789. case 't': /* horizontal tab */
  2790. return '\t';
  2791. case 'r': /* carriage-return */
  2792. return '\r';
  2793. case 'f': /* form-feed */
  2794. return '\f';
  2795. case 'v': /* vertical tab */
  2796. return '\13';
  2797. case 'a': /* alarm(bell) */
  2798. return '\007';
  2799. case 'e': /* escape */
  2800. return 033;
  2801. case '0': case '1': case '2': case '3': /* octal constant */
  2802. case '4': case '5': case '6': case '7':
  2803. {
  2804. int numlen;
  2805. pushback(c, parser_state);
  2806. c = scan_oct(lex_p, 3, &numlen);
  2807. lex_p += numlen;
  2808. }
  2809. return c;
  2810. case 'x': /* hex constant */
  2811. {
  2812. int numlen;
  2813. c = scan_hex(lex_p, 2, &numlen);
  2814. if (numlen == 0) {
  2815. yyerror("Invalid escape character syntax");
  2816. return 0;
  2817. }
  2818. lex_p += numlen;
  2819. }
  2820. return c;
  2821. case 'b': /* backspace */
  2822. return '\010';
  2823. case 's': /* space */
  2824. return ' ';
  2825. case 'M':
  2826. if ((c = nextc()) != '-') {
  2827. yyerror("Invalid escape character syntax");
  2828. pushback(c, parser_state);
  2829. return '\0';
  2830. }
  2831. if ((c = nextc()) == '\\') {
  2832. return read_escape(parser_state) | 0x80;
  2833. }
  2834. else if (c == -1) goto eof;
  2835. else {
  2836. return ((c & 0xff) | 0x80);
  2837. }
  2838. case 'C':
  2839. if ((c = nextc()) != '-') {
  2840. yyerror("Invalid escape character syntax");
  2841. pushback(c, parser_state);
  2842. return '\0';
  2843. }
  2844. case 'c':
  2845. if ((c = nextc())== '\\') {
  2846. c = read_escape(parser_state);
  2847. }
  2848. else if (c == '?')
  2849. return 0177;
  2850. else if (c == -1) goto eof;
  2851. return c & 0x9f;
  2852. eof:
  2853. case -1:
  2854. yyerror("Invalid escape character syntax");
  2855. return '\0';
  2856. default:
  2857. return c;
  2858. }
  2859. }
  2860. static int
  2861. tokadd_escape(int term, rb_parser_state *parser_state)
  2862. {
  2863. int c;
  2864. switch (c = nextc()) {
  2865. case '\n':
  2866. return 0; /* just ignore */
  2867. case '0': case '1': case '2': case '3': /* octal constant */
  2868. case '4': case '5': case '6': case '7':
  2869. {
  2870. int i;
  2871. tokadd((char)'\\', parser_state);
  2872. tokadd((char)c, parser_state);
  2873. for (i=0; i<2; i++) {
  2874. c = nextc();
  2875. if (c == -1) goto eof;
  2876. if (c < '0' || '7' < c) {
  2877. pushback(c, parser_state);
  2878. break;
  2879. }
  2880. tokadd((char)c, parser_state);
  2881. }
  2882. }
  2883. return 0;
  2884. case 'x': /* hex constant */
  2885. {
  2886. int numlen;
  2887. tokadd('\\', parser_state);
  2888. tokadd((char)c, parser_state);
  2889. scan_hex(lex_p, 2, &numlen);
  2890. if (numlen == 0) {
  2891. yyerror("Invalid escape character syntax");
  2892. return -1;
  2893. }
  2894. while (numlen--)
  2895. tokadd((char)nextc(), parser_state);
  2896. }
  2897. return 0;
  2898. case 'M':
  2899. if ((c = nextc()) != '-') {
  2900. yyerror("Invalid escape character syntax");
  2901. pushback(c, parser_state);
  2902. return 0;
  2903. }
  2904. tokadd('\\',parser_state);
  2905. tokadd('M', parser_state);
  2906. tokadd('-', parser_state);
  2907. goto escaped;
  2908. case 'C':
  2909. if ((c = nextc()) != '-') {
  2910. yyerror("Invalid escape character syntax");
  2911. pushback(c, parser_state);
  2912. return 0;
  2913. }
  2914. tokadd('\\', parser_state);
  2915. tokadd('C', parser_state);
  2916. tokadd('-', parser_state);
  2917. goto escaped;
  2918. case 'c':
  2919. tokadd('\\', parser_state);
  2920. tokadd('c', parser_state);
  2921. escaped:
  2922. if ((c = nextc()) == '\\') {
  2923. return tokadd_escape(term, parser_state);
  2924. }
  2925. else if (c == -1) goto eof;
  2926. tokadd((char)c, parser_state);
  2927. return 0;
  2928. eof:
  2929. case -1:
  2930. yyerror("Invalid escape character syntax");
  2931. return -1;
  2932. default:
  2933. if (c != '\\' || c != term)
  2934. tokadd('\\', parser_state);
  2935. tokadd((char)c, parser_state);
  2936. }
  2937. return 0;
  2938. }
  2939. static int
  2940. regx_options(rb_parser_state *parser_state)
  2941. {
  2942. char kcode = 0;
  2943. int options = 0;
  2944. int c;
  2945. newtok(parser_state);
  2946. while (c = nextc(), ISALPHA(c)) {
  2947. switch (c) {
  2948. case 'i':
  2949. options |= RE_OPTION_IGNORECASE;
  2950. break;
  2951. case 'x':
  2952. options |= RE_OPTION_EXTENDED;
  2953. break;
  2954. case 'm':
  2955. options |= RE_OPTION_MULTILINE;
  2956. break;
  2957. case 'o':
  2958. options |= RE_OPTION_ONCE;
  2959. break;
  2960. case 'G':
  2961. options |= RE_OPTION_CAPTURE_GROUP;
  2962. break;
  2963. case 'g':
  2964. options |= RE_OPTION_DONT_CAPTURE_GROUP;
  2965. break;
  2966. case 'n':
  2967. kcode = 16;
  2968. break;
  2969. case 'e':
  2970. kcode = 32;
  2971. break;
  2972. case 's':
  2973. kcode = 48;
  2974. break;
  2975. case 'u':
  2976. kcode = 64;
  2977. break;
  2978. default:
  2979. tokadd((char)c, parser_state);
  2980. break;
  2981. }
  2982. }
  2983. pushback(c, parser_state);
  2984. if (toklen()) {
  2985. tokfix();
  2986. rb_compile_error(parser_state, "unknown regexp option%s - %s",
  2987. toklen() > 1 ? "s" : "", tok());
  2988. }
  2989. return options | kcode;
  2990. }
  2991. #define STR_FUNC_ESCAPE 0x01
  2992. #define STR_FUNC_EXPAND 0x02
  2993. #define STR_FUNC_REGEXP 0x04
  2994. #define STR_FUNC_QWORDS 0x08
  2995. #define STR_FUNC_SYMBOL 0x10
  2996. #define STR_FUNC_INDENT 0x20
  2997. enum string_type {
  2998. str_squote = (0),
  2999. str_dquote = (STR_FUNC_EXPAND),
  3000. str_xquote = (STR_FUNC_EXPAND),
  3001. str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND),
  3002. str_sword = (STR_FUNC_QWORDS),
  3003. str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND),
  3004. str_ssym = (STR_FUNC_SYMBOL),
  3005. str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND),
  3006. };
  3007. static int tokadd_string(int func, int term, int paren, quark *nest, rb_parser_state *parser_state)
  3008. {
  3009. int c;
  3010. while ((c = nextc()) != -1) {
  3011. if (paren && c == paren) {
  3012. ++*nest;
  3013. }
  3014. else if (c == term) {
  3015. if (!nest || !*nest) {
  3016. pushback(c, parser_state);
  3017. break;
  3018. }
  3019. --*nest;
  3020. }
  3021. else if ((func & STR_FUNC_EXPAND) && c == '#' && lex_p < lex_pend) {
  3022. int c2 = *(lex_p);
  3023. if (c2 == '$' || c2 == '@' || c2 == '{') {
  3024. pushback(c, parser_state);
  3025. break;
  3026. }
  3027. }
  3028. else if (c == '\\') {
  3029. c = nextc();
  3030. switch (c) {
  3031. case '\n':
  3032. if (func & STR_FUNC_QWORDS) break;
  3033. if (func & STR_FUNC_EXPAND) continue;
  3034. tokadd('\\', parser_state);
  3035. break;
  3036. case '\\':
  3037. if (func & STR_FUNC_ESCAPE) tokadd((char)c, parser_state);
  3038. break;
  3039. default:
  3040. if (func & STR_FUNC_REGEXP) {
  3041. pushback(c, parser_state);
  3042. if (tokadd_escape(term, parser_state) < 0)
  3043. return -1;
  3044. continue;
  3045. }
  3046. else if (func & STR_FUNC_EXPAND) {
  3047. pushback(c, parser_state);
  3048. if (func & STR_FUNC_ESCAPE) tokadd('\\', parser_state);
  3049. c = read_escape(parser_state);
  3050. }
  3051. else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
  3052. /* ignore backslashed spaces in %w */
  3053. }
  3054. else if (c != term && !(paren && c == paren)) {
  3055. tokadd('\\', parser_state);
  3056. }
  3057. }
  3058. }
  3059. else if (ismbchar(c)) {
  3060. int i, len = mbclen(c)-1;
  3061. for (i = 0; i < len; i++) {
  3062. tokadd((char)c, parser_state);
  3063. c = nextc();
  3064. }
  3065. }
  3066. else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
  3067. pushback(c, parser_state);
  3068. break;
  3069. }
  3070. if (!c && (func & STR_FUNC_SYMBOL)) {
  3071. func &= ~STR_FUNC_SYMBOL;
  3072. rb_compile_error(parser_state, "symbol cannot contain '\\0'");
  3073. continue;
  3074. }
  3075. tokadd((char)c, parser_state);
  3076. }
  3077. return c;
  3078. }
  3079. #define NEW_STRTERM(func, term, paren) \
  3080. node_newnode(NODE_STRTERM, (VALUE)(func), \
  3081. (VALUE)((term) | ((paren) << (CHAR_BIT * 2))), 0)
  3082. #define pslval ((YYSTYPE *)lval)
  3083. static int
  3084. parse_string(NODE *quote, rb_parser_state *parser_state)
  3085. {
  3086. int func = (int)quote->nd_func;
  3087. int term = nd_term(quote);
  3088. int paren = nd_paren(quote);
  3089. int c, space = 0;
  3090. long start_line = ruby_sourceline;
  3091. if (func == -1) return tSTRING_END;
  3092. c = nextc();
  3093. if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
  3094. do {c = nextc();} while (ISSPACE(c));
  3095. space = 1;
  3096. }
  3097. if (c == term && !quote->nd_nest) {
  3098. if (func & STR_FUNC_QWORDS) {
  3099. quote->nd_func = -1;
  3100. return ' ';
  3101. }
  3102. if (!(func & STR_FUNC_REGEXP)) return tSTRING_END;
  3103. pslval->num = regx_options(parser_state);
  3104. return tREGEXP_END;
  3105. }
  3106. if (space) {
  3107. pushback(c, parser_state);
  3108. return ' ';
  3109. }
  3110. newtok(parser_state);
  3111. if ((func & STR_FUNC_EXPAND) && c == '#') {
  3112. switch (c = nextc()) {
  3113. case '$':
  3114. case '@':
  3115. pushback(c, parser_state);
  3116. return tSTRING_DVAR;
  3117. case '{':
  3118. return tSTRING_DBEG;
  3119. }
  3120. tokadd('#', parser_state);
  3121. }
  3122. pushback(c, parser_state);
  3123. if (tokadd_string(func, term, paren, &quote->nd_nest, parser_state) == -1) {
  3124. ruby_sourceline = nd_line(quote);
  3125. rb_compile_error(parser_state, "unterminated string meets end of file");
  3126. return tSTRING_END;
  3127. }
  3128. tokfix();
  3129. pslval->node = NEW_STR(string_new(tok(), toklen()));
  3130. nd_set_line(pslval->node, start_line);
  3131. return tSTRING_CONTENT;
  3132. }
  3133. /* Called when the lexer detects a heredoc is beginning. This pulls
  3134. in more characters and detects what kind of heredoc it is. */
  3135. static int
  3136. heredoc_identifier(rb_parser_state *parser_state)
  3137. {
  3138. int c = nextc(), term, func = 0;
  3139. size_t len;
  3140. if (c == '-') {
  3141. c = nextc();
  3142. func = STR_FUNC_INDENT;
  3143. }
  3144. switch (c) {
  3145. case '\'':
  3146. func |= str_squote; goto quoted;
  3147. case '"':
  3148. func |= str_dquote; goto quoted;
  3149. case '`':
  3150. func |= str_xquote;
  3151. quoted:
  3152. /* The heredoc indent is quoted, so its easy to find, we just
  3153. continue to consume characters into the token buffer until
  3154. we hit the terminating character. */
  3155. newtok(parser_state);
  3156. tokadd((char)func, parser_state);
  3157. term = c;
  3158. /* Where of where has the term gone.. */
  3159. while ((c = nextc()) != -1 && c != term) {
  3160. len = mbclen(c);
  3161. do {
  3162. tokadd((char)c, parser_state);
  3163. } while (--len > 0 && (c = nextc()) != -1);
  3164. }
  3165. /* Ack! end of file or end of string. */
  3166. if (c == -1) {
  3167. rb_compile_error(parser_state, "unterminated here document identifier");
  3168. return 0;
  3169. }
  3170. break;
  3171. default:
  3172. /* Ok, this is an unquoted heredoc ident. We just consume
  3173. until we hit a non-ident character. */
  3174. /* Do a quick check that first character is actually valid.
  3175. if it's not, then this isn't actually a heredoc at all!
  3176. It sucks that it's way down here in this function that in
  3177. finally bails with this not being a heredoc.*/
  3178. if (!is_identchar(c)) {
  3179. pushback(c, parser_state);
  3180. if (func & STR_FUNC_INDENT) {
  3181. pushback('-', parser_state);
  3182. }
  3183. return 0;
  3184. }
  3185. /* Finally, setup the token buffer and begin to fill it. */
  3186. newtok(parser_state);
  3187. term = '"';
  3188. tokadd((char)(func |= str_dquote), parser_state);
  3189. do {
  3190. len = mbclen(c);
  3191. do { tokadd((char)c, parser_state); } while (--len > 0 && (c = nextc()) != -1);
  3192. } while ((c = nextc()) != -1 && is_identchar(c));
  3193. pushback(c, parser_state);
  3194. break;
  3195. }
  3196. /* Fixup the token buffer, ie set the last character to null. */
  3197. tokfix();
  3198. len = lex_p - lex_pbeg;
  3199. lex_p = lex_pend;
  3200. pslval->id = 0;
  3201. /* Tell the lexer that we're inside a string now. nd_lit is
  3202. the heredoc identifier that we watch the stream for to
  3203. detect the end of the heredoc. */
  3204. bstring str = bstrcpy(lex_lastline);
  3205. lex_strterm = node_newnode(NODE_HEREDOC,
  3206. (VALUE)string_new(tok(), toklen()), /* nd_lit */
  3207. (VALUE)len, /* nd_nth */
  3208. (VALUE)str); /* nd_orig */
  3209. return term == '`' ? tXSTRING_BEG : tSTRING_BEG;
  3210. }
  3211. static void
  3212. heredoc_restore(NODE *here, rb_parser_state *parser_state)
  3213. {
  3214. bstring line = here->nd_orig;
  3215. bdestroy(lex_lastline);
  3216. lex_lastline = line;
  3217. lex_pbeg = bdata(line);
  3218. lex_pend = lex_pbeg + blength(line);
  3219. lex_p = lex_pbeg + here->nd_nth;
  3220. heredoc_end = ruby_sourceline;
  3221. ruby_sourceline = nd_line(here);
  3222. bdestroy((bstring)here->nd_lit);
  3223. }
  3224. static int
  3225. whole_match_p(const char *eos, int len, int indent, rb_parser_state *parser_state)
  3226. {
  3227. char *p = lex_pbeg;
  3228. int n;
  3229. if (indent) {
  3230. while (*p && ISSPACE(*p)) p++;
  3231. }
  3232. n = (int)(lex_pend - (p + len));
  3233. if (n < 0 || (n > 0 && p[len] != '\n' && p[len] != '\r')) return FALSE;
  3234. if (strncmp(eos, p, len) == 0) return TRUE;
  3235. return FALSE;
  3236. }
  3237. /* Called when the lexer knows it's inside a heredoc. This function
  3238. is responsible for detecting an expandions (ie #{}) in the heredoc
  3239. and emitting a lex token and also detecting the end of the heredoc. */
  3240. static int
  3241. here_document(NODE *here, rb_parser_state *parser_state)
  3242. {
  3243. int c, func, indent = 0;
  3244. char *eos, *p, *pend;
  3245. long len;
  3246. bstring str = NULL;
  3247. /* eos == the heredoc ident that we found when the heredoc started */
  3248. eos = bdata(here->nd_str);
  3249. len = blength(here->nd_str) - 1;
  3250. /* indicates if we should search for expansions. */
  3251. indent = (func = *eos++) & STR_FUNC_INDENT;
  3252. /* Ack! EOF or end of input string! */
  3253. if ((c = nextc()) == -1) {
  3254. error:
  3255. rb_compile_error(parser_state, "can't find string \"%s\" anywhere before EOF", eos);
  3256. heredoc_restore(lex_strterm, parser_state);
  3257. lex_strterm = 0;
  3258. return 0;
  3259. }
  3260. /* Gr. not yet sure what was_bol() means other than it seems like
  3261. it means only 1 character has been consumed. */
  3262. if (was_bol() && whole_match_p(eos, (int)len, indent, parser_state)) {
  3263. heredoc_restore(lex_strterm, parser_state);
  3264. return tSTRING_END;
  3265. }
  3266. /* If aren't doing expansions, we can just scan until
  3267. we find the identifier. */
  3268. if ((func & STR_FUNC_EXPAND) == 0) {
  3269. do {
  3270. p = bdata(lex_lastline);
  3271. pend = lex_pend;
  3272. if (pend > p) {
  3273. switch (pend[-1]) {
  3274. case '\n':
  3275. if (--pend == p || pend[-1] != '\r') {
  3276. pend++;
  3277. break;
  3278. }
  3279. case '\r':
  3280. --pend;
  3281. }
  3282. }
  3283. if (str) {
  3284. bcatblk(str, p, (int)(pend - p));
  3285. } else {
  3286. str = blk2bstr(p, (int)(pend - p));
  3287. }
  3288. if (pend < lex_pend) bcatblk(str, "\n", 1);
  3289. lex_p = lex_pend;
  3290. if (nextc() == -1) {
  3291. if (str) bdestroy(str);
  3292. goto error;
  3293. }
  3294. } while (!whole_match_p(eos, (int)len, indent, parser_state));
  3295. }
  3296. else {
  3297. newtok(parser_state);
  3298. if (c == '#') {
  3299. switch (c = nextc()) {
  3300. case '$':
  3301. case '@':
  3302. pushback(c, parser_state);
  3303. return tSTRING_DVAR;
  3304. case '{':
  3305. return tSTRING_DBEG;
  3306. }
  3307. tokadd('#', parser_state);
  3308. }
  3309. /* Loop while we haven't found a the heredoc ident. */
  3310. do {
  3311. pushback(c, parser_state);
  3312. /* Scan up until a \n and fill in the token buffer. */
  3313. if ((c = tokadd_string(func, '\n', 0, NULL, parser_state)) == -1) goto error;
  3314. /* We finished scanning, but didn't find a \n, so we setup the node
  3315. and have the lexer file in more. */
  3316. if (c != '\n') {
  3317. pslval->node = NEW_STR(string_new(tok(), toklen()));
  3318. return tSTRING_CONTENT;
  3319. }
  3320. /* I think this consumes the \n */
  3321. tokadd((char)nextc(), parser_state);
  3322. if ((c = nextc()) == -1) goto error;
  3323. } while (!whole_match_p(eos, (int)len, indent, parser_state));
  3324. str = string_new(tok(), toklen());
  3325. }
  3326. heredoc_restore(lex_strterm, parser_state);
  3327. lex_strterm = NEW_STRTERM(-1, 0, 0);
  3328. pslval->node = NEW_STR(str);
  3329. return tSTRING_CONTENT;
  3330. }
  3331. #include "lex.c.tab"
  3332. static void
  3333. arg_ambiguous()
  3334. {
  3335. rb_warning("ambiguous first argument; put parentheses or even spaces");
  3336. }
  3337. #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
  3338. static char* parse_comment(struct rb_parser_state* parser_state) {
  3339. int len = (int)(lex_pend - lex_p);
  3340. char* str = lex_p;
  3341. while(len-- > 0 && ISSPACE(str[0])) str++;
  3342. if(len <= 2) return NULL;
  3343. if(str[0] == '-' && str[1] == '*' && str[2] == '-') return str;
  3344. return NULL;
  3345. }
  3346. static int
  3347. yylex(void *yylval_v, void *vstate)
  3348. {
  3349. register int c;
  3350. int space_seen = 0;
  3351. int cmd_state;
  3352. struct rb_parser_state *parser_state;
  3353. bstring cur_line;
  3354. enum lex_state_e last_state;
  3355. YYSTYPE *yylval = (YYSTYPE*)yylval_v;
  3356. parser_state = (struct rb_parser_state*)vstate;
  3357. lval = (void *)yylval;
  3358. /*
  3359. c = nextc();
  3360. printf("lex char: %c\n", c);
  3361. pushback(c, parser_state);
  3362. */
  3363. if (lex_strterm) {
  3364. int token;
  3365. if (nd_type(lex_strterm) == NODE_HEREDOC) {
  3366. token = here_document(lex_strterm, parser_state);
  3367. if (token == tSTRING_END) {
  3368. lex_strterm = 0;
  3369. lex_state = EXPR_END;
  3370. }
  3371. }
  3372. else {
  3373. token = parse_string(lex_strterm, parser_state);
  3374. if (token == tSTRING_END || token == tREGEXP_END) {
  3375. lex_strterm = 0;
  3376. lex_state = EXPR_END;
  3377. }
  3378. }
  3379. return token;
  3380. }
  3381. cmd_state = command_start;
  3382. command_start = FALSE;
  3383. retry:
  3384. switch (c = nextc()) {
  3385. case '\0': /* NUL */
  3386. case '\004': /* ^D */
  3387. case '\032': /* ^Z */
  3388. case -1: /* end of script. */
  3389. return 0;
  3390. /* white spaces */
  3391. case ' ': case '\t': case '\f': case '\r':
  3392. case '\13': /* '\v' */
  3393. space_seen++;
  3394. goto retry;
  3395. case '#': /* it's a comment */
  3396. if(char* str = parse_comment(parser_state)) {
  3397. int len = (int)(lex_pend - str - 1); // - 1 for the \n
  3398. cur_line = blk2bstr(str, len);
  3399. magic_comments->push_back(cur_line);
  3400. }
  3401. lex_p = lex_pend;
  3402. /* fall through */
  3403. case '\n':
  3404. switch (lex_state) {
  3405. case EXPR_BEG:
  3406. case EXPR_FNAME:
  3407. case EXPR_DOT:
  3408. case EXPR_CLASS:
  3409. goto retry;
  3410. default:
  3411. break;
  3412. }
  3413. command_start = TRUE;
  3414. lex_state = EXPR_BEG;
  3415. return '\n';
  3416. case '*':
  3417. if ((c = nextc()) == '*') {
  3418. if ((c = nextc()) == '=') {
  3419. pslval->id = tPOW;
  3420. lex_state = EXPR_BEG;
  3421. return tOP_ASGN;
  3422. }
  3423. pushback(c, parser_state);
  3424. c = tPOW;
  3425. }
  3426. else {
  3427. if (c == '=') {
  3428. pslval->id = '*';
  3429. lex_state = EXPR_BEG;
  3430. return tOP_ASGN;
  3431. }
  3432. pushback(c, parser_state);
  3433. if (IS_ARG() && space_seen && !ISSPACE(c)){
  3434. rb_warning("`*' interpreted as argument prefix");
  3435. c = tSTAR;
  3436. }
  3437. else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
  3438. c = tSTAR;
  3439. }
  3440. else {
  3441. c = '*';
  3442. }
  3443. }
  3444. switch (lex_state) {
  3445. case EXPR_FNAME: case EXPR_DOT:
  3446. lex_state = EXPR_ARG; break;
  3447. default:
  3448. lex_state = EXPR_BEG; break;
  3449. }
  3450. return c;
  3451. case '!':
  3452. lex_state = EXPR_BEG;
  3453. if ((c = nextc()) == '=') {
  3454. return tNEQ;
  3455. }
  3456. if (c == '~') {
  3457. return tNMATCH;
  3458. }
  3459. pushback(c, parser_state);
  3460. return '!';
  3461. case '=':
  3462. if (was_bol()) {
  3463. /* skip embedded rd document */
  3464. if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
  3465. for (;;) {
  3466. lex_p = lex_pend;
  3467. c = nextc();
  3468. if (c == -1) {
  3469. rb_compile_error(parser_state, "embedded document meets end of file");
  3470. return 0;
  3471. }
  3472. if (c != '=') continue;
  3473. if (strncmp(lex_p, "end", 3) == 0 &&
  3474. (lex_p + 3 == lex_pend || ISSPACE(lex_p[3]))) {
  3475. break;
  3476. }
  3477. }
  3478. lex_p = lex_pend;
  3479. goto retry;
  3480. }
  3481. }
  3482. switch (lex_state) {
  3483. case EXPR_FNAME: case EXPR_DOT:
  3484. lex_state = EXPR_ARG; break;
  3485. default:
  3486. lex_state = EXPR_BEG; break;
  3487. }
  3488. if ((c = nextc()) == '=') {
  3489. if ((c = nextc()) == '=') {
  3490. return tEQQ;
  3491. }
  3492. pushback(c, parser_state);
  3493. return tEQ;
  3494. }
  3495. if (c == '~') {
  3496. return tMATCH;
  3497. }
  3498. else if (c == '>') {
  3499. return tASSOC;
  3500. }
  3501. pushback(c, parser_state);
  3502. return '=';
  3503. case '<':
  3504. c = nextc();
  3505. if (c == '<' &&
  3506. lex_state != EXPR_END &&
  3507. lex_state != EXPR_DOT &&
  3508. lex_state != EXPR_ENDARG &&
  3509. lex_state != EXPR_CLASS &&
  3510. (!IS_ARG() || space_seen)) {
  3511. int token = heredoc_identifier(parser_state);
  3512. if (token) return token;
  3513. }
  3514. switch (lex_state) {
  3515. case EXPR_FNAME: case EXPR_DOT:
  3516. lex_state = EXPR_ARG; break;
  3517. default:
  3518. lex_state = EXPR_BEG; break;
  3519. }
  3520. if (c == '=') {
  3521. if ((c = nextc()) == '>') {
  3522. return tCMP;
  3523. }
  3524. pushback(c, parser_state);
  3525. return tLEQ;
  3526. }
  3527. if (c == '<') {
  3528. if ((c = nextc()) == '=') {
  3529. pslval->id = tLSHFT;
  3530. lex_state = EXPR_BEG;
  3531. return tOP_ASGN;
  3532. }
  3533. pushback(c, parser_state);
  3534. return tLSHFT;
  3535. }
  3536. pushback(c, parser_state);
  3537. return '<';
  3538. case '>':
  3539. switch (lex_state) {
  3540. case EXPR_FNAME: case EXPR_DOT:
  3541. lex_state = EXPR_ARG; break;
  3542. default:
  3543. lex_state = EXPR_BEG; break;
  3544. }
  3545. if ((c = nextc()) == '=') {
  3546. return tGEQ;
  3547. }
  3548. if (c == '>') {
  3549. if ((c = nextc()) == '=') {
  3550. pslval->id = tRSHFT;
  3551. lex_state = EXPR_BEG;
  3552. return tOP_ASGN;
  3553. }
  3554. pushback(c, parser_state);
  3555. return tRSHFT;
  3556. }
  3557. pushback(c, parser_state);
  3558. return '>';
  3559. case '"':
  3560. lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
  3561. return tSTRING_BEG;
  3562. case '`':
  3563. if (lex_state == EXPR_FNAME) {
  3564. lex_state = EXPR_END;
  3565. return c;
  3566. }
  3567. if (lex_state == EXPR_DOT) {
  3568. if (cmd_state)
  3569. lex_state = EXPR_CMDARG;
  3570. else
  3571. lex_state = EXPR_ARG;
  3572. return c;
  3573. }
  3574. lex_strterm = NEW_STRTERM(str_xquote, '`', 0);
  3575. pslval->id = 0; /* so that xstring gets used normally */
  3576. return tXSTRING_BEG;
  3577. case '\'':
  3578. lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
  3579. pslval->id = 0; /* so that xstring gets used normally */
  3580. return tSTRING_BEG;
  3581. case '?':
  3582. if (lex_state == EXPR_END || lex_state == EXPR_ENDARG) {
  3583. lex_state = EXPR_BEG;
  3584. return '?';
  3585. }
  3586. c = nextc();
  3587. if (c == -1) {
  3588. rb_compile_error(parser_state, "incomplete character syntax");
  3589. return 0;
  3590. }
  3591. if (ISSPACE(c)){
  3592. if (!IS_ARG()){
  3593. int c2 = 0;
  3594. switch (c) {
  3595. case ' ':
  3596. c2 = 's';
  3597. break;
  3598. case '\n':
  3599. c2 = 'n';
  3600. break;
  3601. case '\t':
  3602. c2 = 't';
  3603. break;
  3604. case '\v':
  3605. c2 = 'v';
  3606. break;
  3607. case '\r':
  3608. c2 = 'r';
  3609. break;
  3610. case '\f':
  3611. c2 = 'f';
  3612. break;
  3613. }
  3614. if (c2) {
  3615. rb_warn("invalid character syntax; use ?\\%c", c2);
  3616. }
  3617. }
  3618. ternary:
  3619. pushback(c, parser_state);
  3620. lex_state = EXPR_BEG;
  3621. ternary_colon = 1;
  3622. return '?';
  3623. }
  3624. else if (ismbchar(c)) {
  3625. rb_warn("multibyte character literal not supported yet; use ?\\%.3o", c);
  3626. goto ternary;
  3627. }
  3628. else if ((ISALNUM(c) || c == '_') && lex_p < lex_pend && is_identchar(*(lex_p))) {
  3629. goto ternary;
  3630. }
  3631. else if (c == '\\') {
  3632. c = read_escape(parser_state);
  3633. }
  3634. c &= 0xff;
  3635. lex_state = EXPR_END;
  3636. pslval->node = NEW_FIXNUM((intptr_t)c);
  3637. return tINTEGER;
  3638. case '&':
  3639. if ((c = nextc()) == '&') {
  3640. lex_state = EXPR_BEG;
  3641. if ((c = nextc()) == '=') {
  3642. pslval->id = tANDOP;
  3643. lex_state = EXPR_BEG;
  3644. return tOP_ASGN;
  3645. }
  3646. pushback(c, parser_state);
  3647. return tANDOP;
  3648. }
  3649. else if (c == '=') {
  3650. pslval->id = '&';
  3651. lex_state = EXPR_BEG;
  3652. return tOP_ASGN;
  3653. }
  3654. pushback(c, parser_state);
  3655. if (IS_ARG() && space_seen && !ISSPACE(c)){
  3656. rb_warning("`&' interpreted as argument prefix");
  3657. c = tAMPER;
  3658. }
  3659. else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
  3660. c = tAMPER;
  3661. }
  3662. else {
  3663. c = '&';
  3664. }
  3665. switch (lex_state) {
  3666. case EXPR_FNAME: case EXPR_DOT:
  3667. lex_state = EXPR_ARG; break;
  3668. default:
  3669. lex_state = EXPR_BEG;
  3670. }
  3671. return c;
  3672. case '|':
  3673. if ((c = nextc()) == '|') {
  3674. lex_state = EXPR_BEG;
  3675. if ((c = nextc()) == '=') {
  3676. pslval->id = tOROP;
  3677. lex_state = EXPR_BEG;
  3678. return tOP_ASGN;
  3679. }
  3680. pushback(c, parser_state);
  3681. return tOROP;
  3682. }
  3683. if (c == '=') {
  3684. pslval->id = '|';
  3685. lex_state = EXPR_BEG;
  3686. return tOP_ASGN;
  3687. }
  3688. if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
  3689. lex_state = EXPR_ARG;
  3690. }
  3691. else {
  3692. lex_state = EXPR_BEG;
  3693. }
  3694. pushback(c, parser_state);
  3695. return '|';
  3696. case '+':
  3697. c = nextc();
  3698. if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
  3699. lex_state = EXPR_ARG;
  3700. if (c == '@') {
  3701. return tUPLUS;
  3702. }
  3703. pushback(c, parser_state);
  3704. return '+';
  3705. }
  3706. if (c == '=') {
  3707. pslval->id = '+';
  3708. lex_state = EXPR_BEG;
  3709. return tOP_ASGN;
  3710. }
  3711. if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
  3712. (IS_ARG() && space_seen && !ISSPACE(c))) {
  3713. if (IS_ARG()) arg_ambiguous();
  3714. lex_state = EXPR_BEG;
  3715. pushback(c, parser_state);
  3716. if (ISDIGIT(c)) {
  3717. c = '+';
  3718. goto start_num;
  3719. }
  3720. return tUPLUS;
  3721. }
  3722. lex_state = EXPR_BEG;
  3723. pushback(c, parser_state);
  3724. return '+';
  3725. case '-':
  3726. c = nextc();
  3727. if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
  3728. lex_state = EXPR_ARG;
  3729. if (c == '@') {
  3730. return tUMINUS;
  3731. }
  3732. pushback(c, parser_state);
  3733. return '-';
  3734. }
  3735. if (c == '=') {
  3736. pslval->id = '-';
  3737. lex_state = EXPR_BEG;
  3738. return tOP_ASGN;
  3739. }
  3740. if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
  3741. (IS_ARG() && space_seen && !ISSPACE(c))) {
  3742. if (IS_ARG()) arg_ambiguous();
  3743. lex_state = EXPR_BEG;
  3744. pushback(c, parser_state);
  3745. if (ISDIGIT(c)) {
  3746. return tUMINUS_NUM;
  3747. }
  3748. return tUMINUS;
  3749. }
  3750. lex_state = EXPR_BEG;
  3751. pushback(c, parser_state);
  3752. return '-';
  3753. case '.':
  3754. lex_state = EXPR_BEG;
  3755. if ((c = nextc()) == '.') {
  3756. if ((c = nextc()) == '.') {
  3757. return tDOT3;
  3758. }
  3759. pushback(c, parser_state);
  3760. return tDOT2;
  3761. }
  3762. pushback(c, parser_state);
  3763. if (ISDIGIT(c)) {
  3764. yyerror("no .<digit> floating literal anymore; put 0 before dot");
  3765. }
  3766. lex_state = EXPR_DOT;
  3767. return '.';
  3768. start_num:
  3769. case '0': case '1': case '2': case '3': case '4':
  3770. case '5': case '6': case '7': case '8': case '9':
  3771. {
  3772. int is_float, seen_point, seen_e, nondigit;
  3773. is_float = seen_point = seen_e = nondigit = 0;
  3774. lex_state = EXPR_END;
  3775. newtok(parser_state);
  3776. if (c == '-' || c == '+') {
  3777. tokadd((char)c,parser_state);
  3778. c = nextc();
  3779. }
  3780. if (c == '0') {
  3781. int start = toklen();
  3782. c = nextc();
  3783. if (c == 'x' || c == 'X') {
  3784. /* hexadecimal */
  3785. c = nextc();
  3786. if (ISXDIGIT(c)) {
  3787. do {
  3788. if (c == '_') {
  3789. if (nondigit) break;
  3790. nondigit = c;
  3791. continue;
  3792. }
  3793. if (!ISXDIGIT(c)) break;
  3794. nondigit = 0;
  3795. tokadd((char)c,parser_state);
  3796. } while ((c = nextc()) != -1);
  3797. }
  3798. pushback(c, parser_state);
  3799. tokfix();
  3800. if (toklen() == start) {
  3801. yyerror("numeric literal without digits");
  3802. }
  3803. else if (nondigit) goto trailing_uc;
  3804. pslval->node = NEW_HEXNUM(string_new2(tok()));
  3805. return tINTEGER;
  3806. }
  3807. if (c == 'b' || c == 'B') {
  3808. /* binary */
  3809. c = nextc();
  3810. if (c == '0' || c == '1') {
  3811. do {
  3812. if (c == '_') {
  3813. if (nondigit) break;
  3814. nondigit = c;
  3815. continue;
  3816. }
  3817. if (c != '0' && c != '1') break;
  3818. nondigit = 0;
  3819. tokadd((char)c, parser_state);
  3820. } while ((c = nextc()) != -1);
  3821. }
  3822. pushback(c, parser_state);
  3823. tokfix();
  3824. if (toklen() == start) {
  3825. yyerror("numeric literal without digits");
  3826. }
  3827. else if (nondigit) goto trailing_uc;
  3828. pslval->node = NEW_BINNUM(string_new2(tok()));
  3829. return tINTEGER;
  3830. }
  3831. if (c == 'd' || c == 'D') {
  3832. /* decimal */
  3833. c = nextc();
  3834. if (ISDIGIT(c)) {
  3835. do {
  3836. if (c == '_') {
  3837. if (nondigit) break;
  3838. nondigit = c;
  3839. continue;
  3840. }
  3841. if (!ISDIGIT(c)) break;
  3842. nondigit = 0;
  3843. tokadd((char)c, parser_state);
  3844. } while ((c = nextc()) != -1);
  3845. }
  3846. pushback(c, parser_state);
  3847. tokfix();
  3848. if (toklen() == start) {
  3849. yyerror("numeric literal without digits");
  3850. }
  3851. else if (nondigit) goto trailing_uc;
  3852. pslval->node = NEW_NUMBER(string_new2(tok()));
  3853. return tINTEGER;
  3854. }
  3855. if (c == '_') {
  3856. /* 0_0 */
  3857. goto octal_number;
  3858. }
  3859. if (c == 'o' || c == 'O') {
  3860. /* prefixed octal */
  3861. c = nextc();
  3862. if (c == '_') {
  3863. yyerror("numeric literal without digits");
  3864. }
  3865. }
  3866. if (c >= '0' && c <= '7') {
  3867. /* octal */
  3868. octal_number:
  3869. do {
  3870. if (c == '_') {
  3871. if (nondigit) break;
  3872. nondigit = c;
  3873. continue;
  3874. }
  3875. if (c < '0' || c > '7') break;
  3876. nondigit = 0;
  3877. tokadd((char)c, parser_state);
  3878. } while ((c = nextc()) != -1);
  3879. if (toklen() > start) {
  3880. pushback(c, parser_state);
  3881. tokfix();
  3882. if (nondigit) goto trailing_uc;
  3883. pslval->node = NEW_OCTNUM(string_new2(tok()));
  3884. return tINTEGER;
  3885. }
  3886. if (nondigit) {
  3887. pushback(c, parser_state);
  3888. goto trailing_uc;
  3889. }
  3890. }
  3891. if (c > '7' && c <= '9') {
  3892. yyerror("Illegal octal digit");
  3893. }
  3894. else if (c == '.' || c == 'e' || c == 'E') {
  3895. tokadd('0', parser_state);
  3896. }
  3897. else {
  3898. pushback(c, parser_state);
  3899. pslval->node = NEW_FIXNUM(0);
  3900. return tINTEGER;
  3901. }
  3902. }
  3903. for (;;) {
  3904. switch (c) {
  3905. case '0': case '1': case '2': case '3': case '4':
  3906. case '5': case '6': case '7': case '8': case '9':
  3907. nondigit = 0;
  3908. tokadd((char)c, parser_state);
  3909. break;
  3910. case '.':
  3911. if (nondigit) goto trailing_uc;
  3912. if (seen_point || seen_e) {
  3913. goto decode_num;
  3914. }
  3915. else {
  3916. int c0 = nextc();
  3917. if (!ISDIGIT(c0)) {
  3918. pushback(c0, parser_state);
  3919. goto decode_num;
  3920. }
  3921. c = c0;
  3922. }
  3923. tokadd('.', parser_state);
  3924. tokadd((char)c, parser_state);
  3925. is_float++;
  3926. seen_point++;
  3927. nondigit = 0;
  3928. break;
  3929. case 'e':
  3930. case 'E':
  3931. if (nondigit) {
  3932. pushback(c, parser_state);
  3933. c = nondigit;
  3934. goto decode_num;
  3935. }
  3936. if (seen_e) {
  3937. goto decode_num;
  3938. }
  3939. tokadd((char)c, parser_state);
  3940. seen_e++;
  3941. is_float++;
  3942. nondigit = c;
  3943. c = nextc();
  3944. if (c != '-' && c != '+') continue;
  3945. tokadd((char)c, parser_state);
  3946. nondigit = c;
  3947. break;
  3948. case '_': /* `_' in number just ignored */
  3949. if (nondigit) goto decode_num;
  3950. nondigit = c;
  3951. break;
  3952. default:
  3953. goto decode_num;
  3954. }
  3955. c = nextc();
  3956. }
  3957. decode_num:
  3958. pushback(c, parser_state);
  3959. tokfix();
  3960. if (nondigit) {
  3961. char tmp[30];
  3962. trailing_uc:
  3963. snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit);
  3964. yyerror(tmp);
  3965. }
  3966. if (is_float) {
  3967. pslval->node = NEW_FLOAT(string_new2(tok()));
  3968. return tFLOAT;
  3969. }
  3970. pslval->node = NEW_NUMBER(string_new2(tok()));
  3971. return tINTEGER;
  3972. }
  3973. case ']':
  3974. case '}':
  3975. case ')':
  3976. COND_LEXPOP();
  3977. CMDARG_LEXPOP();
  3978. lex_state = EXPR_END;
  3979. return c;
  3980. case ':':
  3981. c = nextc();
  3982. if (c == ':') {
  3983. if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
  3984. lex_state == EXPR_CLASS || (IS_ARG() && space_seen)) {
  3985. lex_state = EXPR_BEG;
  3986. return tCOLON3;
  3987. }
  3988. lex_state = EXPR_DOT;
  3989. return tCOLON2;
  3990. }
  3991. if (lex_state == EXPR_END || lex_state == EXPR_ENDARG || ISSPACE(c)) {
  3992. pushback(c, parser_state);
  3993. lex_state = EXPR_BEG;
  3994. return ':';
  3995. }
  3996. switch (c) {
  3997. case '\'':
  3998. lex_strterm = NEW_STRTERM(str_ssym, (intptr_t)c, 0);
  3999. break;
  4000. case '"':
  4001. lex_strterm = NEW_STRTERM(str_dsym, (intptr_t)c, 0);
  4002. break;
  4003. default:
  4004. pushback(c, parser_state);
  4005. break;
  4006. }
  4007. lex_state = EXPR_FNAME;
  4008. return tSYMBEG;
  4009. case '/':
  4010. if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
  4011. lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
  4012. return tREGEXP_BEG;
  4013. }
  4014. if ((c = nextc()) == '=') {
  4015. pslval->id = '/';
  4016. lex_state = EXPR_BEG;
  4017. return tOP_ASGN;
  4018. }
  4019. pushback(c, parser_state);
  4020. if (IS_ARG() && space_seen) {
  4021. if (!ISSPACE(c)) {
  4022. arg_ambiguous();
  4023. lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
  4024. return tREGEXP_BEG;
  4025. }
  4026. }
  4027. switch (lex_state) {
  4028. case EXPR_FNAME: case EXPR_DOT:
  4029. lex_state = EXPR_ARG; break;
  4030. default:
  4031. lex_state = EXPR_BEG; break;
  4032. }
  4033. return '/';
  4034. case '^':
  4035. if ((c = nextc()) == '=') {
  4036. pslval->id = '^';
  4037. lex_state = EXPR_BEG;
  4038. return tOP_ASGN;
  4039. }
  4040. switch (lex_state) {
  4041. case EXPR_FNAME: case EXPR_DOT:
  4042. lex_state = EXPR_ARG; break;
  4043. default:
  4044. lex_state = EXPR_BEG; break;
  4045. }
  4046. pushback(c, parser_state);
  4047. return '^';
  4048. case ';':
  4049. command_start = TRUE;
  4050. case ',':
  4051. lex_state = EXPR_BEG;
  4052. return c;
  4053. case '~':
  4054. if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
  4055. if ((c = nextc()) != '@') {
  4056. pushback(c, parser_state);
  4057. }
  4058. }
  4059. switch (lex_state) {
  4060. case EXPR_FNAME: case EXPR_DOT:
  4061. lex_state = EXPR_ARG; break;
  4062. default:
  4063. lex_state = EXPR_BEG; break;
  4064. }
  4065. return '~';
  4066. case '(':
  4067. command_start = TRUE;
  4068. if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
  4069. c = tLPAREN;
  4070. }
  4071. else if (space_seen) {
  4072. if (lex_state == EXPR_CMDARG) {
  4073. c = tLPAREN_ARG;
  4074. }
  4075. else if (lex_state == EXPR_ARG) {
  4076. rb_warn("don't put space before argument parentheses");
  4077. c = '(';
  4078. }
  4079. }
  4080. COND_PUSH(0);
  4081. CMDARG_PUSH(0);
  4082. lex_state = EXPR_BEG;
  4083. return c;
  4084. case '[':
  4085. if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
  4086. lex_state = EXPR_ARG;
  4087. if ((c = nextc()) == ']') {
  4088. if ((c = nextc()) == '=') {
  4089. return tASET;
  4090. }
  4091. pushback(c, parser_state);
  4092. return tAREF;
  4093. }
  4094. pushback(c, parser_state);
  4095. return '[';
  4096. }
  4097. else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
  4098. c = tLBRACK;
  4099. }
  4100. else if (IS_ARG() && space_seen) {
  4101. c = tLBRACK;
  4102. }
  4103. lex_state = EXPR_BEG;
  4104. COND_PUSH(0);
  4105. CMDARG_PUSH(0);
  4106. return c;
  4107. case '{':
  4108. if (IS_ARG() || lex_state == EXPR_END)
  4109. c = '{'; /* block (primary) */
  4110. else if (lex_state == EXPR_ENDARG)
  4111. c = tLBRACE_ARG; /* block (expr) */
  4112. else
  4113. c = tLBRACE; /* hash */
  4114. COND_PUSH(0);
  4115. CMDARG_PUSH(0);
  4116. lex_state = EXPR_BEG;
  4117. return c;
  4118. case '\\':
  4119. c = nextc();
  4120. if (c == '\n') {
  4121. space_seen = 1;
  4122. goto retry; /* skip \\n */
  4123. }
  4124. pushback(c, parser_state);
  4125. if(lex_state == EXPR_BEG
  4126. || lex_state == EXPR_MID || space_seen) {
  4127. lex_state = EXPR_DOT;
  4128. return tUBS;
  4129. }
  4130. lex_state = EXPR_DOT;
  4131. return '\\';
  4132. case '%':
  4133. if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
  4134. intptr_t term;
  4135. intptr_t paren;
  4136. char tmpstr[256];
  4137. char *cur;
  4138. c = nextc();
  4139. quotation:
  4140. if (!ISALNUM(c)) {
  4141. term = c;
  4142. c = 'Q';
  4143. }
  4144. else {
  4145. term = nextc();
  4146. if (ISALNUM(term) || ismbchar(term)) {
  4147. cur = tmpstr;
  4148. *cur++ = c;
  4149. while(ISALNUM(term) || ismbchar(term)) {
  4150. *cur++ = term;
  4151. term = nextc();
  4152. }
  4153. *cur = 0;
  4154. c = 1;
  4155. }
  4156. }
  4157. if (c == -1 || term == -1) {
  4158. rb_compile_error(parser_state, "unterminated quoted string meets end of file");
  4159. return 0;
  4160. }
  4161. paren = term;
  4162. if (term == '(') term = ')';
  4163. else if (term == '[') term = ']';
  4164. else if (term == '{') term = '}';
  4165. else if (term == '<') term = '>';
  4166. else paren = 0;
  4167. switch (c) {
  4168. case 'Q':
  4169. lex_strterm = NEW_STRTERM(str_dquote, term, paren);
  4170. return tSTRING_BEG;
  4171. case 'q':
  4172. lex_strterm = NEW_STRTERM(str_squote, term, paren);
  4173. return tSTRING_BEG;
  4174. case 'W':
  4175. lex_strterm = NEW_STRTERM(str_dquote | STR_FUNC_QWORDS, term, paren);
  4176. do {c = nextc();} while (ISSPACE(c));
  4177. pushback(c, parser_state);
  4178. return tWORDS_BEG;
  4179. case 'w':
  4180. lex_strterm = NEW_STRTERM(str_squote | STR_FUNC_QWORDS, term, paren);
  4181. do {c = nextc();} while (ISSPACE(c));
  4182. pushback(c, parser_state);
  4183. return tQWORDS_BEG;
  4184. case 'x':
  4185. lex_strterm = NEW_STRTERM(str_xquote, term, paren);
  4186. pslval->id = 0;
  4187. return tXSTRING_BEG;
  4188. case 'r':
  4189. lex_strterm = NEW_STRTERM(str_regexp, term, paren);
  4190. return tREGEXP_BEG;
  4191. case 's':
  4192. lex_strterm = NEW_STRTERM(str_ssym, term, paren);
  4193. lex_state = EXPR_FNAME;
  4194. return tSYMBEG;
  4195. case 1:
  4196. lex_strterm = NEW_STRTERM(str_xquote, term, paren);
  4197. pslval->id = rb_parser_sym(parser_state, tmpstr);
  4198. return tXSTRING_BEG;
  4199. default:
  4200. lex_strterm = NEW_STRTERM(str_xquote, term, paren);
  4201. tmpstr[0] = c;
  4202. tmpstr[1] = 0;
  4203. pslval->id = rb_parser_sym(parser_state, tmpstr);
  4204. return tXSTRING_BEG;
  4205. }
  4206. }
  4207. if ((c = nextc()) == '=') {
  4208. pslval->id = '%';
  4209. lex_state = EXPR_BEG;
  4210. return tOP_ASGN;
  4211. }
  4212. if (IS_ARG() && space_seen && !ISSPACE(c)) {
  4213. goto quotation;
  4214. }
  4215. switch (lex_state) {
  4216. case EXPR_FNAME: case EXPR_DOT:
  4217. lex_state = EXPR_ARG; break;
  4218. default:
  4219. lex_state = EXPR_BEG; break;
  4220. }
  4221. pushback(c, parser_state);
  4222. return '%';
  4223. case '$':
  4224. last_state = lex_state;
  4225. lex_state = EXPR_END;
  4226. newtok(parser_state);
  4227. c = nextc();
  4228. switch (c) {
  4229. case '_': /* $_: last read line string */
  4230. c = nextc();
  4231. if (is_identchar(c)) {
  4232. tokadd('$', parser_state);
  4233. tokadd('_', parser_state);
  4234. break;
  4235. }
  4236. pushback(c, parser_state);
  4237. c = '_';
  4238. /* fall through */
  4239. case '~': /* $~: match-data */
  4240. local_cnt(c);
  4241. /* fall through */
  4242. case '*': /* $*: argv */
  4243. case '$': /* $$: pid */
  4244. case '?': /* $?: last status */
  4245. case '!': /* $!: error string */
  4246. case '@': /* $@: error position */
  4247. case '/': /* $/: input record separator */
  4248. case '\\': /* $\: output record separator */
  4249. case ';': /* $;: field separator */
  4250. case ',': /* $,: output field separator */
  4251. case '.': /* $.: last read line number */
  4252. case '=': /* $=: ignorecase */
  4253. case ':': /* $:: load path */
  4254. case '<': /* $<: reading filename */
  4255. case '>': /* $>: default output handle */
  4256. case '\"': /* $": already loaded files */
  4257. tokadd('$', parser_state);
  4258. tokadd((char)c, parser_state);
  4259. tokfix();
  4260. pslval->id = rb_parser_sym(parser_state, tok());
  4261. return tGVAR;
  4262. case '-':
  4263. tokadd('$', parser_state);
  4264. tokadd((char)c, parser_state);
  4265. c = nextc();
  4266. tokadd((char)c, parser_state);
  4267. gvar:
  4268. tokfix();
  4269. pslval->id = rb_parser_sym(parser_state, tok());
  4270. /* xxx shouldn't check if valid option variable */
  4271. return tGVAR;
  4272. case '&': /* $&: last match */
  4273. case '`': /* $`: string before last match */
  4274. case '\'': /* $': string after last match */
  4275. case '+': /* $+: string matches last paren. */
  4276. if (last_state == EXPR_FNAME) {
  4277. tokadd((char)'$', parser_state);
  4278. tokadd(c, parser_state);
  4279. goto gvar;
  4280. }
  4281. pslval->node = NEW_BACK_REF((intptr_t)c);
  4282. return tBACK_REF;
  4283. case '1': case '2': case '3':
  4284. case '4': case '5': case '6':
  4285. case '7': case '8': case '9':
  4286. tokadd('$', parser_state);
  4287. do {
  4288. tokadd((char)c, parser_state);
  4289. c = nextc();
  4290. } while (ISDIGIT(c));
  4291. pushback(c, parser_state);
  4292. if (last_state == EXPR_FNAME) goto gvar;
  4293. tokfix();
  4294. pslval->node = NEW_NTH_REF((intptr_t)atoi(tok()+1));
  4295. return tNTH_REF;
  4296. default:
  4297. if (!is_identchar(c)) {
  4298. pushback(c, parser_state);
  4299. return '$';
  4300. }
  4301. case '0':
  4302. tokadd('$', parser_state);
  4303. }
  4304. break;
  4305. case '@':
  4306. c = nextc();
  4307. newtok(parser_state);
  4308. tokadd('@', parser_state);
  4309. if (c == '@') {
  4310. tokadd('@', parser_state);
  4311. c = nextc();
  4312. }
  4313. if (ISDIGIT(c)) {
  4314. if (tokidx == 1) {
  4315. rb_compile_error(parser_state,
  4316. "`@%c' is not allowed as an instance variable name", c);
  4317. }
  4318. else {
  4319. rb_compile_error(parser_state,
  4320. "`@@%c' is not allowed as a class variable name", c);
  4321. }
  4322. }
  4323. if (!is_identchar(c)) {
  4324. pushback(c, parser_state);
  4325. return '@';
  4326. }
  4327. break;
  4328. case '_':
  4329. if (was_bol() && whole_match_p("__END__", 7, 0, parser_state)) {
  4330. end_seen = 1;
  4331. return -1;
  4332. }
  4333. newtok(parser_state);
  4334. break;
  4335. default:
  4336. if (!is_identchar(c)) {
  4337. rb_compile_error(parser_state, "Invalid char `\\%03o' in expression", c);
  4338. goto retry;
  4339. }
  4340. newtok(parser_state);
  4341. break;
  4342. }
  4343. do {
  4344. tokadd((char)c, parser_state);
  4345. if (ismbchar(c)) {
  4346. int i, len = mbclen(c)-1;
  4347. for (i = 0; i < len; i++) {
  4348. c = nextc();
  4349. tokadd((char)c, parser_state);
  4350. }
  4351. }
  4352. c = nextc();
  4353. } while (is_identchar(c));
  4354. if ((c == '!' || c == '?') && is_identchar(tok()[0]) && !peek('=')) {
  4355. tokadd((char)c, parser_state);
  4356. }
  4357. else {
  4358. pushback(c, parser_state);
  4359. }
  4360. tokfix();
  4361. {
  4362. int result = 0;
  4363. last_state = lex_state;
  4364. switch (tok()[0]) {
  4365. case '$':
  4366. lex_state = EXPR_END;
  4367. result = tGVAR;
  4368. break;
  4369. case '@':
  4370. lex_state = EXPR_END;
  4371. if (tok()[1] == '@')
  4372. result = tCVAR;
  4373. else
  4374. result = tIVAR;
  4375. break;
  4376. default:
  4377. if (toklast() == '!' || toklast() == '?') {
  4378. result = tFID;
  4379. }
  4380. else {
  4381. if (lex_state == EXPR_FNAME) {
  4382. if ((c = nextc()) == '=' && !peek('~') && !peek('>') &&
  4383. (!peek('=') || (lex_p + 1 < lex_pend && (lex_p)[1] == '>'))) {
  4384. result = tIDENTIFIER;
  4385. tokadd((char)c, parser_state);
  4386. tokfix();
  4387. }
  4388. else {
  4389. pushback(c, parser_state);
  4390. }
  4391. }
  4392. if (result == 0 && ISUPPER(tok()[0])) {
  4393. result = tCONSTANT;
  4394. }
  4395. else {
  4396. result = tIDENTIFIER;
  4397. }
  4398. }
  4399. if (lex_state != EXPR_DOT) {
  4400. const struct kwtable *kw;
  4401. /* See if it is a reserved word. */
  4402. kw = mel_reserved_word(tok(), toklen());
  4403. if (kw) {
  4404. enum lex_state_e state = lex_state;
  4405. lex_state = kw->state;
  4406. if (state == EXPR_FNAME) {
  4407. pslval->id = rb_parser_sym(parser_state, kw->name);
  4408. // Hack. Ignore the different variants of do
  4409. // if we're just trying to match a FNAME
  4410. if(kw->id[0] == kDO) return kDO;
  4411. }
  4412. if (kw->id[0] == kDO) {
  4413. command_start = TRUE;
  4414. if (COND_P()) return kDO_COND;
  4415. if (CMDARG_P() && state != EXPR_CMDARG)
  4416. return kDO_BLOCK;
  4417. if (state == EXPR_ENDARG)
  4418. return kDO_BLOCK;
  4419. return kDO;
  4420. }
  4421. if (state == EXPR_BEG)
  4422. return kw->id[0];
  4423. else {
  4424. if (kw->id[0] != kw->id[1])
  4425. lex_state = EXPR_BEG;
  4426. return kw->id[1];
  4427. }
  4428. }
  4429. }
  4430. if (lex_state == EXPR_BEG ||
  4431. lex_state == EXPR_MID ||
  4432. lex_state == EXPR_DOT ||
  4433. lex_state == EXPR_ARG ||
  4434. lex_state == EXPR_CMDARG) {
  4435. if (cmd_state) {
  4436. lex_state = EXPR_CMDARG;
  4437. }
  4438. else {
  4439. lex_state = EXPR_ARG;
  4440. }
  4441. }
  4442. else {
  4443. lex_state = EXPR_END;
  4444. }
  4445. }
  4446. pslval->id = rb_parser_sym(parser_state, tok());
  4447. if(is_local_id(pslval->id) &&
  4448. last_state != EXPR_DOT &&
  4449. local_id(pslval->id)) {
  4450. lex_state = EXPR_END;
  4451. }
  4452. /* if (is_local_id(pslval->id) && local_id(pslval->id)) { */
  4453. /* lex_state = EXPR_END; */
  4454. /* } */
  4455. return result;
  4456. }
  4457. }
  4458. NODE*
  4459. parser_node_newnode(rb_parser_state *parser_state, enum node_type type,
  4460. VALUE a0, VALUE a1, VALUE a2)
  4461. {
  4462. NODE *n = (NODE*)pt_allocate(parser_state, sizeof(NODE));
  4463. n->flags = 0;
  4464. nd_set_type(n, type);
  4465. nd_set_line(n, ruby_sourceline);
  4466. n->nd_file = ruby_sourcefile;
  4467. n->u1.value = a0;
  4468. n->u2.value = a1;
  4469. n->u3.value = a2;
  4470. return n;
  4471. }
  4472. static NODE*
  4473. newline_node(rb_parser_state *parser_state, NODE *node)
  4474. {
  4475. NODE *nl = 0;
  4476. if (node) {
  4477. if (nd_type(node) == NODE_NEWLINE) return node;
  4478. nl = NEW_NEWLINE(node);
  4479. fixpos(nl, node);
  4480. nl->nd_nth = nd_line(node);
  4481. }
  4482. return nl;
  4483. }
  4484. static void
  4485. fixpos(NODE *node, NODE *orig)
  4486. {
  4487. if (!node) return;
  4488. if (!orig) return;
  4489. if (orig == (NODE*)1) return;
  4490. node->nd_file = orig->nd_file;
  4491. nd_set_line(node, nd_line(orig));
  4492. }
  4493. static void
  4494. parser_warning(rb_parser_state *parser_state, NODE *node, const char *mesg)
  4495. {
  4496. int line = ruby_sourceline;
  4497. if(emit_warnings) {
  4498. ruby_sourceline = nd_line(node);
  4499. printf("%s:%i: warning: %s\n", ruby_sourcefile, ruby_sourceline, mesg);
  4500. ruby_sourceline = line;
  4501. }
  4502. }
  4503. static NODE*
  4504. block_append(rb_parser_state *parser_state, NODE *head, NODE *tail)
  4505. {
  4506. NODE *end, *h = head;
  4507. if (tail == 0) return head;
  4508. again:
  4509. if (h == 0) return tail;
  4510. switch (nd_type(h)) {
  4511. case NODE_NEWLINE:
  4512. h = h->nd_next;
  4513. goto again;
  4514. case NODE_STR:
  4515. case NODE_LIT:
  4516. parser_warning(parser_state, h, "unused literal ignored");
  4517. return tail;
  4518. default:
  4519. h = end = NEW_BLOCK(head);
  4520. end->nd_end = end;
  4521. fixpos(end, head);
  4522. head = end;
  4523. break;
  4524. case NODE_BLOCK:
  4525. end = h->nd_end;
  4526. break;
  4527. }
  4528. if (verbose) {
  4529. NODE *nd = end->nd_head;
  4530. newline:
  4531. switch (nd_type(nd)) {
  4532. case NODE_RETURN:
  4533. case NODE_BREAK:
  4534. case NODE_NEXT:
  4535. case NODE_REDO:
  4536. case NODE_RETRY:
  4537. parser_warning(parser_state, nd, "statement not reached");
  4538. break;
  4539. case NODE_NEWLINE:
  4540. nd = nd->nd_next;
  4541. goto newline;
  4542. default:
  4543. break;
  4544. }
  4545. }
  4546. if (nd_type(tail) != NODE_BLOCK) {
  4547. tail = NEW_BLOCK(tail);
  4548. tail->nd_end = tail;
  4549. }
  4550. end->nd_next = tail;
  4551. h->nd_end = tail->nd_end;
  4552. return head;
  4553. }
  4554. /* append item to the list */
  4555. static NODE*
  4556. list_append(rb_parser_state *parser_state, NODE *list, NODE *item)
  4557. {
  4558. NODE *last;
  4559. if (list == 0) return NEW_LIST(item);
  4560. if (list->nd_next) {
  4561. last = list->nd_next->nd_end;
  4562. }
  4563. else {
  4564. last = list;
  4565. }
  4566. list->nd_alen += 1;
  4567. last->nd_next = NEW_LIST(item);
  4568. list->nd_next->nd_end = last->nd_next;
  4569. return list;
  4570. }
  4571. /* concat two lists */
  4572. static NODE*
  4573. list_concat(NODE *head, NODE *tail)
  4574. {
  4575. NODE *last;
  4576. if (head->nd_next) {
  4577. last = head->nd_next->nd_end;
  4578. }
  4579. else {
  4580. last = head;
  4581. }
  4582. head->nd_alen += tail->nd_alen;
  4583. last->nd_next = tail;
  4584. if (tail->nd_next) {
  4585. head->nd_next->nd_end = tail->nd_next->nd_end;
  4586. }
  4587. else {
  4588. head->nd_next->nd_end = tail;
  4589. }
  4590. return head;
  4591. }
  4592. /* concat two string literals */
  4593. static NODE *
  4594. literal_concat(rb_parser_state *parser_state, NODE *head, NODE *tail)
  4595. {
  4596. enum node_type htype;
  4597. if (!head) return tail;
  4598. if (!tail) return head;
  4599. htype = (enum node_type)nd_type(head);
  4600. if (htype == NODE_EVSTR) {
  4601. NODE *node = NEW_DSTR(string_new(0, 0));
  4602. head = list_append(parser_state, node, head);
  4603. }
  4604. switch (nd_type(tail)) {
  4605. case NODE_STR:
  4606. if (htype == NODE_STR) {
  4607. if(head->nd_str) {
  4608. bconcat(head->nd_str, tail->nd_str);
  4609. bdestroy(tail->nd_str);
  4610. } else {
  4611. head = tail;
  4612. }
  4613. }
  4614. else {
  4615. list_append(parser_state, head, tail);
  4616. }
  4617. break;
  4618. case NODE_DSTR:
  4619. if (htype == NODE_STR) {
  4620. bconcat(head->nd_str, tail->nd_str);
  4621. bdestroy(tail->nd_str);
  4622. tail->nd_lit = head->nd_lit;
  4623. head = tail;
  4624. }
  4625. else {
  4626. nd_set_type(tail, NODE_ARRAY);
  4627. tail->nd_head = NEW_STR(tail->nd_lit);
  4628. list_concat(head, tail);
  4629. }
  4630. break;
  4631. case NODE_EVSTR:
  4632. if (htype == NODE_STR) {
  4633. nd_set_type(head, NODE_DSTR);
  4634. head->nd_alen = 1;
  4635. }
  4636. list_append(parser_state, head, tail);
  4637. break;
  4638. }
  4639. return head;
  4640. }
  4641. static NODE *
  4642. evstr2dstr(rb_parser_state *parser_state, NODE *node)
  4643. {
  4644. if (nd_type(node) == NODE_EVSTR) {
  4645. node = list_append(parser_state, NEW_DSTR(string_new(0, 0)), node);
  4646. }
  4647. return node;
  4648. }
  4649. static NODE *
  4650. new_evstr(rb_parser_state *parser_state, NODE *node)
  4651. {
  4652. NODE *head = node;
  4653. again:
  4654. if (node) {
  4655. switch (nd_type(node)) {
  4656. case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
  4657. return node;
  4658. case NODE_NEWLINE:
  4659. node = node->nd_next;
  4660. goto again;
  4661. }
  4662. }
  4663. return NEW_EVSTR(head);
  4664. }
  4665. static const struct {
  4666. QUID token;
  4667. const char name[12];
  4668. } op_tbl[] = {
  4669. {tDOT2, ".."},
  4670. {tDOT3, "..."},
  4671. {'+', "+"},
  4672. {'-', "-"},
  4673. {'+', "+(binary)"},
  4674. {'-', "-(binary)"},
  4675. {'*', "*"},
  4676. {'/', "/"},
  4677. {'%', "%"},
  4678. {tPOW, "**"},
  4679. {tUPLUS, "+@"},
  4680. {tUMINUS, "-@"},
  4681. {tUPLUS, "+(unary)"},
  4682. {tUMINUS, "-(unary)"},
  4683. {'|', "|"},
  4684. {'^', "^"},
  4685. {'&', "&"},
  4686. {tCMP, "<=>"},
  4687. {'>', ">"},
  4688. {tGEQ, ">="},
  4689. {'<', "<"},
  4690. {tLEQ, "<="},
  4691. {tEQ, "=="},
  4692. {tEQQ, "==="},
  4693. {tNEQ, "!="},
  4694. {tMATCH, "=~"},
  4695. {tNMATCH, "!~"},
  4696. {'!', "!"},
  4697. {'~', "~"},
  4698. {'!', "!(unary)"},
  4699. {'~', "~(unary)"},
  4700. {'!', "!@"},
  4701. {'~', "~@"},
  4702. {tAREF, "[]"},
  4703. {tASET, "[]="},
  4704. {tLSHFT, "<<"},
  4705. {tRSHFT, ">>"},
  4706. {tCOLON2, "::"},
  4707. {'`', "`"},
  4708. {0, ""}
  4709. };
  4710. static QUID convert_op(rb_parser_state *parser_state, QUID id) {
  4711. int i;
  4712. for(i = 0; op_tbl[i].token; i++) {
  4713. if(op_tbl[i].token == id) {
  4714. return rb_parser_sym(parser_state, op_tbl[i].name);
  4715. }
  4716. }
  4717. return id;
  4718. }
  4719. static NODE *
  4720. call_op(NODE *recv, QUID id, int narg, NODE *arg1, rb_parser_state *parser_state)
  4721. {
  4722. value_expr(recv);
  4723. if (narg == 1) {
  4724. value_expr(arg1);
  4725. arg1 = NEW_LIST(arg1);
  4726. }
  4727. else {
  4728. arg1 = 0;
  4729. }
  4730. id = convert_op(parser_state, id);
  4731. NODE* n = NEW_CALL(recv, id, arg1);
  4732. fixpos(n, recv);
  4733. return n;
  4734. }
  4735. static NODE*
  4736. match_gen(NODE *node1, NODE *node2, rb_parser_state *parser_state)
  4737. {
  4738. local_cnt('~');
  4739. value_expr(node1);
  4740. value_expr(node2);
  4741. if (node1) {
  4742. switch (nd_type(node1)) {
  4743. case NODE_DREGX:
  4744. case NODE_DREGX_ONCE:
  4745. return NEW_MATCH2(node1, node2);
  4746. case NODE_REGEX:
  4747. return NEW_MATCH2(node1, node2);
  4748. }
  4749. }
  4750. if (node2) {
  4751. switch (nd_type(node2)) {
  4752. case NODE_DREGX:
  4753. case NODE_DREGX_ONCE:
  4754. return NEW_MATCH3(node2, node1);
  4755. case NODE_REGEX:
  4756. return NEW_MATCH3(node2, node1);
  4757. }
  4758. }
  4759. return NEW_CALL(node1, convert_op(parser_state, tMATCH), NEW_LIST(node2));
  4760. }
  4761. static NODE*
  4762. mel_gettable(rb_parser_state *parser_state, QUID id)
  4763. {
  4764. if (id == kSELF) {
  4765. return NEW_SELF();
  4766. }
  4767. else if (id == kNIL) {
  4768. return NEW_NIL();
  4769. }
  4770. else if (id == kTRUE) {
  4771. return NEW_TRUE();
  4772. }
  4773. else if (id == kFALSE) {
  4774. return NEW_FALSE();
  4775. }
  4776. else if (id == k__FILE__) {
  4777. return NEW_FILE();
  4778. }
  4779. else if (id == k__LINE__) {
  4780. return NEW_FIXNUM(ruby_sourceline);
  4781. }
  4782. else if (is_local_id(id)) {
  4783. if (local_id(id)) return NEW_LVAR(id);
  4784. /* method call without arguments */
  4785. return NEW_VCALL(id);
  4786. }
  4787. else if (is_global_id(id)) {
  4788. return NEW_GVAR(id);
  4789. }
  4790. else if (is_instance_id(id)) {
  4791. return NEW_IVAR(id);
  4792. }
  4793. else if (is_const_id(id)) {
  4794. return NEW_CONST(id);
  4795. }
  4796. else if (is_class_id(id)) {
  4797. return NEW_CVAR(id);
  4798. }
  4799. /* FIXME: indicate which identifier. */
  4800. rb_compile_error(parser_state, "identifier is not valid 1\n");
  4801. return 0;
  4802. }
  4803. static void
  4804. reset_block(rb_parser_state *parser_state) {
  4805. if(!variables->block_vars) {
  4806. variables->block_vars = var_table_create();
  4807. } else {
  4808. variables->block_vars = var_table_push(variables->block_vars);
  4809. }
  4810. }
  4811. static NODE *
  4812. extract_block_vars(rb_parser_state *parser_state, NODE* node, var_table vars)
  4813. {
  4814. int i;
  4815. NODE *var, *out = node;
  4816. // we don't create any DASGN_CURR nodes
  4817. goto out;
  4818. if (!node) goto out;
  4819. if(var_table_size(vars) == 0) goto out;
  4820. var = NULL;
  4821. for(i = 0; i < var_table_size(vars); i++) {
  4822. var = NEW_DASGN_CURR(var_table_get(vars, i), var);
  4823. }
  4824. out = block_append(parser_state, var, node);
  4825. out:
  4826. variables->block_vars = var_table_pop(variables->block_vars);
  4827. return out;
  4828. }
  4829. static NODE*
  4830. assignable(QUID id, NODE *val, rb_parser_state *parser_state)
  4831. {
  4832. value_expr(val);
  4833. if (id == kSELF) {
  4834. yyerror("Can't change the value of self");
  4835. }
  4836. else if (id == kNIL) {
  4837. yyerror("Can't assign to nil");
  4838. }
  4839. else if (id == kTRUE) {
  4840. yyerror("Can't assign to true");
  4841. }
  4842. else if (id == kFALSE) {
  4843. yyerror("Can't assign to false");
  4844. }
  4845. else if (id == k__FILE__) {
  4846. yyerror("Can't assign to __FILE__");
  4847. }
  4848. else if (id == k__LINE__) {
  4849. yyerror("Can't assign to __LINE__");
  4850. }
  4851. else if (is_local_id(id)) {
  4852. if(variables->block_vars) {
  4853. var_table_add(variables->block_vars, id);
  4854. }
  4855. return NEW_LASGN(id, val);
  4856. }
  4857. else if (is_global_id(id)) {
  4858. return NEW_GASGN(id, val);
  4859. }
  4860. else if (is_instance_id(id)) {
  4861. return NEW_IASGN(id, val);
  4862. }
  4863. else if (is_const_id(id)) {
  4864. if (in_def || in_single)
  4865. yyerror("dynamic constant assignment");
  4866. return NEW_CDECL(id, val, 0);
  4867. }
  4868. else if (is_class_id(id)) {
  4869. if (in_def || in_single) return NEW_CVASGN(id, val);
  4870. return NEW_CVDECL(id, val);
  4871. }
  4872. else {
  4873. /* FIXME: indicate which identifier. */
  4874. rb_compile_error(parser_state, "identifier is not valid 2 (%d)\n", id);
  4875. }
  4876. return 0;
  4877. }
  4878. static NODE *
  4879. aryset(NODE *recv, NODE *idx, rb_parser_state *parser_state)
  4880. {
  4881. if (recv && nd_type(recv) == NODE_SELF)
  4882. recv = (NODE *)1;
  4883. else
  4884. value_expr(recv);
  4885. return NEW_ATTRASGN(recv, convert_op(parser_state, tASET), idx);
  4886. }
  4887. static QUID
  4888. rb_id_attrset(rb_parser_state* parser_state, QUID id)
  4889. {
  4890. id &= ~ID_SCOPE_MASK;
  4891. id |= ID_ATTRSET;
  4892. return id;
  4893. }
  4894. static NODE *
  4895. attrset(NODE *recv, QUID id, rb_parser_state *parser_state)
  4896. {
  4897. if (recv && nd_type(recv) == NODE_SELF)
  4898. recv = (NODE *)1;
  4899. else
  4900. value_expr(recv);
  4901. return NEW_ATTRASGN(recv, rb_id_attrset(parser_state, id), 0);
  4902. }
  4903. static void
  4904. rb_backref_error(NODE *node, rb_parser_state *parser_state)
  4905. {
  4906. switch (nd_type(node)) {
  4907. case NODE_NTH_REF:
  4908. rb_compile_error(parser_state, "Can't set variable $%u", node->nd_nth);
  4909. break;
  4910. case NODE_BACK_REF:
  4911. rb_compile_error(parser_state, "Can't set variable $%c", (int)node->nd_nth);
  4912. break;
  4913. }
  4914. }
  4915. static NODE *
  4916. arg_concat(rb_parser_state *parser_state, NODE *node1, NODE *node2)
  4917. {
  4918. if (!node2) return node1;
  4919. return NEW_ARGSCAT(node1, node2);
  4920. }
  4921. static NODE *
  4922. arg_add(rb_parser_state *parser_state, NODE *node1, NODE *node2)
  4923. {
  4924. if (!node1) return NEW_LIST(node2);
  4925. if (nd_type(node1) == NODE_ARRAY) {
  4926. return list_append(parser_state, node1, node2);
  4927. }
  4928. else {
  4929. return NEW_ARGSPUSH(node1, node2);
  4930. }
  4931. }
  4932. static NODE*
  4933. node_assign(NODE *lhs, NODE *rhs, rb_parser_state *parser_state)
  4934. {
  4935. if (!lhs) return 0;
  4936. value_expr(rhs);
  4937. switch (nd_type(lhs)) {
  4938. case NODE_GASGN:
  4939. case NODE_IASGN:
  4940. case NODE_LASGN:
  4941. case NODE_DASGN:
  4942. case NODE_DASGN_CURR:
  4943. case NODE_MASGN:
  4944. case NODE_CDECL:
  4945. case NODE_CVDECL:
  4946. case NODE_CVASGN:
  4947. lhs->nd_value = rhs;
  4948. break;
  4949. case NODE_ATTRASGN:
  4950. case NODE_CALL:
  4951. lhs->nd_args = arg_add(parser_state, lhs->nd_args, rhs);
  4952. break;
  4953. default:
  4954. /* should not happen */
  4955. break;
  4956. }
  4957. return lhs;
  4958. }
  4959. static int
  4960. value_expr0(NODE *node, rb_parser_state *parser_state)
  4961. {
  4962. int cond = 0;
  4963. while (node) {
  4964. switch (nd_type(node)) {
  4965. case NODE_DEFN:
  4966. case NODE_DEFS:
  4967. parser_warning(parser_state, node, "void value expression");
  4968. return FALSE;
  4969. case NODE_RETURN:
  4970. case NODE_BREAK:
  4971. case NODE_NEXT:
  4972. case NODE_REDO:
  4973. case NODE_RETRY:
  4974. if (!cond) yyerror("void value expression");
  4975. /* or "control never reach"? */
  4976. return FALSE;
  4977. case NODE_BLOCK:
  4978. while (node->nd_next) {
  4979. node = node->nd_next;
  4980. }
  4981. node = node->nd_head;
  4982. break;
  4983. case NODE_BEGIN:
  4984. node = node->nd_body;
  4985. break;
  4986. case NODE_IF:
  4987. if (!value_expr(node->nd_body)) return FALSE;
  4988. node = node->nd_else;
  4989. break;
  4990. case NODE_AND:
  4991. case NODE_OR:
  4992. cond = 1;
  4993. node = node->nd_2nd;
  4994. break;
  4995. case NODE_NEWLINE:
  4996. node = node->nd_next;
  4997. break;
  4998. default:
  4999. return TRUE;
  5000. }
  5001. }
  5002. return TRUE;
  5003. }
  5004. static void
  5005. void_expr0(NODE *node, rb_parser_state *parser_state)
  5006. {
  5007. const char *useless = NULL;
  5008. if (!verbose) return;
  5009. again:
  5010. if (!node) return;
  5011. switch (nd_type(node)) {
  5012. case NODE_NEWLINE:
  5013. node = node->nd_next;
  5014. goto again;
  5015. case NODE_CALL:
  5016. switch (node->nd_mid) {
  5017. case '+':
  5018. case '-':
  5019. case '*':
  5020. case '/':
  5021. case '%':
  5022. case tPOW:
  5023. case tUPLUS:
  5024. case tUMINUS:
  5025. case '|':
  5026. case '^':
  5027. case '&':
  5028. case tCMP:
  5029. case '>':
  5030. case tGEQ:
  5031. case '<':
  5032. case tLEQ:
  5033. case tEQ:
  5034. case tNEQ:
  5035. useless = "";
  5036. break;
  5037. }
  5038. break;
  5039. case NODE_LVAR:
  5040. case NODE_DVAR:
  5041. case NODE_GVAR:
  5042. case NODE_IVAR:
  5043. case NODE_CVAR:
  5044. case NODE_NTH_REF:
  5045. case NODE_BACK_REF:
  5046. useless = "a variable";
  5047. break;
  5048. case NODE_CONST:
  5049. case NODE_CREF:
  5050. useless = "a constant";
  5051. break;
  5052. case NODE_LIT:
  5053. case NODE_STR:
  5054. case NODE_DSTR:
  5055. case NODE_DREGX:
  5056. case NODE_DREGX_ONCE:
  5057. useless = "a literal";
  5058. break;
  5059. case NODE_COLON2:
  5060. case NODE_COLON3:
  5061. useless = "::";
  5062. break;
  5063. case NODE_DOT2:
  5064. useless = "..";
  5065. break;
  5066. case NODE_DOT3:
  5067. useless = "...";
  5068. break;
  5069. case NODE_SELF:
  5070. useless = "self";
  5071. break;
  5072. case NODE_NIL:
  5073. useless = "nil";
  5074. break;
  5075. case NODE_TRUE:
  5076. useless = "true";
  5077. break;
  5078. case NODE_FALSE:
  5079. useless = "false";
  5080. break;
  5081. case NODE_DEFINED:
  5082. useless = "defined?";
  5083. break;
  5084. }
  5085. if (useless) {
  5086. int line = ruby_sourceline;
  5087. ruby_sourceline = nd_line(node);
  5088. rb_warn("useless use of %s in void context", useless);
  5089. ruby_sourceline = line;
  5090. }
  5091. }
  5092. static void
  5093. void_stmts(NODE *node, rb_parser_state *parser_state)
  5094. {
  5095. if (!verbose) return;
  5096. if (!node) return;
  5097. if (nd_type(node) != NODE_BLOCK) return;
  5098. for (;;) {
  5099. if (!node->nd_next) return;
  5100. void_expr(node->nd_head);
  5101. node = node->nd_next;
  5102. }
  5103. }
  5104. static NODE *
  5105. remove_begin(NODE *node, rb_parser_state *parser_state)
  5106. {
  5107. NODE **n = &node;
  5108. while (*n) {
  5109. switch (nd_type(*n)) {
  5110. case NODE_NEWLINE:
  5111. n = &(*n)->nd_next;
  5112. continue;
  5113. case NODE_BEGIN:
  5114. *n = (*n)->nd_body;
  5115. default:
  5116. return node;
  5117. }
  5118. }
  5119. return node;
  5120. }
  5121. static int
  5122. assign_in_cond(NODE *node, rb_parser_state *parser_state)
  5123. {
  5124. switch (nd_type(node)) {
  5125. case NODE_MASGN:
  5126. yyerror("multiple assignment in conditional");
  5127. return 1;
  5128. case NODE_LASGN:
  5129. case NODE_DASGN:
  5130. case NODE_GASGN:
  5131. case NODE_IASGN:
  5132. break;
  5133. case NODE_NEWLINE:
  5134. default:
  5135. return 0;
  5136. }
  5137. switch (nd_type(node->nd_value)) {
  5138. case NODE_LIT:
  5139. case NODE_STR:
  5140. case NODE_NIL:
  5141. case NODE_TRUE:
  5142. case NODE_FALSE:
  5143. return 1;
  5144. case NODE_DSTR:
  5145. case NODE_XSTR:
  5146. case NODE_DXSTR:
  5147. case NODE_EVSTR:
  5148. case NODE_DREGX:
  5149. default:
  5150. break;
  5151. }
  5152. return 1;
  5153. }
  5154. static int
  5155. parser_e_option_supplied(rb_parser_state* parser_state)
  5156. {
  5157. if (strcmp(ruby_sourcefile, "-e") == 0)
  5158. return TRUE;
  5159. return FALSE;
  5160. }
  5161. #define e_option_supplied() parser_e_option_supplied(parser_state)
  5162. static void
  5163. warn_unless_e_option(rb_parser_state *parser_state, NODE *node, const char *str)
  5164. {
  5165. if (!e_option_supplied()) parser_warning(parser_state, node, str);
  5166. }
  5167. static NODE *cond0(NODE *node, rb_parser_state *parser_state);
  5168. static NODE*
  5169. range_op(NODE *node, rb_parser_state *parser_state)
  5170. {
  5171. enum node_type type;
  5172. if (!e_option_supplied()) return node;
  5173. if (node == 0) return 0;
  5174. value_expr(node);
  5175. node = cond0(node, parser_state);
  5176. type = (enum node_type)nd_type(node);
  5177. if (type == NODE_NEWLINE) {
  5178. node = node->nd_next;
  5179. type = (enum node_type)nd_type(node);
  5180. }
  5181. if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
  5182. warn_unless_e_option(parser_state, node, "integer literal in conditional range");
  5183. return call_op(node,tEQ,1,NEW_GVAR(rb_parser_sym(parser_state, "$.")), parser_state);
  5184. }
  5185. return node;
  5186. }
  5187. static int
  5188. literal_node(NODE *node)
  5189. {
  5190. if (!node) return 1; /* same as NODE_NIL */
  5191. switch (nd_type(node)) {
  5192. case NODE_LIT:
  5193. case NODE_STR:
  5194. case NODE_DSTR:
  5195. case NODE_EVSTR:
  5196. case NODE_DREGX:
  5197. case NODE_DREGX_ONCE:
  5198. case NODE_DSYM:
  5199. return 2;
  5200. case NODE_TRUE:
  5201. case NODE_FALSE:
  5202. case NODE_NIL:
  5203. return 1;
  5204. }
  5205. return 0;
  5206. }
  5207. static NODE*
  5208. cond0(NODE *node, rb_parser_state *parser_state)
  5209. {
  5210. if (node == 0) return 0;
  5211. assign_in_cond(node, parser_state);
  5212. switch (nd_type(node)) {
  5213. case NODE_DSTR:
  5214. case NODE_EVSTR:
  5215. case NODE_STR:
  5216. break;
  5217. case NODE_DREGX:
  5218. case NODE_DREGX_ONCE:
  5219. local_cnt('_');
  5220. local_cnt('~');
  5221. return NEW_MATCH2(node, NEW_GVAR(rb_parser_sym(parser_state, "$_")));
  5222. case NODE_AND:
  5223. case NODE_OR:
  5224. node->nd_1st = cond0(node->nd_1st, parser_state);
  5225. node->nd_2nd = cond0(node->nd_2nd, parser_state);
  5226. break;
  5227. case NODE_DOT2:
  5228. case NODE_DOT3:
  5229. node->nd_beg = range_op(node->nd_beg, parser_state);
  5230. node->nd_end = range_op(node->nd_end, parser_state);
  5231. if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
  5232. else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
  5233. if (!e_option_supplied()) {
  5234. int b = literal_node(node->nd_beg);
  5235. int e = literal_node(node->nd_end);
  5236. if ((b == 1 && e == 1) || (b + e >= 2 && verbose)) {
  5237. }
  5238. }
  5239. break;
  5240. case NODE_DSYM:
  5241. break;
  5242. case NODE_REGEX:
  5243. nd_set_type(node, NODE_MATCH);
  5244. local_cnt('_');
  5245. local_cnt('~');
  5246. default:
  5247. break;
  5248. }
  5249. return node;
  5250. }
  5251. static NODE*
  5252. cond(NODE *node, rb_parser_state *parser_state)
  5253. {
  5254. if (node == 0) return 0;
  5255. value_expr(node);
  5256. if (nd_type(node) == NODE_NEWLINE){
  5257. node->nd_next = cond0(node->nd_next, parser_state);
  5258. return node;
  5259. }
  5260. return cond0(node, parser_state);
  5261. }
  5262. static NODE*
  5263. logop(enum node_type type, NODE *left, NODE *right, rb_parser_state *parser_state)
  5264. {
  5265. value_expr(left);
  5266. if (left && nd_type(left) == type) {
  5267. NODE *node = left, *second;
  5268. while ((second = node->nd_2nd) != 0 && nd_type(second) == type) {
  5269. node = second;
  5270. }
  5271. node->nd_2nd = NEW_NODE(type, second, right, 0);
  5272. return left;
  5273. }
  5274. return NEW_NODE(type, left, right, 0);
  5275. }
  5276. static int
  5277. cond_negative(NODE **nodep)
  5278. {
  5279. NODE *c = *nodep;
  5280. if (!c) return 0;
  5281. switch (nd_type(c)) {
  5282. case NODE_NOT:
  5283. *nodep = c->nd_body;
  5284. return 1;
  5285. case NODE_NEWLINE:
  5286. if (c->nd_next && nd_type(c->nd_next) == NODE_NOT) {
  5287. c->nd_next = c->nd_next->nd_body;
  5288. return 1;
  5289. }
  5290. }
  5291. return 0;
  5292. }
  5293. static void
  5294. no_blockarg(rb_parser_state *parser_state, NODE *node)
  5295. {
  5296. if (node && nd_type(node) == NODE_BLOCK_PASS) {
  5297. rb_compile_error(parser_state, "block argument should not be given");
  5298. }
  5299. }
  5300. static NODE *
  5301. ret_args(rb_parser_state *parser_state, NODE *node)
  5302. {
  5303. if (node) {
  5304. no_blockarg(parser_state, node);
  5305. if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) {
  5306. node = node->nd_head;
  5307. }
  5308. if (node && nd_type(node) == NODE_SPLAT) {
  5309. node = NEW_SVALUE(node);
  5310. }
  5311. }
  5312. return node;
  5313. }
  5314. static NODE *
  5315. new_yield(rb_parser_state *parser_state, NODE *node)
  5316. {
  5317. VALUE state = Qtrue;
  5318. if (node) {
  5319. no_blockarg(parser_state, node);
  5320. if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) {
  5321. node = node->nd_head;
  5322. state = Qfalse;
  5323. }
  5324. if (node && nd_type(node) == NODE_SPLAT) {
  5325. state = Qtrue;
  5326. }
  5327. }
  5328. else {
  5329. state = Qfalse;
  5330. }
  5331. return NEW_YIELD(node, state);
  5332. }
  5333. static NODE *
  5334. arg_blk_pass(NODE *node1, NODE *node2)
  5335. {
  5336. if (node2) {
  5337. node2->nd_head = node1;
  5338. return node2;
  5339. }
  5340. return node1;
  5341. }
  5342. static NODE*
  5343. arg_prepend(rb_parser_state *parser_state, NODE *node1, NODE *node2)
  5344. {
  5345. switch (nd_type(node2)) {
  5346. case NODE_ARRAY:
  5347. return list_concat(NEW_LIST(node1), node2);
  5348. case NODE_SPLAT:
  5349. return arg_concat(parser_state, node1, node2->nd_head);
  5350. case NODE_BLOCK_PASS:
  5351. node2->nd_body = arg_prepend(parser_state, node1, node2->nd_body);
  5352. return node2;
  5353. default:
  5354. printf("unknown nodetype(%d) for arg_prepend", nd_type(node2));
  5355. abort();
  5356. }
  5357. return 0; /* not reached */
  5358. }
  5359. static NODE*
  5360. new_call(rb_parser_state *parser_state, NODE *r,QUID m,NODE *a)
  5361. {
  5362. if (a && nd_type(a) == NODE_BLOCK_PASS) {
  5363. a->nd_iter = NEW_CALL(r, convert_op(parser_state, m),a->nd_head);
  5364. return a;
  5365. }
  5366. return NEW_CALL(r, convert_op(parser_state, m),a);
  5367. }
  5368. static NODE*
  5369. new_fcall(rb_parser_state *parser_state,QUID m,NODE *a)
  5370. {
  5371. if (a && nd_type(a) == NODE_BLOCK_PASS) {
  5372. a->nd_iter = NEW_FCALL(m,a->nd_head);
  5373. return a;
  5374. }
  5375. return NEW_FCALL(m, a);
  5376. }
  5377. static NODE*
  5378. new_super(rb_parser_state *parser_state,NODE *a)
  5379. {
  5380. if (a && nd_type(a) == NODE_BLOCK_PASS) {
  5381. a->nd_iter = NEW_SUPER(a->nd_head);
  5382. return a;
  5383. }
  5384. return NEW_SUPER(a);
  5385. }
  5386. static void
  5387. mel_local_push(rb_parser_state *parser_state, int cnt)
  5388. {
  5389. variables = LocalState::push(variables);
  5390. }
  5391. static void
  5392. mel_local_pop(rb_parser_state *parser_state)
  5393. {
  5394. variables = LocalState::pop(variables);
  5395. }
  5396. static QUID*
  5397. mel_local_tbl(rb_parser_state *parser_state)
  5398. {
  5399. QUID *lcl_tbl;
  5400. var_table tbl;
  5401. int i, len;
  5402. tbl = variables->local_vars;
  5403. len = var_table_size(tbl);
  5404. lcl_tbl = (QUID*)pt_allocate(parser_state, (int)(sizeof(QUID) * (len + 3)));
  5405. lcl_tbl[0] = (QUID)len;
  5406. lcl_tbl[1] = '_';
  5407. lcl_tbl[2] = '~';
  5408. for(i = 0; i < len; i++) {
  5409. lcl_tbl[i + 3] = var_table_get(tbl, i);
  5410. }
  5411. return lcl_tbl;
  5412. }
  5413. static intptr_t
  5414. mel_local_cnt(rb_parser_state *parser_state, QUID id)
  5415. {
  5416. int idx;
  5417. /* Leave these hardcoded here because they arne't REALLY ids at all. */
  5418. if(id == '_') {
  5419. return 0;
  5420. } else if(id == '~') {
  5421. return 1;
  5422. }
  5423. // if there are block variables, check to see if there is already
  5424. // a local by this name. If not, create one in the top block_vars
  5425. // table.
  5426. if(variables->block_vars) {
  5427. idx = var_table_find_chained(variables->block_vars, id);
  5428. if(idx >= 0) {
  5429. return idx;
  5430. } else {
  5431. return var_table_add(variables->block_vars, id);
  5432. }
  5433. }
  5434. idx = var_table_find(variables->local_vars, id);
  5435. if(idx >= 0) {
  5436. return idx + 2;
  5437. }
  5438. return var_table_add(variables->local_vars, id);
  5439. }
  5440. static int
  5441. mel_local_id(rb_parser_state *parser_state, QUID id)
  5442. {
  5443. if(variables->block_vars) {
  5444. if(var_table_find_chained(variables->block_vars, id) >= 0) return 1;
  5445. }
  5446. if(var_table_find(variables->local_vars, id) >= 0) return 1;
  5447. return 0;
  5448. }
  5449. static QUID
  5450. rb_parser_sym(rb_parser_state *parser_state, const char *name)
  5451. {
  5452. const char *m = name;
  5453. QUID id, pre, qrk, bef;
  5454. int last;
  5455. id = 0;
  5456. last = (int)strlen(name)-1;
  5457. switch (*name) {
  5458. case '$':
  5459. id |= ID_GLOBAL;
  5460. m++;
  5461. if(!m[0]) { // Detect a :"$"
  5462. id = ID_LOCAL;
  5463. } else if (!is_identchar(*m)) {
  5464. m++;
  5465. }
  5466. break;
  5467. case '@':
  5468. if (name[1] == '@') {
  5469. m++;
  5470. id |= ID_CLASS;
  5471. }
  5472. else {
  5473. id |= ID_INSTANCE;
  5474. }
  5475. m++;
  5476. break;
  5477. default:
  5478. if (name[0] != '_' && !ISALPHA(name[0]) && !ismbchar(name[0])) {
  5479. int i;
  5480. for (i=0; op_tbl[i].token; i++) {
  5481. if (*op_tbl[i].name == *name &&
  5482. strcmp(op_tbl[i].name, name) == 0) {
  5483. id = op_tbl[i].token;
  5484. return id;
  5485. }
  5486. }
  5487. }
  5488. if (name[last] == '=') {
  5489. id = ID_ATTRSET;
  5490. }
  5491. else if (ISUPPER(name[0])) {
  5492. id = ID_CONST;
  5493. }
  5494. else {
  5495. id = ID_LOCAL;
  5496. }
  5497. break;
  5498. }
  5499. while (m <= name + last && is_identchar(*m)) {
  5500. m += mbclen(*m);
  5501. }
  5502. if (*m) id = ID_JUNK;
  5503. qrk = (QUID)quark_from_string(parser_state, name);
  5504. pre = qrk + tLAST_TOKEN;
  5505. bef = id;
  5506. id |= ( pre << ID_SCOPE_SHIFT );
  5507. return id;
  5508. }
  5509. static int
  5510. scan_oct(const char *start, int len, int *retlen)
  5511. {
  5512. register const char *s = start;
  5513. register int retval = 0;
  5514. while (len-- && *s >= '0' && *s <= '7') {
  5515. retval <<= 3;
  5516. retval |= *s++ - '0';
  5517. }
  5518. *retlen = (int)(s - start);
  5519. return retval;
  5520. }
  5521. static int
  5522. scan_hex(const char *start, int len, int *retlen)
  5523. {
  5524. static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
  5525. register const char *s = start;
  5526. register int retval = 0;
  5527. const char *tmp;
  5528. while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
  5529. retval <<= 4;
  5530. retval |= (int)((tmp - hexdigit) & 15);
  5531. s++;
  5532. }
  5533. *retlen = (int)(s - start);
  5534. return retval;
  5535. }
  5536. const char *op_to_name(rb_parser_state* parser_state, QUID id) {
  5537. if(id < tLAST_TOKEN) {
  5538. int i = 0;
  5539. for (i=0; op_tbl[i].token; i++) {
  5540. if (op_tbl[i].token == id)
  5541. return op_tbl[i].name;
  5542. }
  5543. }
  5544. return NULL;
  5545. }
  5546. quark id_to_quark(rb_parser_state* parser_state, QUID id) {
  5547. quark qrk;
  5548. qrk = (quark)((id >> ID_SCOPE_SHIFT) - tLAST_TOKEN);
  5549. return qrk;
  5550. }
  5551. }; // namespace grammar18
  5552. }; // namespace melbourne