Annotation of parser3/src/main/compile.y, revision 1.48
1.24 paf 1: /*
1.48 ! paf 2: $Id: compile.y,v 1.47 2001/03/06 10:49:23 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: constructor_one_param_value
219: | constructor_two_params_value /* $var(=;2*2) $var(%d;2*2) $var(+;1) */
1.1 paf 220: ;
1.27 paf 221:
1.32 paf 222: constructor_one_param_value:
223: empty_value /* optimized $var() case */
224: | STRING /* optimized $var(STRING) case */
225: | complex_constructor_param_value /* $var(something complex) */
1.1 paf 226: ;
227: complex_constructor_param_value: complex_constructor_param_body {
1.25 paf 228: $$=N(POOL);
1.3 paf 229: OP($$, OP_CREATE_EWPOOL); /* stack: empty write context */
1.9 paf 230: P($$, $1); /* some codes to that context */
231: OP($$, OP_REDUCE_EWPOOL); /* context=pop; stack: context.value() */
1.1 paf 232: };
1.27 paf 233: complex_constructor_param_body: codes__excluding_sole_str_literal;
234: codes__excluding_sole_str_literal: action | code codes { $$=$1; P($$, $2) };
235:
1.32 paf 236: constructor_two_params_value: STRING ';' constructor_one_param_value {
1.38 paf 237: char *operator_or_fmt=SLA2S($1)->cstr();
1.25 paf 238: $$=N(POOL);
1.9 paf 239: P($$, $1); /* stack: ncontext name operator_or_fmt */
1.3 paf 240: P($$, $3); /* stack: ncontext name operator_or_fmt expr */
1.1 paf 241: switch(operator_or_fmt[0]) {
242: case '=': case '%':
1.3 paf 243: OP($$, OP_EXPRESSION_EVAL);
1.1 paf 244: break;
245: case '+': case '-': case '*': case '/':
1.3 paf 246: OP($$, OP_MODIFY_EVAL);
1.1 paf 247: break;
248: default:
1.6 paf 249: strcpy(PC->error, "invalid modification operator");
250: YYERROR;
1.1 paf 251: }
252: /* stack: ncontext name value */
253: };
254:
255: /* call */
256:
1.38 paf 257: call: '^' call_name store_params EON { /* ^field.$method{vasya} */
1.42 paf 258: $$=$2; /* with_xxx,diving code; stack: context,method_junction */
1.9 paf 259: OP($$, OP_GET_METHOD_FRAME); /* stack: context,method_frame */
260: P($$, $3); /* filling method_frame.store_params */
261: OP($$, OP_CALL); /* method_frame=pop; ncontext=pop; call(ncontext,method_frame) */
1.1 paf 262: };
263:
1.43 paf 264: call_name: name_without_curly_rdive;
1.38 paf 265:
1.9 paf 266: store_params: store_param | store_params store_param { $$=$1; P($$, $2) };
1.1 paf 267: store_param: store_round_param | store_curly_param;
1.47 paf 268: store_round_param: '[' store_param_parts ']' {$$=$2};
1.31 paf 269: store_param_parts:
1.32 paf 270: store_param_part
271: | store_param_parts ';' store_param_part { $$=$1; P($$, $3) }
1.31 paf 272: ;
1.10 paf 273: store_curly_param: '{' maybe_codes '}' {
1.25 paf 274: $$=N(POOL);
1.29 paf 275: PCA($$, $2);
1.9 paf 276: OP($$, OP_STORE_PARAM);
1.1 paf 277: };
1.32 paf 278: store_param_part:
1.33 paf 279: empty /* optimized () case */
280: | STRING { /* optimized (STRING) case */
1.32 paf 281: $$=$1;
282: OP($$, OP_STORE_PARAM);
283: }
1.33 paf 284: | complex_constructor_param_value { /* (something complex) */
1.32 paf 285: $$=$1;
286: OP($$, OP_STORE_PARAM);
287: }
288: ;
1.1 paf 289:
290: /* name */
291:
1.20 paf 292: name_expr_dive_code: name_expr_value | name_path name_expr_value { $$=$1; P($$, $2) };
1.1 paf 293:
1.9 paf 294: name_path: name_step | name_path name_step { $$=$1; P($$, $2) };
1.1 paf 295: name_step: name_advance1 '.';
296: name_advance1: name_expr_value {
297: /* stack: context */
298: $$=$1; /* stack: context,name */
1.9 paf 299: OP($$, OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */
1.1 paf 300: };
301: name_advance2: name_expr_value {
302: /* stack: context */
303: $$=$1; /* stack: context,name */
1.9 paf 304: OP($$, OP_GET_ELEMENT); /* name=pop; context=pop; stack: context.get_element(name) */
1.1 paf 305: }
1.4 paf 306: | STRING BOGUS
1.1 paf 307: ;
308: name_expr_value:
1.4 paf 309: STRING /* subname_is_const */
1.1 paf 310: | name_expr_subvar_value /* $subname_is_var_value */
311: | name_expr_with_subvar_value /* xxx$part_of_subname_is_var_value[$...] */
312: ;
313: name_expr_subvar_value: '$' subvar_ref_name_rdive {
314: $$=$2;
1.9 paf 315: OP($$, OP_GET_ELEMENT);
1.1 paf 316: };
1.4 paf 317: name_expr_with_subvar_value: STRING subvar_get_writes {
1.25 paf 318: $$=N(POOL);
1.3 paf 319: OP($$, OP_CREATE_EWPOOL);
1.9 paf 320: P($$, $1);
1.17 paf 321: OP($$, OP_WRITE);
1.9 paf 322: P($$, $2);
323: OP($$, OP_REDUCE_EWPOOL);
1.1 paf 324: };
1.18 paf 325: subvar_ref_name_rdive: subvar_ref_name_rdive_read | subvar_ref_name_rdive_root;
326: subvar_ref_name_rdive_read: STRING {
1.25 paf 327: $$=N(POOL);
1.18 paf 328: OP($$, OP_WITH_READ);
1.9 paf 329: P($$, $1);
1.1 paf 330: };
1.18 paf 331: subvar_ref_name_rdive_root: ':' STRING {
1.25 paf 332: $$=N(POOL);
1.18 paf 333: OP($$, OP_WITH_ROOT);
334: P($$, $2);
335: };
1.9 paf 336: subvar_get_writes: subvar__get_write | subvar_get_writes subvar__get_write { $$=$1; P($$, $2) };
1.1 paf 337: subvar__get_write: '$' subvar_ref_name_rdive {
338: $$=$2;
1.17 paf 339: OP($$, OP_GET_ELEMENT__WRITE);
1.42 paf 340: };
341:
1.44 paf 342: class_prefix: STRING ':' {
1.42 paf 343: String& name=*SLA2S($1);
344: VClass *vclass=static_cast<VClass *>(PC->request->classes().get(name));
345: if(!vclass) {
346: strcpy(PC->error, "'");
347: strcat(PC->error, name.cstr());
348: strcat(PC->error, "' class is undefined in call");
349: YYERROR;
350: }
1.48 ! paf 351: //TODO: убрать зависимость от статических @USE, сделать имя, а не ссылку
1.42 paf 352: $$=CL(vclass); // vclass
1.1 paf 353: };
354:
355:
356: /* with */
357:
358: with: '$' name_without_curly_rdive '{' codes '}' {
359: $$=$2;
1.9 paf 360: OP($$, OP_CREATE_RWPOOL);
361: P($$, $4);
362: OP($$, OP_REDUCE_RWPOOL);
1.17 paf 363: OP($$, OP_WRITE);
1.1 paf 364: };
365:
1.27 paf 366: /* basics */
1.1 paf 367:
1.4 paf 368: write_str_literal: STRING {
1.38 paf 369: if(SLA2S($1)->size()) {
1.30 paf 370: $$=$1;
371: OP($$, OP_WRITE);
372: } else {
373: // optimized case of special end of macro. see yylex
374: $$=N(POOL);
375: }
1.26 paf 376: };
1.38 paf 377: empty_value: /* empty */ { $$=SL(NEW VString(POOL)) };
1.25 paf 378: empty: /* empty */ { $$=N(POOL) };
1.1 paf 379:
380: %%
381:
382: /*
383: 000$111(2222)00
384: 000$111{3333}00
1.9 paf 385: $,^: push,=0
1.1 paf 386: 1:( { break=pop
387: 2:( ) pop
388: 3:{ } pop
389:
390: 000^111(2222)4444{33333}4000
1.9 paf 391: $,^: push,=0
1.1 paf 392: 1:( { break=pop
393: 2:( )=4
394: 3:{ }=4
395: 4:[^({]=pop
396: */
397:
398: int yylex(YYSTYPE *lvalp, void *pc) {
399: #define lexical_brackets_nestage PC->brackets_nestages[PC->sp]
1.48 ! paf 400: #define RC {result=c; goto break2; }
1.1 paf 401:
402: register int c;
403: int result;
404:
405: if(PC->pending_state) {
406: result=PC->pending_state;
407: PC->pending_state=0;
408: return result;
409: }
410:
1.9 paf 411: char *begin=PC->source;
412: char *end;
413: int begin_line=PC->line;
1.1 paf 414: while(1) {
1.9 paf 415: c=*(end=(PC->source++));
1.1 paf 416:
1.4 paf 417: if(c=='\n') {
1.1 paf 418: PC->line++;
1.8 paf 419: PC->col=0;
1.10 paf 420: } else
1.4 paf 421: PC->col++;
1.1 paf 422:
1.48 ! paf 423: // escaping: ^^ ^$ ^; ^) ^} ^( ^{ ^"
! 424: if(c=='^')
! 425: switch(*PC->source) {
! 426: case '^': case '$': case ';':
! 427: case '[': case ']':
! 428: case '{': case '}':
! 429: case '"':
1.40 paf 430: if(end!=begin) {
431: // append piece till ^
432: PC->string->APPEND(begin, end-begin, PC->file, begin_line);
433: }
434: // reset piece 'start' position & line
435: begin=PC->source; // ^
1.9 paf 436: begin_line=PC->line;
1.40 paf 437: // skip over ^ and _
438: PC->source++;
439: // skip analysis = forced literal
1.1 paf 440: continue;
441: }
442: switch(PC->ls) {
1.10 paf 443:
444: // USER'S = NOT OURS
1.1 paf 445: case LS_USER:
1.48 ! paf 446: switch(c) {
! 447: case '$':
1.10 paf 448: push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48 ! paf 449: RC;
! 450: case '^':
! 451: push_LS(PC, LS_METHOD_NAME);
! 452: RC;
! 453: case '@':
! 454: if(PC->col==0+1) {
! 455: push_LS(PC, LS_DEF_NAME);
! 456: RC;
! 457: }
! 458: break;
1.1 paf 459: }
1.48 ! paf 460: break;
! 461:
! 462: // STRING IN EXPRESSION
! 463: case LS_EXPRESSION_STRING:
! 464: switch(c) {
! 465: case '"':
! 466: pop_LS(PC); //"abc".
! 467: RC;
! 468: case '$':
! 469: push_LS(PC, LS_VAR_NAME_SIMPLE);
! 470: RC;
! 471: case '^':
1.10 paf 472: push_LS(PC, LS_METHOD_NAME);
1.48 ! paf 473: RC;
1.10 paf 474: }
475: break;
476:
477: // METHOD DEFINITION
478: case LS_DEF_NAME:
1.48 ! paf 479: switch(c) {
! 480: case '[':
1.10 paf 481: PC->ls=LS_DEF_PARAMS;
1.48 ! paf 482: RC;
! 483: case '\n':
! 484: PC->ls=LS_DEF_SPECIAL_BODY;
! 485: RC;
1.10 paf 486: }
487: break;
1.48 ! paf 488:
1.10 paf 489: case LS_DEF_PARAMS:
1.48 ! paf 490: switch(c) {
! 491: case ';':
! 492: RC;
! 493: case ']':
1.10 paf 494: PC->ls=*PC->source=='['?LS_DEF_LOCALS:LS_DEF_COMMENT;
1.48 ! paf 495: RC;
! 496: case c=='\n': // wrong. bailing out
1.10 paf 497: pop_LS(PC);
1.48 ! paf 498: RC;
1.10 paf 499: }
500: break;
1.48 ! paf 501:
1.10 paf 502: case LS_DEF_LOCALS:
1.48 ! paf 503: switch(c) {
! 504: case '[':
! 505: case ';':
! 506: RC;
! 507: case ']':
1.10 paf 508: PC->ls=LS_DEF_COMMENT;
1.48 ! paf 509: RC;
! 510: case '\n': // wrong. bailing out
1.10 paf 511: pop_LS(PC);
1.48 ! paf 512: RC;
1.10 paf 513: }
514: break;
1.48 ! paf 515:
1.10 paf 516: case LS_DEF_COMMENT:
517: if(c=='\n') {
518: pop_LS(PC);
1.48 ! paf 519: RC;
1.37 paf 520: }
521: break;
522:
1.48 ! paf 523: case LS_DEF_SPECIAL_BODY:
1.37 paf 524: if(c=='\n') {
1.48 ! paf 525: switch(*PC->source) {
! 526: case '@': case 0: // end of special_code
1.37 paf 527: pop_LS(PC);
1.48 ! paf 528: break;
! 529: }
! 530: RC;
! 531: }
! 532: break;
! 533:
! 534: // (EXPRESSION)
! 535: case LS_EXPRESSION_BODY:
! 536: switch(c) {
! 537: case ')':
! 538: if(--lexical_brackets_nestage==0)
! 539: pop_LS(PC); //(EXPRESSION).
! 540: RC;
! 541: case '$':
! 542: push_LS(PC, LS_VAR_NAME_IN_EXPRESSION);
! 543: RC;
! 544: case '^':
! 545: push_LS(PC, LS_METHOD_NAME);
! 546: RC;
! 547: case '(':
! 548: lexical_brackets_nestage++;
! 549: RC;
! 550: case '+': case '-': case '*': case '/': case '%':
! 551: case ';':
! 552: RC;
! 553: case '&': case '|':
! 554: case '<': case '>': case '=': case '!':
! 555: ?
! 556: break;
! 557: case '"':
! 558: push_LS(PC, LS_EXPRESSION_STRING);
! 559: RC;
! 560: break;
! 561: case ' ': case '\t': case '\n':
! 562: if(end!=begin) {
! 563: // append piece till whitespace
! 564: PC->string->APPEND(begin, end-begin, PC->file, begin_line);
! 565: }
! 566: // skip over whitespace
! 567: PC->source++;
! 568: // reset piece 'start' position & line
! 569: begin=PC->source; // ^
! 570: begin_line=PC->line;
! 571: continue;
1.1 paf 572: }
573: break;
574:
1.10 paf 575: // VARIABLE GET/PUT/WITH
1.1 paf 576: case LS_VAR_NAME_SIMPLE:
1.48 ! paf 577: case LS_VAR_NAME_IN_EXPRESSION:
! 578: if(PC->ls==LS_VAR_NAME_IN_EXPRESSION) {
! 579: // name in expression ends also before binary operators
! 580: switch(c) {
! 581: case '+': case '-': case '*': case '/': case '%':
! 582: case '&': case '|':
! 583: case '<': case '>': case '=': case '!':
! 584: pop_LS(PC);
! 585: PC->source--; if(--PC->col<0) { PC->line--; PC->col=-1; }
! 586: result=EON;
! 587: goto break2;
! 588: }
! 589: }
! 590: switch(c) {
! 591: case 0:
! 592: case ' ': case '\t': case '\n':
! 593: case ';':
! 594: case ']': case '}':
1.1 paf 595: pop_LS(PC);
1.32 paf 596: PC->source--; if(--PC->col<0) { PC->line--; PC->col=-1; }
1.13 paf 597: result=EON;
1.1 paf 598: goto break2;
1.48 ! paf 599: case '[':
! 600: PC->ls=LS_VAR_SQUARE;
1.1 paf 601: lexical_brackets_nestage=1;
1.48 ! paf 602: RC;
! 603: case '{':
! 604: if(begin==end) { // ${name}, no need of EON, switching LS
! 605: PC->ls=LS_VAR_NAME_CURLY;
! 606: } else {
! 607: PC->ls=LS_VAR_CURLY;
! 608: lexical_brackets_nestage=1;
! 609: }
! 610:
! 611: RC;
! 612: case '(':
! 613: PC->ls=LS_EXPRESSION_BODY;
1.1 paf 614: lexical_brackets_nestage=1;
1.48 ! paf 615: RC;
! 616: case '.': // name part delim
! 617: case '$': // name part subvar
! 618: case ':': // ':name' or 'class:name'
! 619: RC;
1.1 paf 620: }
621: break;
1.48 ! paf 622:
1.1 paf 623: case LS_VAR_NAME_CURLY:
1.48 ! paf 624: switch(c) {
! 625: case '}': // ${name} finished, restoring LS
1.1 paf 626: pop_LS(PC);
1.48 ! paf 627: RC;
! 628: case '.': // name part delim
! 629: case '$': // name part subvar
! 630: case ':': // ':name' or 'class:name'
! 631: RC;
1.1 paf 632: }
633: break;
1.48 ! paf 634:
! 635: case LS_VAR_SQUARE:
! 636: switch(c) {
! 637: case '$':
1.10 paf 638: push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48 ! paf 639: RC;
! 640: case '^':
1.10 paf 641: push_LS(PC, LS_METHOD_NAME);
1.48 ! paf 642: RC;
! 643: case ']':
1.1 paf 644: if(--lexical_brackets_nestage==0) {
645: pop_LS(PC);
1.48 ! paf 646: RC;
1.1 paf 647: }
1.48 ! paf 648: break;
! 649: case ';': // operator_or_fmt;value delim
! 650: RC;
! 651: case '[':
! 652: lexical_brackets_nestage++;
! 653: break;
1.1 paf 654: }
655: break;
1.48 ! paf 656:
1.1 paf 657: case LS_VAR_CURLY:
1.48 ! paf 658: switch(c) {
! 659: case '$':
1.10 paf 660: push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48 ! paf 661: RC;
! 662: case '^':
1.10 paf 663: push_LS(PC, LS_METHOD_NAME);
1.48 ! paf 664: RC;
! 665: case '}':
1.1 paf 666: if(--lexical_brackets_nestage==0) {
667: pop_LS(PC);
1.48 ! paf 668: RC;
1.1 paf 669: }
1.48 ! paf 670: break;
! 671: case '{':
1.1 paf 672: lexical_brackets_nestage++;
1.48 ! paf 673: break;
! 674: }
1.1 paf 675: break;
676:
1.10 paf 677: // METHOD CALL
1.1 paf 678: case LS_METHOD_NAME:
1.48 ! paf 679: switch(c) {
! 680: case '[':
! 681: PC->ls=LS_METHOD_SQUARE;
1.1 paf 682: lexical_brackets_nestage=1;
1.48 ! paf 683: RC;
! 684: case '{':
1.1 paf 685: PC->ls=LS_METHOD_CURLY;
686: lexical_brackets_nestage=1;
1.48 ! paf 687: RC;
! 688: case '.': // name part delim
! 689: case '$': // name part subvar
! 690: case ':': // ':name' or 'class:name'
! 691: RC;
1.1 paf 692: }
693: break;
1.48 ! paf 694:
! 695: case LS_METHOD_SQUARE:
! 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 ';': // param delim
! 704: RC;
! 705: case ']':
1.1 paf 706: if(--lexical_brackets_nestage==0) {
707: PC->ls=LS_METHOD_AFTER;
1.48 ! paf 708: RC;
1.1 paf 709: }
1.48 ! paf 710: break;
! 711: case '[':
1.1 paf 712: lexical_brackets_nestage++;
1.48 ! paf 713: break;
! 714: }
1.1 paf 715: break;
1.48 ! paf 716:
1.1 paf 717: case LS_METHOD_CURLY:
1.48 ! paf 718: switch(c) {
! 719: case '$':
1.10 paf 720: push_LS(PC, LS_VAR_NAME_SIMPLE);
1.48 ! paf 721: RC;
! 722: case '^':
1.10 paf 723: push_LS(PC, LS_METHOD_NAME);
1.48 ! paf 724: RC;
! 725: case '}':
1.1 paf 726: if(--lexical_brackets_nestage==0) {
727: PC->ls=LS_METHOD_AFTER;
1.48 ! paf 728: RC;
1.1 paf 729: }
1.48 ! paf 730: break;
! 731: case '{':
1.1 paf 732: lexical_brackets_nestage++;
1.48 ! paf 733: break;
! 734: }
1.1 paf 735: break;
1.48 ! paf 736:
1.1 paf 737: case LS_METHOD_AFTER:
1.47 paf 738: if(c=='[') {/* )( }( */
1.48 ! paf 739: PC->ls=LS_METHOD_SQUARE;
1.1 paf 740: lexical_brackets_nestage=1;
1.48 ! paf 741: RC;
1.1 paf 742: }
743: if(c=='{') {/* ){ }{ */
744: PC->ls=LS_METHOD_CURLY;
745: lexical_brackets_nestage=1;
1.48 ! paf 746: RC;
1.1 paf 747: }
748: pop_LS(PC);
1.32 paf 749: PC->source--; if(--PC->col<0) { PC->line--; PC->col=-1; }
1.13 paf 750: result=EON;
1.1 paf 751: goto break2;
752: }
1.9 paf 753: if(c==0) {
1.1 paf 754: result=-1;
755: break;
756: }
757: }
758:
759: break2:
1.9 paf 760: if(begin==end)
1.1 paf 761: return result;
762: else {
763: PC->pending_state=result;
1.10 paf 764: // strip last \n before LS_DEF_NAME or EOF
765: if((c=='@' || c==0) && end[-1]=='\n')
766: end--;
1.30 paf 767: if(end!=begin) {
768: // append last piece
769: PC->string->APPEND(begin, end-begin, PC->file, begin_line/*, start_col*/);
770: }
1.17 paf 771: // create STRING value: array of OP_VALUE+vstring
1.45 paf 772: *lvalp=SL(NEW VString(*PC->string));
1.10 paf 773: // new pieces storage
1.25 paf 774: PC->string=NEW String(POOL);
1.10 paf 775: // go!
1.4 paf 776: return STRING;
1.1 paf 777: }
778: }
779:
1.9 paf 780: int real_yyerror(parse_control *pc, char *s) /* Called by yyparse on error */
1.1 paf 781: {
1.16 paf 782: //fprintf(stderr, "[%s]\n", s);
1.6 paf 783:
1.46 paf 784: strncpy(pc->error, s, MAX_STRING); // TODO: перепроверить с треклятым последним байтом
1.1 paf 785: return 1;
786: }
787:
788: static void
1.9 paf 789: yyprint(
1.1 paf 790: FILE *file,
791: int type,
792: YYSTYPE value)
793: {
1.9 paf 794: if(type==STRING)
1.38 paf 795: fprintf(file, " \"%s\"", SLA2S(value)->cstr());
1.1 paf 796: }
797:
E-mail: