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

1.24      paf         1: /*
1.55    ! paf         2:   $Id: compile.y,v 1.54 2001/03/06 14:28:35 paf Exp $
1.24      paf         3: */
                      4: 
1.1       paf         5: %{
1.9       paf         6: #define YYSTYPE  Array/*<op>*/ *
                      7: #define YYPARSE_PARAM  pc
                      8: #define YYLEX_PARAM  pc
                      9: #define YYDEBUG  1
1.1       paf        10: #define YYERROR_VERBOSE
1.9       paf        11: #define yyerror(msg)  real_yyerror((parse_control *)pc, msg)
                     12: #define YYPRINT(file, type, value)  yyprint(file, type, value)
1.1       paf        13: 
                     14: #include <stdio.h>
                     15: #include <string.h>
                     16: #include <stdlib.h>
                     17: 
                     18: #include "compile_tools.h"
1.8       paf        19: #include "pa_value.h"
1.12      paf        20: #include "pa_request.h"
1.39      paf        21: #include "pa_vobject.h"
1.52      paf        22: #include "pa_vdouble.h"
1.39      paf        23: 
                     24: #define SELF_NAME "self"
                     25: #define USES_NAME "USES"
1.1       paf        26: 
1.9       paf        27: int real_yyerror(parse_control *pc, char *s);
                     28: static void yyprint(FILE *file, int type, YYSTYPE value);
1.1       paf        29: int yylex(YYSTYPE *lvalp, void *pc);
                     30: 
                     31: 
1.8       paf        32: // local convinient inplace typecast & var
1.9       paf        33: #define PC  ((parse_control *)pc)
1.25      paf        34: #define POOL  *PC->pool
                     35: #undef NEW
                     36: #define NEW new(POOL)
1.1       paf        37: %}
                     38: 
                     39: %pure_parser
                     40: 
1.13      paf        41: %token EON
1.4       paf        42: %token STRING
1.1       paf        43: %token BOGUS
1.55    ! paf        44: 
        !            45: %left '-' '+'
        !            46: %left '*' '/'
        !            47: %left NEG     /* negation--unary minus */
        !            48: /*%right '^'    /* exponentiation        */
1.1       paf        49: 
                     50: %%
                     51: 
1.10      paf        52: all:
                     53:        one_big_piece {
1.25      paf        54:        String& name_main=*NEW String(POOL);
1.11      paf        55:        name_main.APPEND_CONST(MAIN_METHOD_NAME);
1.25      paf        56:        Array& param_names=*NEW Array(POOL);
                     57:        Array& local_names=*NEW Array(POOL);
1.34      paf        58:        Method& method=*NEW Method(POOL, name_main, param_names, local_names, *$1);
                     59:        PC->vclass->add_method(name_main, method);
1.10      paf        60: }
                     61: |      methods;
                     62: 
                     63: methods: method | methods method;
                     64: one_big_piece: maybe_codes;
                     65: 
1.34      paf        66: method: control_method | code_method;
                     67: 
                     68: control_method: '@' STRING '\n' 
                     69:                                control_strings {
1.38      paf        70:        String& name=*SLA2S($2);
1.34      paf        71:        YYSTYPE strings_code=$4;
1.37      paf        72:        if(strings_code->size()<1*2) {
                     73:                strcpy(PC->error, "@");
                     74:                strcat(PC->error, name.cstr());
                     75:                strcat(PC->error, " is empty");
                     76:                YYERROR;
                     77:        }
1.36      paf        78:        if(name==CLASS_NAME) {
1.34      paf        79:                if(strings_code->size()==1*2) 
1.38      paf        80:                        PC->vclass->set_name(*SLA2S(strings_code));
1.34      paf        81:                else {
                     82:                        strcpy(PC->error, "@"CLASS_NAME" must contain sole name");
                     83:                        YYERROR;
                     84:                }
                     85:        } else {
1.36      paf        86:                if(name==USES_NAME) {
1.34      paf        87:                        for(int i=0; i<strings_code->size(); i+=2) {
1.38      paf        88:                                String *file=SLA2S(strings_code, i);
1.35      paf        89:                                file->APPEND_CONST(".p");
                     90:                                PC->request->use(file->cstr(), 0);
1.34      paf        91:                        }
1.45      paf        92:                } else if(name==BASE_NAME) {
                     93:                        if(strings_code->size()==1*2) {
                     94:                                String& base_name=*SLA2S(strings_code);
                     95:                                VClass *base=static_cast<VClass *>(
                     96:                                        PC->request->classes().get(base_name));
                     97:                                if(!base) {
                     98:                                        strcpy(PC->error, base_name.cstr());
                     99:                                        strcat(PC->error, ": undefined class in @"BASE_NAME);
1.34      paf       100:                                        YYERROR;
                    101:                                }
1.45      paf       102:                                PC->vclass->set_base(*base);
                    103:                        } else {
                    104:                                strcpy(PC->error, "@"BASE_NAME" must contain sole name");
                    105:                                YYERROR;
1.34      paf       106:                        }
                    107:                } else {
1.36      paf       108:                        strcpy(PC->error, name.cstr());
1.34      paf       109:                        strcat(PC->error, ": invalid special name. valid names are "
1.45      paf       110:                                CLASS_NAME", "USES_NAME" and "BASE_NAME);
1.34      paf       111:                        YYERROR;
                    112:                }
                    113:        }
                    114: };
