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