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