コード例 #1
0
ファイル: parse_num.c プロジェクト: MasterDuke17/MoarVM
static double parse_int_frac_exp(MVMThreadContext *tc, MVMCodepointIter *ci, MVMCodepoint *cp, MVMString* s, double radix, int leading_zero) {
    /*
     * What we do here is extract the digits from the original string,
     * effectively stripping off underscores and converting fancy Unicode
     * digits to regular ones. We then ASCII-fy those digits and stuff
     * them into digits_buf (along with double-ish things like the dot
     * and 'e'). At the end we give the resultant string to strtod() to
     * do all the dirty work for us, so we don't have to worry about
     * handling denormals or picking closest representable double
     */
    int digits = 0;
    int frac_digits = 0;
    int digit;
    int ends_with_underscore = 0;
    char *digits_buf = (char *)MVM_malloc(1 + MVM_string_graphs(tc, s));
    char *digits_buf_tail = digits_buf;
    double result;

    if (*cp == '_')
        parse_error(tc, s, "number can't start with _");

    if (*cp != '.') {
        while (*cp == '_' || (digit = cp_value(tc, *cp)) != -1) {
            ends_with_underscore = *cp == '_';
            if (*cp != '_') {
                if (digit >= radix) break;
                *digits_buf_tail++ = '0' + digit;
                digits++;
            }
            get_cp(tc, ci, cp);
        }
        if (ends_with_underscore)
            parse_error(tc, s, "a number can't end in underscore");
    }


    if (*cp == '.') {
        *digits_buf_tail++ = '.';
        get_cp(tc, ci, cp);
        if (*cp == '_')
            parse_error(tc, s, "radix point can't be followed by _");
        while (*cp == '_' || (digit = cp_value(tc, *cp)) != -1) {
            ends_with_underscore = *cp == '_';
            if (*cp != '_') {
                if (digit >= radix) break;
                *digits_buf_tail++ = '0' + digit;
                frac_digits++;
            }
            get_cp(tc, ci, cp);
        }
        if (frac_digits == 0)
            parse_error(tc, s,
                "radix point must be followed by one or more valid digits");
        if (ends_with_underscore)
            parse_error(tc, s, "a number can't end in underscore");
    }

    if (digits == 0 && frac_digits == 0 && !leading_zero)
        parse_error(tc, s, "expecting a number");

    if (*cp == 'E' || *cp == 'e') {
        int e_digits = 0;

        *digits_buf_tail++ = 'e';
        get_cp(tc, ci, cp);

        if (parse_sign(tc, ci, cp) == -1)
            *digits_buf_tail++ = '-';
        if (*cp == '_')
            parse_error(tc, s, "'e' or 'E' can't be followed by _");
        while (*cp == '_' || (digit = cp_value(tc, *cp)) != -1) {
            if (*cp != '_') {
                if (digit >= radix) break;
                *digits_buf_tail++ = '0' + digit;
                e_digits++;
            }
            get_cp(tc, ci, cp);
        }
        if (e_digits == 0)
            parse_error(tc, s,
                "'e' or 'E' must be followed by one or more valid digits");
    }

    *digits_buf_tail = '\0';
    result = strtod(digits_buf, NULL);
    MVM_free(digits_buf);
    return result;
}
コード例 #2
0
ファイル: parse_num.c プロジェクト: MasterDuke17/MoarVM
static double parse_simple_number(MVMThreadContext *tc, MVMCodepointIter *ci, MVMCodepoint *cp, MVMString *s) {
    double sign;
    /* Handle NaN here, to make later parsing simpler */

    if (match_word(tc, ci, cp, "NaN", s)) {
        return MVM_num_nan(tc);
    }

    sign = parse_sign(tc, ci, cp);

    if (match_word(tc, ci, cp, "Inf", s)) {
        return sign * MVM_num_posinf(tc);
    }
    else if (*cp == ':') {
        int radix;
        double body;
        get_cp(tc, ci, cp);
        radix = (int) parse_int_frac_exp(tc, ci, cp, s, 10, 0);
        if (*cp == '<') {
            get_cp(tc, ci, cp);
            body = parse_int_frac_exp(tc, ci, cp, s, radix, 0);
            if (*cp == '>') { /* > */
                get_cp(tc, ci, cp);
                return sign * body;
            }
            parse_error(tc, s, "malformed ':radix<>' style radix number, expecting '>' after the body");
        }
        else if (*cp == 171) { /* « */
            get_cp(tc, ci, cp);
            body = parse_int_frac_exp(tc, ci, cp, s, radix, 0);
            if (*cp == 187) { /* » */
                get_cp(tc, ci, cp);
                return sign * body;
            }
            parse_error(tc, s, "malformed ':radix«»' style radix number, expecting '>' after the body");
        }
        else if (*cp == '[') {
            double result = 0;
            get_cp(tc, ci, cp);
            while (*cp != ']' && MVM_string_ci_has_more(tc, ci)) {
                double digit = parse_decimal_integer(tc, ci, cp, s);
                result = result * radix + digit;
                if (*cp == ',') {
                    get_cp(tc, ci, cp);
                }
            }
            if (*cp == ']') {
                get_cp(tc, ci, cp);
                return sign * result;
            }
            parse_error(tc, s, "malformed ':radix[]' style radix number, expecting ']' after the body");
        }
        parse_error(tc, s, "malformed ':radix' style number. Expected <, [ or « after ':radix'");
    }
    else if (*cp == '0') {
        int radix = 0;

        get_cp(tc, ci, cp);
        switch (*cp) {
        case 'b': radix =  2; break;
        case 'o': radix =  8; break;
        case 'd': radix = 10; break;
        case 'x': radix = 16; break;
        }
        if (radix) {
            get_cp(tc, ci, cp);
            if (*cp == '_') get_cp(tc, ci, cp);
            return sign * parse_int_frac_exp(tc, ci, cp, s, radix, 1);
        }
        return sign * parse_int_frac_exp(tc, ci, cp, s, 10, 1);
    }
    else {
        return sign * parse_int_frac_exp(tc, ci, cp, s, 10, 0);
    }
}
コード例 #3
0
ファイル: expression.c プロジェクト: 38/basiclone
Data* parse_term( char** p )
{
	Data* ret = NULL;
	while(1)
	{
		char op;
		int sign;
		if( ret )
		{
			parse_ws(p);
			op = *((*p));
			if( op != '*' && op != '/' ) 
			{
				break; /*last chr should not be parsed*/
			}
			else
				(*p)++;
		}
		sign=parse_sign(p);
		if( sign == 0 ) sign = 1;
		Data* factor = parse_factor(p);
		if( factor->type == TYPE_ERROR )
		{
			dispose(ret);
			return factor; /*throw*/
		}
		if( sign == -1 )
		{
			if( factor->type == TYPE_STRING )
			{
				dispose(factor);
				dispose(ret);
				return Raise(SYNTAX);
			}
			else if( factor->type == TYPE_REAL )
				factor->storage.Real = -factor->storage.Real;
			else
				factor->storage.Integer = - factor->storage.Integer;
		}
		parse_ws(p);
		if( **p == '^' )
		{/*exponent*/
			(*p)++;
			Data* exponent = parse_factor(p);
			factor = temp_var(factor);
			if( exponent->type == TYPE_ERROR )
			{
				dispose(ret);
				dispose(factor);
				return exponent;
			}
			if( exponent->type == TYPE_STRING || factor->type == TYPE_STRING)
			{
				dispose(ret);
				dispose(factor);	
				dispose(exponent);
				return Data_new( TYPE_ERROR , (Storage)Error_new(TYPE_MISMATCH) , 1 );
			}
			if( factor->type == TYPE_INTEGER )
			{
				factor->storage.Real = factor->storage.Integer;
				factor->type = TYPE_REAL;
			}
			if( exponent->type == TYPE_INTEGER )
			{
				factor->storage.Real = factor->storage.Integer;
				factor->type = TYPE_REAL;
			}
			factor->storage.Real = exp( log(factor->storage.Real) * exponent->storage.Real); 
			dispose(exponent);
		}
		
		if( ret == NULL )
			ret = factor;
		else
		{
			ret = temp_var(ret);
			if( ret->type == TYPE_STRING )
			{
				dispose(ret);
				dispose(factor);
				return Raise(TYPE_MISMATCH);
			}
			else
			{
				if( op == '*' )
				{
					if( ret->type == TYPE_REAL || factor->type == TYPE_REAL )
					{
						if( ret->type == TYPE_INTEGER )
						{
							ret->type = TYPE_REAL;
							ret->storage.Real = ret->storage.Integer;
						}
						if( factor->type == TYPE_INTEGER )
						{
							factor->type = TYPE_REAL;
							factor->storage.Real = factor->storage.Integer;
						}
						ret->storage.Real *= factor->storage.Real;
											
					}
					else
						ret->storage.Integer *= factor->storage.Integer;
				}
				else
				{
					if( ret->type == TYPE_INTEGER )
					{
						ret->type = TYPE_REAL;
						ret->storage.Real = ret->storage.Integer;
					}
					if( factor->type == TYPE_INTEGER )
					{
						factor->type = TYPE_REAL;
						factor->storage.Real = factor->storage.Integer;
					}
					if( factor->storage.Real == 0 )
					{
						dispose( ret );
						dispose( factor );
						return Raise(DIV_BY_ZERO);
					}
					ret->storage.Real /= factor->storage.Real;
				}
					
			}
			dispose(factor);
		}
	}
	return ret;
}
コード例 #4
0
ファイル: expression.c プロジェクト: 38/basiclone
Data* parse_aexpr(char** p)
{
	Data* ret = NULL;
	while(parse_ws(p),**p)
	{
		int sign ;
		sign = parse_sign(p);
		if( !ret || sign )
		{
			Data* term = parse_term(p);
			if( term->type == TYPE_ERROR )
			{
				dispose(ret);
				return term;    /*Throw the error*/
			}
			else if( !ret )      /* First term */
			{
				if( sign != 0 && term->type == TYPE_STRING )   
						  /* There are one or more negitive/positive sign before A string*/
						  /* e.g. : +"illegal"*/
				{
					dispose(term);
					dispose(ret);						
					return Raise(SYNTAX); /*raise a syntax error*/
				}
				else ret = term;
				if( sign < 0 )
				{/*only INTEGER and REAL */
					if( term->type == TYPE_INTEGER )
						term->storage.Integer = -term->storage.Integer;
					else
						term->storage.Real = -term->storage.Real;
				}
			}
			else if( term->type == TYPE_STRING )
			{
				ret = temp_var(ret);
				if( sign > 0 )  /* AC + STRING */
				{
					if( ret->type != TYPE_STRING )
					{
						/* non-string + string is illegal */
						dispose(term);
						dispose(ret);
						return Raise(TYPE_MISMATCH);
					}
					/* do strcat */
					char* A = ret->storage.String;
					char* B = term->storage.String;
					int  lA = strlen(A);
					int  lB = strlen(B);
					char* temp = (char*)malloc( lA + lB + 1);
					strcpy( temp , A );
					strcpy( temp + lA , B );
					ret->storage.String = temp;
					if( A != init_value[TYPE_STRING].String )
						free(A);   /*dispose old string*/
					dispose(term);     /*dispose this term*/
				}
				else
				{
					/* AC - string is illegal */
					dispose(term);
					dispose(ret);
					return Raise(TYPE_MISMATCH);
				}
			}
			else if( term->type == TYPE_INTEGER )
			{
				ret = temp_var(ret);
				/*AC + INTEGER*/
				if( ret->type == TYPE_STRING )
				{/*Type Mismatch*/
					dispose(ret);
					dispose(term);
					return Raise(TYPE_MISMATCH);
				}
				else if( ret->type == TYPE_INTEGER )
				{/*Integer + Integer*/
					ret->storage.Integer += sign * term->storage.Integer;
					dispose(term);
				}
				else if( ret->type == TYPE_REAL )
				{/*Real + Integer*/
					ret->storage.Real += sign * term->storage.Integer;
					dispose(term);					
				}
			} 
			else if( term->type == TYPE_REAL )
			{

				double org;
				ret = temp_var(ret);
				/*AC + REAL */
				if( ret->type == TYPE_STRING )
				{/*Type Mismatch*/
					dispose(ret);
					dispose(term);
					return Raise(TYPE_MISMATCH);
				}


				if( ret->type == TYPE_REAL )
					org = ret->storage.Real;
				else
					org = ret->storage.Integer;
				ret->type = TYPE_REAL;
				ret->storage.Real = org + sign * term->storage.Real;
				dispose(term);
			}
		}
		else
			break; 
	}
	if( ret == NULL )
		ret=Raise(SYNTAX);
	return ret;
}
コード例 #5
0
ファイル: sign.c プロジェクト: Firehed/RotK
void do_sign(CHAR_DATA *ch,char *argument)
{
    parse_sign(ch,argument,NOTE_SIGN);
}