--- parser3/src/main/compile.y 2004/04/06 11:58:15 1.209.2.1 +++ parser3/src/main/compile.y 2005/12/16 14:04:20 1.219 @@ -2,10 +2,10 @@ /** @file Parser: compiler(lexical parser and grammar). - Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com) Author: Alexander Petrosyan (http://design.ru/paf) - $Id: compile.y,v 1.209.2.1 2004/04/06 11:58:15 paf Exp $ + $Id: compile.y,v 1.219 2005/12/16 14:04:20 paf Exp $ */ /** @@ -48,6 +48,10 @@ static int real_yyerror(Parse_control* p static void yyprint(FILE* file, int type, YYSTYPE value); static int yylex(YYSTYPE* lvalp, void* pc); +static const VBool vfalse(false); +static const VBool vtrue(true); +static const VVoid vvoid; + // local convinient inplace typecast & var #undef PC #define PC (*(Parse_control *)pc) @@ -93,6 +97,9 @@ static int yylex(YYSTYPE* lvalp, void* p %token DEXISTS "-d" %token IS "is" +%token LITERAL_TRUE "true" +%token LITERAL_FALSE "false" + /* logical */ %left "!||" %left "||" @@ -343,9 +350,14 @@ construct: | construct_round | construct_curly ; -construct_square: '[' any_constructor_code_value ']' { +construct_square: '[' { + // allow $result_or_other_variable[ letters here any time ] + *reinterpret_cast(&$$)=PC.explicit_result; PC.explicit_result=false; +} any_constructor_code_value { + PC.explicit_result=*reinterpret_cast(&$2); +} ']' { // stack: context, name - $$=$2; // stack: context, name, value + $$=$3; // stack: context, name, value O(*$$, OP_CONSTRUCT_VALUE); /* value=pop; name=pop; context=pop; construct(context,name,value) */ } ; @@ -381,14 +393,9 @@ codes__excluding_sole_str_literal: actio call: call_value { $$=$1; /* stack: value */ - if(PC.explicit_result) - changetail_or_append(*$$, - OP_CALL, true, /*->*/ OP_CALL__WRITE__EXPLICIT_RESULT, - /*or */OP_WRITE_VALUE/*__EXPLICIT_RESULT*/); /* value=pop; check_empty(value) */ - else - changetail_or_append(*$$, - OP_CALL, true, /*->*/ OP_CALL__WRITE, - /*or */OP_WRITE_VALUE); /* value=pop; wcontext.write(value) */ + changetail_or_append(*$$, + OP_CALL, true, /*->*/ OP_CALL__WRITE, + /*or */OP_WRITE_VALUE); /* value=pop; wcontext.write(value) */ }; call_value: '^' { PC.in_call_value=true; @@ -402,7 +409,7 @@ call_value: '^' { YYSTYPE params_code=$5; if(params_code->count()==4) { // probably [] case. [OP_VALUE+origin+Void+STORE_PARAM] if(Value* value=LA2V(*params_code)) // it is OP_VALUE+origin+value? - if(!value->is_defined()) // value is VVoid? + if(value->is_void()) // value is VVoid? params_code=0; // ^zzz[] case. don't append lone empty param. } /* stack: context, method_junction */ @@ -417,7 +424,12 @@ store_param: | store_round_param | store_curly_param ; -store_square_param: '[' store_code_param_parts ']' {$$=$2}; +store_square_param: '[' { + // allow ^call[ letters here any time ] + *reinterpret_cast(&$$)=PC.explicit_result; PC.explicit_result=false; +} store_code_param_parts { + PC.explicit_result=*reinterpret_cast(&$2); +} ']' {$$=$3}; store_round_param: '(' store_expr_param_parts ')' {$$=$2}; store_curly_param: '{' store_curly_param_parts '}' {$$=$2}; store_code_param_parts: @@ -436,9 +448,20 @@ store_code_param_part: code_param_value $$=$1; O(*$$, OP_STORE_PARAM); }; -store_expr_param_part: write_expr_value { - $$=N(); - OA(*$$, OP_EXPR_CODE__STORE_PARAM, $1); +store_expr_param_part: expr_value { + YYSTYPE expr_code=$1; + if(expr_code->count()==3 + && (*expr_code)[0].code==OP_VALUE) { // optimizing (double/bool/incidently 'string' too) case. [OP_VALUE+origin+Double] + $$=expr_code; + O(*$$, OP_STORE_PARAM); // no evaluating + } else { + ArrayOperation* code=N(); + O(*code, OP_PREPARE_TO_EXPRESSION); + P(*code, *expr_code); + O(*code, OP_WRITE_EXPR_RESULT); + $$=N(); + OA(*$$, OP_EXPR_CODE__STORE_PARAM, code); + } }; store_curly_param_part: maybe_codes { $$=N(); @@ -449,12 +472,6 @@ code_param_value: | STRING /* optimized [STRING] case */ | constructor_code_value /* [something complex] */ ; -write_expr_value: expr_value { - $$=N(); - O(*$$, OP_PREPARE_TO_EXPRESSION); - P(*$$, *$1); - O(*$$, OP_WRITE_EXPR_RESULT); -}; /* name */ @@ -496,9 +513,14 @@ name_expr_with_subvar_value: STRING subv $$=N(); OA(*$$, OP_STRING_POOL, code); }; -name_square_code_value: '[' codes ']' { +name_square_code_value: '[' { + // allow $result_or_other_variable[ letters here any time ] + *reinterpret_cast(&$$)=PC.explicit_result; PC.explicit_result=false; +} codes { + PC.explicit_result=*reinterpret_cast(&$2); +} ']' { $$=N(); - OA(*$$, OP_OBJECT_POOL, $2); /* stack: empty write context */ + OA(*$$, OP_OBJECT_POOL, $3); /* stack: empty write context */ /* some code that writes to that context */ /* context=pop; stack: context.value() */ }; @@ -541,17 +563,15 @@ class_constructor_prefix: class_static_p /* expr */ -expr_value: expr { - // see OP_PREPARE_TO_EXPRESSION!! - if(($$=$1)->count()==2) // only one string literal in there? - change_string_literal_to_double_literal(*$$); // make that string literal Double -}; +expr_value: expr; expr: - STRING + double_or_STRING +| true_value +| false_value | get_value | call_value -| '"' string_inside_quotes_value '"' { $$ = $2; } -| '\'' string_inside_quotes_value '\'' { $$ = $2; } +| '"' string_inside_quotes_value '"' { $$ = $2 } +| '\'' string_inside_quotes_value '\'' { $$ = $2 } | '(' expr ')' { $$ = $2; } /* stack: operand // stack: @operand */ | '-' expr %prec NUNARY { $$=$2; O(*$$, OP_NEG) } @@ -592,6 +612,11 @@ expr: | expr "is" expr { $$=$1; P(*$$, *$3); O(*$$, OP_IS) } ; +double_or_STRING: STRING { + // optimized from OP_STRING->OP_VALUE for doubles + maybe_change_string_literal_to_double_literal(*($$=$1)); +}; + string_inside_quotes_value: maybe_codes { $$=N(); OA(*$$, OP_STRING_POOL, $1); /* stack: empty write context */ @@ -606,7 +631,10 @@ write_string: STRING { change_string_literal_to_write_string_literal(*($$=$1)) }; -void_value: /* empty */ { $$=VL(new VVoid(), 0, 0, 0) }; +void_value: /* empty */ { $$=VL(/*we know that we will not change it*/const_cast(&vvoid), 0, 0, 0) } +true_value: "true" { $$ = VL(/*we know that we will not change it*/const_cast(&vtrue), 0, 0, 0) } +false_value: "false" { $$ = VL(/*we know that we will not change it*/const_cast(&vfalse), 0, 0, 0) } + empty: /* empty */ { $$=N() }; %% @@ -730,9 +758,9 @@ default: } // #HH ? if(pc.source[0]=='#' && pc.source[1] && pc.source[2]) { - char c= + char c=(char)( hex_value[(unsigned char)pc.source[1]]*0x10+ - hex_value[(unsigned char)pc.source[2]]; + hex_value[(unsigned char)pc.source[2]]); if(c==0) { result=BAD_HEX_LITERAL; goto break2; // wrong hex value[no ^#00 chars allowed]: bail out @@ -1050,6 +1078,22 @@ default: goto break2; } break; + case 't': + if(end==begin) // right after whitespace + if(pc.source[0]=='r' && pc.source[1]=='u' && pc.source[2]=='e') { // def + skip_analized=3; + result=LITERAL_TRUE; + goto break2; + } + break; + case 'f': + if(end==begin) // right after whitespace + if(pc.source[0]=='a' && pc.source[1]=='l' && pc.source[2]=='s' && pc.source[3]=='e') { // def + skip_analized=4; + result=LITERAL_FALSE; + goto break2; + } + break; case ' ': case '\t': case '\n': if(end!=begin) { // there were a string after previous operator? result=0; // return that string