1.37      paf       115: control_strings: control_string | control_strings control_string { $$=$1; P($$, $2) };
                    116: control_string: maybe_string '\n';
                    117: maybe_string: empty | STRING;
1.34      paf       118: 
                    119: code_method: '@' STRING bracketed_maybe_strings maybe_bracketed_strings maybe_comment '\n' 
1.10      paf       120:                        maybe_codes {
1.38      paf       121:        const String *name=SLA2S($2);
1.10      paf       122: 
                    123:        YYSTYPE params_names_code=$3;
1.25      paf       124:        Array& params_names=*NEW Array(POOL);
1.10      paf       125:        for(int i=0; i<params_names_code->size(); i+=2)
1.38      paf       126:                params_names+=SLA2S(params_names_code, i);
1.10      paf       127: 
                    128:        YYSTYPE locals_names_code=$4;
1.25      paf       129:        Array& locals_names=*NEW Array(POOL);
1.10      paf       130:        for(int i=0; i<locals_names_code->size(); i+=2)
1.38      paf       131:                locals_names+=SLA2S(locals_names_code, i);
1.10      paf       132: 
1.34      paf       133:        Method& method=*NEW Method(POOL, *name, params_names, locals_names, *$7);
                    134:        PC->vclass->add_method(*name, method);
1.8       paf       135: };
1.10      paf       136: 
                    137: maybe_bracketed_strings: empty | bracketed_maybe_strings;
                    138: bracketed_maybe_strings: '[' maybe_strings ']' {$$=$2};
                    139: maybe_strings: empty | strings;
                    140: strings: STRING | strings ';' STRING { $$=$1; P($$, $3) };
                    141: 
                    142: maybe_comment: empty | STRING;
1.1       paf       143: 
                    144: /* codes */
                    145: 
1.10      paf       146: maybe_codes: empty | codes;
                    147: 
1.1       paf       148: codes: code | codes code { 
                    149:        $$=$1; 
1.9       paf       150:        P($$, $2);
1.1       paf       151: };
                    152: code: write_str_literal | action;
                    153: action: get | put | with | call;
                    154: 
                    155: /* get */
                    156: 
1.42      paf       157: get: '$' get_name {
1.1       paf       158:        $$=$2; /* stack: resulting value */
1.54      paf       159:        O($$, OP_WRITE); /* value=pop; write(value) */
1.1       paf       160: };
1.43      paf       161: get_name: name_without_curly_rdive EON | name_in_curly_rdive;
1.1       paf       162: name_in_curly_rdive: '{' name_without_curly_rdive '}' { $$=$2 };
1.44      paf       163: name_without_curly_rdive: 
                    164:        name_without_curly_rdive_read 
                    165: |      name_without_curly_rdive_root
                    166: |      name_without_curly_rdive_class;
1.19      paf       167: name_without_curly_rdive_read: name_without_curly_rdive_code {
1.25      paf       168:        $$=N(POOL); 
1.22      paf       169:        Array *diving_code=$1;
1.38      paf       170:        String *first_name=SLA2S(diving_code);
1.23      paf       171:        if(first_name && *first_name==SELF_NAME) {
1.54      paf       172:                O($$, OP_WITH_SELF); /* stack: starting context */
1.22      paf       173:                P($$, diving_code, 
                    174:                        /* skip over... */
                    175:                        diving_code->size()>2?3/*OP_+string+get_element*/:2/*OP_+string*/);
                    176:        } else {
1.54      paf       177:                O($$, OP_WITH_READ); /* stack: starting context */
1.22      paf       178:                P($$, diving_code);
                    179:        }
                    180:        /* diving code; stack: current context */
1.1       paf       181: };
1.19      paf       182: name_without_curly_rdive_root: ':' name_without_curly_rdive_code {
1.25      paf       183:        $$=N(POOL); 
1.54      paf       184:        O($$, OP_WITH_ROOT); /* stack: starting context */
1.19      paf       185:        P($$, $2); /* diving code; stack: current context */
                    186: };
1.44      paf       187: name_without_curly_rdive_class: class_prefix name_without_curly_rdive_code { $$=$1; P($$, $2) };
1.19      paf       188: name_without_curly_rdive_code: name_advance2 | name_path name_advance2 { $$=$1; P($$, $2) };
1.1       paf       189: 
                    190: /* put */
                    191: 
