Annotation of coherent/d/bin/bc/gram.y, revision 1.1.1.1

1.1       root        1: /*     Bc - an infix desk calculator */
                      2: 
                      3: %{
                      4: #include <stdio.h>
                      5: #include "bc.h"
                      6: #define        YYTNAMES
                      7: 
                      8: /* This will generate yyerror() and error recovery */
                      9: #define YYSYNTAX       goto YYerract
                     10: /* This will enter error recovery */
                     11: #define YYERROR                ++yyerrflag; goto YYerract
                     12: 
                     13: static code    *breakloc       = NULL; /* where to go on break statement */
                     14: static code    *contloc        = NULL; /* where to go on continue statement */
                     15: static dicent  *retfrom        = NULL; /* what function to return from */
                     16: static dicent  **dvec;                 /* list of locals */
                     17: static dicent  **pardvec;              /* list of formal parameters */
                     18: static dicent  **autdvec;              /* list of automatic variables */
                     19: static int     ldvec;                  /* length of dvec */
                     20: static int     lpardvec;               /* length of pardvec */
                     21: static int     lautdvec;               /* length of autdvec */
                     22: %}
                     23: 
                     24: 
                     25: %union {
                     26:        opcode  opcode;
                     27:        rvalue  *lvalue;
                     28:        char    *svalue;
                     29:        dicent  *dvalue;
                     30:        int     ivalue;
                     31:        code    *location;
                     32: }
                     33: 
                     34: 
                     35: %token <lvalue>        NUMBER
                     36: %token <svalue>        STRING
                     37: %token <dvalue>        IDENTIFIER
                     38: %token                 ADDAB   AUTO    BREAK   CONTINUE DECR   DEFINE
                     39: %token                 DIVAB   DO      DOT     ELSE    EQP      ERROR
                     40: %token                 EXPAB   FOR     GEP     GTP     IBASE    IF
                     41: %token                 INCR    LENGTH_ LEP     LTP     MULAB    NEP
                     42: %token                 OBASE   QUIT    REMAB   RETURN_ SCALE_   SQRT_
                     43: %token                 SUBAB   WHILE
                     44: 
                     45: %type  <opcode>        assignment_op   special_load    special_store
                     46: %type  <opcode>        function_like_primitive         relational
                     47: %type  <dvalue>        local
                     48: %type  <ivalue>        argument_list   non_empty_argument_list
                     49: %type  <location>      jump_true       jump_false      else_part
                     50: %type  <location>      goto            save_loc        save_break
                     51: %type  <location>      save_continue
                     52: 
                     53: %right '='
                     54: %left  '+'     '-'
                     55: %left  '*'     '/'     '%'
                     56: %right '^'
                     57: %left  INCR    DECR    UMINUS
                     58: 
                     59: %%
                     60: /* Error recovery: allok is FALSE if any syntax or semantic error
                     61:  * occurred, but the error production will be reduced in all cases
                     62:  * except one, the case where cstream overflows.
                     63:  */
                     64: 
                     65: session:
                     66:        /* empty */
                     67: |      session statement {
                     68:                emitop(STOP);
                     69: immfix:                if (allok)
                     70:                        interp();
                     71:                litfree(cstream, loc);
                     72:                loc = cstream;
                     73:                allok = TRUE;
                     74:                breakloc = contloc = retfrom = NULL;
                     75:        }
                     76: |      session definition {
                     77:                if (loc[-1].opcode != RETURN) {
                     78:                        emitop(PGLSC);
                     79:                        emitnum(&zero);
                     80:                        emitop(LOAD);
                     81:                        emitop(RETURN);
                     82:                        emitid(retfrom);
                     83:                }
                     84: deffix:                if (allok)
                     85:                        install(&retfrom->globalv.fvalue, pardvec, lpardvec,
                     86:                                autdvec, lautdvec);
                     87:                else {
                     88:                        remloc(pardvec, lpardvec);
                     89:                        remloc(autdvec, lautdvec);
                     90:                        retfrom->globalt = UNDEFINED;
                     91:                        litfree(cstream, loc);
                     92:                }
                     93:                mpfree(pardvec);
                     94:                lpardvec = 0;
                     95:                pardvec = NULL;
                     96:                mpfree(autdvec);
                     97:                lautdvec = 0;
                     98:                autdvec = NULL;
                     99:                mpfree(dvec);
                    100:                ldvec = 0;
                    101:                dvec = NULL;
                    102:                loc = cstream;
                    103:                allok = TRUE;
                    104:                breakloc = contloc = retfrom = NULL;
                    105:        }
                    106: |      session error '\n' {
                    107:                YYERROK;
                    108:                if (retfrom != NULL)
                    109:                        goto deffix;
                    110:                else
                    111:                        goto immfix;
                    112:        }
                    113: ;
                    114: 
                    115: /*
                    116:  *     Statements.
                    117:  */
                    118: 
                    119: statement:
                    120:        /*
                    121:         * The code generated for an IF statement  with an else part is as
                    122:         * follows:
                    123:         *                      if not condition, goto L1
                    124:         *                      true part of IF statement
                    125:         *                      goto L2
                    126:         *      L1:             false part of IF statement
                    127:         *      L2:
                    128:         *
                    129:         * If there is no ELSE part, then the code generated is as
                    130:         * follows:
                    131:         *                      if not condition, goto L1
                    132:         *                      true part of IF statement
                    133:         *      L1:
                    134:         */
                    135:        IF '(' jump_false ')'                                   /* $1  */
                    136:                statement                                       /* $5  */
                    137:                else_part {                                     /* $6  */
                    138:                        patch($3, $6);
                    139:                }
                    140: |
                    141:        /*
                    142:         * The code generated for the WHILE statement is as
                    143:         * follows:
                    144:         *      CONTINUE:       if condition, goto L1
                    145:         *      BREAK:          goto L2
                    146:         *      L1:             body of WHILE statement
                    147:         *                      goto CONTINUE
                    148:         *      L2:
                    149:         */
                    150:        WHILE save_continue '(' jump_true ')'                   /* $1  */
                    151:                save_break goto                                 /* $6  */
                    152:                save_loc statement                              /* $8  */
                    153:                goto {                                          /* $10 */
                    154:                        patch($4, $8);
                    155:                        patch($7, loc);
                    156:                        patch($10, contloc);
                    157:                        breakloc = $6;                  /* restore break */
                    158:                        contloc = $2;                   /* restore continue */
                    159:                }
                    160: |
                    161:        /*
                    162:         * The code produced for the FOR statement is as
                    163:         * follows:
                    164:         *                      initialization expression
                    165:         *      L1:             if condition, goto L3
                    166:         *      BREAK:          goto L4
                    167:         *      CONTINUE:       increment expression
                    168:         *                      goto L1
                    169:         *      L3:             body of FOR statement
                    170:         *                      goto CONTINUE
                    171:         *      L4:
                    172:         */
                    173:        FOR '(' optional_expression_list';'                     /* $1  */
                    174:                save_loc jump_true ';'                          /* $5  */
                    175:                save_break goto                                 /* $8  */
                    176:                save_continue optional_expression_list ')'      /* $10 */
                    177:                goto                                            /* $13 */
                    178:                save_loc statement                              /* $14 */
                    179:                goto {                                          /* $16 */
                    180:                        patch($6, $14);
                    181:                        patch($9, loc);
                    182:                        patch($13, $5);
                    183:                        patch($16, contloc);
                    184:                        breakloc = $8;
                    185:                        contloc = $10;
                    186:                }
                    187: |
                    188:        /*
                    189:         * The code produced for the DO-WHILE statement is as
                    190:         * follows:
                    191:         *                      goto L1
                    192:         *      BREAK:          goto L3
                    193:         *      CONTINUE:       goto L2
                    194:         *      L1:             body of DO-WHILE statement
                    195:         *      L2:             if condition, goto L1
                    196:         *      L3:
                    197:         */
                    198:        DO goto                                                 /* $1  */
                    199:                save_break goto                                 /* $3  */
                    200:                save_continue goto                              /* $5  */
                    201:                save_loc statement WHILE '('                    /* $7  */
                    202:                save_loc jump_true ')' end_of_statement {       /* $11 */
                    203:                        patch($2, $7);
                    204:                        patch($4, loc);
                    205:                        patch($6, $11);
                    206:                        patch($12, $7);
                    207:                        breakloc = $3;
                    208:                        contloc = $5;
                    209:                }
                    210: |      BREAK end_of_statement {
                    211:                if (breakloc == NULL) {
                    212:                        gerror("Break not in loop");
                    213:                        YYERROR;
                    214:                }
                    215:                emitop(BRALW);
                    216:                emitaddr(breakloc);
                    217:        }
                    218: |      CONTINUE end_of_statement {
                    219:                if (contloc == NULL) {
                    220:                        gerror("Continue not in loop");
                    221:                        YYERROR;
                    222:                }
                    223:                emitop(BRALW);
                    224:                emitaddr(contloc);
                    225:        }
                    226: |      RETURN_ end_of_statement {
                    227:                if (retfrom == NULL) {
                    228:                        gerror("Return not in function");
                    229:                        YYERROR;
                    230:                }
                    231:                emitop(PGLSC);
                    232:                emitnum(&zero);
                    233:                emitop(LOAD);
                    234:                emitop(RETURN);
                    235:                emitid(retfrom);
                    236:        }
                    237: |      RETURN_ expression end_of_statement {
                    238:                if (retfrom == NULL) {
                    239:                        gerror("Return not in function");
                    240:                        YYERROR;
                    241:                }
                    242:                emitop(RETURN);
                    243:                emitid(retfrom);
                    244:        }
                    245: |      assignment_expression end_of_statement {
                    246:                emitop(POP);
                    247:        }
                    248: |      non_assignment_expression end_of_statement {
                    249:                emitop(PRNUM);
                    250:                emitop(PRNL);
                    251:        }
                    252: |      non_assignment_expression '$' end_of_statement {
                    253:                emitop(PRNUM);
                    254:        }
                    255: |      STRING end_of_statement {
                    256:                emitop(PRSTR);
                    257:                emitstr($1);
                    258:                emitop(PRNL);
                    259:        }
                    260: |      STRING '$' end_of_statement {
                    261:                emitop(PRSTR);
                    262:                emitstr($1);
                    263:        }
                    264: |      '{' statement_list '}'
                    265: |      QUIT end_of_statement {
                    266:                emitop(EXIT);
                    267:        }
                    268: |      end_of_statement
                    269: ;
                    270: 
                    271: end_of_statement:
                    272:        ';'
                    273: |      '\n'
                    274: ;
                    275: 
                    276: statement_list:
                    277:        /* empty */
                    278: |      statement_list statement
                    279: ;
                    280: 
                    281: else_part:
                    282:        /* empty */ {
                    283:                $$ = loc;
                    284:        }
                    285: |      ELSE goto save_loc statement {
                    286:                $$ = $3;
                    287:                patch($2, loc);
                    288:        }
                    289: ;
                    290: 
                    291: optional_expression_list:
                    292:        /* empty */
                    293: |      non_empty_expression_list
                    294: ;
                    295: 
                    296: non_empty_expression_list:
                    297:        expression {
                    298:                emitop(POP);
                    299:        }
                    300: |      non_empty_expression_list ',' expression {
                    301:                emitop(POP);
                    302:        }
                    303: ;
                    304: 
                    305: goto:
                    306:        /* empty */ {
                    307:                emitop(BRALW);
                    308:                $$ = emitzap;
                    309:        }
                    310: ;
                    311: 
                    312: save_loc:
                    313:        /* empty */ {
                    314:                $$ = loc;
                    315:        }
                    316: ;
                    317: 
                    318: save_break:
                    319:        /* empty */ {
                    320:                $$ = breakloc;
                    321:                breakloc = loc;
                    322:        }
                    323: ;
                    324: 
                    325: save_continue:
                    326:        /* empty */ {
                    327:                $$ = contloc;
                    328:                contloc = loc;
                    329:        }
                    330: ;
                    331: 
                    332: /*
                    333:  *     Function definition.
                    334:  */
                    335: 
                    336: definition:
                    337:        definition_header '(' parameter_list ')'                /* $1 */
                    338:                optional_nl '{' '\n'                            /* $5 */
                    339:                optional_auto statement_list '}'                /* $8 */
                    340: ;
                    341: 
                    342: definition_header:
                    343:        DEFINE IDENTIFIER {
                    344:                if (chkfunc($2)) {
                    345:                        retfrom = $2;
                    346:                } else {
                    347:                        YYERROR;
                    348:                }
                    349:        }
                    350: ;
                    351: 
                    352: parameter_list:
                    353:        /* empty */
                    354: |      non_empty_local_list {
                    355:                pardvec = dvec;
                    356:                lpardvec = ldvec;
                    357:                locaddr(pardvec, lpardvec, 0);
                    358:                dvec = NULL;
                    359:                ldvec = 0;
                    360:        }
                    361: ;
                    362: 
                    363: optional_auto:
                    364:        /* empty */
                    365: |      AUTO non_empty_local_list end_of_statement {
                    366:                autdvec = dvec;
                    367:                lautdvec = ldvec;
                    368:                locaddr(autdvec, lautdvec, lpardvec);
                    369:                dvec = NULL;
                    370:                ldvec = 0;
                    371:        }
                    372: ;
                    373: 
                    374: non_empty_local_list:
                    375:        local {
                    376:                dvec = (dicent **)mpalc(ldvec * sizeof (*dvec));
                    377:                dvec += ldvec;
                    378:                *--dvec = $1;
                    379:        }
                    380: |      local ',' non_empty_local_list {
                    381:                *--dvec = $1;
                    382:        }
                    383: ;
                    384: 
                    385: local:
                    386:        IDENTIFIER {
                    387:                if ($1->localt != UNDEFINED) {
                    388:                        gerror("Attempt to redeclare %s", $1->word);
                    389:                        YYERROR;
                    390:                }
                    391:                $1->localt = SCALAR;
                    392:                ++ldvec;
                    393:                /* $$ = $1 */
                    394:        }
                    395: |      IDENTIFIER '[' ']' {
                    396:                if ($1->localt != UNDEFINED) {
                    397:                        gerror("Attempt to redeclare %s", $1->word);
                    398:                        YYERROR;
                    399:                }
                    400:                $1->localt = ARRAY;
                    401:                ++ldvec;
                    402:                /* $$ = $1 */
                    403:        }
                    404: ;
                    405: 
                    406: optional_nl:
                    407:        /* empty */
                    408: |      '\n'
                    409: ;
                    410: 
                    411: /*
                    412:  *     Expressions.
                    413:  */
                    414: 
                    415: expression:
                    416:        assignment_expression
                    417: |      non_assignment_expression
                    418: ;
                    419: 
                    420: assignment_expression:
                    421:        l_value '=' expression {
                    422:                emitop(STORE);
                    423:        }
                    424: |      l_value add_r_value assignment_op expression {
                    425:                emitop($3);
                    426:                emitop(STORE);
                    427:        }
                    428: |      special_store '=' expression {
                    429:                emitop($1);
                    430:        }
                    431: |      special_load assignment_op expression {
                    432:                emitop($2);
                    433:                emitop($1);
                    434:        }
                    435: ;
                    436: 
                    437: non_assignment_expression:
                    438:        NUMBER {
                    439:                emitop(PLISC);
                    440:                emitnum($1);
                    441:                emitop(LOAD);
                    442:        }
                    443: |      l_value {
                    444:                emitop(LOAD);
                    445:        }
                    446: |      special_load
                    447: |      IDENTIFIER '(' argument_list ')' {
                    448:                if (chkfunc($1)) {
                    449:                        emitop(CALL);
                    450:                        emitid($1);
                    451:                        emitcnt($3);
                    452:                } else {
                    453:                        YYERROR;
                    454:                }
                    455:        }
                    456: |      INCR l_value {
                    457:                emitop(PRVAL);
                    458:                emitop(INC);
                    459:                emitop(STORE);
                    460:        }
                    461: |      INCR special_load {
                    462:                emitop(INC);
                    463:                emitop($2);
                    464:        }
                    465: |      DECR l_value {
                    466:                emitop(PRVAL);
                    467:                emitop(DEC);
                    468:                emitop(STORE);
                    469:        }
                    470: |      DECR special_load {
                    471:                emitop(DEC);
                    472:                emitop($2);
                    473:        }
                    474: |      l_value INCR {
                    475:                emitop(PRVAL);
                    476:                emitop(INC);
                    477:                emitop(STORE);
                    478:                emitop(DEC);
                    479:        }
                    480: |      special_load INCR {
                    481:                emitop(INC);
                    482:                emitop($1);
                    483:                emitop(DEC);
                    484:        }
                    485: |      l_value DECR {
                    486:                emitop(PRVAL);
                    487:                emitop(DEC);
                    488:                emitop(STORE);
                    489:                emitop(INC);
                    490:        }
                    491: |      special_load DECR {
                    492:                emitop(DEC);
                    493:                emitop($1);
                    494:                emitop(INC);
                    495:        }
                    496: |      '-' non_assignment_expression   %prec UMINUS {
                    497:                emitop(NEG);
                    498:        }
                    499: |      non_assignment_expression '^' non_assignment_expression {
                    500:                emitop(EXP);
                    501:        }
                    502: |      non_assignment_expression '*' non_assignment_expression {
                    503:                emitop(MUL);
                    504:        }
                    505: |      non_assignment_expression '/' non_assignment_expression {
                    506:                emitop(DIV);
                    507:        }
                    508: |      non_assignment_expression '%' non_assignment_expression {
                    509:                emitop(REM);
                    510:        }
                    511: |      non_assignment_expression '+' non_assignment_expression {
                    512:                emitop(ADD);
                    513:        }
                    514: |      non_assignment_expression '-' non_assignment_expression {
                    515:                emitop(SUB);
                    516:        }
                    517: |      '(' expression ')'
                    518: |      function_like_primitive '(' expression ')' {
                    519:                emitop($1);
                    520:        }
                    521: ;
                    522: 
                    523: l_value:
                    524:        IDENTIFIER {
                    525:                if (chktype($1, SCALAR))
                    526:                        sload($1);
                    527:                else {
                    528:                        YYERROR;
                    529:                }
                    530:        }
                    531: |      IDENTIFIER '[' expression ']' {
                    532:                if (chktype($1, ARRAY))
                    533:                        aeload($1);
                    534:                else {
                    535:                        YYERROR;
                    536:                }
                    537:        }
                    538: |      DOT {
                    539:                emitop(PGLSC);
                    540:                emitnum(&dot);
                    541:        }
                    542: ;
                    543: 
                    544: argument:
                    545:        expression
                    546: |      IDENTIFIER '[' ']' {
                    547:                if (chktype($1, ARRAY))
                    548:                        arload($1);
                    549:                else {
                    550:                        YYERROR;
                    551:                }
                    552:        }
                    553: ;
                    554: 
                    555: argument_list:
                    556:        /* empty */ {
                    557:                $$ = 0;
                    558:        }
                    559: |      non_empty_argument_list
                    560:                /* $$ = $1 */
                    561: ;
                    562: 
                    563: non_empty_argument_list:
                    564:        argument {
                    565:                $$ = 1;
                    566:        }
                    567: |      non_empty_argument_list ',' argument {
                    568:                $$ = $1 + 1;
                    569:        }
                    570: ;
                    571: 
                    572: add_r_value:
                    573:        /* empty */ {
                    574:                emitop(PRVAL);
                    575:        }
                    576: ;
                    577: 
                    578: special_store:
                    579:        IBASE {
                    580:                $$ = SIBASE;
                    581:        }
                    582: |      OBASE {
                    583:                $$ = SOBASE;
                    584:        }
                    585: |      SCALE_ {
                    586:                $$ = SSCALE;
                    587:        }
                    588: ;
                    589: 
                    590: special_load:
                    591:        IBASE {
                    592:                emitop(LIBASE);
                    593:                $$ = SIBASE;
                    594:        }
                    595: |      OBASE {
                    596:                emitop(LOBASE);
                    597:                $$ = SOBASE;
                    598:        }
                    599: |      SCALE_ {
                    600:                emitop(LSCALE);
                    601:                $$ = SSCALE;
                    602:        }
                    603: ;
                    604: 
                    605: assignment_op:
                    606:        ADDAB {
                    607:                $$ = ADD;
                    608:        }
                    609: |      SUBAB {
                    610:                $$ = SUB;
                    611:        }
                    612: |      MULAB {
                    613:                $$ = MUL;
                    614:        }
                    615: |      DIVAB {
                    616:                $$ = DIV;
                    617:        }
                    618: |      REMAB {
                    619:                $$ = REM;
                    620:        }
                    621: |      EXPAB {
                    622:                $$ = EXP;
                    623:        }
                    624: ;
                    625: 
                    626: function_like_primitive:
                    627:        SQRT_ {
                    628:                $$ = SQRT;
                    629:        }
                    630: |      LENGTH_ {
                    631:                $$ = LENGTH;
                    632:        }
                    633: |      SCALE_ {
                    634:                $$ = SCALE;
                    635:        }
                    636: ;
                    637: 
                    638: /*
                    639:  *     Conditionals.
                    640:  */
                    641: 
                    642: jump_true:
                    643:        /* empty */ {
                    644:                emitop(BRALW);
                    645:                $$ = emitzap;
                    646:        }
                    647: |      non_assignment_expression relational non_assignment_expression {
                    648:                emitop($2);
                    649:                $$ = emitzap;
                    650:        }
                    651: ;
                    652: 
                    653: jump_false:
                    654:        /* empty */ {
                    655:                emitop(BRNEV);
                    656:                $$ = emitzap;
                    657:        }
                    658: |      non_assignment_expression relational non_assignment_expression {
                    659:                emitop(negate($2));
                    660:                $$ = emitzap;
                    661:        }
                    662: ;
                    663: 
                    664: relational:
                    665:        LTP {
                    666:                $$ = BRLT;
                    667:        }
                    668: |      LEP {
                    669:                $$ = BRLE;
                    670:        }
                    671: |      EQP {
                    672:                $$ = BREQ;
                    673:        }
                    674: |      GEP {
                    675:                $$ = BRGE;
                    676:        }
                    677: |      GTP {
                    678:                $$ = BRGT;
                    679:        }
                    680: |      NEP {
                    681:                $$ = BRNE;
                    682:        }
                    683: ;
                    684: 
                    685: %%
                    686: 
                    687: /*
                    688:  *     Yyerror is the error routine called on a syntax error by
                    689:  *     yyparse.
                    690:  */
                    691: 
                    692: yyerror(m)
                    693: char *m;
                    694: {
                    695:        register struct yytname *ptr;
                    696: 
                    697:        for (ptr = yytnames; ptr->tn_name != NULL; ++ptr)
                    698:                if (ptr->tn_val == yychar)
                    699:                        return gerror("%s at %s", m, ptr->tn_name);
                    700:        return gerror("%s", m);
                    701: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.