diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-22 14:42:53 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-22 14:42:53 -0200 |
commit | 0050d983fc2f3cc56442cadd73a93823643ac53d (patch) | |
tree | 6abc67442252231122429f72a2a71c9a3d5110a3 | |
parent | 04b143ddf931f5312209ddfc1d8d14ede6997afd (diff) | |
download | lua-0050d983fc2f3cc56442cadd73a93823643ac53d.tar.gz lua-0050d983fc2f3cc56442cadd73a93823643ac53d.tar.bz2 lua-0050d983fc2f3cc56442cadd73a93823643ac53d.zip |
make more clear "primitive" recursive definitions
-rw-r--r-- | lparser.c | 206 |
1 files changed, 100 insertions, 106 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.197 2002/11/22 13:59:04 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.198 2002/11/22 16:35:20 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -47,9 +47,7 @@ typedef struct BlockCnt { | |||
47 | /* | 47 | /* |
48 | ** prototypes for recursive non-terminal functions | 48 | ** prototypes for recursive non-terminal functions |
49 | */ | 49 | */ |
50 | static void body (LexState *ls, expdesc *v, int needself, int line); | ||
51 | static void chunk (LexState *ls); | 50 | static void chunk (LexState *ls); |
52 | static void constructor (LexState *ls, expdesc *v); | ||
53 | static void expr (LexState *ls, expdesc *v); | 51 | static void expr (LexState *ls, expdesc *v); |
54 | 52 | ||
55 | 53 | ||
@@ -400,69 +398,6 @@ static void luaY_index (LexState *ls, expdesc *v) { | |||
400 | } | 398 | } |
401 | 399 | ||
402 | 400 | ||
403 | static int explist1 (LexState *ls, expdesc *v) { | ||
404 | /* explist1 -> expr { `,' expr } */ | ||
405 | int n = 1; /* at least one expression */ | ||
406 | expr(ls, v); | ||
407 | while (testnext(ls, ',')) { | ||
408 | luaK_exp2nextreg(ls->fs, v); | ||
409 | expr(ls, v); | ||
410 | n++; | ||
411 | } | ||
412 | return n; | ||
413 | } | ||
414 | |||
415 | |||
416 | static void funcargs (LexState *ls, expdesc *f) { | ||
417 | FuncState *fs = ls->fs; | ||
418 | expdesc args; | ||
419 | int base, nparams; | ||
420 | int line = ls->linenumber; | ||
421 | switch (ls->t.token) { | ||
422 | case '(': { /* funcargs -> `(' [ explist1 ] `)' */ | ||
423 | if (line != ls->lastline) | ||
424 | luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); | ||
425 | next(ls); | ||
426 | if (ls->t.token == ')') /* arg list is empty? */ | ||
427 | args.k = VVOID; | ||
428 | else { | ||
429 | explist1(ls, &args); | ||
430 | luaK_setcallreturns(fs, &args, LUA_MULTRET); | ||
431 | } | ||
432 | check_match(ls, ')', '(', line); | ||
433 | break; | ||
434 | } | ||
435 | case '{': { /* funcargs -> constructor */ | ||
436 | constructor(ls, &args); | ||
437 | break; | ||
438 | } | ||
439 | case TK_STRING: { /* funcargs -> STRING */ | ||
440 | codestring(ls, &args, ls->t.seminfo.ts); | ||
441 | next(ls); /* must use `seminfo' before `next' */ | ||
442 | break; | ||
443 | } | ||
444 | default: { | ||
445 | luaX_syntaxerror(ls, "function arguments expected"); | ||
446 | return; | ||
447 | } | ||
448 | } | ||
449 | lua_assert(f->k == VNONRELOC); | ||
450 | base = f->info; /* base register for call */ | ||
451 | if (args.k == VCALL) | ||
452 | nparams = LUA_MULTRET; /* open call */ | ||
453 | else { | ||
454 | if (args.k != VVOID) | ||
455 | luaK_exp2nextreg(fs, &args); /* close last argument */ | ||
456 | nparams = fs->freereg - (base+1); | ||
457 | } | ||
458 | init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); | ||
459 | luaK_fixline(fs, line); | ||
460 | fs->freereg = base+1; /* call remove function and arguments and leaves | ||
461 | (unless changed) one result */ | ||
462 | } | ||
463 | |||
464 | |||
465 | |||
466 | /* | 401 | /* |
467 | ** {====================================================================== | 402 | ** {====================================================================== |
468 | ** Rules for Constructors | 403 | ** Rules for Constructors |
@@ -578,11 +513,107 @@ static void constructor (LexState *ls, expdesc *t) { | |||
578 | SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */ | 513 | SETARG_C(fs->f->code[pc], luaO_log2(cc.nh)+1); /* set initial table size */ |
579 | } | 514 | } |
580 | 515 | ||
581 | |||
582 | /* }====================================================================== */ | 516 | /* }====================================================================== */ |
583 | 517 | ||
584 | 518 | ||
585 | 519 | ||
520 | static void parlist (LexState *ls) { | ||
521 | /* parlist -> [ param { `,' param } ] */ | ||
522 | int nparams = 0; | ||
523 | int dots = 0; | ||
524 | if (ls->t.token != ')') { /* is `parlist' not empty? */ | ||
525 | do { | ||
526 | switch (ls->t.token) { | ||
527 | case TK_DOTS: dots = 1; next(ls); break; | ||
528 | case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; | ||
529 | default: luaX_syntaxerror(ls, "<name> or `...' expected"); | ||
530 | } | ||
531 | } while (!dots && testnext(ls, ',')); | ||
532 | } | ||
533 | code_params(ls, nparams, dots); | ||
534 | } | ||
535 | |||
536 | |||
537 | static void body (LexState *ls, expdesc *e, int needself, int line) { | ||
538 | /* body -> `(' parlist `)' chunk END */ | ||
539 | FuncState new_fs; | ||
540 | open_func(ls, &new_fs); | ||
541 | new_fs.f->lineDefined = line; | ||
542 | check(ls, '('); | ||
543 | if (needself) | ||
544 | create_local(ls, "self"); | ||
545 | parlist(ls); | ||
546 | check(ls, ')'); | ||
547 | chunk(ls); | ||
548 | check_match(ls, TK_END, TK_FUNCTION, line); | ||
549 | close_func(ls); | ||
550 | pushclosure(ls, &new_fs, e); | ||
551 | } | ||
552 | |||
553 | |||
554 | static int explist1 (LexState *ls, expdesc *v) { | ||
555 | /* explist1 -> expr { `,' expr } */ | ||
556 | int n = 1; /* at least one expression */ | ||
557 | expr(ls, v); | ||
558 | while (testnext(ls, ',')) { | ||
559 | luaK_exp2nextreg(ls->fs, v); | ||
560 | expr(ls, v); | ||
561 | n++; | ||
562 | } | ||
563 | return n; | ||
564 | } | ||
565 | |||
566 | |||
567 | static void funcargs (LexState *ls, expdesc *f) { | ||
568 | FuncState *fs = ls->fs; | ||
569 | expdesc args; | ||
570 | int base, nparams; | ||
571 | int line = ls->linenumber; | ||
572 | switch (ls->t.token) { | ||
573 | case '(': { /* funcargs -> `(' [ explist1 ] `)' */ | ||
574 | if (line != ls->lastline) | ||
575 | luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); | ||
576 | next(ls); | ||
577 | if (ls->t.token == ')') /* arg list is empty? */ | ||
578 | args.k = VVOID; | ||
579 | else { | ||
580 | explist1(ls, &args); | ||
581 | luaK_setcallreturns(fs, &args, LUA_MULTRET); | ||
582 | } | ||
583 | check_match(ls, ')', '(', line); | ||
584 | break; | ||
585 | } | ||
586 | case '{': { /* funcargs -> constructor */ | ||
587 | constructor(ls, &args); | ||
588 | break; | ||
589 | } | ||
590 | case TK_STRING: { /* funcargs -> STRING */ | ||
591 | codestring(ls, &args, ls->t.seminfo.ts); | ||
592 | next(ls); /* must use `seminfo' before `next' */ | ||
593 | break; | ||
594 | } | ||
595 | default: { | ||
596 | luaX_syntaxerror(ls, "function arguments expected"); | ||
597 | return; | ||
598 | } | ||
599 | } | ||
600 | lua_assert(f->k == VNONRELOC); | ||
601 | base = f->info; /* base register for call */ | ||
602 | if (args.k == VCALL) | ||
603 | nparams = LUA_MULTRET; /* open call */ | ||
604 | else { | ||
605 | if (args.k != VVOID) | ||
606 | luaK_exp2nextreg(fs, &args); /* close last argument */ | ||
607 | nparams = fs->freereg - (base+1); | ||
608 | } | ||
609 | init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); | ||
610 | luaK_fixline(fs, line); | ||
611 | fs->freereg = base+1; /* call remove function and arguments and leaves | ||
612 | (unless changed) one result */ | ||
613 | } | ||
614 | |||
615 | |||
616 | |||
586 | 617 | ||
587 | /* | 618 | /* |
588 | ** {====================================================================== | 619 | ** {====================================================================== |
@@ -703,8 +734,6 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
703 | } | 734 | } |
704 | 735 | ||
705 | 736 | ||
706 | |||
707 | |||
708 | static UnOpr getunopr (int op) { | 737 | static UnOpr getunopr (int op) { |
709 | switch (op) { | 738 | switch (op) { |
710 | case TK_NOT: return OPR_NOT; | 739 | case TK_NOT: return OPR_NOT; |
@@ -788,6 +817,7 @@ static void expr (LexState *ls, expdesc *v) { | |||
788 | /* }==================================================================== */ | 817 | /* }==================================================================== */ |
789 | 818 | ||
790 | 819 | ||
820 | |||
791 | /* | 821 | /* |
792 | ** {====================================================================== | 822 | ** {====================================================================== |
793 | ** Rules for Statements | 823 | ** Rules for Statements |
@@ -1268,43 +1298,6 @@ static int statement (LexState *ls) { | |||
1268 | } | 1298 | } |
1269 | 1299 | ||
1270 | 1300 | ||
1271 | static void parlist (LexState *ls) { | ||
1272 | /* parlist -> [ param { `,' param } ] */ | ||
1273 | int nparams = 0; | ||
1274 | int dots = 0; | ||
1275 | if (ls->t.token != ')') { /* is `parlist' not empty? */ | ||
1276 | do { | ||
1277 | switch (ls->t.token) { | ||
1278 | case TK_DOTS: dots = 1; next(ls); break; | ||
1279 | case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; | ||
1280 | default: luaX_syntaxerror(ls, "<name> or `...' expected"); | ||
1281 | } | ||
1282 | } while (!dots && testnext(ls, ',')); | ||
1283 | } | ||
1284 | code_params(ls, nparams, dots); | ||
1285 | } | ||
1286 | |||
1287 | |||
1288 | static void body (LexState *ls, expdesc *e, int needself, int line) { | ||
1289 | /* body -> `(' parlist `)' chunk END */ | ||
1290 | FuncState new_fs; | ||
1291 | open_func(ls, &new_fs); | ||
1292 | new_fs.f->lineDefined = line; | ||
1293 | check(ls, '('); | ||
1294 | if (needself) | ||
1295 | create_local(ls, "self"); | ||
1296 | parlist(ls); | ||
1297 | check(ls, ')'); | ||
1298 | chunk(ls); | ||
1299 | check_match(ls, TK_END, TK_FUNCTION, line); | ||
1300 | close_func(ls); | ||
1301 | pushclosure(ls, &new_fs, e); | ||
1302 | } | ||
1303 | |||
1304 | |||
1305 | /* }====================================================================== */ | ||
1306 | |||
1307 | |||
1308 | static void chunk (LexState *ls) { | 1301 | static void chunk (LexState *ls) { |
1309 | /* chunk -> { stat [`;'] } */ | 1302 | /* chunk -> { stat [`;'] } */ |
1310 | int islast = 0; | 1303 | int islast = 0; |
@@ -1318,3 +1311,4 @@ static void chunk (LexState *ls) { | |||
1318 | leavelevel(ls); | 1311 | leavelevel(ls); |
1319 | } | 1312 | } |
1320 | 1313 | ||
1314 | /* }====================================================================== */ | ||