PageRenderTime 95ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/ext/melbourne/grammar.y

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