--- parser3/src/main/compile.y 2001/04/03 17:15:07 1.123 +++ parser3/src/main/compile.y 2001/05/28 06:10:06 1.138 @@ -5,7 +5,7 @@ Author: Alexander Petrosyan (http://design.ru/paf) - $Id: compile.y,v 1.123 2001/04/03 17:15:07 paf Exp $ + $Id: compile.y,v 1.138 2001/05/28 06:10:06 parser Exp $ */ /** @@ -28,25 +28,21 @@ #define yyerror(msg) real_yyerror((parse_control *)pc, msg) #define YYPRINT(file, type, value) yyprint(file, type, value) -#include "pa_config_includes.h" -#include -#include -#include - #include "compile_tools.h" #include "pa_value.h" #include "pa_request.h" #include "pa_vobject.h" #include "pa_vdouble.h" #include "pa_globals.h" -#include "pa_vunknown.h" +#include "pa_vnothing.h" #define SELF_ELEMENT_NAME "self" #define USE_CONTROL_METHOD_NAME "USE" +#define END_CONTROL_METHOD_NAME "end" -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); -int yylex(YYSTYPE *lvalp, void *pc); +static int yylex(YYSTYPE *lvalp, void *pc); // local convinient inplace typecast & var @@ -85,22 +81,22 @@ int yylex(YYSTYPE *lvalp, void *pc); %token DEF "def" %token IN "in" %token FEXISTS "-f" +%token DEXISTS "-d" %token IS "is" /* logical */ -%left "is" -%left "lt" "gt" "le" "ge" -%left "eq" "ne" -%left '<' '>' "<=" ">=" "##" -%left "==" "!=" +%left "##" %left "||" %left "&&" -%left "def" "in" "-f" +%left '<' '>' "<=" ">=" "lt" "gt" "le" "ge" +%left "==" "!=" "eq" "ne" +%left "is" "def" "in" "-f" "-d" %left '!' /* bitwise */ %left '#' -%left '&' '|' +%left '|' +%left '&' %left '~' /* numerical */ @@ -127,9 +123,11 @@ one_big_piece: maybe_codes; method: control_method | code_method; control_method: '@' STRING '\n' - control_strings { + maybe_control_strings { const String& command=*LA2S($2); YYSTYPE strings_code=$4; + if(command==END_CONTROL_METHOD_NAME && strings_code->size()==0) + break; if(strings_code->size()<1*2) { strcpy(PC.error, "@"); strcat(PC.error, command.cstr()); @@ -137,7 +135,7 @@ control_method: '@' STRING '\n' YYERROR; } if(command==CLASS_NAME) { - if(PC.cclass!=&PC.request->ROOT) { // already changed from default? + if(PC.cclass) { // already changed from default? strcpy(PC.error, "class already have a name '"); strncat(PC.error, PC.cclass->name().cstr(), 100); strcat(PC.error, "'"); @@ -149,54 +147,51 @@ control_method: '@' STRING '\n' // creating the class PC.cclass=NEW VClass(POOL); PC.cclass->set_name(*name); - // defaulting base. may change with @BASE - PC.cclass->set_base(PC.request->ROOT); // append to request's classes PC.request->classes().put(*name, PC.cclass); } else { strcpy(PC.error, "@"CLASS_NAME" must contain sole name"); YYERROR; } - } else { - if(command==USE_CONTROL_METHOD_NAME) { - for(int i=0; isize(); i+=2) - PC.request->use_file( - PC.request->absolute(*LA2S(strings_code, i))); - } else if(command==BASE_NAME) { - if(PC.cclass->base()!=&PC.request->ROOT) { // already changed from default? - strcpy(PC.error, "class already have a base '"); - strncat(PC.error, PC.cclass->base()->name().cstr(), 100); - strcat(PC.error, "'"); + } else if(command==USE_CONTROL_METHOD_NAME) { + for(int i=0; isize(); i+=2) + PC.request->use_file( + PC.request->absolute(*LA2S(strings_code, i))); + } else if(command==BASE_NAME) { + if(PC.cclass->base()!=&PC.request->OP) { // already changed from default? + strcpy(PC.error, "class already have a base '"); + strncat(PC.error, PC.cclass->base()->name().cstr(), 100); + strcat(PC.error, "'"); + YYERROR; + } + if(strings_code->size()==1*2) { + const String& base_name=*LA2S(strings_code); + VClass *base=static_cast( + PC.request->classes().get(base_name)); + if(!base) { + strcpy(PC.error, base_name.cstr()); + strcat(PC.error, ": undefined class in @"BASE_NAME); YYERROR; } - if(strings_code->size()==1*2) { - const String& base_name=*LA2S(strings_code); - VClass *base=static_cast( - PC.request->classes().get(base_name)); - if(!base) { - strcpy(PC.error, base_name.cstr()); - strcat(PC.error, ": undefined class in @"BASE_NAME); - YYERROR; - } - // @CLASS == @BASE sanity check - if(PC.cclass==base) { - strcpy(PC.error, "@"CLASS_NAME" equals @"BASE_NAME); - YYERROR; - } - PC.cclass->set_base(*base); - } else { - strcpy(PC.error, "@"BASE_NAME" must contain sole name"); + // @CLASS == @BASE sanity check + if(PC.cclass==base) { + strcpy(PC.error, "@"CLASS_NAME" equals @"BASE_NAME); YYERROR; } + PC.cclass->set_base(*base); } 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"'"); + strcpy(PC.error, "@"BASE_NAME" must contain sole name"); 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_string: maybe_string '\n'; maybe_string: empty | STRING; @@ -349,9 +344,9 @@ call_value: '^' call_name store_params E O($$, OP_GET_METHOD_FRAME); /* stack: context,method_frame */ YYSTYPE params_code=$3; - if(params_code->size()==3) // probably [] case. [OP_VALUE + Unknown + STORE_PARAM] + if(params_code->size()==3) // probably [] case. [OP_VALUE + Nothing + STORE_PARAM] if(Value *value=LA2V(params_code)) // it is OP_VALUE + value? - if(!value->is_defined()) // value is VUnknown? + if(!value->is_defined()) // value is VNothing? params_code=0; // ^zzz[] case. don't append lone empty param. if(params_code) P($$, params_code); // filling method_frame.store_params @@ -463,7 +458,7 @@ class_prefix: STRING ':' { /* with */ -with: '$' name_without_curly_rdive '{' codes '}' { +with: '$' name_without_curly_rdive '{' maybe_codes '}' { $$=$2; O($$, OP_CREATE_RWPOOL); P($$, $4); @@ -490,6 +485,7 @@ expr: | "def" expr { $$=$2; O($$, OP_DEF) } | "in" expr { $$=$2; O($$, OP_IN) } | "-f" expr { $$=$2; O($$, OP_FEXISTS) } +| "-d" expr { $$=$2; O($$, OP_DEXISTS) } /* stack: a,b // stack: a@b */ | expr '-' expr { $$=$1; P($$, $3); O($$, OP_SUB) } | expr '+' expr { $$=$1; P($$, $3); O($$, OP_ADD) } @@ -531,7 +527,7 @@ write_string: STRING { change_string_literal_to_write_string_literal($$=$1) }; -unknown_value: /* empty */ { $$=VL(NEW VUnknown(POOL)) }; +unknown_value: /* empty */ { $$=VL(NEW VNothing(POOL)) }; empty: /* empty */ { $$=N(POOL) }; %% @@ -581,8 +577,9 @@ static int yylex(YYSTYPE *lvalp, void *p if(c=='^' && PC.ls!=LS_COMMENT && PC.ls!=LS_DEF_COMMENT) switch(*PC.source) { - // escaping: ^^ ^$ ^; ^) ^} ^( ^{ ^" + // escaping: ^^ & co case '^': case '$': case ';': + case '(': case ')': case '[': case ']': case '{': case '}': case '"': @@ -760,11 +757,19 @@ static int yylex(YYSTYPE *lvalp, void *p lexical_brackets_nestage++; RC; case '-': - if(*PC.source=='f') { // -f + switch(*PC.source) { + case 'f': // -f skip_analized=1; result=FEXISTS; - } else + goto break2; + case 'd': // -d + skip_analized=1; + result=DEXISTS; + goto break2; + default: result=c; + goto break2; + } goto break2; case '+': case '*': case '/': case '%': case '~': @@ -866,13 +871,14 @@ static int yylex(YYSTYPE *lvalp, void *p case 0: case ' ': case '\t': case '\n': case ';': - case ']': case '}': case ')': case '"': + case ']': case '}': case ')': + case '"': case '\'': case '<': case '>': // these stand for HTML brackets and expression binary ops case '+': case '*': case '/': case '%': case '&': case '|': case '=': case '!': // common delimiters - case '\'': case ',': + case ',': pop_LS(PC); PC.source--; if(--PC.col<0) { PC.line--; PC.col=-1; } result=EON; @@ -1053,8 +1059,10 @@ break2: if((c=='@' || c==0) && end[-1]=='\n') { // we are before LS_DEF_NAME or EOF? // strip last \n 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 PC.string->APPEND_CLEAN(begin, end-begin, PC.file, begin_line/*, start_col*/); }