|
|
| version 1.142, 2001/06/28 07:33:38 | version 1.156, 2001/07/26 14:15:45 |
|---|---|
| Line 4 | Line 4 |
| Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) |
| $Id$ | |
| */ | */ |
| %{ | |
| static char *RCSId="$Id$"; | |
| /** | /** |
| @todo parser4: | @todo parser4: |
| Line 19 | Line 19 |
| -#: in iis make up specialized Pool object for that | -#: in iis make up specialized Pool object for that |
| */ | */ |
| %{ | |
| #define YYSTYPE Array/*<Operation>*/ * | #define YYSTYPE Array/*<Operation>*/ * |
| #define YYPARSE_PARAM pc | #define YYPARSE_PARAM pc |
| #define YYLEX_PARAM pc | #define YYLEX_PARAM pc |
| Line 38 | Line 37 |
| #define SELF_ELEMENT_NAME "self" | #define SELF_ELEMENT_NAME "self" |
| #define USE_CONTROL_METHOD_NAME "USE" | #define USE_CONTROL_METHOD_NAME "USE" |
| #define END_CONTROL_METHOD_NAME "end" | |
| static int real_yyerror(parse_control *pc, char *s); | static int real_yyerror(parse_control *pc, char *s); |
| static void yyprint(FILE *file, int type, YYSTYPE value); | static void yyprint(FILE *file, int type, YYSTYPE value); |
| Line 105 static int yylex(YYSTYPE *lvalp, void *p | Line 103 static int yylex(YYSTYPE *lvalp, void *p |
| %left NEG /* negation: unary - */ | %left NEG /* negation: unary - */ |
| %% | %% |
| all: | all: |
| one_big_piece { | one_big_piece { |
| Method& method=*NEW Method(POOL, | Method& method=*NEW Method(POOL, |
| *main_method_name, | *main_method_name, |
| Line 126 control_method: '@' STRING '\n' | Line 124 control_method: '@' STRING '\n' |
| maybe_control_strings { | maybe_control_strings { |
| const String& command=*LA2S($2); | const String& command=*LA2S($2); |
| YYSTYPE strings_code=$4; | YYSTYPE strings_code=$4; |
| if(command==END_CONTROL_METHOD_NAME && strings_code->size()==0) | |
| break; | |
| if(strings_code->size()<1*2) { | if(strings_code->size()<1*2) { |
| strcpy(PC.error, "@"); | strcpy(PC.error, "@"); |
| strcat(PC.error, command.cstr()); | strcat(PC.error, command.cstr()); |
| Line 135 control_method: '@' STRING '\n' | Line 131 control_method: '@' STRING '\n' |
| YYERROR; | YYERROR; |
| } | } |
| if(command==CLASS_NAME) { | if(command==CLASS_NAME) { |
| if(PC.cclass) { // already changed from default? | if(PC.cclass->base()) { // already changed from default? |
| strcpy(PC.error, "class already have a name '"); | strcpy(PC.error, "class already have a name '"); |
| strncat(PC.error, PC.cclass->name().cstr(), 100); | strncat(PC.error, PC.cclass->name().cstr(), 100); |
| strcat(PC.error, "'"); | strcat(PC.error, "'"); |
| Line 158 control_method: '@' STRING '\n' | Line 154 control_method: '@' STRING '\n' |
| PC.request->use_file( | PC.request->use_file( |
| PC.request->absolute(*LA2S(strings_code, i))); | PC.request->absolute(*LA2S(strings_code, i))); |
| } else if(command==BASE_NAME) { | } else if(command==BASE_NAME) { |
| if(PC.cclass->base()!=&PC.request->OP) { // already changed from default? | if(PC.cclass->base()) { // already changed from default? |
| strcpy(PC.error, "class already have a base '"); | strcpy(PC.error, "class already have a base '"); |
| strncat(PC.error, PC.cclass->base()->name().cstr(), 100); | strncat(PC.error, PC.cclass->base()->name().cstr(), 100); |
| strcat(PC.error, "'"); | strcat(PC.error, "'"); |
| Line 238 maybe_codes: empty | codes; | Line 234 maybe_codes: empty | codes; |
| codes: code | codes code { $$=$1; P($$, $2) }; | codes: code | codes code { $$=$1; P($$, $2) }; |
| code: write_string | action; | code: write_string | action; |
| action: get | put | with | call; | action: get | put | call; |
| /* get */ | /* get */ |
| Line 251 get_name_value: name_without_curly_rdive | Line 247 get_name_value: name_without_curly_rdive |
| name_in_curly_rdive: '{' name_without_curly_rdive '}' { $$=$2 }; | name_in_curly_rdive: '{' name_without_curly_rdive '}' { $$=$2 }; |
| name_without_curly_rdive: | name_without_curly_rdive: |
| name_without_curly_rdive_read | name_without_curly_rdive_read |
| | name_without_curly_rdive_root | |
| | name_without_curly_rdive_class; | | name_without_curly_rdive_class; |
| name_without_curly_rdive_read: name_without_curly_rdive_code { | name_without_curly_rdive_read: name_without_curly_rdive_code { |
| $$=N(POOL); | $$=N(POOL); |
| Line 268 name_without_curly_rdive_read: name_with | Line 263 name_without_curly_rdive_read: name_with |
| } | } |
| /* diving code; stack: current context */ | /* diving code; stack: current context */ |
| }; | }; |
| name_without_curly_rdive_root: ':' name_without_curly_rdive_code { | |
| $$=N(POOL); | |
| O($$, OP_WITH_ROOT); /* stack: starting context */ | |
| P($$, $2); /* diving code; stack: current context */ | |
| }; | |
| name_without_curly_rdive_class: class_prefix name_without_curly_rdive_code { $$=$1; P($$, $2) }; | name_without_curly_rdive_class: class_prefix name_without_curly_rdive_code { $$=$1; P($$, $2) }; |
| name_without_curly_rdive_code: name_advance2 | name_path name_advance2 { $$=$1; P($$, $2) }; | name_without_curly_rdive_code: name_advance2 | name_path name_advance2 { $$=$1; P($$, $2) }; |
| Line 308 name_expr_wdive_root: ':' name_expr_dive | Line 298 name_expr_wdive_root: ':' name_expr_dive |
| }; | }; |
| name_expr_wdive_class: class_prefix name_expr_dive_code { $$=$1; P($$, $2) }; | name_expr_wdive_class: class_prefix name_expr_dive_code { $$=$1; P($$, $2) }; |
| construct: construct_by_code | construct_by_expr; | construct: |
| construct_by_code: '[' any_constructor_code_value ']' { | construct_square | |
| $$=$2; /* stack: context, name, value */ | construct_round | |
| construct_curly | |
| ; | |
| construct_square: '[' any_constructor_code_value ']' { | |
| // stack: context, name | |
| $$=$2; // stack: context, name, value | |
| O($$, OP_CONSTRUCT_VALUE); /* value=pop; name=pop; context=pop; construct(context,name,value) */ | O($$, OP_CONSTRUCT_VALUE); /* value=pop; name=pop; context=pop; construct(context,name,value) */ |
| } | } |
| ; | ; |
| construct_by_expr: '(' expr_value ')' { | construct_round: '(' expr_value ')' { |
| $$=$2; /* stack: context, name, value */ | // stack: context, name |
| $$=$2; // stack: context, name, value | |
| O($$, OP_CONSTRUCT_EXPR); /* value=pop; name=pop; context=pop; construct(context,name,value) */ | O($$, OP_CONSTRUCT_EXPR); /* value=pop; name=pop; context=pop; construct(context,name,value) */ |
| } | } |
| ; | ; |
| construct_curly: '{' maybe_codes '}' { | |
| // stack: context, name | |
| $$=N(POOL); | |
| CCA($$, $2); /* code=pop; name=pop; context=pop; construct(context,name,junction(code)) */ | |
| }; | |
| any_constructor_code_value: | any_constructor_code_value: |
| unknown_value /* optimized $var[] case */ | empty_string_value /* optimized $var[] case */ |
| | STRING /* optimized $var[STRING] case */ | | STRING /* optimized $var[STRING] case */ |
| | constructor_code_value /* $var[something complex] */ | | constructor_code_value /* $var[something complex] */ |
| ; | ; |
| Line 339 call: call_value { | Line 341 call: call_value { |
| $$=$1; /* stack: value */ | $$=$1; /* stack: value */ |
| O($$, OP_WRITE_VALUE); /* value=pop; wcontext.write(value) */ | O($$, OP_WRITE_VALUE); /* value=pop; wcontext.write(value) */ |
| }; | }; |
| call_value: '^' call_name store_params EON { /* ^field.$method{vasya} */ | call_value: '^' { PC.object_constructor_allowed=true } |
| $$=$2; /* with_xxx,diving code; stack: context,method_junction */ | call_name { PC.object_constructor_allowed=false } |
| store_params EON { /* ^field.$method{vasya} */ | |
| $$=$3; /* with_xxx,diving code; stack: context,method_junction */ | |
| O($$, OP_GET_METHOD_FRAME); /* stack: context,method_frame */ | O($$, OP_GET_METHOD_FRAME); /* stack: context,method_frame */ |
| YYSTYPE params_code=$3; | YYSTYPE params_code=$5; |
| if(params_code->size()==3) // probably [] case. [OP_VALUE + Void + STORE_PARAM] | if(params_code->size()==3) // probably [] case. [OP_VALUE + Void + STORE_PARAM] |
| if(Value *value=LA2V(params_code)) // it is OP_VALUE + value? | if(Value *value=LA2V(params_code)) // it is OP_VALUE + value? |
| if(!value->is_defined()) // value is VVoid? | if(!value->is_defined()) // value is VVoid? |
| Line 389 store_curly_param_part: maybe_codes { | Line 393 store_curly_param_part: maybe_codes { |
| PCA($$, $1); | PCA($$, $1); |
| }; | }; |
| code_param_value: | code_param_value: |
| unknown_value /* optimized [;...] case */ | empty_void_value /* optimized [;...] case */ |
| | STRING /* optimized [STRING] case */ | | STRING /* optimized [STRING] case */ |
| | constructor_code_value /* [something complex] */ | | constructor_code_value /* [something complex] */ |
| ; | ; |
| Line 433 name_expr_with_subvar_value: STRING subv | Line 437 name_expr_with_subvar_value: STRING subv |
| P($$, $2); | P($$, $2); |
| O($$, OP_REDUCE_EWPOOL); | O($$, OP_REDUCE_EWPOOL); |
| }; | }; |
| subvar_ref_name_rdive: subvar_ref_name_rdive_read | subvar_ref_name_rdive_root; | subvar_ref_name_rdive: STRING { |
| subvar_ref_name_rdive_read: STRING { | |
| $$=N(POOL); | $$=N(POOL); |
| O($$, OP_WITH_READ); | O($$, OP_WITH_READ); |
| P($$, $1); | P($$, $1); |
| }; | }; |
| subvar_ref_name_rdive_root: ':' STRING { | |
| $$=N(POOL); | |
| O($$, OP_WITH_ROOT); | |
| P($$, $2); | |
| }; | |
| subvar_get_writes: subvar__get_write | subvar_get_writes subvar__get_write { $$=$1; P($$, $2) }; | subvar_get_writes: subvar__get_write | subvar_get_writes subvar__get_write { $$=$1; P($$, $2) }; |
| subvar__get_write: '$' subvar_ref_name_rdive { | subvar__get_write: '$' subvar_ref_name_rdive { |
| $$=$2; | $$=$2; |
| O($$, OP_GET_ELEMENT__WRITE); | O($$, OP_GET_ELEMENT__WRITE); |
| }; | }; |
| class_prefix: STRING ':' { | class_prefix: |
| class_static_prefix | |
| | class_constructor_prefix | |
| ; | |
| class_static_prefix: STRING ':' { | |
| $$=$1; // stack: class name string | $$=$1; // stack: class name string |
| O($$, OP_GET_CLASS); | O($$, OP_GET_CLASS); |
| }; | }; |
| class_constructor_prefix: class_static_prefix ':' { | |
| $$=$1; | |
| /* with */ | if(!PC.object_constructor_allowed) { |
| strcpy(PC.error, ":: not allowed here"); | |
| with: '$' name_without_curly_rdive '{' maybe_codes '}' { | YYERROR; |
| $$=$2; | } |
| O($$, OP_CREATE_RWPOOL); | O($$, OP_PREPARE_TO_CONSTRUCT_OBJECT); |
| P($$, $4); | |
| O($$, OP_REDUCE_RWPOOL); | |
| O($$, OP_WRITE_VALUE); | |
| }; | }; |
| /* expr */ | /* expr */ |
| expr_value: expr { | expr_value: expr { |
| Line 477 expr: | Line 477 expr: |
| | get_value | | get_value |
| | call_value | | call_value |
| | '"' string_inside_quotes_value '"' { $$ = $2; } | | '"' string_inside_quotes_value '"' { $$ = $2; } |
| | '\'' string_inside_quotes_value '\'' { $$ = $2; } | |
| | '(' expr ')' { $$ = $2; } | | '(' expr ')' { $$ = $2; } |
| /* stack: operand // stack: @operand */ | /* stack: operand // stack: @operand */ |
| | '-' expr %prec NEG { $$=$2; O($$, OP_NEG) } | | '-' expr %prec NEG { $$=$2; O($$, OP_NEG) } |
| Line 527 write_string: STRING { | Line 528 write_string: STRING { |
| change_string_literal_to_write_string_literal($$=$1) | change_string_literal_to_write_string_literal($$=$1) |
| }; | }; |
| unknown_value: /* empty */ { $$=VL(NEW VVoid(POOL)) }; | empty_void_value: /* empty */ { $$=VL(NEW VVoid(POOL)) }; |
| empty_string_value: /* empty */ { $$=VL(NEW VString(POOL)) }; | |
| empty: /* empty */ { $$=N(POOL) }; | empty: /* empty */ { $$=N(POOL) }; |
| %% | %% |
| Line 636 static int yylex(YYSTYPE *lvalp, void *p | Line 638 static int yylex(YYSTYPE *lvalp, void *p |
| // USER'S = NOT OURS | // USER'S = NOT OURS |
| case LS_USER: | case LS_USER: |
| if(PC.trim_bof) | |
| switch(c) { | |
| case '\n': case ' ': case '\t': | |
| begin=PC.source; | |
| begin_line=PC.line; | |
| continue; // skip it | |
| default: | |
| PC.trim_bof=false; | |
| } | |
| switch(c) { | switch(c) { |
| case '$': | case '$': |
| push_LS(PC, LS_VAR_NAME_SIMPLE); | push_LS(PC, LS_VAR_NAME_SIMPLE); |
| Line 665 static int yylex(YYSTYPE *lvalp, void *p | Line 676 static int yylex(YYSTYPE *lvalp, void *p |
| break; | break; |
| // STRING IN EXPRESSION | // STRING IN EXPRESSION |
| case LS_EXPRESSION_STRING: | case LS_EXPRESSION_STRING_QUOTED: |
| case LS_EXPRESSION_STRING_APOSTROFED: | |
| switch(c) { | switch(c) { |
| case '"': | case '"': |
| pop_LS(PC); //"abc". | case '\'': |
| RC; | if( |
| PC.ls == LS_EXPRESSION_STRING_QUOTED && c=='"' || | |
| PC.ls == LS_EXPRESSION_STRING_APOSTROFED && c=='\'') { | |
| pop_LS(PC); //"abc". | 'abc'. | |
| RC; | |
| } | |
| break; | |
| case '$': | case '$': |
| push_LS(PC, LS_VAR_NAME_SIMPLE); | push_LS(PC, LS_VAR_NAME_SIMPLE); |
| RC; | RC; |
| Line 726 static int yylex(YYSTYPE *lvalp, void *p | Line 744 static int yylex(YYSTYPE *lvalp, void *p |
| break; | break; |
| case LS_DEF_SPECIAL_BODY: | case LS_DEF_SPECIAL_BODY: |
| // @todo in case | |
| // ################ | |
| // @next-method | |
| // we are here with c=='@' | |
| // which is wrong, and need action | |
| if(c=='\n') { | if(c=='\n') { |
| switch(*PC.source) { | switch(*PC.source) { |
| case '@': case 0: // end of special_code | case '@': case 0: // end of special_code |
| Line 795 static int yylex(YYSTYPE *lvalp, void *p | Line 818 static int yylex(YYSTYPE *lvalp, void *p |
| result=c; | result=c; |
| goto break2; | goto break2; |
| case '"': | case '"': |
| push_LS(PC, LS_EXPRESSION_STRING); | push_LS(PC, LS_EXPRESSION_STRING_QUOTED); |
| RC; | |
| case '\'': | |
| push_LS(PC, LS_EXPRESSION_STRING_APOSTROFED); | |
| RC; | RC; |
| case 'l': case 'g': case 'e': case 'n': | case 'l': case 'g': case 'e': case 'n': |
| if(end==begin) // right after whitespace | if(end==begin) // right after whitespace |