1.52      paf       192: put: '$' name_expr_wdive constructor_value {
1.20      paf       193:        $$=$2; /* stack: context,name */
1.52      paf       194:        P($$, $3); /* stack: context,name,constructor_value */
1.54      paf       195:        O($$, OP_CONSTRUCT); /* value=pop; name=pop; context=pop; construct(context,name,value) */
1.20      paf       196: };
1.44      paf       197: name_expr_wdive: 
                    198:        name_expr_wdive_write
                    199: |      name_expr_wdive_root
                    200: |      name_expr_wdive_class;
1.28      paf       201: name_expr_wdive_write: name_expr_dive_code {
1.44      paf       202:        $$=N(POOL);
1.23      paf       203:        Array *diving_code=$1;
1.38      paf       204:        String *first_name=SLA2S(diving_code);
1.23      paf       205:        if(first_name && *first_name==SELF_NAME) {
1.54      paf       206:                O($$, OP_WITH_SELF); /* stack: starting context */
1.23      paf       207:                P($$, diving_code, 
                    208:                        /* skip over... */
                    209:                        diving_code->size()>2?3/*OP_+string+get_element*/:2/*OP_+string*/);
                    210:        } else {
1.54      paf       211:                O($$, OP_WITH_WRITE); /* stack: starting context */
1.23      paf       212:                P($$, diving_code);
                    213:        }
                    214:        /* diving code; stack: current context */
1.20      paf       215: };
1.28      paf       216: name_expr_wdive_root: ':' name_expr_dive_code {
1.25      paf       217:        $$=N(POOL); 
1.54      paf       218:        O($$, OP_WITH_ROOT); /* stack: starting context */
1.9       paf       219:        P($$, $2); /* diving code; stack: context,name */
1.1       paf       220: };
1.44      paf       221: name_expr_wdive_class: class_prefix name_expr_dive_code { $$=$1; P($$, $2) };
1.20      paf       222: 
1.1       paf       223: constructor_value: 
1.55    ! paf       224:        '[' any_constructor_code_value ']' { $$=$2 }
        !           225: |      '(' any_expression ')' { $$=$2 }
1.52      paf       226: ;
1.55    ! paf       227: any_constructor_code_value: 
        !           228:        empty_string_value /* optimized $var[] case */
1.52      paf       229: |      STRING /* optimized $var[STRING] case */
1.55    ! paf       230: |      constructor_code_value /* $var[something complex] */
1.1       paf       231: ;
1.55    ! paf       232: constructor_code_value: constructor_code {
1.25      paf       233:        $$=N(POOL); 
1.54      paf       234:        O($$, OP_CREATE_EWPOOL); /* stack: empty write context */
1.9       paf       235:        P($$, $1); /* some codes to that context */
1.54      paf       236:        O($$, OP_REDUCE_EWPOOL); /* context=pop; stack: context.value() */
1.1       paf       237: };
1.55    ! paf       238: constructor_code: codes__excluding_sole_str_literal;
1.27      paf       239: codes__excluding_sole_str_literal: action | code codes { $$=$1; P($$, $2) };
                    240: 
1.1       paf       241: /* call */
                    242: 
1.38      paf       243: call: '^' call_name store_params EON { /* ^field.$method{vasya} */
1.42      paf       244:        $$=$2; /* with_xxx,diving code; stack: context,method_junction */
1.54      paf       245:        O($$, OP_GET_METHOD_FRAME); /* stack: context,method_frame */
1.9       paf       246:        P($$, $3); /* filling method_frame.store_params */
1.54      paf       247:        O($$, OP_CALL); /* method_frame=pop; ncontext=pop; call(ncontext,method_frame) */
1.1       paf       248: };
                    249: 
1.43      paf       250: call_name: name_without_curly_rdive;
1.38      paf       251: 
1.9       paf       252: store_params: store_param | store_params store_param { $$=$1; P($$, $2) };
1.1       paf       253: store_param: store_round_param | store_curly_param;
1.47      paf       254: store_round_param: '[' store_param_parts ']' {$$=$2};
1.31      paf       255: store_param_parts:
1.32      paf       256:        store_param_part
                    257: |      store_param_parts ';' store_param_part { $$=$1; P($$, $3) }
1.31      paf       258: ;
1.10      paf       259: store_curly_param: '{' maybe_codes '}' {
1.25      paf       260:        $$=N(POOL); 
1.29      paf       261:        PCA($$, $2);
1.54      paf       262:        O($$, OP_STORE_PARAM);
1.1       paf       263: };
1.32      paf       264: store_param_part: 
1.33      paf       265:        empty /* optimized () case */
                    266: |      STRING { /* optimized (STRING) case */
1.32      paf       267:        $$=$1;
1.54      paf       268:        O($$, OP_STORE_PARAM);
1.32      paf       269: }
1.55    ! paf       270: |      constructor_code_value { /* (something complex) */
1.32      paf       271:        $$=$1;
1.54      paf       272:        O($$, OP_STORE_PARAM);
1.32      paf       273: }
                    274: ;
1.1       paf       275: 
                    276: /* name */
                    277: 
1.20      paf       278: name_expr_dive_code: name_expr_value | name_path name_expr_value { $$=$1; P($$, $2) };
1.1       paf       279: 
1.9       paf       280: name_path: name_step | name_path name_step { $$=$1; P($$, $2) };
1.1       paf       281: name_step: name_advance1 '.';
                    282: name_advance1: name_expr_value {
                    283:        /* stack: context */
                    284:        $$=$1; /* stack: context,name */
1.54      paf       285:        O($$, OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */
1.1       paf       286: };
                    287: name_advance2: name_expr_value {
                    288:        /* stack: context */
                    289:        $$=$1; /* stack: context,name */
1.54      paf       290:        O($$, OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */
1.1       paf       291: }
1.4       paf       292: |      STRING BOGUS
1.1       paf       293: ;
                    294: name_expr_value: 
1.4       paf       295:        STRING /* subname_is_const */
1.1       paf       296: |      name_expr_subvar_value /* $subname_is_var_value */
                    297: |      name_expr_with_subvar_value /* xxx$part_of_subname_is_var_value[$...] */
                    298: ;
                    299: name_expr_subvar_value: '$' subvar_ref_name_rdive {
                    300:        $$=$2;
1.54      paf       301:        O($$, OP_GET_ELEMENT);
1.1       paf       302: };
1.4       paf       303: name_expr_with_subvar_value: STRING subvar_get_writes {
1.25      paf       304:        $$=N(POOL); 
1.54      paf       305:        O($$, OP_CREATE_EWPOOL);
1.9       paf       306:        P($$, $1);
1.54      paf       307:        O($$, OP_WRITE);
1.9       paf       308:        P($$, $2);
1.54      paf       309:        O($$, OP_REDUCE_EWPOOL);
1.1       paf       310: };
1.18      paf       311: subvar_ref_name_rdive: subvar_ref_name_rdive_read | subvar_ref_name_rdive_root;
                    312: subvar_ref_name_rdive_read: STRING {
1.25      paf       313:        $$=N(POOL); 
1.54      paf       314:        O($$, OP_WITH_READ);
1.9       paf       315:        P($$, $1);
1.1       paf       316: };
1.18      paf       317: subvar_ref_name_rdive_root: ':' STRING {
1.25      paf       318:        $$=N(POOL); 
1.54      paf       319:        O($$, OP_WITH_ROOT);
1.18      paf       320:        P($$, $2);
                    321: };
1.9       paf       322: subvar_get_writes: subvar__get_write | subvar_get_writes subvar__get_write { $$=$1; P($$, $2) };
1.1       paf       323: subvar__get_write: '$' subvar_ref_name_rdive {
                    324:        $$=$2;
1.54      paf       325:        O($$, OP_GET_ELEMENT__WRITE);
1.42      paf       326: };
                    327: 
1.44      paf       328: class_prefix: STRING ':' {
1.42      paf       329:        String& name=*SLA2S($1);
                    330:        VClass *vclass=static_cast<VClass *>(PC->request->classes().get(name));
                    331:        if(!vclass) {
                    332:                strcpy(PC->error, "'");
                    333:                strcat(PC->error, name.cstr());
                    334:                strcat(PC->error, "' class is undefined in call");
                    335:                YYERROR;
                    336:        }
1.48      paf       337:        //TODO: убрать зависимость от статических @USE, сделать имя, а не ссылку
1.42      paf       338:        $$=CL(vclass); // vclass
1.1       paf       339: };
                    340: 
                    341: 
                    342: /* with */
                    343: 
                    344: with: '$' name_without_curly_rdive '{' codes '}' {
                    345:        $$=$2;
1.54      paf       346:        O($$, OP_CREATE_RWPOOL);
1.9       paf       347:        P($$, $4);
1.54      paf       348:        O($$, OP_REDUCE_RWPOOL);
                    349:        O($$, OP_WRITE);
1.1       paf       350: };
1.53      paf       351: 
                    352: /* expression */
                    353: 
1.55    ! paf       354: any_expression:
        !           355:        empty_double_value /* optimized $var() case */
        !           356: /*|    number /* optimized $var(number) case */
        !           357: |      expression /* $var(something complex) */
1.53      paf       358: ;
1.55    ! paf       359: expression: 
        !           360:        number
        !           361: |      expression '+' expression {
        !           362:        $$=$1; // stack: first operand
        !           363:        P($$, $3); // stack: first,second operands
        !           364:        O($$, OP_ADD); // value=first*second; stack: value
        !           365: }
        !           366: |      expression '-' expression {
        !           367:        $$=$1; // stack: first operand
        !           368:        P($$, $3); // stack: first,second operands
        !           369:        O($$, OP_SUB); // value=first*second; stack: value
        !           370: }
        !           371: |      expression '*' expression {
1.53      paf       372:        $$=$1; // stack: first operand
                    373:        P($$, $3); // stack: first,second operands
1.54      paf       374:        O($$, OP_MUL); // value=first*second; stack: value
1.55    ! paf       375: }
        !           376: |      expression '/' expression {
        !           377:        $$=$1; // stack: first operand
        !           378:        P($$, $3); // stack: first,second operands
        !           379:        O($$, OP_DIV); // value=first*second; stack: value
1.53      paf       380: };
1.55    ! paf       381: 
1.53      paf       382: 
                    383: /*
                    384: complex_expression_value: complex_expression {
                    385:        $$=N(POOL); 
1.54      paf       386:        O($$, OP_CREATE_SWPOOL); /* stack: empty write context * /
1.53      paf       387:        P($$, $1); /* some codes to that context * /
1.54      paf       388:        O($$, OP_REDUCE_SWPOOL); /* context=pop; stack: context.get_string() * /
1.53      paf       389: };
                    390: */
1.1       paf       391: 
1.27      paf       392: /* basics */
1.1       paf       393: 
1.4       paf       394: write_str_literal: STRING {
1.38      paf       395:        if(SLA2S($1)->size()) {
1.30      paf       396:                $$=$1;
1.54      paf       397:                O($$, OP_WRITE);
1.30      paf       398:        } else {
                    399:                // optimized case of special end of macro. see yylex
                    400:                $$=N(POOL);
                    401:        }
1.26      paf       402: };
1.54      paf       403: number: STRING {
                    404:        change_string_literal_to_double_literal($$=$1);
                    405: };
                    406: 
1.55    ! paf       407: empty_double_value: /* empty */ { $$=VL(NEW VDouble(POOL)) };
        !           408: empty_string_value: /* empty */ { $$=VL(NEW VString(POOL)) };
1.25      paf       409: empty: /* empty */ { $$=N(POOL) };
1.1       paf       410: 
                    411: %%
                    412: 
                    413: /*
                    414:        000$111(2222)00 
                    415:                000$111{3333}00
1.9       paf       416:        $,^: push,=0
1.1       paf       417:        1:( { break=pop
                    418:        2:( )  pop
                    419:        3:{ }  pop
                    420: 
                    421:        000^111(2222)4444{33333}4000
1.9       paf       422:        $,^: push,=0
1.1       paf       423:        1:( { break=pop
                    424:        2:( )=4
                    425:        3:{ }=4
                    426:                4:[^({]=pop
                    427: */
                    428: 
                    429: int yylex(YYSTYPE *lvalp, void *pc) {
                    430:        #define lexical_brackets_nestage PC->brackets_nestages[PC->sp]
1.48      paf       431:        #define RC {result=c; goto break2; }
1.1       paf       432: 
                    433:     register int c;
                    434:     int result;
                    435:        
                    436:        if(PC->pending_state) {
                    437:                result=PC->pending_state;
                    438:                PC->pending_state=0;
                    439:                return result;
                    440:        }
                    441:        
1.9       paf       442:        char *begin=PC->source;
                    443:        char *end;
                    444:        int begin_line=PC->line;
1.50      paf       445:        while(true) {
1.9       paf       446:                c=*(end=(PC->source++));
1.1       paf       447: 
1.4       paf       448:                if(c=='\n') {
1.1       paf       449:                        PC->line++;
1.8       paf       450:                        PC->col=0;
1.10      paf       451:                } else
1.4       paf       452:                        PC->col++;
1.1       paf       453: 
1.48      paf       454:                // escaping: ^^ ^$ ^; ^) ^} ^( ^{ ^"
                    455:                if(c=='^') 
                    456:                        switch(*PC->source) {
                    457:                        case '^': case '$': case ';':
                    458:                        case '[': case ']':
                    459:                        case '{': case '}':
                    460:                        case '"':
1.40      paf       461:                                if(end!=begin) {
                    462:                                        // append piece till ^
                    463:                                        PC->string->APPEND(begin, end-begin, PC->file, begin_line);
                    464:                                }
                    465:                                // reset piece 'start' position & line
                    466:                                begin=PC->source; // ^
1.9       paf       467:                                begin_line=PC->line;
1.40      paf       468:                                // skip over ^ and _
1.50      paf       469:                                PC->source++;  PC->col++;
1.40      paf       470:                                // skip analysis = forced literal
1.1       paf       471:                                continue;
                    472:                        }
                    473:                switch(PC->ls) {
1.10      paf       474: 
                    475:                // USER'S = NOT OURS
1.1       paf       476:                case LS_USER:
1.48      paf       477:                        switch(c) {
                    478:                        case '$':
1.10      paf       479:                                push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48      paf       480:                                RC;
                    481:                        case '^':
                    482:                                push_LS(PC, LS_METHOD_NAME);
                    483:                                RC;
                    484:                        case '@':
                    485:                                if(PC->col==0+1) {
                    486:                                        push_LS(PC, LS_DEF_NAME);
                    487:                                        RC;
                    488:                                }
                    489:                                break;
1.1       paf       490:                        }
1.48      paf       491:                        break;
                    492:                        
                    493:                // STRING IN EXPRESSION
                    494:                case LS_EXPRESSION_STRING:
                    495:                        switch(c) {
                    496:                        case '"':
                    497:                                pop_LS(PC); //"abc".
                    498:                                RC;
                    499:                        case '$':
                    500:                                push_LS(PC, LS_VAR_NAME_SIMPLE);
                    501:                                RC;
                    502:                        case '^':
1.10      paf       503:                                push_LS(PC, LS_METHOD_NAME);
1.48      paf       504:                                RC;
1.10      paf       505:                        }
                    506:                        break;
                    507: 
                    508:                // METHOD DEFINITION
                    509:                case LS_DEF_NAME:
1.48      paf       510:                        switch(c) {
                    511:                        case '[':
1.10      paf       512:                                PC->ls=LS_DEF_PARAMS;
1.48      paf       513:                                RC;
                    514:                        case '\n':
                    515:                                PC->ls=LS_DEF_SPECIAL_BODY;
                    516:                                RC;
1.10      paf       517:                        }
                    518:                        break;
1.48      paf       519: 
1.10      paf       520:                case LS_DEF_PARAMS:
1.48      paf       521:                        switch(c) {
                    522:                        case ';':
                    523:                                RC;
                    524:                        case ']':
1.10      paf       525:                                PC->ls=*PC->source=='['?LS_DEF_LOCALS:LS_DEF_COMMENT;
1.48      paf       526:                                RC;
1.49      paf       527:                        case '\n': // wrong. bailing out
1.10      paf       528:                                pop_LS(PC);
1.48      paf       529:                                RC;
1.10      paf       530:                        }
                    531:                        break;
1.48      paf       532: 
1.10      paf       533:                case LS_DEF_LOCALS:
1.48      paf       534:                        switch(c) {
                    535:                        case '[':
                    536:                        case ';':
                    537:                                RC;
                    538:                        case ']':
1.10      paf       539:                                PC->ls=LS_DEF_COMMENT;
1.48      paf       540:                                RC;
                    541:                        case '\n': // wrong. bailing out
1.10      paf       542:                                pop_LS(PC);
1.48      paf       543:                                RC;
1.10      paf       544:                        }
                    545:                        break;
1.48      paf       546: 
1.10      paf       547:                case LS_DEF_COMMENT:
                    548:                        if(c=='\n') {
                    549:                                pop_LS(PC);
1.48      paf       550:                                RC;
1.37      paf       551:                        }
                    552:                        break;
                    553: 
1.48      paf       554:                case LS_DEF_SPECIAL_BODY:
1.37      paf       555:                        if(c=='\n') {
1.48      paf       556:                                switch(*PC->source) {
                    557:                                case '@': case 0: // end of special_code
1.37      paf       558:                                        pop_LS(PC);
1.48      paf       559:                                        break;
                    560:                                }
                    561:                                RC;
                    562:                        }
                    563:                        break;
                    564: 
                    565:                // (EXPRESSION)
                    566:                case LS_EXPRESSION_BODY:
                    567:                        switch(c) {
                    568:                        case ')':
                    569:                                if(--lexical_brackets_nestage==0)
                    570:                                        pop_LS(PC); //(EXPRESSION).
                    571:                                RC;
                    572:                        case '$':
                    573:                                push_LS(PC, LS_VAR_NAME_IN_EXPRESSION);                         
                    574:                                RC;
                    575:                        case '^':
                    576:                                push_LS(PC, LS_METHOD_NAME);
                    577:                                RC;
                    578:                        case '(':
                    579:                                lexical_brackets_nestage++;
                    580:                                RC;
                    581:                        case '+': case '-': case '*': case '/': case '%': 
1.49      paf       582:                        case '&': case '|': 
                    583:                        case '<': case '>': case '=': case '!':
1.48      paf       584:                        case ';':
                    585:                                RC;
                    586:                        case '"':
                    587:                                push_LS(PC, LS_EXPRESSION_STRING);
                    588:                                RC;
1.50      paf       589:                        case 'l': case 'g': case 'e': case 'n':
1.51      paf       590:                                if(end==begin) // right after whitespace
                    591:                                        switch(char next_c=*PC->source) {
                    592: //                                     case '?': // ok [and bad cases, yacc would bark at them]
                    593:                                        case 't': // lt gt [et nt]
                    594:                                        case 'e': // le ge ne [ee]
                    595:                                        case 'q': // eq [lq gq nq]
                    596:                                                PC->source++;  PC->col++;
                    597:                                                PC->pending_state=next_c;
                    598:                                                return c;
1.50      paf       599:                                        }
1.48      paf       600:                                break;
                    601:                        case ' ': case '\t': case '\n':
                    602:                                if(end!=begin) {
                    603:                                        // append piece till whitespace
                    604:                                        PC->string->APPEND(begin, end-begin, PC->file, begin_line);
                    605:                                }
                    606:                                // reset piece 'start' position & line
1.50      paf       607:                                begin=PC->source; // after whitespace
1.48      paf       608:                                begin_line=PC->line;
                    609:                                continue;
1.1       paf       610:                        }
                    611:                        break;
                    612: 
1.10      paf       613:                // VARIABLE GET/PUT/WITH
1.1       paf       614:                case LS_VAR_NAME_SIMPLE:
1.48      paf       615:                case LS_VAR_NAME_IN_EXPRESSION:
                    616:                        if(PC->ls==LS_VAR_NAME_IN_EXPRESSION) {
                    617:                                // name in expression ends also before binary operators 
                    618:                                switch(c) {
                    619:                                case '+': case '-': case '*': case '/': case '%': 
                    620:                                case '&': case '|': 
                    621:                                case '<': case '>': case '=': case '!':
                    622:                                        pop_LS(PC);
                    623:                                        PC->source--;  if(--PC->col<0) { PC->line--;  PC->col=-1; }
                    624:                                        result=EON;
                    625:                                        goto break2;
                    626:                                }
                    627:                        }
                    628:                        switch(c) {
                    629:                        case 0:
                    630:                        case ' ': case '\t': case '\n':
                    631:                        case ';':
                    632:                        case ']': case '}':
1.1       paf       633:                                pop_LS(PC);
1.32      paf       634:                                PC->source--;  if(--PC->col<0) { PC->line--;  PC->col=-1; }
1.13      paf       635:                                result=EON;
1.1       paf       636:                                goto break2;
1.48      paf       637:                        case '[':
                    638:                                PC->ls=LS_VAR_SQUARE;
1.1       paf       639:                                lexical_brackets_nestage=1;
1.48      paf       640:                                RC;
                    641:                        case '{':
                    642:                                if(begin==end) { // ${name}, no need of EON, switching LS
                    643:                                        PC->ls=LS_VAR_NAME_CURLY; 
                    644:                                } else {
                    645:                                        PC->ls=LS_VAR_CURLY;
                    646:                                        lexical_brackets_nestage=1;
                    647:                                }
                    648:                                
                    649:                                RC;
                    650:                        case '(':
                    651:                                PC->ls=LS_EXPRESSION_BODY;
1.1       paf       652:                                lexical_brackets_nestage=1;
1.48      paf       653:                                RC;
                    654:                        case '.': // name part delim
                    655:                        case '$': // name part subvar
                    656:                        case ':': // ':name' or 'class:name'
                    657:                                RC;
1.1       paf       658:                        }
                    659:                        break;
1.48      paf       660: 
1.1       paf       661:                case LS_VAR_NAME_CURLY:
1.48      paf       662:                        switch(c) {
                    663:                        case '}': // ${name} finished, restoring LS
1.1       paf       664:                                pop_LS(PC);
1.48      paf       665:                                RC;
                    666:                        case '.': // name part delim
                    667:                        case '$': // name part subvar
                    668:                        case ':': // ':name' or 'class:name'
                    669:                                RC;
1.1       paf       670:                        }
                    671:                        break;
1.48      paf       672: 
                    673:                case LS_VAR_SQUARE:
                    674:                        switch(c) {
                    675:                        case '$':
1.10      paf       676:                                push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48      paf       677:                                RC;
                    678:                        case '^':
1.10      paf       679:                                push_LS(PC, LS_METHOD_NAME);
1.48      paf       680:                                RC;
                    681:                        case ']':
1.1       paf       682:                                if(--lexical_brackets_nestage==0) {
                    683:                                        pop_LS(PC);
1.48      paf       684:                                        RC;
1.1       paf       685:                                }
1.48      paf       686:                                break;
                    687:                        case ';': // operator_or_fmt;value delim
                    688:                                RC;
                    689:                        case '[':
                    690:                                lexical_brackets_nestage++;
                    691:                                break;
1.1       paf       692:                        }
                    693:                        break;
1.48      paf       694: 
1.1       paf       695:                case LS_VAR_CURLY:
1.48      paf       696:                        switch(c) {
                    697:                        case '$':
1.10      paf       698:                                push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48      paf       699:                                RC;
                    700:                        case '^':
1.10      paf       701:                                push_LS(PC, LS_METHOD_NAME);
1.48      paf       702:                                RC;
                    703:                        case '}':
1.1       paf       704:                                if(--lexical_brackets_nestage==0) {
                    705:                                        pop_LS(PC);
1.48      paf       706:                                        RC;
1.1       paf       707:                                }
1.48      paf       708:                                break;
                    709:                        case '{':
1.1       paf       710:                                lexical_brackets_nestage++;
1.48      paf       711:                                break;
                    712:                        }
1.1       paf       713:                        break;
                    714: 
1.10      paf       715:                // METHOD CALL
1.1       paf       716:                case LS_METHOD_NAME:
1.48      paf       717:                        switch(c) {
                    718:                        case '[':
                    719:                                PC->ls=LS_METHOD_SQUARE;
1.1       paf       720:                                lexical_brackets_nestage=1;
1.48      paf       721:                                RC;
                    722:                        case '{':
1.1       paf       723:                                PC->ls=LS_METHOD_CURLY;
                    724:                                lexical_brackets_nestage=1;
1.48      paf       725:                                RC;
                    726:                        case '.': // name part delim 
                    727:                        case '$': // name part subvar
                    728:                        case ':': // ':name' or 'class:name'
                    729:                                RC;
1.1       paf       730:                        }
                    731:                        break;
1.48      paf       732: 
                    733:                case LS_METHOD_SQUARE:
                    734:                        switch(c) {
                    735:                        case '$':
1.10      paf       736:                                push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48      paf       737:                                RC;
                    738:                        case '^':
1.10      paf       739:                                push_LS(PC, LS_METHOD_NAME);
1.48      paf       740:                                RC;
                    741:                        case ';': // param delim
                    742:                                RC;
                    743:                        case ']':
1.1       paf       744:                                if(--lexical_brackets_nestage==0) {
                    745:                                        PC->ls=LS_METHOD_AFTER;
1.48      paf       746:                                        RC;
1.1       paf       747:                                }
1.48      paf       748:                                break;
                    749:                        case '[':
1.1       paf       750:                                lexical_brackets_nestage++;
1.48      paf       751:                                break;
                    752:                        }
1.1       paf       753:                        break;
1.48      paf       754: 
1.1       paf       755:                case LS_METHOD_CURLY:
1.48      paf       756:                        switch(c) {
                    757:                        case '$':
1.10      paf       758:                                push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48      paf       759:                                RC;
                    760:                        case '^':
1.10      paf       761:                                push_LS(PC, LS_METHOD_NAME);
1.48      paf       762:                                RC;
                    763:                        case '}':
1.1       paf       764:                                if(--lexical_brackets_nestage==0) {
                    765:                                        PC->ls=LS_METHOD_AFTER;
1.48      paf       766:                                        RC;
1.1       paf       767:                                }
1.48      paf       768:                                break;
                    769:                        case '{':
1.1       paf       770:                                lexical_brackets_nestage++;
1.48      paf       771:                                break;
                    772:                        }
1.1       paf       773:                        break;
1.48      paf       774: 
1.1       paf       775:                case LS_METHOD_AFTER:
1.47      paf       776:                        if(c=='[') {/* )( }( */
1.48      paf       777:                                PC->ls=LS_METHOD_SQUARE;
1.1       paf       778:                                lexical_brackets_nestage=1;
1.48      paf       779:                                RC;
1.1       paf       780:                        }                                          
                    781:                        if(c=='{') {/* ){ }{ */
                    782:                                PC->ls=LS_METHOD_CURLY;
                    783:                                lexical_brackets_nestage=1;
1.48      paf       784:                                RC;
1.1       paf       785:                        }                                          
                    786:                        pop_LS(PC);
1.32      paf       787:                        PC->source--;  if(--PC->col<0) { PC->line--;  PC->col=-1; }
1.13      paf       788:                        result=EON;
1.1       paf       789:                        goto break2;
                    790:                }
1.9       paf       791:                if(c==0) {
1.1       paf       792:                        result=-1;
                    793:                        break;
                    794:                }
                    795:        }
                    796: 
                    797: break2:
1.9       paf       798:        if(begin==end)
1.1       paf       799:                return result;
                    800:        else {
                    801:                PC->pending_state=result;
1.10      paf       802:                // strip last \n before LS_DEF_NAME or EOF
                    803:                if((c=='@' || c==0) && end[-1]=='\n')
                    804:                        end--;
1.30      paf       805:                if(end!=begin) {
                    806:                        // append last piece
                    807:                        PC->string->APPEND(begin, end-begin, PC->file, begin_line/*, start_col*/);
                    808:                }
1.17      paf       809:                // create STRING value: array of OP_VALUE+vstring
1.55    ! paf       810:                *lvalp=VL(NEW VString(*PC->string));
1.10      paf       811:                // new pieces storage
1.25      paf       812:                PC->string=NEW String(POOL);
1.10      paf       813:                // go!
1.4       paf       814:                return STRING;
1.1       paf       815:        }
                    816: }
                    817: 
1.9       paf       818: int real_yyerror(parse_control *pc, char *s)  /* Called by yyparse on error */
1.1       paf       819:      {
1.16      paf       820:        //fprintf(stderr, "[%s]\n", s);
1.6       paf       821: 
1.46      paf       822:           strncpy(pc->error, s, MAX_STRING); // TODO: перепроверить с треклятым последним байтом
1.1       paf       823:           return 1;
                    824:      }
                    825: 
                    826: static void
1.9       paf       827:      yyprint(
1.1       paf       828:           FILE *file,
                    829:           int type,
                    830:           YYSTYPE value)
                    831:      {
1.9       paf       832:        if(type==STRING)
1.38      paf       833:          fprintf(file, " \"%s\"", SLA2S(value)->cstr());
1.1       paf       834:      }
                    835: 

E-mail: