--- parser3/src/main/compile.y 2001/03/08 09:31:47 1.70 +++ parser3/src/main/compile.y 2001/03/10 15:17:46 1.84 @@ -1,5 +1,5 @@ /* - $Id: compile.y,v 1.70 2001/03/08 09:31:47 paf Exp $ + $Id: compile.y,v 1.84 2001/03/10 15:17:46 paf Exp $ */ %{ @@ -22,7 +22,7 @@ #include "pa_vdouble.h" #define SELF_NAME "self" -#define USES_NAME "USES" +#define USE_NAME "USE" int real_yyerror(parse_control *pc, char *s); static void yyprint(FILE *file, int type, YYSTYPE value); @@ -86,14 +86,16 @@ int yylex(YYSTYPE *lvalp, void *pc); %% -all: +all: /* TODO: у ^execute непременно задать какой-то name, см. 'RUN' */ one_big_piece { - String& name_main=*NEW String(POOL); - name_main.APPEND_CONST(MAIN_METHOD_NAME); - Array& param_names=*NEW Array(POOL); - Array& local_names=*NEW Array(POOL); - Method& method=*NEW Method(POOL, name_main, param_names, local_names, *$1); - PC->vclass->add_method(name_main, method); + String& MAIN=*NEW String(POOL); + MAIN.APPEND_CONST(MAIN_METHOD_NAME); + Method& method=*NEW Method(POOL, + MAIN, + 0, 0, /*min, max numbered_params_count*/ + 0/*param_names*/, 0/*local_names*/, + $1/*parser_code*/, 0/*native_code*/); + PC->vclass->add_method(MAIN, method); } | methods; @@ -104,31 +106,51 @@ method: control_method | code_method; control_method: '@' STRING '\n' control_strings { - String& name=*SLA2S($2); + const String& command=*SLA2S($2); YYSTYPE strings_code=$4; if(strings_code->size()<1*2) { strcpy(PC->error, "@"); - strcat(PC->error, name.cstr()); + strcat(PC->error, command.cstr()); strcat(PC->error, " is empty"); YYERROR; } - if(name==CLASS_NAME) { - if(strings_code->size()==1*2) - PC->vclass->set_name(*SLA2S(strings_code)); - else { + if(command==CLASS_NAME) { + if(PC->vclass!=&PC->request->root_class) { // already changed from default? + strcpy(PC->error, "class already have a name '"); + strncat(PC->error, PC->vclass->name().cstr(), 100); + strcat(PC->error, "'"); + YYERROR; + } + if(strings_code->size()==1*2) { + // new class' name + const String *name=SLA2S(strings_code); + // creating the class + PC->vclass=NEW VClass(POOL); + PC->vclass->set_name(*name); + // defaulting base. may change with @BASE + PC->vclass->set_base(PC->request->root_class); + // append to request's classes + PC->request->classes_array()+=PC->vclass; + PC->request->classes().put(*name, PC->vclass); + } else { strcpy(PC->error, "@"CLASS_NAME" must contain sole name"); YYERROR; } } else { - if(name==USES_NAME) { + if(command==USE_NAME) { for(int i=0; isize(); i+=2) { - String *file=SLA2S(strings_code, i); - file->APPEND_CONST(".p"); - PC->request->use(file->cstr(), 0); + String file(*SLA2S(strings_code, i)); + file.APPEND_CONST(".p"); + PC->request->use(file.cstr(), 0); + } + } else if(command==BASE_NAME) { + if(PC->vclass->base()!=&PC->request->root_class) { // already changed from default? + strcpy(PC->error, "there must be only one @"BASE_NAME); + YYERROR; } - } else if(name==BASE_NAME) { if(strings_code->size()==1*2) { - String& base_name=*SLA2S(strings_code); + // TODO: преодолеть self и циклические base + const String& base_name=*SLA2S(strings_code); VClass *base=static_cast( PC->request->classes().get(base_name)); if(!base) { @@ -142,9 +164,9 @@ control_method: '@' STRING '\n' YYERROR; } } else { - strcpy(PC->error, name.cstr()); + strcpy(PC->error, command.cstr()); strcat(PC->error, ": invalid special name. valid names are " - CLASS_NAME", "USES_NAME" and "BASE_NAME); + CLASS_NAME", "USE_NAME" and "BASE_NAME); YYERROR; } } @@ -158,16 +180,26 @@ code_method: '@' STRING bracketed_maybe_ const String *name=SLA2S($2); YYSTYPE params_names_code=$3; - Array& params_names=*NEW Array(POOL); - for(int i=0; isize(); i+=2) - params_names+=SLA2S(params_names_code, i); + Array *params_names=0; + if(int size=params_names_code->size()) { + params_names=NEW Array(POOL); + for(int i=0; isize(); i+=2) - locals_names+=SLA2S(locals_names_code, i); + Array *locals_names=0; + if(int size=locals_names_code->size()) { + locals_names=NEW Array(POOL); + for(int i=0; ivclass->add_method(*name, method); }; @@ -186,7 +218,7 @@ codes: code | codes code { $$=$1; P($$, $2); }; -code: write_str_literal | action; +code: write_string | action; action: get | put | with | call; /* get */ @@ -205,7 +237,7 @@ name_without_curly_rdive: name_without_curly_rdive_read: name_without_curly_rdive_code { $$=N(POOL); Array *diving_code=$1; - String *first_name=SLA2S(diving_code); + const String *first_name=SLA2S(diving_code); if(first_name && *first_name==SELF_NAME) { O($$, OP_WITH_SELF); /* stack: starting context */ P($$, diving_code, @@ -227,10 +259,9 @@ name_without_curly_rdive_code: name_adva /* put */ -put: '$' name_expr_wdive constructor_value { +put: '$' name_expr_wdive construct { $$=$2; /* stack: context,name */ P($$, $3); /* stack: context,name,constructor_value */ - O($$, OP_CONSTRUCT); /* value=pop; name=pop; context=pop; construct(context,name,value) */ }; name_expr_wdive: name_expr_wdive_write @@ -239,7 +270,7 @@ name_expr_wdive: name_expr_wdive_write: name_expr_dive_code { $$=N(POOL); Array *diving_code=$1; - String *first_name=SLA2S(diving_code); + const String *first_name=SLA2S(diving_code); if(first_name && *first_name==SELF_NAME) { O($$, OP_WITH_SELF); /* stack: starting context */ P($$, diving_code, @@ -258,9 +289,16 @@ name_expr_wdive_root: ':' name_expr_dive }; name_expr_wdive_class: class_prefix name_expr_dive_code { $$=$1; P($$, $2) }; -constructor_value: - '[' any_constructor_code_value ']' { $$=$2 } -| '(' any_expr ')' { $$=$2 } +construct: construct_by_code | construct_by_expr; +construct_by_code: '[' any_constructor_code_value ']' { + $$=$2; /* stack: context, name, value */ + O($$, OP_CONSTRUCT_VALUE); /* value=pop; name=pop; context=pop; construct(context,name,value) */ +} +; +construct_by_expr: '(' any_expr ')' { + $$=$2; /* stack: context, name, value */ + O($$, OP_CONSTRUCT_EXPR); /* value=pop; name=pop; context=pop; construct(context,name,value) */ +} ; any_constructor_code_value: empty_string_value /* optimized $var[] case */ @@ -312,19 +350,19 @@ store_expr_param_parts: | store_expr_param_parts ';' store_expr_param_part { $$=$1; P($$, $3) } ; store_code_param_part: - empty /* optimized () case */ -| STRING { /* optimized (STRING) case */ + empty /* optimized [] case */ +| STRING { /* optimized [STRING] case */ $$=$1; O($$, OP_STORE_PARAM); } -| constructor_code_value { /* (something complex) */ +| constructor_code_value { /* [something complex] */ $$=$1; + O($$, OP_STORE_PARAM); } ; store_expr_param_part: write_expr_value { $$=N(POOL); PCA($$, $1); - O($$, OP_STORE_PARAM); }; write_expr_value: any_expr { $$=$1; @@ -384,16 +422,8 @@ subvar__get_write: '$' subvar_ref_name_r }; class_prefix: STRING ':' { - String& name=*SLA2S($1); - VClass *vclass=static_cast(PC->request->classes().get(name)); - if(!vclass) { - strcpy(PC->error, "'"); - strcat(PC->error, name.cstr()); - strcat(PC->error, "' class is undefined in call"); - YYERROR; - } - //TODO: убрать зависимость от статических @USE, сделать имя, а не ссылку - $$=CL(vclass); // vclass + $$=$1; // stack: class name string + O($$, OP_GET_CLASS); }; @@ -411,12 +441,11 @@ with: '$' name_without_curly_rdive '{' c any_expr: empty_double_value /* optimized $var() case */ -| optimized_expr /* $var(something) */ +| expr_value /* $var(something) */ ; -optimized_expr: expr { - if(($$=$1)->size()==2) { // only one string literal in there? +expr_value: expr { + if(($$=$1)->size()==2) // only one string literal in there? change_string_literal_to_double_literal($$); // make that string literal Double - } }; expr: STRING @@ -466,12 +495,12 @@ string_inside_quotes_value: maybe_codes /* basics */ -write_str_literal: STRING { - $$=$1; - O($$, OP_WRITE); +write_string: STRING { + // optimized from OP_STRING+OP_WRITE to OP_STRING__WRITE + change_string_literal_to_write_string_literal($$=$1) }; -empty_double_value: /* empty */ { $$=VL(NEW VDouble(POOL)) }; +empty_double_value: /* empty */ { $$=VL(NEW VDouble(POOL, 0)) }; empty_string_value: /* empty */ { $$=VL(NEW VString(POOL)) }; empty: /* empty */ { $$=N(POOL) }; @@ -519,6 +548,8 @@ int yylex(YYSTYPE *lvalp, void *pc) { } else PC->col++; + // todo: # in 0+1 column comment + // escaping: ^^ ^$ ^; ^) ^} ^( ^{ ^" if(c=='^') switch(*PC->source) { @@ -739,7 +770,7 @@ int yylex(YYSTYPE *lvalp, void *pc) { switch(c) { case '+': case '-': case '*': case '/': case '%': case '&': case '|': - case '<': case '>': case '=': case '!': + case '=': case '!': pop_LS(PC); PC->source--; if(--PC->col<0) { PC->line--; PC->col=-1; } result=EON; @@ -751,6 +782,7 @@ int yylex(YYSTYPE *lvalp, void *pc) { case ' ': case '\t': case '\n': case ';': case ']': case '}': case ')': case '"': + case '<': case '>': // these stand for HTML brackets and expression binary ops pop_LS(PC); PC->source--; if(--PC->col<0) { PC->line--; PC->col=-1; } result=EON;