From: yu.dongliang <18588496441@163.com> Date: Tue, 9 Jun 2026 11:02:52 +0000 (+0800) Subject: 1, support const double / float literal number such as .618, .5f, etc. X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=f101ffe49261d263f323026fc1cc1f019c65643b;p=scf.git 1, support const double / float literal number such as .618, .5f, etc. 2, support const number calculate with u64 type. --- diff --git a/core/scf_calculate.c b/core/scf_calculate.c index 2e429c1..6f068ad 100644 --- a/core/scf_calculate.c +++ b/core/scf_calculate.c @@ -3,6 +3,7 @@ #include"scf_calculate_i32.c" #include"scf_calculate_u32.c" #include"scf_calculate_i64.c" +#include"scf_calculate_u64.c" #include"scf_calculate_float.c" #include"scf_calculate_double.c" @@ -99,6 +100,37 @@ scf_calculate_t base_calculates[] = {"i64", SCF_OP_GE, SCF_VAR_I64, SCF_VAR_I64, SCF_VAR_I64, scf_i64_ge}, {"i64", SCF_OP_LE, SCF_VAR_I64, SCF_VAR_I64, SCF_VAR_I64, scf_i64_le}, + // u64 + {"u64", SCF_OP_ADD, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_add}, + {"u64", SCF_OP_SUB, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_sub}, + {"u64", SCF_OP_MUL, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_mul}, + {"u64", SCF_OP_DIV, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_div}, + {"u64", SCF_OP_MOD, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_mod}, + + {"u64", SCF_OP_SHL, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_shl}, + {"u64", SCF_OP_SHR, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_shr}, + + {"u64", SCF_OP_INC, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_inc}, + {"u64", SCF_OP_DEC, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_dec}, + + {"u64", SCF_OP_NEG, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_neg}, + + {"u64", SCF_OP_BIT_AND, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_bit_and}, + {"u64", SCF_OP_BIT_OR, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_bit_or}, + {"u64", SCF_OP_BIT_NOT, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_bit_not}, + + {"u64", SCF_OP_LOGIC_AND, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_logic_and}, + {"u64", SCF_OP_LOGIC_OR, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_logic_or}, + {"u64", SCF_OP_LOGIC_NOT, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_logic_not}, + + {"u64", SCF_OP_GT, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_gt}, + {"u64", SCF_OP_LT, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_lt}, + + {"u64", SCF_OP_EQ, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_eq}, + {"u64", SCF_OP_NE, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_ne}, + {"u64", SCF_OP_GE, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_ge}, + {"u64", SCF_OP_LE, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_le}, + {"float", SCF_OP_ADD, SCF_VAR_FLOAT, SCF_VAR_FLOAT, SCF_VAR_FLOAT, scf_float_add}, {"float", SCF_OP_SUB, SCF_VAR_FLOAT, SCF_VAR_FLOAT, SCF_VAR_FLOAT, scf_float_sub}, {"float", SCF_OP_MUL, SCF_VAR_FLOAT, SCF_VAR_FLOAT, SCF_VAR_FLOAT, scf_float_mul}, @@ -136,4 +168,3 @@ scf_calculate_t* scf_find_base_calculate(int op_type, int src0_type, int src1_ty return NULL; } - diff --git a/core/scf_calculate.h b/core/scf_calculate.h index 145e252..4d2b19a 100644 --- a/core/scf_calculate.h +++ b/core/scf_calculate.h @@ -19,4 +19,3 @@ typedef struct { scf_calculate_t* scf_find_base_calculate(int op_type, int src0_type, int src1_type); #endif - diff --git a/core/scf_calculate_i32.c b/core/scf_calculate_i32.c index 50fc79c..c01ad95 100644 --- a/core/scf_calculate_i32.c +++ b/core/scf_calculate_i32.c @@ -63,4 +63,3 @@ SCF_I32_BINARY_OP(eq, ==) SCF_I32_BINARY_OP(ne, !=) SCF_I32_BINARY_OP(ge, >=) SCF_I32_BINARY_OP(le, <=) - diff --git a/core/scf_calculate_i64.c b/core/scf_calculate_i64.c index 06aa716..ed2eee9 100644 --- a/core/scf_calculate_i64.c +++ b/core/scf_calculate_i64.c @@ -63,4 +63,3 @@ SCF_I64_BINARY_OP(eq, ==) SCF_I64_BINARY_OP(ne, !=) SCF_I64_BINARY_OP(ge, >=) SCF_I64_BINARY_OP(le, <=) - diff --git a/core/scf_calculate_u32.c b/core/scf_calculate_u32.c index 7ecb10f..fa982d2 100644 --- a/core/scf_calculate_u32.c +++ b/core/scf_calculate_u32.c @@ -63,4 +63,3 @@ SCF_U32_BINARY_OP(eq, ==) SCF_U32_BINARY_OP(ne, !=) SCF_U32_BINARY_OP(ge, >=) SCF_U32_BINARY_OP(le, <=) - diff --git a/core/scf_calculate_u64.c b/core/scf_calculate_u64.c new file mode 100644 index 0000000..36aaebd --- /dev/null +++ b/core/scf_calculate_u64.c @@ -0,0 +1,65 @@ +#include"scf_calculate.h" + +#define SCF_U64_BINARY_OP(name, op) \ +int scf_u64_##name(scf_ast_t* ast, scf_variable_t** pret, scf_variable_t* src0, scf_variable_t* src1) \ +{ \ + scf_type_t* t = scf_block_find_type_type(ast->current_block, SCF_VAR_U64); \ + scf_variable_t* r = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 0, 0, NULL); \ + if (!r) \ + return -ENOMEM; \ + r->data.u64 = src0->data.u64 op src1->data.u64; \ + if (pret) \ + *pret = r; \ + return 0; \ +} + +#define SCF_U64_UNARY_OP(name, op) \ +int scf_u64_##name(scf_ast_t* ast, scf_variable_t** pret, scf_variable_t* src0, scf_variable_t* src1) \ +{ \ + scf_type_t* t = scf_block_find_type_type(ast->current_block, SCF_VAR_U64); \ + scf_variable_t* r = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 0, 0, NULL); \ + if (!r) \ + return -ENOMEM; \ + r->data.u64 = op src0->data.u64; \ + if (pret) \ + *pret = r; \ + return 0; \ +} + +#define SCF_U64_UPDATE_OP(name, op) \ +int scf_u64_##name(scf_ast_t* ast, scf_variable_t** pret, scf_variable_t* src0, scf_variable_t* src1) \ +{ \ + op src0->data.u64; \ + if (pret) \ + *pret = scf_variable_ref(src0); \ + return 0; \ +} + +SCF_U64_BINARY_OP(add, +) +SCF_U64_BINARY_OP(sub, -) +SCF_U64_BINARY_OP(mul, *) +SCF_U64_BINARY_OP(div, /) +SCF_U64_BINARY_OP(mod, %) + +SCF_U64_BINARY_OP(shl, <<) +SCF_U64_BINARY_OP(shr, >>) + +SCF_U64_UPDATE_OP(inc, ++); +SCF_U64_UPDATE_OP(dec, --); + +SCF_U64_UNARY_OP(neg, -) + +SCF_U64_BINARY_OP(bit_and, &) +SCF_U64_BINARY_OP(bit_or, |) +SCF_U64_UNARY_OP(bit_not, ~) + +SCF_U64_BINARY_OP(logic_and, &&) +SCF_U64_BINARY_OP(logic_or, ||) +SCF_U64_UNARY_OP(logic_not, !) + +SCF_U64_BINARY_OP(gt, >) +SCF_U64_BINARY_OP(lt, <) +SCF_U64_BINARY_OP(eq, ==) +SCF_U64_BINARY_OP(ne, !=) +SCF_U64_BINARY_OP(ge, >=) +SCF_U64_BINARY_OP(le, <=) diff --git a/examples/const_postfix.c b/examples/const_postfix.c new file mode 100644 index 0000000..6103d2e --- /dev/null +++ b/examples/const_postfix.c @@ -0,0 +1,11 @@ +int printf(const char* fmt, ...); + +int a = 0; + +int main() +{ + int* p = &a; + + printf("%#lx\n", p & ~0x1ull); + return 0; +} diff --git a/examples/float_inc.c b/examples/float_inc.c index c22fe88..8e22f6f 100644 --- a/examples/float_inc.c +++ b/examples/float_inc.c @@ -3,7 +3,7 @@ int printf(const char* fmt, ...); int main() { - double d; + double d = .5f; for (d = 0.1; d < 10.0; d++) printf("%lg\n", d); return 0; diff --git a/lex/scf_lex_test.c b/lex/scf_lex_test.c index 28e8223..a42dbb1 100644 --- a/lex/scf_lex_test.c +++ b/lex/scf_lex_test.c @@ -4,9 +4,7 @@ int main(int argc, char* argv[]) { scf_lex_t* lex = NULL; - scf_string_t* text = scf_string_cstr("document.write(\"hello js\n\")"); - - if (scf_lex_open(&lex, argv[1], text) < 0) { + if (scf_lex_open(&lex, argv[1], NULL) < 0) { scf_loge("\n"); return -1; } diff --git a/lex/scf_lex_util.c b/lex/scf_lex_util.c index f18756f..2a09659 100644 --- a/lex/scf_lex_util.c +++ b/lex/scf_lex_util.c @@ -41,25 +41,26 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex) return c; } + int n = 0; if (0x6 == (ret >> 5)) { - c->c = ret & 0x1f; - c->len = 2; + c->c = ret & 0x1f; + n = 2; } else if (0xe == (ret >> 4)) { - c->c = ret & 0xf; - c->len = 3; + c->c = ret & 0xf; + n = 3; } else if (0x1e == (ret >> 3)) { - c->c = ret & 0x7; - c->len = 4; + c->c = ret & 0x7; + n = 4; } else if (0x3e == (ret >> 2)) { - c->c = ret & 0x3; - c->len = 5; + c->c = ret & 0x3; + n = 5; } else if (0x7e == (ret >> 1)) { - c->c = ret & 0x1; - c->len = 6; + c->c = ret & 0x1; + n = 6; } else { scf_loge("utf8 first byte wrong %#x, file: %s, line: %d\n", ret, lex->file->data, lex->nb_lines); free(c); @@ -69,7 +70,7 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex) c->utf8[0] = ret; int i; - for (i = 1; i < c->len; i++) { + for (i = 1; i < n; i++) { ret = __lex_getc(lex); @@ -79,12 +80,13 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex) c->utf8[i] = ret; } else { - scf_loge("utf8 byte[%d] wrong %#x, file: %s, line: %d\n", i + 1, ret, lex->file->data, lex->nb_lines); + scf_loge("utf8 byte[%d] wrong %#x, file: %s, line: %d\n", i, ret, lex->file->data, lex->nb_lines); free(c); return NULL; } } + c->len = n; return c; } @@ -212,71 +214,123 @@ int _lex_op3_ll1(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0, return 0; } +static scf_key_word_t number_postfix[] = +{ + {"l", SCF_LEX_WORD_CONST_INT}, + {"ll", SCF_LEX_WORD_CONST_I64}, + + {"u", SCF_LEX_WORD_CONST_U32}, + {"ul", SCF_LEX_WORD_CONST_U32}, + {"ull", SCF_LEX_WORD_CONST_U64}, + + {"f", SCF_LEX_WORD_CONST_FLOAT}, + {"lf", SCF_LEX_WORD_CONST_DOUBLE}, +}; + +static int _lex_number_postfix(const char* postfix, int n) +{ + scf_key_word_t* key; + int i; + + for (i = 0; i < sizeof(number_postfix) / sizeof(number_postfix[0]); i++) { + key = &number_postfix[i]; + + if (!strncmp(key->text, postfix, n)) + return key->type; + } + + return -EINVAL; +} + int _lex_number_base_10(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_char_t* c2; - scf_char_t* c3; - scf_lex_word_t* w; + scf_char_t* c2; + scf_char_t* c3; + scf_lex_word_t* w; + int type = -1; int dot = 0; int exp = 0; int neg = 0; uint64_t value = 0; uint64_t num; + char postfix[8]; + int n = 0; + while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '9') { - num = c2->c - '0'; - value *= 10; - value += num; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - } else if ('.' == c2->c) { + if ('a' <= tmp && 'z' >= tmp) { - c3 = _lex_pop_char(lex); + if (n > 0 || 'e' != tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - _lex_push_char(lex, c3); + goto next; + } + + } else if (n > 0) { + _lex_push_char(lex, c2); + c2 = NULL; + + postfix[n] = '\0'; + + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } + + break; + } + + if (tmp >= '0' && tmp <= '9') + value = value * 10 + tmp - '0'; + + else if ('.' == tmp) { + c3 = _lex_pop_char(lex); + tmp = c3->c; - if ('.' == c3->c) { - c3 = NULL; + _lex_push_char(lex, c3); + c3 = NULL; + if ('.' == tmp) { _lex_push_char(lex, c2); c2 = NULL; break; } - c3 = NULL; - if (++dot > 1) { scf_loge("\n"); - return -EINVAL; + goto error; } - } else if ('e' == c2->c || 'E' == c2->c) { - exp++; - - if (exp > 1) { + } else if ('e' == tmp) { + if (++exp > 1) { scf_loge("\n"); - return -EINVAL; + goto error; } - } else if ('-' == c2->c) { - neg++; - - if (0 == exp || neg > 1) { + } else if ('-' == tmp) { + if (0 == exp || ++neg > 1) { scf_loge("\n"); - return -EINVAL; + goto error; } } else if ('_' == c2->c) { - + // only to split every 3-4 numbers, no other use. } else { _lex_push_char(lex, c2); c2 = NULL; break; } +next: assert(1 == c2->len); scf_string_cat_cstr_len(s, c2->utf8, 1); lex->pos++; @@ -286,10 +340,18 @@ int _lex_number_base_10(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) } if (exp > 0 || dot > 0) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); - w->data.d = atof(s->data); + if (SCF_LEX_WORD_CONST_FLOAT == type) { + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_FLOAT); + w->data.f = atof(s->data); + } else { + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); + w->data.d = atof(s->data); + } } else { - if (value & ~0xffffffffULL) + if (type > 0) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + + else if (value & ~0xffffffffULL) w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); else w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); @@ -302,57 +364,66 @@ int _lex_number_base_10(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) *pword = w; return 0; + +error: + free(c2); + return -EINVAL; } int _lex_number_base_16(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_char_t* c2; - scf_lex_word_t* w; + scf_char_t* c2; + scf_lex_word_t* w; + int type = -1; uint64_t value = 0; - uint64_t value2; + + char postfix[8]; + int n = 0; while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '9') - value2 = c2->c - '0'; - - else if ('a' <= c2->c && 'f' >= c2->c) - value2 = c2->c - 'a' + 10; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - else if ('A' <= c2->c && 'F' >= c2->c) - value2 = c2->c - 'A' + 10; + if ('g' <= tmp && 'z' >= tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - else if ('_' == c2->c) { - assert(1 == c2->len); - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; - - free(c2); - c2 = NULL; + goto next; - } else { + } else if (n > 0) { _lex_push_char(lex, c2); c2 = NULL; - if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); - else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); - - w->data.u64 = value; + postfix[n] = '\0'; - w->text = s; - s = NULL; + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } - *pword = w; - return 0; + break; } - value <<= 4; - value += value2; + if (tmp >= '0' && tmp <= '9') + value = (value << 4) + tmp - '0'; + + else if ('a' <= tmp && 'f' >= tmp) + value = (value << 4) + tmp - 'a' + 10; + + else if ('_' == tmp) { + // only to split every 3-4 numbers, no other use. + } else { + _lex_push_char(lex, c2); + c2 = NULL; + break; + } +next: assert(1 == c2->len); scf_string_cat_cstr_len(s, c2->utf8, 1); lex->pos++; @@ -360,149 +431,266 @@ int _lex_number_base_16(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) free(c2); c2 = NULL; } + + if (type > 0) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + + else if (value & ~0xffffffffULL) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + else + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + + w->data.u64 = value; + + w->text = s; + s = NULL; + + *pword = w; + return 0; + +error: + free(c2); + return -EINVAL; } int _lex_number_base_8(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_char_t* c2; - scf_lex_word_t* w; + scf_char_t* c2; + scf_lex_word_t* w; + int type = -1; uint64_t value = 0; + char postfix[8]; + int n = 0; + while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '7') { - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - value = (value << 3) + c2->c - '0'; + if ('a' <= tmp && 'z' >= tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - free(c2); + goto next; + + } else if (n > 0) { + _lex_push_char(lex, c2); c2 = NULL; - } else if ('8' == c2->c || '9' == c2->c) { - scf_loge("number must be 0-7 when base 8"); + postfix[n] = '\0'; - free(c2); - c2 = NULL; - return -1; + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } - } else if ('_' == c2->c) { - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + break; + } - free(c2); - c2 = NULL; + if (tmp >= '0' && tmp <= '7') + value = (value << 3) + tmp - '0'; + + else if ('8' == tmp || '9' == tmp) { + scf_loge("number must be 0-7 when base 8"); + goto error; + } else if ('_' == tmp) { + // only to split every 3-4 numbers, no other use. } else { _lex_push_char(lex, c2); c2 = NULL; + break; + } - if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); - else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); - w->data.u64 = value; - - w->text = s; - s = NULL; +next: + assert(1 == c2->len); + scf_string_cat_cstr_len(s, c2->utf8, 1); + lex->pos++; - *pword = w; - return 0; - } + free(c2); + c2 = NULL; } + + if (type > 0) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + + else if (value & ~0xffffffffULL) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + else + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + w->data.u64 = value; + + w->text = s; + s = NULL; + + *pword = w; + return 0; + +error: + free(c2); + return -EINVAL; } int _lex_number_base_2(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_char_t* c2; - scf_lex_word_t* w; + scf_char_t* c2; + scf_lex_word_t* w; + int type = -1; uint64_t value = 0; + char postfix[8]; + int n = 0; + while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '1') { - assert(1 == c2->len); - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - value = (value << 1) + c2->c - '0'; + if ('a' <= tmp && 'z' >= tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - free(c2); + goto next; + + } else if (n > 0) { + _lex_push_char(lex, c2); c2 = NULL; - } else if (c2->c >= '2' && c2->c <= '9') { - scf_loge("number must be 0-1 when base 2"); + postfix[n] = '\0'; - free(c2); - c2 = NULL; - return -1; + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } - } else if ('_' == c2->c) { - assert(1 == c2->len); - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + break; + } - free(c2); - c2 = NULL; + if (tmp >= '0' && tmp <= '1') + value = (value << 1) + tmp - '0'; + + else if (tmp >= '2' && tmp <= '9') { + scf_loge("number must be 0-1 when base 2"); + goto error; + } else if ('_' == tmp) { + // only to split every 3-4 numbers, no other use. } else { _lex_push_char(lex, c2); c2 = NULL; + break; + } - if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); - else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); - w->data.u64 = value; - - w->text = s; - s = NULL; +next: + assert(1 == c2->len); + scf_string_cat_cstr_len(s, c2->utf8, 1); + lex->pos++; - *pword = w; - return 0; - } + free(c2); + c2 = NULL; } + + if (type > 0) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + + else if (value & ~0xffffffffULL) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + else + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + w->data.u64 = value; + + w->text = s; + s = NULL; + + *pword = w; + return 0; + +error: + free(c2); + return -EINVAL; } int _lex_double(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_lex_word_t* w; - scf_char_t* c2; + scf_char_t* c2; + scf_lex_word_t* w; + + int type = -1; + char postfix[8]; + int n = 0; while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '9') { - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - free(c2); - c2 = NULL; + if ('a' <= tmp && 'z' >= tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - } else if ('.' == c2->c) { - scf_loge("too many '.' for number in file: %s, line: %d\n", lex->file->data, lex->nb_lines); + goto next; - free(c2); + } else if (n > 0) { + _lex_push_char(lex, c2); c2 = NULL; - return -1; + postfix[n] = '\0'; + + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } + + break; + } + + if (tmp >= '0' && tmp <= '9') { + + } else if ('.' == tmp) { + scf_loge("too many '.' for number in file: %s, line: %d\n", lex->file->data, lex->nb_lines); + goto error; } else { _lex_push_char(lex, c2); c2 = NULL; break; } + +next: + assert(1 == c2->len); + scf_string_cat_cstr_len(s, c2->utf8, 1); + lex->pos++; + + free(c2); + c2 = NULL; } - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); - w->data.d = atof(s->data); + if (SCF_LEX_WORD_CONST_FLOAT == type) { + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_FLOAT); + w->data.f = atof(s->data); + } else { + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); + w->data.d = atof(s->data); + } w->text = s; *pword = w; return 0; + +error: + free(c2); + return -EINVAL; } int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) @@ -510,8 +698,6 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) scf_char_t* c1 = _lex_pop_char(lex); scf_char_t* c2 = NULL; scf_lex_word_t* w = NULL; - scf_lex_word_t* w1 = NULL; - scf_lex_word_t* w2 = NULL; scf_string_t* s = scf_string_cstr_len(c0->utf8, c0->len); lex->pos += c0->len; @@ -547,90 +733,53 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) c2 = NULL; } - } else { - if (lex->asm_flag - && 'a' <= (c1->c | 0x20) - && 'z' >= (c1->c | 0x20)) { - - do { - scf_string_cat_cstr_len(s, c1->utf8, 1); - lex->pos++; - - free(c1); - c1 = _lex_pop_char(lex); - - if (!c1) { - scf_string_free(s); - return -ENOMEM; - } - } while ('a' <= (c1->c | 0x20) && 'z' >= (c1->c | 0x20)); - - _lex_push_char(lex, c1); - c1 = NULL; + } else if (lex->asm_flag + && 'a' <= (c1->c | 0x20) + && 'z' >= (c1->c | 0x20)) { + do { + scf_string_cat_cstr_len(s, c1->utf8, 1); + lex->pos++; - int type = _find_key_word(s->data); - if (type < 0) { - scf_loge("unknown asm key word '%s', file: %s, line: %d\n", s->data, lex->file->data, lex->nb_lines); + free(c1); + c1 = _lex_pop_char(lex); - scf_string_free(s); - return -EINVAL; - } - - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); - if (!w) { + if (!c1) { scf_string_free(s); return -ENOMEM; } + } while ('a' <= (c1->c | 0x20) && 'z' >= (c1->c | 0x20)); - w->text = s; - s = NULL; + _lex_push_char(lex, c1); + c1 = NULL; - *pword = w; - return 0; + int type = _find_key_word(s->data); + if (type < 0) { + scf_loge("unknown asm key word '%s', file: %s, line: %d\n", s->data, lex->file->data, lex->nb_lines); + + scf_string_free(s); + return -EINVAL; + } + + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + if (!w) { + scf_string_free(s); + return -ENOMEM; } - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_DOT); w->text = s; s = NULL; + } else { + int tmp = c1->c; _lex_push_char(lex, c1); c1 = NULL; - int ret = __lex_pop_word(lex, &w1); - if (ret < 0) { - scf_lex_word_free(w); - return ret; - } - - if (SCF_LEX_WORD_CONST_CHAR <= w1->type && w1->type <= SCF_LEX_WORD_CONST_U64) { - - ret = __lex_pop_word(lex, &w2); - if (ret < 0) { - scf_lex_word_free(w); - scf_lex_word_free(w1); - return ret; - } - - scf_lex_push_word(lex, w2); - - if (w2->type != SCF_LEX_WORD_ASSIGN && w2->type != SCF_LEX_WORD_DOT) { - w->type = SCF_LEX_WORD_CONST_DOUBLE; - - ret = scf_string_cat(w->text, w1->text); - scf_lex_word_free(w1); - w1 = NULL; - - if (ret < 0) { - scf_lex_word_free(w); - return ret; - } + if ('0' <= tmp && '9' >= tmp) // for double / float .5, .618, etc. + return _lex_double(lex, pword, s); - w->data.d = atof(w->text->data); - } - } - - if (w1) - scf_lex_push_word(lex, w1); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_DOT); + w->text = s; + s = NULL; } *pword = w; diff --git a/parse/Makefile b/parse/Makefile index 787673c..594763d 100644 --- a/parse/Makefile +++ b/parse/Makefile @@ -168,7 +168,7 @@ CFILES += scf_dfa_async.c CFILES += scf_dfa_block.c -CFLAGS += -g +CFLAGS += -g -O3 #CFLAGS += -Wall CFLAGS += -I../util CFLAGS += -I../core diff --git a/util/scf_string.c b/util/scf_string.c index ac82cd5..c73f9a2 100644 --- a/util/scf_string.c +++ b/util/scf_string.c @@ -108,7 +108,7 @@ int scf_string_cmp(const scf_string_t* s0, const scf_string_t* s1) if (s0->len > s1->len) return 1; - return strncmp(s0->data, s1->data, s0->len); + return memcmp(s0->data, s1->data, s0->len); } int scf_string_cmp_cstr(const scf_string_t* s0, const char* str)