Diff for /parser3/src/main/compile.y between versions 1.92 and 1.165.4.1

version 1.92, 2001/03/12 18:13:49 version 1.165.4.1, 2001/09/12 09:52:53
Line 1 Line 1
 /*  /** @file
         Parser          Parser: compiler(lexical parser and grammar).
   
         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)  
   
         $Id$          Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
 */  */
   %{
   static char *RCSId="$Id$"; 
   
 /*  /**
         TODO.parser4:           @todo parser4: 
                 cache compiled code from request to request. to do that...          - cache compiled code from request to request. to do that...
                 1:      make method definitions, @CLASS, @BASE, @USE instructions,                  -#:     make method definitions, @CLASS, @BASE, @USE instructions,
                         which would be executed afterwards, and actions                          which would be executed afterwards, and actions
                         now performed at compile time would be delayed to run time.                          now performed at compile time would be delayed to run time.
                 2:      make cache expiration on time and on disk-change of class source                  -#:     make cache expiration on time and on disk-change of class source
                 3:      in apache use subpools for compiled class storage                  -#:     in apache use subpools for compiled class storage
                 4:      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
 #define YYDEBUG  1  #define YYDEBUG  1
 #define YYERROR_VERBOSE  #define YYERROR_VERBOSE 1
 #define yyerror(msg)  real_yyerror((parse_control *)pc, msg)  #define yyerror(msg)  real_yyerror((parse_control *)pc, msg)
 #define YYPRINT(file, type, value)  yyprint(file, type, value)  #define YYPRINT(file, type, value)  yyprint(file, type, value)
   
 #include <stdio.h>  
 #include <string.h>  
 #include <stdlib.h>  
   
 #include "compile_tools.h"  #include "compile_tools.h"
 #include "pa_value.h"  #include "pa_value.h"
 #include "pa_request.h"  #include "pa_request.h"
 #include "pa_vobject.h"  #include "pa_vobject.h"
 #include "pa_vdouble.h"  #include "pa_vdouble.h"
 #include "core.h"  #include "pa_globals.h"
   #include "pa_vvoid.h"
   
 #define SELF_ELEMENT_NAME "self"  #define SELF_ELEMENT_NAME "self"
 #define USE_CONTROL_METHOD_NAME "use"  #define USE_CONTROL_METHOD_NAME "USE"
   
 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);
 int yylex(YYSTYPE *lvalp, void *pc);  static int yylex(YYSTYPE *lvalp, void *pc);
   
   
 // local convinient inplace typecast & var  // local convinient inplace typecast & var
 #define PC  ((parse_control *)pc)  #define PC  (*(parse_control *)pc)
 #define POOL  *PC->pool  #define POOL  (*PC.pool)
 #undef NEW  #undef NEW
 #define NEW new(POOL)  #define NEW new(POOL)
   #ifndef DOXYGEN
 %}  %}
   
 %pure_parser  %pure_parser
Line 59  int yylex(YYSTYPE *lvalp, void *pc); Line 58  int yylex(YYSTYPE *lvalp, void *pc);
 %token BOGUS  %token BOGUS
   
 %token BAD_STRING_COMPARISON_OPERATOR  %token BAD_STRING_COMPARISON_OPERATOR
   %token BAD_HEX_LITERAL
   
 %token LAND "&&"  %token LAND "&&"
 %token LOR "||"  %token LOR "||"
Line 79  int yylex(YYSTYPE *lvalp, void *pc); Line 79  int yylex(YYSTYPE *lvalp, void *pc);
 %token DEF "def"  %token DEF "def"
 %token IN "in"  %token IN "in"
 %token FEXISTS "-f"  %token FEXISTS "-f"
   %token DEXISTS "-d"
   %token IS "is"
   
 /* logical */  /* logical */
 %left "lt" "gt" "le" "ge"  %left "##"
 %left "eq" "ne"  
 %left '<' '>' "<=" ">=" "##"  
 %left "==" "!="  
 %left "||"  %left "||"
 %left "&&"  %left "&&"
 %left "def" "in" "-f"  %left '<' '>' "<=" ">="   "lt" "gt" "le" "ge"
   %left "==" "!="  "eq" "ne"
   %left "is" "def" "in" "-f" "-d"
 %left '!'  %left '!'
   
 /* bitwise */  /* bitwise */
 %left '#'  %left '#'
 %left '&' '|'  %left '|'
   %left '&' 
 %left '~'  %left '~'
   
 /* numerical */  /* numerical */
Line 101  int yylex(YYSTYPE *lvalp, void *pc); Line 103  int yylex(YYSTYPE *lvalp, void *pc);
 %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, 
                   Method::CT_ANY,
                 0, 0, /*min, max numbered_params_count*/                  0, 0, /*min, max numbered_params_count*/
                 0/*param_names*/, 0/*local_names*/,                   0/*param_names*/, 0/*local_names*/, 
                 $1/*parser_code*/, 0/*native_code*/);                  $1/*parser_code*/, 0/*native_code*/);
         PC->cclass->add_method(*main_method_name, method);          PC.cclass->add_method(*main_method_name, method);
 }  }
 |       methods;  |       methods;
   
Line 118  one_big_piece: maybe_codes; Line 121  one_big_piece: maybe_codes;
 method: control_method | code_method;  method: control_method | code_method;
   
 control_method: '@' STRING '\n'   control_method: '@' STRING '\n' 
                                 control_strings {                                  maybe_control_strings {
         const String& command=*SLA2S($2);          const String& command=*LA2S($2);
         YYSTYPE strings_code=$4;          YYSTYPE strings_code=$4;
         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());
                 strcat(PC->error, " is empty");                  strcat(PC.error, " is empty");
                 YYERROR;                  YYERROR;
         }          }
         if(command==CLASS_NAME) {          if(command==CLASS_NAME) {
                 if(PC->cclass!=&PC->request->root_class) { // 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, "'");
                         YYERROR;                          YYERROR;
                 }                  }
                 if(strings_code->size()==1*2) {                  if(strings_code->size()==1*2) {
                         // new class' name                          // new class' name
                         const String *name=SLA2S(strings_code);                          const String *name=LA2S(strings_code);
                         // creating the class                          // creating the class
                         PC->cclass=NEW VClass(POOL);                          PC.cclass=NEW VClass(POOL);
                         PC->cclass->set_name(*name);                          PC.cclass->set_name(*name);
                         // defaulting base. may change with @BASE  
                         PC->cclass->set_base(PC->request->root_class);  
                         // append to request's classes                          // append to request's classes
                         PC->request->classes_array()+=PC->cclass;                          PC.request->classes().put(*name, PC.cclass);
                         PC->request->classes().put(*name, PC->cclass);  
                 } else {                  } else {
                         strcpy(PC->error, "@"CLASS_NAME" must contain sole name");                          strcpy(PC.error, "@"CLASS_NAME" must contain sole name");
                         YYERROR;                          YYERROR;
                 }                  }
         } else {          } else if(command==USE_CONTROL_METHOD_NAME) {
                 if(command==USE_CONTROL_METHOD_NAME) {                  for(int i=0; i<strings_code->size(); i+=2) 
                         for(int i=0; i<strings_code->size(); i+=2) {                          PC.request->use_file(*LA2S(strings_code, i));
                                 String file(*SLA2S(strings_code, i));          } else if(command==BASE_NAME) {
                                 file.APPEND_CONST(".p");                  if(PC.cclass->base()) { // already changed from default?
                                 PC->request->use_file(file.cstr());                          strcpy(PC.error, "class already have a base '");
                         }                          strncat(PC.error, PC.cclass->base()->name().cstr(), 100);
                 } else if(command==BASE_NAME) {                          strcat(PC.error, "'");
                         if(PC->cclass->base()!=&PC->request->root_class) { // already changed from default?                          YYERROR;
                                 strcpy(PC->error, "class already have a base '");                  }
                                 strncat(PC->error, PC->cclass->base()->name().cstr(), 100);                  if(strings_code->size()==1*2) {
                                 strcat(PC->error, "'");                          const String& base_name=*LA2S(strings_code);
                           VClass *base=static_cast<VClass *>(
                                   PC.request->classes().get(base_name));
                           if(!base) {
                                   strcpy(PC.error, base_name.cstr());
                                   strcat(PC.error, ": undefined class in @"BASE_NAME);
                                 YYERROR;                                  YYERROR;
                         }                          }
                         if(strings_code->size()==1*2) {                          // @CLASS == @BASE sanity check
                                 // TODO: преодолеть self и циклические base                          if(PC.cclass==base) {
                                 const String& base_name=*SLA2S(strings_code);                                  strcpy(PC.error, "@"CLASS_NAME" equals @"BASE_NAME);
                                 VClass *base=static_cast<VClass *>(  
                                         PC->request->classes().get(base_name));  
                                 if(!base) {  
                                         strcpy(PC->error, base_name.cstr());  
                                         strcat(PC->error, ": undefined class in @"BASE_NAME);  
                                         YYERROR;  
                                 }  
                                 PC->cclass->set_base(*base);  
                         } else {  
                                 strcpy(PC->error, "@"BASE_NAME" must contain sole name");  
                                 YYERROR;                                  YYERROR;
                         }                          }
                           PC.cclass->set_base(*base);
                 } else {                  } else {
                         strcpy(PC->error, "'");                          strcpy(PC.error, "@"BASE_NAME" must contain sole name");
                         strncat(PC->error, command.cstr(), MAX_STRING-1);  
                         strcat(PC->error, "' invalid special name. valid names are "  
                                 "'"CLASS_NAME"', '"USE_CONTROL_METHOD_NAME"' and '"BASE_NAME"'");  
                         YYERROR;                          YYERROR;
                 }                  }
           } else {
                   strcpy(PC.error, "'");
                   strncat(PC.error, command.cstr(), MAX_STRING/2);
                   strcat(PC.error, "' invalid special name. valid names are "
                           "'"CLASS_NAME"', '"USE_CONTROL_METHOD_NAME"' and '"BASE_NAME"'");
                   YYERROR;
         }          }
 };  };
   maybe_control_strings: empty | control_strings;
 control_strings: control_string | control_strings control_string { $$=$1; P($$, $2) };  control_strings: control_string | control_strings control_string { $$=$1; P($$, $2) };
 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 {                          maybe_codes {
         const String *name=SLA2S($2);          const String *name=LA2S($2);
   
         YYSTYPE params_names_code=$3;          YYSTYPE params_names_code=$3;
         Array *params_names=0;          Array *params_names=0;
         if(int size=params_names_code->size()) {          if(int size=params_names_code->size()) {
                 params_names=NEW Array(POOL);                  params_names=NEW Array(POOL);
                 for(int i=0; i<size; i+=2)                  for(int i=0; i<size; i+=2)
                         *params_names+=SLA2S(params_names_code, i);                          *params_names+=LA2S(params_names_code, i);
         }          }
   
         YYSTYPE locals_names_code=$4;          YYSTYPE locals_names_code=$4;
Line 208  code_method: '@' STRING bracketed_maybe_ Line 208  code_method: '@' STRING bracketed_maybe_
         if(int size=locals_names_code->size()) {          if(int size=locals_names_code->size()) {
                 locals_names=NEW Array(POOL);                  locals_names=NEW Array(POOL);
                 for(int i=0; i<size; i+=2)                  for(int i=0; i<size; i+=2)
                         *locals_names+=SLA2S(locals_names_code, i);                          *locals_names+=LA2S(locals_names_code, i);
         }          }
   
         Method& method=*NEW Method(POOL,           Method& method=*NEW Method(POOL, 
                 *name,                   *name, 
                   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);                  $7, 0);
         PC->cclass->add_method(*name, method);          PC.cclass->add_method(*name, method);
 };  };
   
 maybe_bracketed_strings: empty | bracketed_maybe_strings;  maybe_bracketed_strings: empty | bracketed_maybe_strings;
Line 232  maybe_codes: empty | codes; Line 233  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 */
   
 get: get_value {  get: get_value {
         $$=$1; /* stack: resulting value */          $$=$1; /* stack: resulting value */
         O($$, OP_WRITE); /* value=pop; wcontext.write(value) */          O($$, OP_WRITE_VALUE); /* value=pop; wcontext.write(value) */
 };  };
 get_value: '$' get_name_value { $$=$2 }  get_value: '$' get_name_value { $$=$2 };
 get_name_value: name_without_curly_rdive EON | name_in_curly_rdive;  get_name_value: name_without_curly_rdive EON | name_in_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); 
         Array *diving_code=$1;          Array *diving_code=$1;
         const String *first_name=SLA2S(diving_code);          const String *first_name=LA2S(diving_code);
         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, 
Line 262  name_without_curly_rdive_read: name_with Line 262  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 277  put: '$' name_expr_wdive construct { Line 272  put: '$' name_expr_wdive construct {
         P($$, $3); /* stack: context,name,constructor_value */          P($$, $3); /* stack: context,name,constructor_value */
 };  };
 name_expr_wdive:   name_expr_wdive: 
         name_expr_wdive_write          name_expr_wdive_root
 |       name_expr_wdive_root  |       name_expr_wdive_write
 |       name_expr_wdive_class;  |       name_expr_wdive_class;
 name_expr_wdive_write: name_expr_dive_code {  name_expr_wdive_root: name_expr_dive_code {
         $$=N(POOL);          $$=N(POOL);
         Array *diving_code=$1;          Array *diving_code=$1;
         const String *first_name=SLA2S(diving_code);          const String *first_name=LA2S(diving_code);
         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->size()>2?3/*OP_+string+get_element*/:2/*OP_+string*/);                          diving_code->size()>2?3/*OP_+string+get_element*/:2/*OP_+string*/);
         } else {          } else {
                 O($$, OP_WITH_WRITE); /* stack: starting context */                  O($$, OP_WITH_ROOT); /* stack: starting context */
                 P($$, diving_code);                  P($$, diving_code);
         }          }
         /* diving code; stack: current context */          /* diving code; stack: current context */
 };  };
 name_expr_wdive_root: ':' name_expr_dive_code {  name_expr_wdive_write: '.' name_expr_dive_code {
         $$=N(POOL);           $$=N(POOL); 
         O($$, OP_WITH_ROOT); /* stack: starting context */          O($$, OP_WITH_WRITE); /* stack: starting context */
         P($$, $2); /* diving code; stack: context,name */          P($$, $2); /* diving code; stack: context,name */
 };  };
 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
         O($$, OP_CONSTRUCT_EXPR); /* value=pop; name=pop; context=pop; construct(context,name,value) */          $$=$2; // stack: context, name, value
           O($$, OP_CONSTRUCT_EXPR); /* value=pop->as_expr_result; 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: 
         empty_string_value /* optimized $var[] case */          void_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 331  codes__excluding_sole_str_literal: actio Line 338  codes__excluding_sole_str_literal: actio
   
 call: call_value {  call: call_value {
         $$=$1; /* stack: value */          $$=$1; /* stack: value */
         O($$, OP_WRITE); /* 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 */
         P($$, $3); /* filling method_frame.store_params */  
         O($$, OP_CALL); /* method_frame=pop; ncontext=pop; call(ncontext,method_frame) stack: value */          YYSTYPE params_code=$5;
           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->is_defined()) // value is VVoid?
                                   params_code=0; // ^zzz[] case. don't append lone empty param.
           if(params_code)
                   P($$, params_code); // filling method_frame.store_params
           O($$, OP_CALL); // method_frame=pop; ncontext=pop; call(ncontext,method_frame) stack: value
 };  };
   
 call_name: name_without_curly_rdive;  call_name: name_without_curly_rdive;
Line 350  store_param: Line 366  store_param:
 ;  ;
 store_square_param: '[' store_code_param_parts ']' {$$=$2};  store_square_param: '[' store_code_param_parts ']' {$$=$2};
 store_round_param: '(' store_expr_param_parts ')' {$$=$2};  store_round_param: '(' store_expr_param_parts ')' {$$=$2};
 store_curly_param: '{' maybe_codes '}' {  store_curly_param: '{' store_curly_param_parts '}' {$$=$2};
         $$=N(POOL);   
         PCA($$, $2);  
 };  
 store_code_param_parts:  store_code_param_parts:
         store_code_param_part          store_code_param_part
 |       store_code_param_parts ';' store_code_param_part { $$=$1; P($$, $3) }  |       store_code_param_parts ';' store_code_param_part { $$=$1; P($$, $3) }
Line 362  store_expr_param_parts: Line 375  store_expr_param_parts:
         store_expr_param_part          store_expr_param_part
 |       store_expr_param_parts ';' store_expr_param_part { $$=$1; P($$, $3) }  |       store_expr_param_parts ';' store_expr_param_part { $$=$1; P($$, $3) }
 ;  ;
 store_code_param_part:   store_curly_param_parts:
         empty /* optimized [] case */          store_curly_param_part
 |       STRING { /* optimized [STRING] case */  |       store_curly_param_parts ';' store_curly_param_part { $$=$1; P($$, $3) }
         $$=$1;  ;
         O($$, OP_STORE_PARAM);  store_code_param_part: code_param_value {
 }  
 |       constructor_code_value { /* [something complex] */  
         $$=$1;          $$=$1;
         O($$, OP_STORE_PARAM);          O($$, OP_STORE_PARAM);
 }  };
 ;  
 store_expr_param_part: write_expr_value {  store_expr_param_part: write_expr_value {
         $$=N(POOL);           $$=N(POOL); 
           PEA($$, $1);
   };
   store_curly_param_part: maybe_codes {
           $$=N(POOL); 
         PCA($$, $1);          PCA($$, $1);
 };  };
   code_param_value:
           void_value /* optimized [;...] case */
   |       STRING /* optimized [STRING] case */
   |       constructor_code_value /* [something complex] */
   ;
 write_expr_value: expr_value {  write_expr_value: expr_value {
         $$=$1;          $$=$1;
         O($$, OP_WRITE);          O($$, OP_WRITE_EXPR_RESULT);
 };  };
   
 /* name */  /* name */
Line 403  name_advance2: name_expr_value { Line 422  name_advance2: name_expr_value {
 name_expr_value:   name_expr_value: 
         STRING /* subname_is_const */          STRING /* subname_is_const */
 |       name_expr_subvar_value /* $subname_is_var_value */  |       name_expr_subvar_value /* $subname_is_var_value */
 |       name_expr_with_subvar_value /* xxx$part_of_subname_is_var_value[$...] */  |       name_expr_with_subvar_value /* xxx$part_of_subname_is_var_value */
   |       name_square_code_value /* [codes] */
 ;  ;
 name_expr_subvar_value: '$' subvar_ref_name_rdive {  name_expr_subvar_value: '$' subvar_ref_name_rdive {
         $$=$2;          $$=$2;
Line 413  name_expr_with_subvar_value: STRING subv Line 433  name_expr_with_subvar_value: STRING subv
         $$=N(POOL);           $$=N(POOL); 
         O($$, OP_CREATE_EWPOOL);          O($$, OP_CREATE_EWPOOL);
         P($$, $1);          P($$, $1);
         O($$, OP_WRITE);          O($$, OP_WRITE_VALUE);
         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;  name_square_code_value: '[' codes ']' {
 subvar_ref_name_rdive_read: STRING {  
         $$=N(POOL);           $$=N(POOL); 
         O($$, OP_WITH_READ);          O($$, OP_CREATE_EWPOOL);
         P($$, $1);          P($$, $2);
           O($$, OP_REDUCE_EWPOOL);
 };  };
 subvar_ref_name_rdive_root: ':' STRING {  subvar_ref_name_rdive: STRING {
         $$=N(POOL);           $$=N(POOL); 
         O($$, OP_WITH_ROOT);          O($$, OP_WITH_READ);
         P($$, $2);          P($$, $1);
 };  };
 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 {
Line 434  subvar__get_write: '$' subvar_ref_name_r Line 454  subvar__get_write: '$' subvar_ref_name_r
         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 '{' codes '}' {                  YYERROR;
         $$=$2;          }
         O($$, OP_CREATE_RWPOOL);          O($$, OP_PREPARE_TO_CONSTRUCT_OBJECT);
         P($$, $4);  
         O($$, OP_REDUCE_RWPOOL);  
         O($$, OP_WRITE);  
 };  };
   
   
 /* expr */  /* expr */
   
 expr_value: expr {  expr_value: expr {
Line 461  expr: Line 483  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 469  expr: Line 492  expr:
 |       "def" expr { $$=$2;  O($$, OP_DEF) }  |       "def" expr { $$=$2;  O($$, OP_DEF) }
 |       "in" expr { $$=$2;  O($$, OP_IN) }  |       "in" expr { $$=$2;  O($$, OP_IN) }
 |       "-f" expr { $$=$2;  O($$, OP_FEXISTS) }  |       "-f" expr { $$=$2;  O($$, OP_FEXISTS) }
   |       "-d" expr { $$=$2;  O($$, OP_DEXISTS) }
 /* stack: a,b // stack: a@b */  /* stack: a,b // stack: a@b */
 |       expr '-' expr { $$=$1;  P($$, $3);  O($$, OP_SUB) }  |       expr '-' expr { $$=$1;  P($$, $3);  O($$, OP_SUB) }
 |       expr '+' expr { $$=$1;  P($$, $3);  O($$, OP_ADD) }  |       expr '+' expr { $$=$1;  P($$, $3);  O($$, OP_ADD) }
Line 493  expr: Line 517  expr:
 |       expr "ge" expr { $$=$1;  P($$, $3);  O($$, OP_STR_GE) }  |       expr "ge" expr { $$=$1;  P($$, $3);  O($$, OP_STR_GE) }
 |       expr "eq" expr { $$=$1;  P($$, $3);  O($$, OP_STR_EQ) }  |       expr "eq" expr { $$=$1;  P($$, $3);  O($$, OP_STR_EQ) }
 |       expr "ne" expr { $$=$1;  P($$, $3);  O($$, OP_STR_NE) }  |       expr "ne" expr { $$=$1;  P($$, $3);  O($$, OP_STR_NE) }
   |       expr "is" expr { $$=$1;  P($$, $3);  O($$, OP_IS) }
 ;  ;
   
 string_inside_quotes_value: maybe_codes {  string_inside_quotes_value: maybe_codes {
Line 505  string_inside_quotes_value: maybe_codes Line 530  string_inside_quotes_value: maybe_codes
 /* basics */  /* basics */
   
 write_string: STRING {  write_string: STRING {
         // optimized from OP_STRING+OP_WRITE to OP_STRING__WRITE          // optimized from OP_STRING+OP_WRITE_VALUE to OP_STRING__WRITE
         change_string_literal_to_write_string_literal($$=$1)          change_string_literal_to_write_string_literal($$=$1)
 };  };
   
 empty_string_value: /* empty */ { $$=VL(NEW VString(POOL)) };  void_value: /* empty */ { $$=VL(NEW VVoid(POOL)) };
 empty: /* empty */ { $$=N(POOL) };  empty: /* empty */ { $$=N(POOL) };
   
 %%  %%
   #endif
   
 /*  /*
         000$111(2222)00           000$111(2222)00 
Line 530  empty: /* empty */ { $$=N(POOL) }; Line 556  empty: /* empty */ { $$=N(POOL) };
                 4:[^({]=pop                  4:[^({]=pop
 */  */
   
 int yylex(YYSTYPE *lvalp, void *pc) {  static int yylex(YYSTYPE *lvalp, void *pc) {
         #define lexical_brackets_nestage PC->brackets_nestages[PC->sp]          #define lexical_brackets_nestage PC.brackets_nestages[PC.sp]
         #define RC {result=c; goto break2; }          #define RC {result=c; goto break2; }
   
     register int c;      register int c;
     int result;      int result;
                   
         if(PC->pending_state) {          if(PC.pending_state) {
                 result=PC->pending_state;                  result=PC.pending_state;
                 PC->pending_state=0;                  PC.pending_state=0;
                 return result;                  return result;
         }          }
                   
         const char *begin=PC->source;          const char *begin=PC.source;
         const char *end;          const char *end;
         int begin_line=PC->line;          int begin_line=PC.line;
         int skip_analized=0;          int skip_analized=0;
         while(true) {          while(true) {
                 c=*(end=(PC->source++));                  c=*(end=(PC.source++));
   //              fprintf(stderr, "\nchar: %c %02X; nestage: %d, sp=%d", c, c, lexical_brackets_nestage, PC.sp);
   
                 if(c=='\n') {                  if(c=='\n') {
                         PC->line++;                          PC.line++;
                         PC->col=0;                          PC.col=0;
                 } else                  } else
                         PC->col++;                          PC.col++;
   
                 // todo: # in 0+1 column comment  
   
                 // escaping: ^^ ^$ ^; ^) ^} ^( ^{ ^"                  if(c=='^' && PC.ls!=LS_COMMENT && PC.ls!=LS_DEF_COMMENT) 
                 if(c=='^')                           switch(*PC.source) {
                         switch(*PC->source) {                          // ^escaping some punctuators
                         case '^': case '$': case ';':                          case '^': case '$': case ';':
                           case '(': case ')':
                         case '[': case ']':                          case '[': case ']':
                         case '{': case '}':                          case '{': case '}':
                         case '"':                          case '"': 
                                 if(end!=begin) {                                  if(end!=begin) {
                                         // append piece till ^                                          // append piece till ^
                                         PC->string->APPEND(begin, end-begin, PC->file, begin_line);                                          PC.string->APPEND_CLEAN(begin, end-begin, PC.file, begin_line);
                                 }                                  }
                                 // reset piece 'begin' position & line                                  // reset piece 'begin' position & line
                                 begin=PC->source; // ^                                  end=begin=PC.source; // ^
                                 begin_line=PC->line;                                  begin_line=PC.line;
                                 // skip over ^ and _                                  if(PC.ls==LS_METHOD_AFTER) {
                                 PC->source++;  PC->col++;                                          pop_LS(PC);
                                 // skip analysis = forced literal                                          result=EON;
                                 continue;                                          skip_analized=-1; // return to ^ afterwards to assure it's literality
                                           goto break2;
                                   } else {
                                           // skip over _ after ^
                                           PC.source++;  PC.col++;
                                           // skip analysis = forced literal
                                           continue;
                                   }
   
                           // converting ^#HH into char(hex(HH))
                           case '#':
                                   if(end!=begin) {
                                           // append piece till ^
                                           PC.string->APPEND_CLEAN(begin, end-begin, PC.file, begin_line);
                                   }
                                   // #HH ?
                                   if(PC.source[0]=='#' && PC.source[1] && PC.source[2]) {
                                           char *hex=(char *)POOL.malloc(1);
                                           hex[0]=
                                                   hex_value[(unsigned char)PC.source[1]]*0x10+
                                                   hex_value[(unsigned char)PC.source[2]];
                                           if(hex[0]==0) {
                                                   result=BAD_HEX_LITERAL;
                                                   goto break2; // wrong hex value[no ^#00 chars allowed]: bail out
                                           }
                                           // append char(hex(HH))
                                           PC.string->APPEND_CLEAN(hex, 1, PC.file, begin_line);
                                           // skip over ^#HH
                                           PC.source+=3;
                                           PC.col+=3;
                                           // reset piece 'begin' position & line
                                           begin=PC.source; // ^
                                           begin_line=PC.line;
                                           continue;
                                   }
                                   break;
                         }                          }
                 switch(PC->ls) {                  // #comment  start skipping
                   if(c=='#' && PC.col==1) {
                           if(end!=begin) {
                                   // append piece till #
                                   PC.string->APPEND_CLEAN(begin, end-begin, PC.file, begin_line);
                           }
                           // fall into COMMENT lexical state [wait for \n]
                           push_LS(PC, LS_COMMENT);
                   }
                   switch(PC.ls) {
   
                 // USER'S = NOT OURS                  // USER'S = NOT OURS
                 case LS_USER:                  case LS_USER:
           case LS_NAME_SQUARE_PART: // name.[here].xxx
                           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 589  int yylex(YYSTYPE *lvalp, void *pc) { Line 669  int yylex(YYSTYPE *lvalp, void *pc) {
                                 push_LS(PC, LS_METHOD_NAME);                                  push_LS(PC, LS_METHOD_NAME);
                                 RC;                                  RC;
                         case '@':                          case '@':
                                 if(PC->col==0+1) {                                  if(PC.col==0+1) {
                                         push_LS(PC, LS_DEF_NAME);                                          push_LS(PC, LS_DEF_NAME);
                                         RC;                                          RC;
                                 }                                  }
                                 break;                                  break;
                           case ']':
                                   if(PC.ls==LS_NAME_SQUARE_PART)
                                           if(--lexical_brackets_nestage==0) {// $name.[co<]?>de<]?>
                                                   pop_LS(PC); // $name.[co<]>de<]!>
                                                   RC;
                                           }
                                   break;
                           case '[': // $name.[co<[>de]
                                   if(PC.ls==LS_NAME_SQUARE_PART)
                                           lexical_brackets_nestage++;
                                   break;
                           }
                           break;
                           
                   // #COMMENT
                   case LS_COMMENT:
                           if(c=='\n') {
                                   // skip comment
                                   begin=PC.source;
                                   begin_line=PC.line;
   
                                   pop_LS(PC);
                                   continue;
                         }                          }
                         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 616  int yylex(YYSTYPE *lvalp, void *pc) { Line 726  int yylex(YYSTYPE *lvalp, void *pc) {
                 case LS_DEF_NAME:                  case LS_DEF_NAME:
                         switch(c) {                          switch(c) {
                         case '[':                          case '[':
                                 PC->ls=LS_DEF_PARAMS;                                  PC.ls=LS_DEF_PARAMS;
                                 RC;                                  RC;
                         case '\n':                          case '\n':
                                 PC->ls=LS_DEF_SPECIAL_BODY;                                  PC.ls=LS_DEF_SPECIAL_BODY;
                                 RC;                                  RC;
                         }                          }
                         break;                          break;
Line 629  int yylex(YYSTYPE *lvalp, void *pc) { Line 739  int yylex(YYSTYPE *lvalp, void *pc) {
                         case ';':                          case ';':
                                 RC;                                  RC;
                         case ']':                          case ']':
                                 PC->ls=*PC->source=='['?LS_DEF_LOCALS:LS_DEF_COMMENT;                                  PC.ls=*PC.source=='['?LS_DEF_LOCALS:LS_DEF_COMMENT;
                                 RC;                                  RC;
                         case '\n': // wrong. bailing out                          case '\n': // wrong. bailing out
                                 pop_LS(PC);                                  pop_LS(PC);
Line 643  int yylex(YYSTYPE *lvalp, void *pc) { Line 753  int yylex(YYSTYPE *lvalp, void *pc) {
                         case ';':                          case ';':
                                 RC;                                  RC;
                         case ']':                          case ']':
                                 PC->ls=LS_DEF_COMMENT;                                  PC.ls=LS_DEF_COMMENT;
                                 RC;                                  RC;
                         case '\n': // wrong. bailing out                          case '\n': // wrong. bailing out
                                 pop_LS(PC);                                  pop_LS(PC);
Line 659  int yylex(YYSTYPE *lvalp, void *pc) { Line 769  int yylex(YYSTYPE *lvalp, void *pc) {
                         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
                                         pop_LS(PC);                                          pop_LS(PC);
                                         break;                                          break;
Line 675  int yylex(YYSTYPE *lvalp, void *pc) { Line 790  int yylex(YYSTYPE *lvalp, void *pc) {
                         switch(c) {                          switch(c) {
                         case ')':                          case ')':
                                 if(--lexical_brackets_nestage==0)                                  if(--lexical_brackets_nestage==0)
                                         if(PC->ls==LS_METHOD_ROUND) // method round param ended                                          if(PC.ls==LS_METHOD_ROUND) // method round param ended
                                                 PC->ls=LS_METHOD_AFTER; // look for method end                                                  PC.ls=LS_METHOD_AFTER; // look for method end
                                         else // PC->ls==LS_VAR_ROUND // variable constructor ended                                          else // PC.ls==LS_VAR_ROUND // variable constructor ended
                                                 pop_LS(PC); // return to normal life                                                  pop_LS(PC); // return to normal life
                                 RC;                                  RC;
                         case '$':                          case '$':
Line 690  int yylex(YYSTYPE *lvalp, void *pc) { Line 805  int yylex(YYSTYPE *lvalp, void *pc) {
                                 lexical_brackets_nestage++;                                  lexical_brackets_nestage++;
                                 RC;                                  RC;
                         case '-':                          case '-':
                                 if(*PC->source=='f') { // -f                                  switch(*PC.source) {
                                   case 'f': // -f
                                         skip_analized=1;                                          skip_analized=1;
                                         result=FEXISTS;                                          result=FEXISTS;
                                 } else                                          goto break2;
                                   case 'd': // -d
                                           skip_analized=1;
                                           result=DEXISTS;
                                           goto break2;
                                   default:
                                         result=c;                                          result=c;
                                           goto break2;
                                   }
                                 goto break2;                                  goto break2;
                         case '+': case '*': case '/': case '%':                           case '+': case '*': case '/': case '%': 
                         case '~':                          case '~':
                         case ';':                          case ';':
                                 RC;                                  RC;
                         case '&': case '|':  case '#':                          case '&': case '|':  case '#':
                                 if(*PC->source==c) { // && ||                                  if(*PC.source==c) { // && ||
                                         result=c=='#'?LXOR:c=='&'?LAND:LOR;                                          result=c=='#'?LXOR:c=='&'?LAND:LOR;
                                         skip_analized=1;                                          skip_analized=1;
                                 } else                                  } else
                                         result=c;                                          result=c;
                                 goto break2;                                  goto break2;
                         case '<': case '>': case '=': case '!':                           case '<': case '>': case '=': case '!': 
                                 if(*PC->source=='=') { // <= >= == !=                                  if(*PC.source=='=') { // <= >= == !=
                                         skip_analized=1;                                          skip_analized=1;
                                         switch(c) {                                          switch(c) {
                                         case '<': result=NLE; break;                                          case '<': result=NLE; break;
Line 720  int yylex(YYSTYPE *lvalp, void *pc) { Line 843  int yylex(YYSTYPE *lvalp, void *pc) {
                                         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
                                         switch(*PC->source) {                                          if(isspace(PC.source[1])) {
 //                                      case '?': // ok [and bad cases, yacc would bark at them]                                                  switch(*PC.source) {
                                         case 't': // lt gt [et nt]                                                          //                                      case '?': // ok [and bad cases, yacc would bark at them]
                                                 result=c=='l'?SLT:c=='g'?SGT:BAD_STRING_COMPARISON_OPERATOR;                                                  case 't': // lt gt [et nt]
                                                 skip_analized=1;                                                          result=c=='l'?SLT:c=='g'?SGT:BAD_STRING_COMPARISON_OPERATOR;
                                                 goto break2;                                                          skip_analized=1;
                                         case 'e': // le ge ne [ee]                                                          goto break2;
                                                 result=c=='l'?SLE:c=='g'?SGE:c=='n'?SNE:BAD_STRING_COMPARISON_OPERATOR;                                                  case 'e': // le ge ne [ee]
                                                 skip_analized=1;                                                          result=c=='l'?SLE:c=='g'?SGE:c=='n'?SNE:BAD_STRING_COMPARISON_OPERATOR;
                                                 goto break2;                                                          skip_analized=1;
                                         case 'q': // eq [lq gq nq]                                                          goto break2;
                                                 result=c=='e'?SEQ:BAD_STRING_COMPARISON_OPERATOR;                                                  case 'q': // eq [lq gq nq]
                                                 skip_analized=1;                                                          result=c=='e'?SEQ:BAD_STRING_COMPARISON_OPERATOR;
                                                 goto break2;                                                          skip_analized=1;
                                                           goto break2;
                                                   }
                                         }                                          }
                                 break;                                  break;
                         case 'i':                          case 'i':
                                 if(end==begin) // right after whitespace                                  if(end==begin) // right after whitespace
                                         if(PC->source[0]=='n') { // in                                          if(isspace(PC.source[1])) {
                                                 skip_analized=1;                                                  switch(PC.source[0]) {
                                                 result=IN;                                                  case 'n': // in
                                                 goto break2;                                                          skip_analized=1;
                                                           result=IN;
                                                           goto break2;
                                                   case 's': // is
                                                           skip_analized=1;
                                                           result=IS;
                                                           goto break2;
                                                   }
                                         }                                          }
                                 break;                                  break;
                         case 'd':                          case 'd':
                                 if(end==begin) // right after whitespace                                  if(end==begin) // right after whitespace
                                         if(PC->source[0]=='e' && PC->source[1]=='f') { // def                                          if(PC.source[0]=='e' && PC.source[1]=='f') { // def
                                                 skip_analized=2;                                                  skip_analized=2;
                                                 result=DEF;                                                  result=DEF;
                                                 goto break2;                                                  goto break2;
Line 764  int yylex(YYSTYPE *lvalp, void *pc) { Line 899  int yylex(YYSTYPE *lvalp, void *pc) {
                                 // that's a leading|traling space or after-operator-space                                  // that's a leading|traling space or after-operator-space
                                 // ignoring it                                  // ignoring it
                                 // reset piece 'begin' position & line                                  // reset piece 'begin' position & line
                                 begin=PC->source; // after whitespace char                                  begin=PC.source; // after whitespace char
                                 begin_line=PC->line;                                  begin_line=PC.line;
                                 continue;                                  continue;
                         }                          }
                         break;                          break;
Line 773  int yylex(YYSTYPE *lvalp, void *pc) { Line 908  int yylex(YYSTYPE *lvalp, void *pc) {
                 // VARIABLE GET/PUT/WITH                  // VARIABLE GET/PUT/WITH
                 case LS_VAR_NAME_SIMPLE:                  case LS_VAR_NAME_SIMPLE:
                 case LS_EXPRESSION_VAR_NAME:                  case LS_EXPRESSION_VAR_NAME:
                         if(PC->ls==LS_EXPRESSION_VAR_NAME) {                  case LS_VAR_NAME_NO_COLON:
                           if(PC.ls==LS_EXPRESSION_VAR_NAME) {
                                 // name in expr ends also before binary operators                                   // name in expr ends also before binary operators 
                                 switch(c) {                                  switch(c) {
                                 case '-':                                   case '-': 
                                         pop_LS(PC);                                          pop_LS(PC);
                                         PC->source--;  if(--PC->col<0) { PC->line--;  PC->col=-1; }                                          PC.source--;  if(--PC.col<0) { PC.line--;  PC.col=-1; }
                                           result=EON;
                                           goto break2;
                                   }
                           }
                           if(PC.ls==LS_VAR_NAME_NO_COLON) {
                                   // name already has ':', stop before next 
                                   switch(c) {
                                   case ':': 
                                           pop_LS(PC);
                                           PC.source--;  if(--PC.col<0) { PC.line--;  PC.col=-1; }
                                         result=EON;                                          result=EON;
                                         goto break2;                                          goto break2;
                                 }                                  }
Line 787  int yylex(YYSTYPE *lvalp, void *pc) { Line 933  int yylex(YYSTYPE *lvalp, void *pc) {
                         case 0:                          case 0:
                         case ' ': case '\t': case '\n':                          case ' ': case '\t': case '\n':
                         case ';':                          case ';':
                         case ']': case '}': case ')': case '"':                          case ']': case '}': case ')': 
                         case '<': case '>':  // these stand for HTML brackets and expression binary ops                          case '"': case '\'':
                           case '<': case '>':  // these stand for HTML brackets AND expression binary ops
                         case '+': case '*': case '/': case '%':                           case '+': case '*': case '/': case '%': 
                         case '&': case '|':                           case '&': case '|': 
                         case '=': case '!':                          case '=': case '!':
                           // common delimiters
                           case ',': case '?':
                           // before call
                           case '^': 
                                 pop_LS(PC);                                  pop_LS(PC);
                                 PC->source--;  if(--PC->col<0) { PC->line--;  PC->col=-1; }                                  PC.source--;  if(--PC.col<0) { PC.line--;  PC.col=-1; }
                                 result=EON;                                  result=EON;
                                 goto break2;                                  goto break2;
                         case '[':                          case '[':
                                 PC->ls=LS_VAR_SQUARE;                                  // $name.<[>code]
                                   if(PC.col>1/*not first column*/ && (
                                           end[-1]=='$'/*was start of get*/ ||
                                           end[-1]==':'/*was class name delim */ ||
                                           end[-1]=='.'/*was name delim */
                                           )) {
                                           push_LS(PC, LS_NAME_SQUARE_PART);
                                           lexical_brackets_nestage=1;
                                           RC;
                                   }
                                   PC.ls=LS_VAR_SQUARE;
                                 lexical_brackets_nestage=1;                                  lexical_brackets_nestage=1;
                                 RC;                                  RC;
                         case '{':                          case '{':
                                 if(begin==end) { // ${name}, no need of EON, switching LS                                  if(begin==end) { // ${name}, no need of EON, switching LS
                                         PC->ls=LS_VAR_NAME_CURLY;                                           PC.ls=LS_VAR_NAME_CURLY; 
                                 } else {                                  } else {
                                         PC->ls=LS_VAR_CURLY;                                          PC.ls=LS_VAR_CURLY;
                                         lexical_brackets_nestage=1;                                          lexical_brackets_nestage=1;
                                 }                                  }
   
                                 RC;                                  RC;
                         case '(':                          case '(':
                                 PC->ls=LS_VAR_ROUND;                                  PC.ls=LS_VAR_ROUND;
                                 lexical_brackets_nestage=1;                                  lexical_brackets_nestage=1;
                                 RC;                                  RC;
                         case '.': // name part delim                          case '.': // name part delim
                         case '$': // name part subvar                          case '$': // name part subvar
                         case ':': // ':name' or 'class:name'                          case ':': // class<:>name
                                   PC.ls=LS_VAR_NAME_NO_COLON; // stop before next ':'
                                 RC;                                  RC;
                         }                          }
                         break;                          break;
   
                 case LS_VAR_NAME_CURLY:                  case LS_VAR_NAME_CURLY:
                         switch(c) {                          switch(c) {
                           case '[':
                                   // ${name.<[>code]}
                                   push_LS(PC, LS_NAME_SQUARE_PART);
                                   lexical_brackets_nestage=1;
                                   RC;
                         case '}': // ${name} finished, restoring LS                          case '}': // ${name} finished, restoring LS
                                 pop_LS(PC);                                  pop_LS(PC);
                                 RC;                                  RC;
Line 878  int yylex(YYSTYPE *lvalp, void *pc) { Line 1045  int yylex(YYSTYPE *lvalp, void *pc) {
                 case LS_METHOD_NAME:                  case LS_METHOD_NAME:
                         switch(c) {                          switch(c) {
                         case '[':                          case '[':
                                 PC->ls=LS_METHOD_SQUARE;                                  // ^name.<[>code].xxx
                                   if(PC.col>1/*not first column*/ && (
                                           end[-1]=='^'/*was start of call*/ || // never, ^[ is literal...
                                           end[-1]==':'/*was class name delim */ ||
                                           end[-1]=='.'/*was name delim */
                                           )) {
                                           push_LS(PC, LS_NAME_SQUARE_PART);
                                           lexical_brackets_nestage=1;
                                           RC;
                                   }
                                   PC.ls=LS_METHOD_SQUARE;
                                 lexical_brackets_nestage=1;                                  lexical_brackets_nestage=1;
                                 RC;                                  RC;
                         case '{':                          case '{':
                                 PC->ls=LS_METHOD_CURLY;                                  PC.ls=LS_METHOD_CURLY;
                                 lexical_brackets_nestage=1;                                  lexical_brackets_nestage=1;
                                 RC;                                  RC;
                         case '(':                          case '(':
                                 PC->ls=LS_METHOD_ROUND;                                  PC.ls=LS_METHOD_ROUND;
                                 lexical_brackets_nestage=1;                                  lexical_brackets_nestage=1;
                                 RC;                                  RC;
                         case '.': // name part delim                           case '.': // name part delim 
Line 908  int yylex(YYSTYPE *lvalp, void *pc) { Line 1085  int yylex(YYSTYPE *lvalp, void *pc) {
                                 RC;                                  RC;
                         case ']':                          case ']':
                                 if(--lexical_brackets_nestage==0) {                                  if(--lexical_brackets_nestage==0) {
                                         PC->ls=LS_METHOD_AFTER;                                          PC.ls=LS_METHOD_AFTER;
                                         RC;                                          RC;
                                 }                                  }
                                 break;                                  break;
Line 926  int yylex(YYSTYPE *lvalp, void *pc) { Line 1103  int yylex(YYSTYPE *lvalp, void *pc) {
                         case '^':                          case '^':
                                 push_LS(PC, LS_METHOD_NAME);                                  push_LS(PC, LS_METHOD_NAME);
                                 RC;                                  RC;
                           case ';': // param delim
                                   RC;
                         case '}':                          case '}':
                                 if(--lexical_brackets_nestage==0) {                                  if(--lexical_brackets_nestage==0) {
                                         PC->ls=LS_METHOD_AFTER;                                          PC.ls=LS_METHOD_AFTER;
                                         RC;                                          RC;
                                 }                                  }
                                 break;                                  break;
Line 940  int yylex(YYSTYPE *lvalp, void *pc) { Line 1119  int yylex(YYSTYPE *lvalp, void *pc) {
   
                 case LS_METHOD_AFTER:                  case LS_METHOD_AFTER:
                         if(c=='[') {/* ][ }[ )[ */                          if(c=='[') {/* ][ }[ )[ */
                                 PC->ls=LS_METHOD_SQUARE;                                  PC.ls=LS_METHOD_SQUARE;
                                 lexical_brackets_nestage=1;                                  lexical_brackets_nestage=1;
                                 RC;                                  RC;
                         }                                                                    }                                          
                         if(c=='{') {/* ]{ }{ ){ */                          if(c=='{') {/* ]{ }{ ){ */
                                 PC->ls=LS_METHOD_CURLY;                                  PC.ls=LS_METHOD_CURLY;
                                 lexical_brackets_nestage=1;                                  lexical_brackets_nestage=1;
                                 RC;                                  RC;
                         }                                                                    }                                          
                         if(c=='(') {/* ]( }( )( */                          if(c=='(') {/* ]( }( )( */
                                 PC->ls=LS_METHOD_ROUND;                                  PC.ls=LS_METHOD_ROUND;
                                 lexical_brackets_nestage=1;                                  lexical_brackets_nestage=1;
                                 RC;                                  RC;
                         }                                                                    }                                          
                         pop_LS(PC);                          pop_LS(PC);
                         PC->source--;  if(--PC->col<0) { PC->line--;  PC->col=-1; }                          PC.source--;  if(--PC.col<0) { PC.line--;  PC.col=-1; }
                         result=EON;                          result=EON;
                         goto break2;                          goto break2;
                 }                  }
Line 970  break2: Line 1149  break2:
                 if((c=='@' || c==0) && end[-1]=='\n') { // we are before LS_DEF_NAME or EOF?                  if((c=='@' || c==0) && end[-1]=='\n') { // we are before LS_DEF_NAME or EOF?
                         // strip last \n                          // strip last \n
                         end--;                          end--;
                           if(end!=begin && end[-1]=='\n') // allow one empty line before LS_DEF_NAME
                                   end--;
                 }                  }
                 if(end!=begin) { // last piece still alive?                  if(end!=begin && PC.ls!=LS_COMMENT) { // last piece still alive and not comment?
                         // append it                          // append it
                         PC->string->APPEND(begin, end-begin, PC->file, begin_line/*, start_col*/);                          PC.string->APPEND_CLEAN(begin, end-begin, PC.file, begin_line/*, start_col*/);
                 }                  }
         }          }
         if(PC->string->size()) { // something accumulated?          if(PC.string->size()) { // something accumulated?
                 // create STRING value: array of OP_VALUE+vstring                  // create STRING value: array of OP_VALUE+vstring
                 *lvalp=VL(NEW VString(*PC->string));                  *lvalp=VL(NEW VString(*PC.string));
                 // new pieces storage                  // new pieces storage
                 PC->string=NEW String(POOL);                  PC.string=NEW String(POOL);
                 // make current result be pending for next call, return STRING for now                  // make current result be pending for next call, return STRING for now
                 PC->pending_state=result;  result=STRING;                  PC.pending_state=result;  result=STRING;
         }          }
         if(skip_analized) {          if(skip_analized) {
                 PC->source+=skip_analized;  PC->col+=skip_analized;                  PC.source+=skip_analized;  PC.col+=skip_analized;
         }          }
         return result;          return result;
 }  }
   
 int real_yyerror(parse_control *pc, char *s)  /* Called by yyparse on error */  static int real_yyerror(parse_control *pc, char *s) {  // Called by yyparse on error
      {             strncpy(PC.error, s, MAX_STRING);
        //fprintf(stderr, "[%s]\n", s);  
   
            strncpy(pc->error, s, MAX_STRING); // TODO: перепроверить с треклятым последним байтом  
            return 1;             return 1;
      }  }
   
 static void  
      yyprint(  
           FILE *file,  
           int type,  
           YYSTYPE value)  
      {  
        if(type==STRING)  
          fprintf(file, " \"%s\"", SLA2S(value)->cstr());  
      }  
   
   static void yyprint(FILE *file, int type, YYSTYPE value) {
           if(type==STRING)
                   fprintf(file, " \"%s\"", LA2S(value)->cstr());
   }

Removed from v.1.92  
changed lines
  Added in v.1.165.4.1


E-mail: