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

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

E-mail: