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

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

E-mail: