--- parser3/src/main/compile.y 2001/03/07 10:35:41 1.65 +++ parser3/src/main/compile.y 2001/03/07 11:19:42 1.68 @@ -1,5 +1,5 @@ /* - $Id: compile.y,v 1.65 2001/03/07 10:35:41 paf Exp $ + $Id: compile.y,v 1.68 2001/03/07 11:19:42 paf Exp $ */ %{ @@ -60,6 +60,10 @@ int yylex(YYSTYPE *lvalp, void *pc); %token SEQ "eq" %token SNE "ne" +%token DEF "def" +%token IN "in" +%token FEXISTS "-f" + /* logical */ %left "lt" "gt" "le" "ge" %left "eq" "ne" @@ -67,12 +71,13 @@ int yylex(YYSTYPE *lvalp, void *pc); %left "==" "!=" %left "||" %left "&&" -%left NOT /* not: unary ! */ +%left "def" "in" "-f" +%left '!' /* bitwise */ %left '#' %left '&' '|' -%left INV /* invertion: unary ~ */ +%left '~' /* numerical */ %left '-' '+' @@ -188,7 +193,7 @@ action: get | put | with | call; get: get_value { $$=$1; /* stack: resulting value */ - O($$, OP_WRITE); /* value=pop; write(value) */ + O($$, OP_WRITE); /* value=pop; wcontext.write(value) */ }; get_value: '$' get_name_value { $$=$2 } get_name_value: name_without_curly_rdive EON | name_in_curly_rdive; @@ -273,11 +278,15 @@ codes__excluding_sole_str_literal: actio /* call */ -call: '^' call_name store_params EON { /* ^field.$method{vasya} */ +call: call_value { + $$=$1; /* stack: value */ + O($$, OP_WRITE); /* value=pop; wcontext.write(value) */ +}; +call_value: '^' call_name store_params EON { /* ^field.$method{vasya} */ $$=$2; /* with_xxx,diving code; stack: context,method_junction */ 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) */ + O($$, OP_CALL); /* method_frame=pop; ncontext=pop; call(ncontext,method_frame) stack: value */ }; call_name: name_without_curly_rdive; @@ -396,13 +405,16 @@ optimized_expr: expr { expr: STRING | get_value +| call_value | '"' string_inside_quotes_value '"' { $$ = $2; } | '(' expr ')' { $$ = $2; } /* stack: operand // stack: @operand */ | '-' expr %prec NEG { $$=$2; O($$, OP_NEG) } -| '~' expr %prec INV { $$=$2; O($$, OP_INV) } -| '!' expr %prec NOT { $$=$2; O($$, OP_NOT) } -/*todo: def in fexists*/ +| '~' expr { $$=$2; O($$, OP_INV) } +| '!' expr { $$=$2; O($$, OP_NOT) } +| "def" expr { $$=$2; O($$, OP_DEF) } +| "in" expr { $$=$2; O($$, OP_IN) } +| "-f" expr { $$=$2; O($$, OP_FEXISTS) } /* stack: a,b // stack: a@b */ | expr '-' expr { $$=$1; P($$, $3); O($$, OP_SUB) } | expr '+' expr { $$=$1; P($$, $3); O($$, OP_ADD) } @@ -481,7 +493,7 @@ int yylex(YYSTYPE *lvalp, void *pc) { char *begin=PC->source; char *end; int begin_line=PC->line; - bool skip_analized_char=false; + int skip_analized=0; while(true) { c=*(end=(PC->source++)); @@ -618,20 +630,27 @@ int yylex(YYSTYPE *lvalp, void *pc) { case '(': lexical_brackets_nestage++; RC; - case '+': case '-': case '*': case '/': case '%': + case '-': + if(*PC->source=='f') { // -f + skip_analized=1; + result=FEXISTS; + } else + result=c; + goto break2; + case '+': case '*': case '/': case '%': case '~': case ';': RC; case '&': case '|': case '#': if(*PC->source==c) { // && || result=c=='#'?LXOR:c=='&'?LAND:LOR; - skip_analized_char=true; + skip_analized=1; } else result=c; goto break2; case '<': case '>': case '=': case '!': if(*PC->source=='=') { // <= >= == != - skip_analized_char=true; + skip_analized=1; switch(c) { case '<': result=NLE; break; case '>': result=NGE; break; @@ -650,15 +669,31 @@ int yylex(YYSTYPE *lvalp, void *pc) { // case '?': // ok [and bad cases, yacc would bark at them] case 't': // lt gt [et nt] result=c=='l'?SLT:c=='g'?SGT:BAD_STRING_COMPARISON_OPERATOR; - skip_analized_char=true; + skip_analized=1; goto break2; case 'e': // le ge ne [ee] result=c=='l'?SLE:c=='g'?SGE:c=='n'?SNE:BAD_STRING_COMPARISON_OPERATOR; - skip_analized_char=true; + skip_analized=1; goto break2; case 'q': // eq [lq gq nq] result=c=='e'?SEQ:BAD_STRING_COMPARISON_OPERATOR; - skip_analized_char=true; + skip_analized=1; + goto break2; + } + break; + case 'i': + if(end==begin) // right after whitespace + if(PC->source[0]=='n') { // in + skip_analized=1; + result=IN; + goto break2; + } + break; + case 'd': + if(end==begin) // right after whitespace + if(PC->source[0]=='e' && PC->source[1]=='f') { // def + skip_analized=2; + result=DEF; goto break2; } break; @@ -879,8 +914,8 @@ break2: // make current result be pending for next call, return STRING for now PC->pending_state=result; result=STRING; } - if(skip_analized_char) { - PC->source++; PC->col++; + if(skip_analized) { + PC->source+=skip_analized; PC->col+=skip_analized; } return result; }