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

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

E-mail: