Annotation of parser3/src/main/compile.y, revision 1.8

1.1       paf         1: %{
1.3       paf         2: #define YYSTYPE Array/*<op>*/ *
1.1       paf         3: #define YYPARSE_PARAM pc
                      4: #define YYLEX_PARAM pc
                      5: #define YYDEBUG 1
                      6: #define YYERROR_VERBOSE
1.4       paf         7: #define yyerror(msg) real_yyerror((parse_control *)pc, msg)
1.1       paf         8: #define YYPRINT(file, type, value)   yyprint (file, type, value)
                      9: 
                     10: #include <stdio.h>
                     11: #include <string.h>
                     12: #include <stdlib.h>
                     13: 
                     14: #include "compile_tools.h"
1.8     ! paf        15: #include "pa_value.h"
1.1       paf        16: 
1.4       paf        17: int real_yyerror (parse_control *pc, char *s);
1.1       paf        18: static void yyprint (FILE *file, int type, YYSTYPE value);
                     19: int yylex(YYSTYPE *lvalp, void *pc);
                     20: 
                     21: 
1.8     ! paf        22: // local convinient inplace typecast & var
1.4       paf        23: #define PC ((parse_control *)pc)
1.8     ! paf        24: #define pool *PC->pool
1.1       paf        25: %}
                     26: 
                     27: %pure_parser
                     28: 
1.4       paf        29: %token END_OF_NAME
                     30: %token STRING
1.1       paf        31: %token BOGUS
                     32: 
                     33: %%
                     34: 
1.8     ! paf        35: result: input { 
        !            36:        String& name_main=*new(pool) String(pool);
        !            37:        name_main.APPEND_CONST("main");
        !            38:        Array& param_names=*new(pool) Array(pool);
        !            39:        Array& local_names=*new(pool) Array(pool);
        !            40:        Method *method=new(pool) Method(pool, name_main, param_names, local_names, *$1);
        !            41:        *PC->methods+=method;
        !            42: };
1.1       paf        43: input: empty | codes;
                     44: 
                     45: /* codes */
                     46: 
                     47: codes: code | codes code { 
                     48:        $$=$1; 
1.3       paf        49:        P($$,$2);
1.1       paf        50: };
                     51: code: write_str_literal | action;
                     52: action: get | put | with | call;
                     53: 
                     54: /* get */
                     55: 
                     56: get: '$' any_name {
                     57:        $$=$2; /* stack: resulting value */
1.3       paf        58:        OP($$,OP_WRITE); /* value=pop; write(value) */
1.1       paf        59: };
                     60: 
1.4       paf        61: any_name: name_without_curly_rdive END_OF_NAME | name_in_curly_rdive;
1.1       paf        62: 
                     63: name_in_curly_rdive: '{' name_without_curly_rdive '}' { $$=$2 };
                     64: name_without_curly_rdive: name_rdive {
                     65:        /* 
                     66:        TODO: подсмотреть в $1, и если там в первом элементе первая буква ":"
                     67:                то выкинуть её и делать не OP_WITH_READ, а WITH_ROOT
                     68:        TODO: подсмотреть в $1, и если там первым элементом self,
                     69:                то выкинуть его и делать не OP_WITH_READ, а WITH_SELF
                     70:        */ 
1.8     ! paf        71:        $$=N(pool); OP($$, OP_WITH_READ); /* stack: starting context */
1.3       paf        72:        P($$,$1); /* diving code; stack: current context */
1.1       paf        73: };
1.3       paf        74: name_rdive: name_advance2 | name_path name_advance2 { $$=$1; P($$,$2) }
1.1       paf        75: 
                     76: /* put */
                     77: 
                     78: put: '$' name_expr_dive '(' constructor_value ')' {
                     79: /*
                     80:        TODO: подсмотреть в $3, и если там в первом элементе первая буква ":"
                     81:                то выкинуть её и делать не OP_WITH_OP_WRITE, а WITH_ROOT
                     82:        TODO: подсмотреть в $3, и если там первым элементом self,
                     83:                то выкинуть его и делать не OP_WITH_OP_WRITE, а WITH_SELF
                     84:                если ничего не осталось - $self(xxx)
                     85:                        обругать
                     86: */
1.8     ! paf        87:        $$=N(pool); 
1.3       paf        88:        OP($$, OP_WITH_WRITE); /* stack: starting context */
                     89:        P($$,$2); /* diving code; stack: context,name */
                     90:        P($$,$4); /* stack: context,name,constructor_value */
                     91:        OP($$,OP_CONSTRUCT); /* value=pop; name=pop; context=pop; construct(context,name,value) */
1.1       paf        92: };
                     93: constructor_value: 
                     94:        constructor_one_param_value
                     95: |      constructor_two_params_value /* $var(=;2*2) $var(%d;2*2) $var(+;1) */
                     96: ;
                     97: constructor_one_param_value: 
                     98:        empty_value /* optimized $var() case */
1.4       paf        99: |      STRING /* optimized $var(STRING) case */
1.1       paf       100: |      complex_constructor_param_value /* $var(something complex) */
                    101: ;
                    102: empty_value: empty;
                    103: complex_constructor_param_value: complex_constructor_param_body {
1.8     ! paf       104:        $$=N(pool); 
1.3       paf       105:        OP($$, OP_CREATE_EWPOOL); /* stack: empty write context */
                    106:        P($$,$1); /* some codes to that context */
                    107:        OP($$,OP_REDUCE_EWPOOL); /* context=pop; stack: context.value() */
1.1       paf       108: };
                    109: complex_constructor_param_body:
                    110:        codes__excluding_sole_str_literal
                    111: |      codes__str__followed_by__excluding_sole_str_literal
                    112: ;
1.4       paf       113: constructor_two_params_value: STRING ';' constructor_one_param_value {
1.7       paf       114:        char *operator_or_fmt=LA2S($1)->cstr();
1.8     ! paf       115:        $$=N(pool);
1.3       paf       116:        P($$, $1);/* stack: ncontext name operator_or_fmt */
                    117:        P($$, $3); /* stack: ncontext name operator_or_fmt expr */
1.1       paf       118:        switch(operator_or_fmt[0]) {
                    119:        case '=': case '%':
1.3       paf       120:                OP($$, OP_EXPRESSION_EVAL);
1.1       paf       121:                break;
                    122:        case '+': case '-': case '*': case '/':
1.3       paf       123:                OP($$, OP_MODIFY_EVAL);
1.1       paf       124:                break;
                    125:        default:
1.6       paf       126:                strcpy(PC->error, "invalid modification operator");
                    127:                YYERROR;
1.1       paf       128:        }
                    129:        /* stack: ncontext name value */
                    130: };
                    131: 
                    132: 
                    133: /* call */
                    134: 
1.4       paf       135: call: '^' name_expr_dive store_params END_OF_NAME { /* ^field.$method{vasya} */
1.1       paf       136: /*
                    137:        TODO: подсмотреть в $3, и если там в первом элементе первая буква ":"
                    138:                то выкинуть её и делать не OP_WITH_READ, а WITH_ROOT
                    139:        TODO: подсмотреть в $3, и если там первым элементом self,
                    140:                то выкинуть его и делать не OP_WITH_READ, а WITH_SELF
                    141:        TODO:
                    142:                если первым в $3 идёт result
                    143:                то
                    144:                        выкинуть его
                    145:                        если там ещё что-то осталось,
                    146:                        то
                    147:                                не OP_WITH_READ, а WITH_RESULT
                    148:                        иначе  // ^result(value)
                    149:                                обругать безобразие
                    150: */
1.8     ! paf       151:        $$=N(pool); 
1.3       paf       152:        OP($$, OP_WITH_READ); /* stack: starting context */
                    153:        P($$,$2); /* diving code; stack: context,method_name */
                    154:        OP($$,OP_GET_METHOD_FRAME); /* stack: context,method_frame */
                    155:        P($$,$3); /* filling method_frame.store_params */
                    156:        OP($$,OP_CALL); /* method_frame=pop; ncontext=pop; call(ncontext,method_frame) */
1.1       paf       157: };
                    158: 
1.3       paf       159: store_params: store_param | store_params store_param { $$=$1; P($$,$2) };
1.1       paf       160: store_param: store_round_param | store_curly_param;
                    161: store_round_param: '(' store_param_parts ')' {$$=$2};
1.3       paf       162: store_param_parts: store_param_part | store_param_parts ';' store_param_part { $$=$1; P($$,$3) };
1.1       paf       163: store_param_part: constructor_one_param_value {
                    164:        $$=$1;
1.3       paf       165:        OP($$,OP_STORE_PARAM);
1.1       paf       166: }
                    167: store_curly_param: '{' input '}' {
1.8     ! paf       168:        $$=N(pool); 
1.3       paf       169:        OP($$, OP_CODE_ARRAY);
                    170:        AA($$,$2);
                    171:        OP($$,OP_CREATE_JUNCTION);
                    172:        OP($$,OP_STORE_PARAM);
1.1       paf       173: };
                    174: 
                    175: /* name */
                    176: 
1.3       paf       177: name_expr_dive: name_expr_value | name_path name_expr_value { $$=$1; P($$,$2) };
1.1       paf       178: 
1.3       paf       179: name_path: name_step | name_path name_step { $$=$1; P($$,$2) };
1.1       paf       180: name_step: name_advance1 '.';
                    181: name_advance1: name_expr_value {
                    182:        /* stack: context */
                    183:        $$=$1; /* stack: context,name */
1.3       paf       184:        OP($$,OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */
1.1       paf       185: };
                    186: name_advance2: name_expr_value {
                    187:        /* stack: context */
                    188:        $$=$1; /* stack: context,name */
1.3       paf       189:        OP($$,OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */
1.1       paf       190: }
1.4       paf       191: |      STRING BOGUS
1.1       paf       192: ;
                    193: name_expr_value: 
1.4       paf       194:        STRING /* subname_is_const */
1.1       paf       195: |      name_expr_subvar_value /* $subname_is_var_value */
                    196: |      name_expr_with_subvar_value /* xxx$part_of_subname_is_var_value[$...] */
                    197: ;
                    198: name_expr_subvar_value: '$' subvar_ref_name_rdive {
                    199:        $$=$2;
1.3       paf       200:        OP($$,OP_GET_ELEMENT);
1.1       paf       201: };
1.4       paf       202: name_expr_with_subvar_value: STRING subvar_get_writes {
1.8     ! paf       203:        $$=N(pool); 
1.3       paf       204:        OP($$, OP_CREATE_EWPOOL);
                    205:        P($$,$1);
                    206:        OP($$,OP_WRITE);
                    207:        P($$,$2);
                    208:        OP($$,OP_REDUCE_EWPOOL);
1.1       paf       209: };
1.4       paf       210: subvar_ref_name_rdive: STRING {
1.1       paf       211: /*
                    212:        TODO: подсмотреть в $1, и если там в первом элементе первая буква ":"
                    213:                то выкинуть её и делать не OP_WITH_READ, а WITH_ROOT
                    214: */
1.8     ! paf       215:        $$=N(pool); OP($$, OP_WITH_READ);
1.3       paf       216:        P($$,$1);
1.1       paf       217: };
1.3       paf       218: subvar_get_writes: subvar__get_write | subvar_get_writes subvar__get_write { $$=$1; P($$,$2) };
1.1       paf       219: subvar__get_write: '$' subvar_ref_name_rdive {
                    220:        $$=$2;
1.3       paf       221:        OP($$,OP_GET_ELEMENT__WRITE);
1.1       paf       222: };
                    223: 
                    224: 
                    225: /* with */
                    226: 
                    227: with: '$' name_without_curly_rdive '{' codes '}' {
                    228:        $$=$2;
1.3       paf       229:        OP($$,OP_CREATE_RWPOOL);
                    230:        P($$,$4);
                    231:        OP($$,OP_REDUCE_RWPOOL);
                    232:        OP($$,OP_WRITE);
1.1       paf       233: };
                    234: 
                    235: /* codes_in_brackets */
                    236: 
                    237: codes__str__followed_by__excluding_sole_str_literal:
                    238:        write_str_literal codes__excluding_sole_str_literal {
                    239:                $$=$1;
1.3       paf       240:                P($$,$2);
1.1       paf       241: }
                    242: ;
                    243: codes__excluding_sole_str_literal:
                    244:        action
                    245: |      codes__excluding_sole_str_literal write_str_literal {
                    246:                $$=$1;
1.3       paf       247:                P($$,$2);
1.1       paf       248: }
                    249: ;
1.4       paf       250: write_str_literal: STRING {
1.1       paf       251:        $$=$1;
1.3       paf       252:        OP($$,OP_WRITE);
1.1       paf       253: };
                    254: 
                    255: /* */
                    256: 
1.8     ! paf       257: empty: /* empty */ { $$=N(pool) };
1.1       paf       258: 
                    259: %%
                    260: 
                    261: /*
                    262:        000$111(2222)00 
                    263:                000$111{3333}00
                    264:        $,^: push, =0
                    265:        1:( { break=pop
                    266:        2:( )  pop
                    267:        3:{ }  pop
                    268: 
                    269:        000^111(2222)4444{33333}4000
                    270:        $,^: push, =0
                    271:        1:( { break=pop
                    272:        2:( )=4
                    273:        3:{ }=4
                    274:                4:[^({]=pop
                    275: */
                    276: 
                    277: int yylex(YYSTYPE *lvalp, void *pc) {
                    278:        #define lexical_brackets_nestage PC->brackets_nestages[PC->sp]
                    279: 
                    280:     register int c;
                    281:     int result;
                    282:        char *start;
                    283:        int start_line;
                    284:        
                    285:        if(PC->pending_state) {
                    286:                result=PC->pending_state;
                    287:                PC->pending_state=0;
                    288:                return result;
                    289:        }
                    290:        
                    291:        start=PC->source;
                    292:        start_line=PC->line;
                    293:        while(1) {
                    294:                c=*PC->source++;
                    295: 
1.4       paf       296:                if(c=='\n') {
1.1       paf       297:                        PC->line++;
1.8     ! paf       298:                        PC->col=0;
1.4       paf       299:                }
                    300:                        PC->col++;
1.1       paf       301: 
                    302:                /* escaping: ^^ ^$ ^; ^) ^} ^( ^{ */
                    303:                if(c=='^') {
                    304:                        char pending_c=*PC->source;
                    305: 
                    306:                        if(pending_c == '^' || pending_c == '$' || pending_c == ';' ||
                    307:                                pending_c == '(' || pending_c == ')' ||
                    308:                                pending_c == '{' || pending_c == '}') {
                    309:                                /* append piece till ^ */
1.3       paf       310:                                PC->string->APPEND(start, PC->source-start -1/*^*/, PC->file, start_line);
1.1       paf       311:                                /* reset piece 'start' position & line */
                    312:                                start=PC->source+1/*^*/;
                    313:                                start_line=PC->line;
                    314:                                /* skip over ^ and _ */
                    315:                                PC->source+=2;
                    316:                                /* skip analysis = forced literal */
                    317:                                continue;
                    318:                        }
                    319:                }
                    320:                switch(PC->ls) {
                    321:                case LS_USER:
                    322:                        if(c=='$') {
                    323:                                push_LS(PC);  PC->ls=LS_VAR_NAME_SIMPLE;
                    324:                                result=c;
                    325:                                goto break2;
                    326:                        }
                    327:                        if(c=='^') {
                    328:                                push_LS(PC);  PC->ls=LS_METHOD_NAME;
                    329:                                result=c;
                    330:                                goto break2;
                    331:                        }
                    332:                        break;
                    333: 
                    334:                /* VAR */
                    335:                case LS_VAR_NAME_SIMPLE:
                    336:                        if(c==0 || 
                    337:                                c==' '|| c=='\t' || c=='\n' || 
                    338:                                c==')' || c=='}') {
                    339:                                pop_LS(PC);
1.4       paf       340:                                PC->source--;   PC->col--;
                    341:                                result=END_OF_NAME;
1.1       paf       342:                                goto break2;
                    343:                        }
1.4       paf       344:                        if(PC->source==start && c=='{') { /* ${name}, no need of END_OF_NAME, switching LS */
1.1       paf       345:                                PC->ls=LS_VAR_NAME_CURLY; 
                    346:                                result=c;
                    347:                                goto break2;
                    348:                        }
                    349:                        if(c=='(') {
                    350:                                PC->ls=LS_VAR_ROUND;
                    351:                                lexical_brackets_nestage=1;
                    352:                                result=c;
                    353:                                goto break2;
                    354:                        }
                    355:                        if(c=='{') {
                    356:                                PC->ls=LS_VAR_CURLY;
                    357:                                lexical_brackets_nestage=1;
                    358:                                result=c;
                    359:                                goto break2;
                    360:                        }
                    361:                        if(c=='.'/* name part delim */ || c=='$'/* name part subvar */) {
                    362:                                result=c;
                    363:                                goto break2;
                    364:                        }
                    365:                        break;
                    366:                case LS_VAR_NAME_CURLY:
                    367:                        if(c=='}') {  /* ${name} finished, restoring LS */
                    368:                                pop_LS(PC);
                    369:                                result=c;
                    370:                                goto break2;
                    371:                        }
                    372:                        if(c=='.'/* name part delim */ || c=='$'/*name part subvar*/) {
                    373:                                result=c;
                    374:                                goto break2;
                    375:                        }
                    376:                        break;
                    377:                case LS_VAR_ROUND:
                    378:                        if(c=='$') {
                    379:                                push_LS(PC);  PC->ls=LS_VAR_NAME_SIMPLE;
                    380:                                result=c;
                    381:                                goto break2;
                    382:                        }
                    383:                        if(c=='^') {
                    384:                                push_LS(PC);  PC->ls=LS_METHOD_NAME;
                    385:                                result=c;
                    386:                                goto break2;
                    387:                        }
                    388:                        if(c==')') {
                    389:                                if(--lexical_brackets_nestage==0) {
                    390:                                        pop_LS(PC);
                    391:                                        result=c;
                    392:                                        goto break2;
                    393:                                }
                    394:                        }
                    395:                        if(c==';'/* operator_or_fmt;value delim */) {
                    396:                                result=c;
                    397:                                goto break2;
                    398:                        }
                    399:                        if(c=='(')
                    400:                                lexical_brackets_nestage++;
                    401:                        break;
                    402:                case LS_VAR_CURLY:
                    403:                        if(c=='$') {
                    404:                                push_LS(PC);  PC->ls=LS_VAR_NAME_SIMPLE;
                    405:                                result=c;
                    406:                                goto break2;
                    407:                        }
                    408:                        if(c=='^') {
                    409:                                push_LS(PC);  PC->ls=LS_METHOD_NAME;
                    410:                                result=c;
                    411:                                goto break2;
                    412:                        }
                    413:                        if(c=='}')
                    414:                                if(--lexical_brackets_nestage==0) {
                    415:                                        pop_LS(PC);
                    416:                                        result=c;
                    417:                                        goto break2;
                    418:                                }
                    419:                        if(c=='{')
                    420:                                lexical_brackets_nestage++;
                    421:                        break;
                    422: 
                    423:                /* METHOD */
                    424:                case LS_METHOD_NAME:
                    425:                        if(c=='(') {
                    426:                                PC->ls=LS_METHOD_ROUND;
                    427:                                lexical_brackets_nestage=1;
                    428:                                result=c;
                    429:                                goto break2;
                    430:                        }
                    431:                        if(c=='{') {
                    432:                                PC->ls=LS_METHOD_CURLY;
                    433:                                lexical_brackets_nestage=1;
                    434:                                result=c;
                    435:                                goto break2;
                    436:                        }
                    437:                        if(c=='.'/* name part delim */ || c=='$'/* name part subvar */) {
                    438:                                result=c;
                    439:                                goto break2;
                    440:                        }
                    441:                        break;
                    442:                case LS_METHOD_ROUND:
                    443:                        if(c=='$') {
                    444:                                push_LS(PC);  PC->ls=LS_VAR_NAME_SIMPLE;
                    445:                                result=c;
                    446:                                goto break2;
                    447:                        }
                    448:                        if(c=='^') {
                    449:                                push_LS(PC);  PC->ls=LS_METHOD_NAME;
                    450:                                result=c;
                    451:                                goto break2;
                    452:                        }
                    453:                        if(c==';'/* param delim */) {
                    454:                                result=c;
                    455:                                goto break2;
                    456:                        }
                    457:                        if(c==')')
                    458:                                if(--lexical_brackets_nestage==0) {
                    459:                                        PC->ls=LS_METHOD_AFTER;
                    460:                                        result=c;
                    461:                                        goto break2;
                    462:                                }
                    463:                        if(c=='(')
                    464:                                lexical_brackets_nestage++;
                    465:                        break;
                    466:                case LS_METHOD_CURLY:
                    467:                        if(c=='$') {
                    468:                                push_LS(PC);  PC->ls=LS_VAR_NAME_SIMPLE;
                    469:                                result=c;
                    470:                                goto break2;
                    471:                        }
                    472:                        if(c=='^') {
                    473:                                push_LS(PC);  PC->ls=LS_METHOD_NAME;
                    474:                                result=c;
                    475:                                goto break2;
                    476:                        }
                    477:                        if(c=='}')
                    478:                                if(--lexical_brackets_nestage==0) {
                    479:                                        PC->ls=LS_METHOD_AFTER;
                    480:                                        result=c;
                    481:                                        goto break2;
                    482:                                }
                    483:                        if(c=='{')
                    484:                                lexical_brackets_nestage++;
                    485:                        break;
                    486:                case LS_METHOD_AFTER:
                    487:                        if(c=='(') {/* )( }( */
                    488:                                PC->ls=LS_METHOD_ROUND;
                    489:                                lexical_brackets_nestage=1;
                    490:                                result=c;
                    491:                                goto break2;
                    492:                        }                                          
                    493:                        if(c=='{') {/* ){ }{ */
                    494:                                PC->ls=LS_METHOD_CURLY;
                    495:                                lexical_brackets_nestage=1;
                    496:                                result=c;
                    497:                                goto break2;
                    498:                        }                                          
                    499:                        pop_LS(PC);
1.4       paf       500:                        PC->source--;  PC->col--;
                    501:                        result=END_OF_NAME;
1.1       paf       502:                        goto break2;
                    503:                }
                    504:                if (c == 0) {
                    505:                        result=-1;
1.4       paf       506:                        PC->source--;  PC->col--;
1.1       paf       507:                        break;
                    508:                }
                    509:        }
                    510: 
                    511: break2:
1.5       paf       512:        if(PC->source-1<=start)
1.1       paf       513:                return result;
                    514:        else {
                    515:                PC->pending_state=result;
                    516:                /* append last piece */
1.4       paf       517:                PC->string->APPEND(start, PC->source-start-1, PC->file, start_line/*, start_col*/);
                    518:                /* create STRING value: array of OP_STRING+string */
1.1       paf       519:                *lvalp=L(PC->string);
                    520:                /* new pieces storage */
1.8     ! paf       521:                PC->string=new(pool) String(pool);
1.1       paf       522:                /* go */
1.4       paf       523:                return STRING;
1.1       paf       524:        }
                    525: }
                    526: 
1.4       paf       527: int real_yyerror (parse_control *pc, char *s)  /* Called by yyparse on error */
1.1       paf       528:      {
1.4       paf       529:        fprintf (stderr, "[%s]\n", s);
1.6       paf       530: 
                    531:           s[MAX_STRING-1]=0; strcpy(pc->error, s);
1.1       paf       532:           return 1;
                    533:      }
                    534: 
                    535: static void
                    536:      yyprint (
                    537:           FILE *file,
                    538:           int type,
                    539:           YYSTYPE value)
                    540:      {
1.4       paf       541:        if (type == STRING)
1.3       paf       542:          fprintf (file, " \"%s\"", LA2S(value)->cstr());
1.1       paf       543:      }
                    544: 

E-mail: