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

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

E-mail: