aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin.cpp49
-rw-r--r--parser.cpp17
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);
}
diff --git a/parser.cpp b/parser.cpp
index 07ca066..b670f36 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -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))
{