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

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

E-mail: