--- parser3/src/main/compile.y 2015/04/06 22:27:26 1.269 +++ parser3/src/main/compile.y 2016/05/24 15:42:43 1.279 @@ -2,13 +2,13 @@ /** @file Parser: compiler(lexical parser and grammar). - Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexander Petrosyan (http://design.ru/paf) */ -volatile const char * IDENT_COMPILE_Y = "$Id: compile.y,v 1.269 2015/04/06 22:27:26 moko Exp $"; +volatile const char * IDENT_COMPILE_Y = "$Id: compile.y,v 1.279 2016/05/24 15:42:43 moko Exp $"; /** @todo parser4: @@ -22,11 +22,9 @@ volatile const char * IDENT_COMPILE_Y = */ #define YYSTYPE ArrayOperation* -#define YYPARSE_PARAM pc -#define YYLEX_PARAM pc #define YYDEBUG 1 -#define YYERROR_VERBOSE 1 -#define yyerror(msg) real_yyerror((Parse_control *)pc, msg) +#define YYERROR_VERBOSE 1 +#define yyerror(pc, msg) real_yyerror(pc, msg) #define YYPRINT(file, type, value) yyprint(file, type, value) #define YYMALLOC pa_malloc #define YYFREE pa_free @@ -45,9 +43,6 @@ volatile const char * IDENT_COMPILE_Y = #define USE_CONTROL_METHOD_NAME "USE" #define OPTIONS_CONTROL_METHOD_NAME "OPTIONS" -#define OPTION_ALL_VARS_LOCAL_NAME "locals" -#define OPTION_PARTIAL_CLASS "partial" -#define REM_OPERATOR_NAME "rem" // forwards @@ -61,20 +56,22 @@ static const VString vempty; // local convinient inplace typecast & var #undef PC -#define PC (*(Parse_control *)pc) +#define PC (*pc) #undef POOL #define POOL (*PC.pool) #ifndef DOXYGEN #define CLASS_ADD if(PC.class_add()){ \ - strncpy(PC.error, PC.cclass->name().cstr(), MAX_STRING/2); \ + strncpy(PC.error, PC.cclass->type(), MAX_STRING/2); \ strcat(PC.error, " - class is already defined"); \ YYERROR; \ } %} -%pure_parser +%pure-parser +%lex-param {Parse_control* pc} +%parse-param {Parse_control* pc} %token EON %token STRING @@ -84,7 +81,6 @@ static const VString vempty; %token BAD_HEX_LITERAL %token BAD_METHOD_DECL_START %token BAD_METHOD_PARAMETER_NAME_CHARACTER -%token BAD_NONWHITESPACE_CHARACTER_IN_EXPLICIT_RESULT_MODE %token LAND "&&" %token LOR "||" @@ -171,7 +167,7 @@ control_method: '@' STRING '\n' // creating the class VStateless_class* cclass=new VClass; PC.cclass_new=cclass; - PC.cclass_new->set_name(name); + PC.cclass_new->set_type(name.cstr()); PC.append=false; } else { strcpy(PC.error, "@" CLASS_NAME " must contain only one line with class name (contains more then one)"); @@ -179,19 +175,21 @@ control_method: '@' STRING '\n' } } else if(command==USE_CONTROL_METHOD_NAME) { CLASS_ADD; - for(size_t i=0; icount(); i+=OPERATIONS_PER_OPVALUE) - PC.request.use_file(PC.request.main_class, LA2S(*strings_code, i)->trim(String::TRIM_END), PC.request.get_used_filename(PC.file_no)); + for(size_t i=0; icount(); i+=OPERATIONS_PER_OPVALUE){ + PC.request.use_file(PC.request.main_class, LA2S(*strings_code, i)->trim(String::TRIM_END), + PC.request.get_used_filename(PC.file_no), strings_code->get(i+1).origin); + } } else if(command==BASE_NAME) { if(PC.append){ strcpy(PC.error, "can't set base while appending methods to class '"); - strncat(PC.error, PC.cclass->name().cstr(), MAX_STRING/2); + strncat(PC.error, PC.cclass->type(), MAX_STRING/2); strcat(PC.error, "'"); YYERROR; } CLASS_ADD; if(PC.cclass->base_class()) { // already changed from default? strcpy(PC.error, "class already have a base '"); - strncat(PC.error, PC.cclass->base_class()->name().cstr(), MAX_STRING/2); + strncat(PC.error, PC.cclass->base_class()->type(), MAX_STRING/2); strcat(PC.error, "'"); YYERROR; } @@ -222,14 +220,14 @@ control_method: '@' STRING '\n' } else if(command==OPTIONS_CONTROL_METHOD_NAME) { for(size_t i=0; icount(); i+=OPERATIONS_PER_OPVALUE) { const String& option=LA2S(*strings_code, i)->trim(String::TRIM_END); - if(option==OPTION_ALL_VARS_LOCAL_NAME){ + if(option==Symbols::LOCALS_SYMBOL){ PC.set_all_vars_local(); - } else if(option==OPTION_PARTIAL_CLASS){ + } else if(option==Symbols::PARTIAL_SYMBOL){ if(PC.cclass_new){ if(VStateless_class* existed=PC.get_existed_class(PC.cclass_new)){ if(!PC.reuse_existed_class(existed)){ strcpy(PC.error, "can't append methods to '"); - strncat(PC.error, PC.cclass_new->name().cstr(), MAX_STRING/2); + strncat(PC.error, PC.cclass_new->type(), MAX_STRING/2); strcat(PC.error, "' - the class wasn't marked as partial"); YYERROR; } @@ -238,20 +236,17 @@ control_method: '@' STRING '\n' PC.cclass_new->set_partial(); } } else { - strcpy(PC.error, "'" OPTION_PARTIAL_CLASS "' option should be used straight after @" CLASS_NAME); + strcpy(PC.error, "'partial' option should be used straight after @" CLASS_NAME); YYERROR; } - } else if(option==method_call_type_static){ + } else if(option==Symbols::STATIC_SYMBOL){ PC.set_methods_call_type(Method::CT_STATIC); - } else if(option==method_call_type_dynamic){ + } else if(option==Symbols::DYNAMIC_SYMBOL){ PC.set_methods_call_type(Method::CT_DYNAMIC); } else { strcpy(PC.error, "'"); strncat(PC.error, option.cstr(), MAX_STRING/2); - strcat(PC.error, "' invalid option. valid options are " - "'" OPTION_PARTIAL_CLASS "', '" OPTION_ALL_VARS_LOCAL_NAME "'" - ", '" METHOD_CALL_TYPE_STATIC "' and '" METHOD_CALL_TYPE_DYNAMIC "'" - ); + strcat(PC.error, "' invalid option. valid options are 'partial', 'locals', 'static' and 'dynamic'"); YYERROR; } } @@ -287,9 +282,9 @@ code_method: '@' STRING bracketed_maybe_ locals_names=new ArrayString; for(int i=0; icount(); + if(count){ + $$=$1; +#ifdef OPTIMIZE_BYTECODE_GET_OBJECT_ELEMENT + !(count==5 && change_first(*$$, OP::OP_GET_OBJECT_ELEMENT, OP::OP_GET_OBJECT_ELEMENT4CALL)) && +#endif +#ifdef OPTIMIZE_BYTECODE_GET_OBJECT_VAR_ELEMENT + !(count==5 && change_first(*$$, OP::OP_GET_OBJECT_VAR_ELEMENT, OP::OP_GET_OBJECT_VAR_ELEMENT4CALL)) && +#endif + !change(*$$, count-1, OP::OP_GET_ELEMENT, OP::OP_GET_ELEMENT4CALL); + } +#endif +}; store_params: store_param | store_params store_param { $$=$1; P(*$$, *$2); }; store_param: @@ -739,7 +752,7 @@ class_static_prefix: STRING ':' { $$=$1; // stack: class name string if(*LA2S(*$$) == BASE_NAME) { // pseudo BASE class if(VStateless_class* base=PC.cclass->base_class()) { - change_string_literal_value(*$$, base->name()); + change_string_literal_value(*$$, *new String(base->type())); } else { strcpy(PC.error, "no base class declared"); YYERROR; @@ -1044,13 +1057,12 @@ default: } if(pc.explicit_result && c) switch(c) { + default: + pc.string.append(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; + continue; } break; @@ -1073,8 +1085,8 @@ default: case '"': case '\'': if( - pc.ls == LS_EXPRESSION_STRING_QUOTED && c=='"' || - pc.ls == LS_EXPRESSION_STRING_APOSTROFED && c=='\'') { + (pc.ls == LS_EXPRESSION_STRING_QUOTED && c=='"') || + (pc.ls == LS_EXPRESSION_STRING_APOSTROFED && c=='\'') ) { pop_LS(pc); //"abc". | 'abc'. RC; } @@ -1147,11 +1159,12 @@ default: case LS_METHOD_ROUND: switch(c) { case ')': - if(--lexical_brackets_nestage==0) + if(--lexical_brackets_nestage==0) { if(pc.ls==LS_METHOD_ROUND) // method round param ended pc.ls=LS_METHOD_AFTER; // look for method end else // pc.ls==LS_VAR_ROUND // variable constructor ended pop_LS(pc); // return to normal life + } RC; case '#': // comment start skipping if(end!=begin) { @@ -1576,13 +1589,12 @@ default: } if(pc.explicit_result && c) switch(c) { + default: + pc.string.append(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; + continue; } break; @@ -1627,9 +1639,13 @@ break2: } if(!pc.string.is_empty()) { // something accumulated? // create STRING value: array of OP_VALUE+origin+vstring +#ifdef SYMBOLS_CACHING + Value *lookup=symbols->get(pc.string); +#else + Value *lookup=0; +#endif *lvalp=VL( - new VString(*new String(pc.string, String::L_CLEAN)), - pc.file_no, pc.string_start.line, pc.string_start.col); + lookup ? lookup : new VString(*new String(pc.string, String::L_CLEAN)), pc.file_no, pc.string_start.line, pc.string_start.col); // new pieces storage pc.string.clear(); pc.string_start.clear();