diff options
-rw-r--r-- | builtin.cpp | 49 | ||||
-rw-r--r-- | parser.cpp | 17 |
2 files changed, 50 insertions, 16 deletions
diff --git a/builtin.cpp b/builtin.cpp index 26bbc9d..de8bd12 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -43,6 +43,20 @@ double str_to_double(string repr, bool &flag) { return val; } +int str_to_int(string repr, bool &flag) { + const char *nptr = repr.c_str(); + char *endptr; + int val = strtol(nptr, &endptr, 10); + if (endptr != nptr + repr.length()) + { + flag = false; + return 0; + } + flag = true; + return val; +} + + int gcd(int a, int b) { int t; while (b) t = b, b = a % b, a = t; @@ -73,17 +87,31 @@ CompNumObj *CompNumObj::from_string(string repr) { if (spos == -1 || ipos == -1 || !(spos < ipos)) return NULL; - bool flag; double real = 0, imag = 1; + IntNumObj *int_ptr; + RatNumObj *rat_ptr; + RealNumObj *real_ptr; if (spos > 0) { - real = str_to_double(repr.substr(0, spos), flag); - if (!flag) return NULL; + string real_str = repr.substr(0, spos); + if (int_ptr = IntNumObj::from_string(real_str)) + real = int_ptr->val; + else if ((rat_ptr = RatNumObj::from_string(real_str))) + real = rat_ptr->a / double(rat_ptr->b); + else if ((real_ptr = RealNumObj::from_string(real_str))) + real = real_ptr->real; + else return NULL; } if (ipos > spos + 1) { - imag = str_to_double(repr.substr(spos + 1, ipos - spos - 1), flag); - if (!flag) return NULL; + string imag_str = repr.substr(spos + 1, ipos - spos - 1); + if (int_ptr = IntNumObj::from_string(imag_str)) + imag = int_ptr->val; + else if ((rat_ptr = RatNumObj::from_string(imag_str))) + imag = rat_ptr->a / double(rat_ptr->b); + else if ((real_ptr = RealNumObj::from_string(imag_str))) + imag = real_ptr->real; + else return NULL; } if (sign) imag = -imag; return new CompNumObj(real, imag); @@ -229,8 +257,15 @@ RatNumObj::RatNumObj(int _a, int _b) : RatNumObj *RatNumObj::from_string(string repr) { int a, b; - if (sscanf(repr.c_str(), "%d/%d", &a, &b) != 2) - return NULL; + int len = repr.length(), pos = -1; + for (int i = 0; i < len; i++) + if (repr[i] == '/') { pos = i; break; } + bool flag; + a = str_to_int(repr.substr(0, pos), flag); + if (!flag) return NULL; + b = str_to_int(repr.substr(pos + 1, len - pos - 1), flag); + if (!flag) return NULL; + return new RatNumObj(a, b); } @@ -19,18 +19,18 @@ void Tokenizor::set_stream(FILE *_stream) { #define IS_NEWLINE(ch) \ ((ch) == '\n') +#define IS_QUOTE(ch) \ + ((ch) == '\"') +#define IS_SLASH(ch) \ + ((ch) == '\\') #define IS_BRACKET(ch) \ ((ch) == '(' || (ch) == ')') #define IS_SPACE(ch) \ ((ch) == ' ' || (ch) == '\t' || IS_NEWLINE(ch)) -#define IS_DELIMITER(ch) \ - (IS_BRACKET(ch) || IS_SPACE(ch)) #define IS_COMMENT(ch) \ ((ch) == ';') -#define IS_QUOTE(ch) \ - ((ch) == '\"') -#define IS_SLASH(ch) \ - ((ch) == '\\') +#define IS_DELIMITER(ch) \ + (IS_BRACKET(ch) || IS_SPACE(ch) || IS_COMMENT(ch) || IS_QUOTE(ch)) #define POP \ do { \ @@ -65,9 +65,8 @@ bool Tokenizor::get_token(string &ret) { bool in_quote = buff_ptr != buff && IS_QUOTE(*buff); if (buff_ptr != buff && (IS_BRACKET(*buff) || - IS_DELIMITER(ch) || - IS_COMMENT(ch) || - IS_QUOTE(ch))) + IS_DELIMITER(ch))) + { if (IS_COMMENT(*buff)) { |