--- parser3/src/main/compile.y 2001/03/06 14:28:35 1.54 +++ parser3/src/main/compile.y 2001/03/07 10:10:50 1.63 @@ -1,5 +1,5 @@ /* - $Id: compile.y,v 1.54 2001/03/06 14:28:35 paf Exp $ + $Id: compile.y,v 1.63 2001/03/07 10:10:50 paf Exp $ */ %{ @@ -41,7 +41,43 @@ int yylex(YYSTYPE *lvalp, void *pc); %token EON %token STRING %token BOGUS -%token LOGICAL_AND LOGICAL_OR + +%token BAD_STRING_COMPARISON_OPERATOR + +%token LAND "&&" +%token LOR "||" +%token LXOR "##" + +%token NLE "<=" +%token NGE ">=" +%token NEQ "==" +%token NNE "!=" + +%token SLT "lt" +%token SGT "gt" +%token SLE "le" +%token SGE "ge" +%token SEQ "eq" +%token SNE "ne" + +/* logical */ +%left "lt" "gt" "le" "ge" +%left "eq" "ne" +%left '<' '>' "<=" ">=" "##" +%left "==" "!=" +%left "||" +%left "&&" +%left NOT /* not: unary ! */ + +/* bitwise */ +%left '#' +%left '&' '|' +%left INV /* invertion: unary ~ */ + +/* numerical */ +%left '-' '+' +%left '*' '/' '%' +%left NEG /* negation: unary - */ %% @@ -217,21 +253,21 @@ name_expr_wdive_root: ':' name_expr_dive name_expr_wdive_class: class_prefix name_expr_dive_code { $$=$1; P($$, $2) }; constructor_value: - '[' constructor_code_value ']' { $$=$2 } -| '(' expression_value ')' { $$=$2 } + '[' any_constructor_code_value ']' { $$=$2 } +| '(' any_expr ')' { $$=$2 } ; -constructor_code_value: - empty_value /* optimized $var[] case */ +any_constructor_code_value: + empty_string_value /* optimized $var[] case */ | STRING /* optimized $var[STRING] case */ -| complex_constructor_code_value /* $var[something complex] */ +| constructor_code_value /* $var[something complex] */ ; -complex_constructor_code_value: complex_constructor_code { +constructor_code_value: constructor_code { $$=N(POOL); O($$, OP_CREATE_EWPOOL); /* stack: empty write context */ P($$, $1); /* some codes to that context */ O($$, OP_REDUCE_EWPOOL); /* context=pop; stack: context.value() */ }; -complex_constructor_code: codes__excluding_sole_str_literal; +constructor_code: codes__excluding_sole_str_literal; codes__excluding_sole_str_literal: action | code codes { $$=$1; P($$, $2) }; /* call */ @@ -263,7 +299,7 @@ store_param_part: $$=$1; O($$, OP_STORE_PARAM); } -| complex_constructor_code_value { /* (something complex) */ +| constructor_code_value { /* (something complex) */ $$=$1; O($$, OP_STORE_PARAM); } @@ -345,22 +381,54 @@ with: '$' name_without_curly_rdive '{' c O($$, OP_WRITE); }; -/* expression */ +/* expr */ -expression_value: - empty_value /* optimized $var() case */ -| number /* optimized $var(STRING) case */ -| complex_expression /* $var(something complex) */ +any_expr: + empty_double_value /* optimized $var() case */ +| optimized_expr /* $var(something) */ ; -complex_expression: expression_operand '*' expression_operand { - $$=$1; // stack: first operand - P($$, $3); // stack: first,second operands - O($$, OP_MUL); // value=first*second; stack: value +optimized_expr: expr { + if(($$=$1)->size()==2) { // only one string literal in there? + change_string_literal_to_double_literal($$); // make that string literal Double + } }; -expression_operand: number; +expr: + STRING +| '"' STRING '"' { $$ = $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*/ +/* stack: a,b // stack: a@b */ +| expr '-' expr { $$=$1; P($$, $3); O($$, OP_SUB) } +| expr '+' expr { $$=$1; P($$, $3); O($$, OP_ADD) } +| expr '*' expr { $$=$1; P($$, $3); O($$, OP_MUL) } +| expr '/' expr { $$=$1; P($$, $3); O($$, OP_DIV) } +| expr '%' expr { $$=$1; P($$, $3); O($$, OP_MOD) } +| expr '&' expr { $$=$1; P($$, $3); O($$, OP_BIN_AND) } +| expr '|' expr { $$=$1; P($$, $3); O($$, OP_BIN_OR) } +| expr '#' expr { $$=$1; P($$, $3); O($$, OP_BIN_XOR) } +| expr "&&" expr { $$=$1; P($$, $3); O($$, OP_LOG_AND) } +| expr "||" expr { $$=$1; P($$, $3); O($$, OP_LOG_OR) } +| expr "##" expr { $$=$1; P($$, $3); O($$, OP_LOG_XOR) } +| expr '<' expr { $$=$1; P($$, $3); O($$, OP_NUM_LT) } +| expr '>' expr { $$=$1; P($$, $3); O($$, OP_NUM_GT) } +| expr "<=" expr { $$=$1; P($$, $3); O($$, OP_NUM_LE) } +| expr ">=" expr { $$=$1; P($$, $3); O($$, OP_NUM_GE) } +| expr "==" expr { $$=$1; P($$, $3); O($$, OP_NUM_EQ) } +| expr "!=" expr { $$=$1; P($$, $3); O($$, OP_NUM_NE) } +| expr "lt" expr { $$=$1; P($$, $3); O($$, OP_STR_LT) } +| expr "gt" expr { $$=$1; P($$, $3); O($$, OP_STR_GT) } +| expr "le" expr { $$=$1; P($$, $3); O($$, OP_STR_LE) } +| expr "ge" expr { $$=$1; P($$, $3); O($$, OP_STR_GE) } +| expr "eq" expr { $$=$1; P($$, $3); O($$, OP_STR_EQ) } +| expr "ne" expr { $$=$1; P($$, $3); O($$, OP_STR_NE) } +; /* -complex_expression_value: complex_expression { +complex_expr_value: complex_expr { $$=N(POOL); O($$, OP_CREATE_SWPOOL); /* stack: empty write context * / P($$, $1); /* some codes to that context * / @@ -371,19 +439,12 @@ complex_expression_value: complex_expres /* basics */ write_str_literal: STRING { - if(SLA2S($1)->size()) { - $$=$1; - O($$, OP_WRITE); - } else { - // optimized case of special end of macro. see yylex - $$=N(POOL); - } -}; -number: STRING { - change_string_literal_to_double_literal($$=$1); + $$=$1; + O($$, OP_WRITE); }; -empty_value: /* empty */ { $$=SL(NEW VString(POOL)) }; +empty_double_value: /* empty */ { $$=VL(NEW VDouble(POOL)) }; +empty_string_value: /* empty */ { $$=VL(NEW VString(POOL)) }; empty: /* empty */ { $$=N(POOL) }; %% @@ -420,6 +481,7 @@ int yylex(YYSTYPE *lvalp, void *pc) { char *begin=PC->source; char *end; int begin_line=PC->line; + bool skip_analized_char=false; while(true) { c=*(end=(PC->source++)); @@ -440,7 +502,7 @@ int yylex(YYSTYPE *lvalp, void *pc) { // append piece till ^ PC->string->APPEND(begin, end-begin, PC->file, begin_line); } - // reset piece 'start' position & line + // reset piece 'begin' position & line begin=PC->source; // ^ begin_line=PC->line; // skip over ^ and _ @@ -557,32 +619,58 @@ int yylex(YYSTYPE *lvalp, void *pc) { lexical_brackets_nestage++; RC; case '+': case '-': case '*': case '/': case '%': - case '&': case '|': - case '<': case '>': case '=': case '!': + case '~': case ';': RC; + case '&': case '|': case '#': + if(*PC->source==c) { // && || + result=c=='#'?LXOR:c=='&'?LAND:LOR; + skip_analized_char=true; + } else + result=c; + goto break2; + case '<': case '>': case '=': case '!': + if(*PC->source=='=') { // <= >= == != + skip_analized_char=true; + switch(c) { + case '<': result=NLE; break; + case '>': result=NGE; break; + case '=': result=NEQ; break; + case '!': result=NNE; break; + } + } else + result=c; + goto break2; case '"': push_LS(PC, LS_EXPRESSION_STRING); RC; case 'l': case 'g': case 'e': case 'n': if(end==begin) // right after whitespace - switch(char next_c=*PC->source) { + switch(*PC->source) { // 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; + 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; + goto break2; case 'q': // eq [lq gq nq] - PC->source++; PC->col++; - PC->pending_state=next_c; - return c; + result=c=='e'?SEQ:BAD_STRING_COMPARISON_OPERATOR; + skip_analized_char=true; + goto break2; } break; case ' ': case '\t': case '\n': - if(end!=begin) { - // append piece till whitespace - PC->string->APPEND(begin, end-begin, PC->file, begin_line); + if(end!=begin) { // there were a string after previous operator? + result=0; // return that string + goto break2; } - // reset piece 'start' position & line - begin=PC->source; // after whitespace + // that's a leading|traling space or after-operator-space + // ignoring it + // reset piece 'begin' position & line + begin=PC->source; // after whitespace char begin_line=PC->line; continue; } @@ -592,7 +680,7 @@ int yylex(YYSTYPE *lvalp, void *pc) { case LS_VAR_NAME_SIMPLE: case LS_VAR_NAME_IN_EXPRESSION: if(PC->ls==LS_VAR_NAME_IN_EXPRESSION) { - // name in expression ends also before binary operators + // name in expr ends also before binary operators switch(c) { case '+': case '-': case '*': case '/': case '%': case '&': case '|': @@ -773,24 +861,28 @@ int yylex(YYSTYPE *lvalp, void *pc) { } break2: - if(begin==end) - return result; - else { - PC->pending_state=result; - // strip last \n before LS_DEF_NAME or EOF - if((c=='@' || c==0) && end[-1]=='\n') + if(end!=begin) { // there is last piece? + if((c=='@' || c==0) && end[-1]=='\n') { // we are before LS_DEF_NAME or EOF? + // strip last \n end--; - if(end!=begin) { - // append last piece + } + if(end!=begin) { // last piece still alive? + // append it PC->string->APPEND(begin, end-begin, PC->file, begin_line/*, start_col*/); } + } + if(PC->string->size()) { // something accumulated? // create STRING value: array of OP_VALUE+vstring - *lvalp=SL(NEW VString(*PC->string)); + *lvalp=VL(NEW VString(*PC->string)); // new pieces storage PC->string=NEW String(POOL); - // go! - return STRING; + // 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++; } + return result; } int real_yyerror(parse_control *pc, char *s) /* Called by yyparse on error */