|
|
| version 1.204.2.8.2.13, 2003/04/03 12:40:53 | version 1.213.10.1, 2005/08/05 13:01:16 |
|---|---|
| Line 41 | Line 41 |
| // defines | // defines |
| #define USE_CONTROL_METHOD_NAME "USE" | #define USE_CONTROL_METHOD_NAME "USE" |
| #define TAB_SIZE 8 | |
| // forwards | // forwards |
| Line 49 static int real_yyerror(Parse_control* p | Line 48 static int real_yyerror(Parse_control* p |
| static void yyprint(FILE* file, int type, YYSTYPE value); | static void yyprint(FILE* file, int type, YYSTYPE value); |
| static int yylex(YYSTYPE* lvalp, void* pc); | static int yylex(YYSTYPE* lvalp, void* pc); |
| // local convinient inplace typecast & var | // local convinient inplace typecast & var |
| #undef PC | #undef PC |
| #define PC (*(Parse_control *)pc) | #define PC (*(Parse_control *)pc) |
| Line 68 static int yylex(YYSTYPE* lvalp, void* p | Line 66 static int yylex(YYSTYPE* lvalp, void* p |
| %token BAD_HEX_LITERAL | %token BAD_HEX_LITERAL |
| %token BAD_METHOD_DECL_START | %token BAD_METHOD_DECL_START |
| %token BAD_METHOD_PARAMETER_NAME_CHARACTER | %token BAD_METHOD_PARAMETER_NAME_CHARACTER |
| %token BAD_MATH_OPERATOR_CHARACTER | %token BAD_NONWHITESPACE_CHARACTER_IN_EXPLICIT_RESULT_MODE |
| %token LAND "&&" | %token LAND "&&" |
| %token LOR "||" | %token LOR "||" |
| Line 138 control_method: '@' STRING '\n' | Line 136 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(strings_code->count()<1*2) { | if(strings_code->count()<1*OPERATIONS_PER_OPVALUE) { |
| strcpy(PC.error, "@"); | strcpy(PC.error, "@"); |
| strcat(PC.error, command.cstr()); | strcat(PC.error, command.cstr()); |
| strcat(PC.error, " is empty"); | strcat(PC.error, " is empty"); |
| Line 151 control_method: '@' STRING '\n' | Line 149 control_method: '@' STRING '\n' |
| strcat(PC.error, "'"); | strcat(PC.error, "'"); |
| YYERROR; | YYERROR; |
| } | } |
| if(strings_code->count()==1*2) { | if(strings_code->count()==1*OPERATIONS_PER_OPVALUE) { |
| // new class' name | // new class' name |
| const String& name=*LA2S(*strings_code); | const String& name=*LA2S(*strings_code); |
| // creating the class | // creating the class |
| Line 161 control_method: '@' STRING '\n' | Line 159 control_method: '@' STRING '\n' |
| // append to request's classes | // append to request's classes |
| PC.request.classes().put(name, cclass); | PC.request.classes().put(name, cclass); |
| } else { | } else { |
| strcpy(PC.error, "@"CLASS_NAME" must contain sole name"); | strcpy(PC.error, "@"CLASS_NAME" must contain only one line with class name (contains more then one)"); |
| YYERROR; | YYERROR; |
| } | } |
| } else if(command==USE_CONTROL_METHOD_NAME) { | } else if(command==USE_CONTROL_METHOD_NAME) { |
| for(size_t i=0; i<strings_code->count(); i+=2) | for(size_t i=0; i<strings_code->count(); i+=OPERATIONS_PER_OPVALUE) |
| PC.request.use_file(PC.request.main_class, *LA2S(*strings_code, i)); | PC.request.use_file(PC.request.main_class, *LA2S(*strings_code, i)); |
| } else if(command==BASE_NAME) { | } else if(command==BASE_NAME) { |
| if(PC.cclass->base_class()) { // already changed from default? | if(PC.cclass->base_class()) { // already changed from default? |
| Line 174 control_method: '@' STRING '\n' | Line 172 control_method: '@' STRING '\n' |
| strcat(PC.error, "'"); | strcat(PC.error, "'"); |
| YYERROR; | YYERROR; |
| } | } |
| if(strings_code->count()==1*2) { | if(strings_code->count()==1*OPERATIONS_PER_OPVALUE) { |
| const String& base_name=*LA2S(*strings_code); | const String& base_name=*LA2S(*strings_code); |
| if(Value* base_class_value=PC.request.classes().get(base_name)) { | if(Value* base_class_value=PC.request.classes().get(base_name)) { |
| // @CLASS == @BASE sanity check | // @CLASS == @BASE sanity check |
| Line 211 control_strings: control_string | contro | Line 209 control_strings: control_string | contro |
| control_string: maybe_string '\n'; | control_string: maybe_string '\n'; |
| maybe_string: empty | STRING; | maybe_string: empty | STRING; |
| code_method: '@' STRING bracketed_maybe_strings maybe_bracketed_strings maybe_comment '\n' | code_method: '@' STRING bracketed_maybe_strings maybe_bracketed_strings maybe_comment '\n' { |
| maybe_codes { | PC.explicit_result=false; |
| const String& name=*LA2S(*$2); | const String& name=*LA2S(*$2); |
| YYSTYPE params_names_code=$3; | YYSTYPE params_names_code=$3; |
| ArrayString* params_names=0; | ArrayString* params_names=0; |
| if(int size=params_names_code->count()) { | if(int size=params_names_code->count()) { |
| params_names=new ArrayString; | params_names=new ArrayString; |
| for(int i=0; i<size; i+=2) | for(int i=0; i<size; i+=OPERATIONS_PER_OPVALUE) |
| *params_names+=LA2S(*params_names_code, i); | *params_names+=LA2S(*params_names_code, i); |
| } | } |
| Line 227 code_method: '@' STRING bracketed_maybe_ | Line 225 code_method: '@' STRING bracketed_maybe_ |
| ArrayString* locals_names=0; | ArrayString* locals_names=0; |
| if(int size=locals_names_code->count()) { | if(int size=locals_names_code->count()) { |
| locals_names=new ArrayString; | locals_names=new ArrayString; |
| for(int i=0; i<size; i+=2) | for(int i=0; i<size; i+=OPERATIONS_PER_OPVALUE) { |
| *locals_names+=LA2S(*locals_names_code, i); | const String* local_name=LA2S(*locals_names_code, i); |
| if(*local_name==RESULT_VAR_NAME) | |
| PC.explicit_result=true; | |
| else | |
| *locals_names+=local_name; | |
| } | |
| } | } |
| Method& method=*new Method( | Method* method=new Method( |
| //name, | //name, |
| Method::CT_ANY, | Method::CT_ANY, |
| 0, 0/*min,max numbered_params_count*/, | 0, 0/*min,max numbered_params_count*/, |
| params_names, locals_names, | params_names, locals_names, |
| $7, 0); | 0/*to be filled later in next {} */, 0); |
| PC.cclass->add_method(PC.alias_method(name), method); | PC.cclass->add_method(PC.alias_method(name), *method); |
| *reinterpret_cast<Method**>(&$$)=method; | |
| // todo: check [][;result;] | |
| } maybe_codes { | |
| // fill in the code | |
| reinterpret_cast<Method*>($7)->parser_code=$8; | |
| }; | }; |
| maybe_bracketed_strings: empty | bracketed_maybe_strings; | maybe_bracketed_strings: empty | bracketed_maybe_strings; |
| Line 275 name_without_curly_rdive_read: name_with | Line 284 name_without_curly_rdive_read: name_with |
| ArrayOperation* diving_code=$1; | ArrayOperation* diving_code=$1; |
| const String* first_name=LA2S(*diving_code); | const String* first_name=LA2S(*diving_code); |
| // self.xxx... -> xxx... | // self.xxx... -> xxx... |
| // OP_VALUE+string+OP_GET_ELEMENT+... -> OP_WITH_SELF+... | // OP_VALUE+origin+string+OP_GET_ELEMENT+... -> OP_WITH_SELF+... |
| if(first_name && *first_name==SELF_ELEMENT_NAME) { | if(first_name && *first_name==SELF_ELEMENT_NAME) { |
| O(*$$, OP_WITH_SELF); /* stack: starting context */ | O(*yyval, OP_WITH_SELF); /* stack: starting context */ |
| P(*$$, *diving_code, | P(*yyval, *diving_code, |
| /* skip over... */ | /* skip over... */ |
| diving_code->count()>=3?3/*OP_VALUE+string+OP_GET_ELEMENTx*/:2/*OP_+string*/); | diving_code->count()>=4?4/*OP_VALUE+origin+string+OP_GET_ELEMENTx*/:3/*OP_+origin+string*/); |
| } else { | } else { |
| O(*$$, OP_WITH_READ); /* stack: starting context */ | O(*yyval, OP_WITH_READ); /* stack: starting context */ |
| // ^if ELEMENT -> ^if ELEMENT_OR_OPERATOR | // ^if ELEMENT -> ^if ELEMENT_OR_OPERATOR |
| // OP_VALUE+string+OP_GET_ELEMENT. -> OP_VALUE+string+OP_GET_ELEMENT_OR_OPERATOR. | // OP_VALUE+origin+string+OP_GET_ELEMENT. -> OP_VALUE+origin+string+OP_GET_ELEMENT_OR_OPERATOR. |
| if(PC.in_call_value && diving_code->count()==3) | if(PC.in_call_value && diving_code->count()==4) |
| diving_code->put(2, OP_GET_ELEMENT_OR_OPERATOR); | diving_code->put(4-1, OP_GET_ELEMENT_OR_OPERATOR); |
| P(*$$, *diving_code); | P(*$$, *diving_code); |
| } | } |
| /* diving code; stack: current context */ | /* diving code; stack: current context */ |
| Line 310 name_expr_wdive_root: name_expr_dive_cod | Line 319 name_expr_wdive_root: name_expr_dive_cod |
| ArrayOperation* diving_code=$1; | ArrayOperation* diving_code=$1; |
| const String* first_name=LA2S(*diving_code); | const String* first_name=LA2S(*diving_code); |
| // $self.xxx... -> $xxx... | // $self.xxx... -> $xxx... |
| // OP_VALUE+string+OP_GET_ELEMENT+... -> OP_WITH_SELF+... | // OP_VALUE+origin+string+OP_GET_ELEMENT+... -> OP_WITH_SELF+... |
| if(first_name && *first_name==SELF_ELEMENT_NAME) { | if(first_name && *first_name==SELF_ELEMENT_NAME) { |
| O(*$$, OP_WITH_SELF); /* stack: starting context */ | O(*$$, OP_WITH_SELF); /* stack: starting context */ |
| P(*$$, *diving_code, | P(*$$, *diving_code, |
| /* skip over... */ | /* skip over... */ |
| diving_code->count()>=3?3/*OP_VALUE+string+OP_GET_ELEMENTx*/:2/*OP_+string*/); | diving_code->count()>=4?4/*OP_VALUE+origin+string+OP_GET_ELEMENTx*/:3/*OP_+origin+string*/); |
| } else { | } else { |
| O(*$$, OP_WITH_ROOT); /* stack: starting context */ | O(*$$, OP_WITH_ROOT); /* stack: starting context */ |
| P(*$$, *diving_code); | P(*$$, *diving_code); |
| Line 334 construct: | Line 343 construct: |
| | construct_round | | construct_round |
| | construct_curly | | construct_curly |
| ; | ; |
| construct_square: '[' any_constructor_code_value ']' { | construct_square: '[' { |
| // allow $result_or_other_variable[ letters here any time ] | |
| *reinterpret_cast<bool*>(&$$)=PC.explicit_result; PC.explicit_result=false; | |
| } any_constructor_code_value { | |
| PC.explicit_result=*reinterpret_cast<bool*>(&$2); | |
| } ']' { | |
| // stack: context, name | // stack: context, name |
| $$=$2; // stack: context, name, value | $$=$3; // 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) */ |
| } | } |
| ; | ; |
| Line 386 call_value: '^' { | Line 400 call_value: '^' { |
| $$=$3; /* with_xxx,diving code; stack: context,method_junction */ | $$=$3; /* with_xxx,diving code; stack: context,method_junction */ |
| YYSTYPE params_code=$5; | YYSTYPE params_code=$5; |
| if(params_code->count()==3) { // probably [] case. [OP_VALUE + Void + STORE_PARAM] | if(params_code->count()==4) { // probably [] case. [OP_VALUE+origin+Void+STORE_PARAM] |
| if(Value* value=LA2V(*params_code)) // it is OP_VALUE + value? | if(Value* value=LA2V(*params_code)) // it is OP_VALUE+origin+value? |
| if(!value->is_defined()) // value is VVoid? | if(!value->is_defined()) // value is VVoid? |
| params_code=0; // ^zzz[] case. don't append lone empty param. | params_code=0; // ^zzz[] case. don't append lone empty param. |
| } | } |
| Line 403 store_param: | Line 417 store_param: |
| | store_round_param | | store_round_param |
| | store_curly_param | | store_curly_param |
| ; | ; |
| store_square_param: '[' store_code_param_parts ']' {$$=$2}; | store_square_param: '[' { |
| // allow ^call[ letters here any time ] | |
| *reinterpret_cast<bool*>(&$$)=PC.explicit_result; PC.explicit_result=false; | |
| } store_code_param_parts { | |
| PC.explicit_result=*reinterpret_cast<bool*>(&$2); | |
| } ']' {$$=$3}; | |
| store_round_param: '(' store_expr_param_parts ')' {$$=$2}; | store_round_param: '(' store_expr_param_parts ')' {$$=$2}; |
| store_curly_param: '{' store_curly_param_parts '}' {$$=$2}; | store_curly_param: '{' store_curly_param_parts '}' {$$=$2}; |
| store_code_param_parts: | store_code_param_parts: |
| Line 482 name_expr_with_subvar_value: STRING subv | Line 501 name_expr_with_subvar_value: STRING subv |
| $$=N(); | $$=N(); |
| OA(*$$, OP_STRING_POOL, code); | OA(*$$, OP_STRING_POOL, code); |
| }; | }; |
| name_square_code_value: '[' codes ']' { | name_square_code_value: '[' { |
| // allow $result_or_other_variable[ letters here any time ] | |
| *reinterpret_cast<bool*>(&$$)=PC.explicit_result; PC.explicit_result=false; | |
| } codes { | |
| PC.explicit_result=*reinterpret_cast<bool*>(&$2); | |
| } ']' { | |
| $$=N(); | $$=N(); |
| OA(*$$, OP_OBJECT_POOL, $2); /* stack: empty write context */ | OA(*$$, OP_OBJECT_POOL, $3); /* stack: empty write context */ |
| /* some code that writes to that context */ | /* some code that writes to that context */ |
| /* context=pop; stack: context.value() */ | /* context=pop; stack: context.value() */ |
| }; | }; |
| Line 527 class_constructor_prefix: class_static_p | Line 551 class_constructor_prefix: class_static_p |
| /* expr */ | /* expr */ |
| expr_value: expr { | expr_value: expr; |
| // see OP_PREPARE_TO_EXPRESSION!! | |
| if(($$=$1)->count()==2) // only one string literal in there? | |
| change_string_literal_to_double_literal(*$$); // make that string literal Double | |
| }; | |
| expr: | expr: |
| STRING | double_or_STRING |
| | get_value | | get_value |
| | call_value | | call_value |
| | '"' string_inside_quotes_value '"' { $$ = $2; } | | '"' string_inside_quotes_value '"' { $$ = $2; } |
| Line 578 expr: | Line 598 expr: |
| | expr "is" expr { $$=$1; P(*$$, *$3); O(*$$, OP_IS) } | | expr "is" expr { $$=$1; P(*$$, *$3); O(*$$, OP_IS) } |
| ; | ; |
| double_or_STRING: STRING { | |
| // optimized from OP_STRING->OP_VALUE for doubles | |
| maybe_change_string_literal_to_double_literal(*($$=$1)); | |
| }; | |
| string_inside_quotes_value: maybe_codes { | string_inside_quotes_value: maybe_codes { |
| $$=N(); | $$=N(); |
| OA(*$$, OP_STRING_POOL, $1); /* stack: empty write context */ | OA(*$$, OP_STRING_POOL, $1); /* stack: empty write context */ |
| Line 645 static int yylex(YYSTYPE *lvalp, void *a | Line 670 static int yylex(YYSTYPE *lvalp, void *a |
| c=*(end=(pc.source++)); | c=*(end=(pc.source++)); |
| // fprintf(stderr, "\nchar: %c %02X; nestage: %d, sp=%d", c, c, lexical_brackets_nestage, pc.sp); | // fprintf(stderr, "\nchar: %c %02X; nestage: %d, sp=%d", c, c, lexical_brackets_nestage, pc.sp); |
| if(c=='\n') { | if(c=='\n') |
| pc.pos_next_line(); | pc.pos_next_line(); |
| } else | else |
| pc.pos.col+=c=='\t'?TAB_SIZE:1; | pc.pos_next_c(c); |
| // fprintf(stderr, "\nchar: %c file(%d:%d)", c, pc.pos.line, pc.pos.col); | |
| if(c=='@' && pc.pos.col==0+1) { | if(pc.pos.col==0+1 && c=='@') { |
| if(pc.ls==LS_DEF_SPECIAL_BODY) { | if(pc.ls==LS_DEF_SPECIAL_BODY) { |
| // @SPECIAL | // @SPECIAL |
| // ... | // ... |
| Line 663 static int yylex(YYSTYPE *lvalp, void *a | Line 689 static int yylex(YYSTYPE *lvalp, void *a |
| } else // @ in first column inside some code [when could that be?] | } else // @ in first column inside some code [when could that be?] |
| result=BAD_METHOD_DECL_START; | result=BAD_METHOD_DECL_START; |
| goto break2; | goto break2; |
| } else if(c=='^') { | } |
| if(c=='^') { | |
| if(pc.ls==LS_METHOD_AFTER) { | if(pc.ls==LS_METHOD_AFTER) { |
| // handle after-method situation | // handle after-method situation |
| pop_LS(pc); | pop_LS(pc); |
| Line 694 default: | Line 721 default: |
| if(!pc.string_start) | if(!pc.string_start) |
| pc.string_start=begin_pos; | pc.string_start=begin_pos; |
| // append piece till ^ | // append piece till ^ |
| pc.string.append_strdup(begin, end-begin); | pc.string.append_strdup_know_length(begin, end-begin); |
| } | } |
| // reset piece 'begin' position & line | // reset piece 'begin' position & line |
| begin=pc.source; // ->punctuation | begin=pc.source; // ->punctuation |
| Line 710 default: | Line 737 default: |
| if(!pc.string_start) | if(!pc.string_start) |
| pc.string_start=begin_pos; | pc.string_start=begin_pos; |
| // append piece till ^ | // append piece till ^ |
| pc.string.append_strdup(begin, end-begin); | pc.string.append_strdup_know_length(begin, end-begin); |
| } | } |
| // #HH ? | // #HH ? |
| if(pc.source[0]=='#' && pc.source[1] && pc.source[2]) { | if(pc.source[0]=='#' && pc.source[1] && pc.source[2]) { |
| Line 743 default: | Line 770 default: |
| if(!pc.string_start) | if(!pc.string_start) |
| pc.string_start=begin_pos; | pc.string_start=begin_pos; |
| // append piece till # | // append piece till # |
| pc.string.append_strdup(begin, end-begin); | pc.string.append_strdup_know_length(begin, end-begin); |
| } | } |
| // fall into COMMENT lexical state [wait for \n] | // fall into COMMENT lexical state [wait for \n] |
| push_LS(pc, LS_USER_COMMENT); | push_LS(pc, LS_USER_COMMENT); |
| Line 782 default: | Line 809 default: |
| lexical_brackets_nestage++; | lexical_brackets_nestage++; |
| break; | break; |
| } | } |
| if(pc.explicit_result && c) | |
| switch(c) { | |
| case '\n': case ' ': case '\t': | |
| begin=pc.source; | |
| begin_pos=pc.pos; | |
| continue; // skip it | |
| default: | |
| result=BAD_NONWHITESPACE_CHARACTER_IN_EXPLICIT_RESULT_MODE; | |
| goto break2; | |
| } | |
| break; | break; |
| // #COMMENT | // #COMMENT |
| Line 888 default: | Line 925 default: |
| if(!pc.string_start) | if(!pc.string_start) |
| pc.string_start=begin_pos; | pc.string_start=begin_pos; |
| // append piece till # | // append piece till # |
| pc.string.append_strdup(begin, end-begin); | pc.string.append_strdup_know_length(begin, end-begin); |
| } | } |
| // fall into COMMENT lexical state [wait for \n] | // fall into COMMENT lexical state [wait for \n] |
| push_LS(pc, LS_EXPRESSION_COMMENT); | push_LS(pc, LS_EXPRESSION_COMMENT); |
| Line 1235 default: | Line 1272 default: |
| case ':': // ':name' or 'class:name' | case ':': // ':name' or 'class:name' |
| case '^': // ^abc^xxx wrong. bailing out | case '^': // ^abc^xxx wrong. bailing out |
| case ']': case '}': case ')': // ^abc]}) wrong. bailing out | case ']': case '}': case ')': // ^abc]}) wrong. bailing out |
| case ' ': // ^if ( wrong. bailing out | |
| RC; | RC; |
| } | } |
| break; | break; |
| Line 1281 default: | Line 1319 default: |
| lexical_brackets_nestage++; | lexical_brackets_nestage++; |
| break; | break; |
| } | } |
| if(pc.explicit_result && c) | |
| switch(c) { | |
| case '\n': case ' ': case '\t': | |
| begin=pc.source; | |
| begin_pos=pc.pos; | |
| continue; // skip it | |
| default: | |
| result=BAD_NONWHITESPACE_CHARACTER_IN_EXPLICIT_RESULT_MODE; | |
| goto break2; | |
| } | |
| break; | break; |
| case LS_METHOD_AFTER: | case LS_METHOD_AFTER: |
| Line 1322 break2: | Line 1370 break2: |
| if(!pc.string_start) | if(!pc.string_start) |
| pc.string_start=begin_pos; | pc.string_start=begin_pos; |
| // append it | // append it |
| pc.string.append_strdup(begin, end-begin); | pc.string.append_strdup_know_length(begin, end-begin); |
| } | } |
| } | } |
| if(!pc.string.is_empty()) { // something accumulated? | if(!pc.string.is_empty()) { // something accumulated? |
| // create STRING value: array of OP_VALUE+vstring | // create STRING value: array of OP_VALUE+origin+vstring |
| *lvalp=VL( | *lvalp=VL( |
| new VString(*new String(pc.string, String::L_CLEAN)), | new VString(*new String(pc.string, String::L_CLEAN)), |
| pc.file_no, pc.string_start.line, pc.string_start.col); | pc.file_no, pc.string_start.line, pc.string_start.col); |