aboutsummaryrefslogtreecommitdiff
path: root/parser.cpp
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-03 12:10:09 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-03 12:10:09 +0800
commite462669c3c3cc04ea29420e14dbb589899d201ec (patch)
treecc217c58388fbf13229bf4a25b639d17458e8fc9 /parser.cpp
parentaf2da07be7d3f8a936640ef92b0692710a22e0d4 (diff)
AST parser can now work!
Diffstat (limited to 'parser.cpp')
-rw-r--r--parser.cpp94
1 files changed, 94 insertions, 0 deletions
diff --git a/parser.cpp b/parser.cpp
new file mode 100644
index 0000000..0143700
--- /dev/null
+++ b/parser.cpp
@@ -0,0 +1,94 @@
+#include <cstdio>
+#include <cctype>
+#include <sstream>
+#include "parser.h"
+#include "builtin.h"
+
+using std::stringstream;
+
+static char buff[TOKEN_BUFF_SIZE];
+static EvalObj *parse_stack[PARSE_STACK_SIZE];
+extern Cons *empty_list;
+
+Tokenizor::Tokenizor() : stream(stdin), buff_ptr(buff) {}
+void Tokenizor::set_stream(FILE *_stream) {
+ stream = _stream;
+}
+
+#define IS_BRACKET(ch) \
+ ((ch) == '(' || (ch) == ')')
+#define IS_SPACE(ch) \
+ ((ch) == ' ' || (ch) == '\t' || (ch) == '\n')
+#define IS_DELIMITER(ch) \
+ (IS_BRACKET(ch) || IS_SPACE(ch))
+#define POP \
+do { \
+ *buff_ptr = 0; \
+ ret = string(buff); \
+ buff_ptr = buff; \
+} while (0)
+
+bool Tokenizor::get_token(string &ret) {
+ char ch;
+ bool flag = false;
+ while (fread(&ch, 1, 1, stream))
+ {
+ if (buff_ptr != buff &&
+ (IS_BRACKET(*buff) || IS_DELIMITER(ch)))
+ {
+ POP;
+ flag = true;
+ }
+ if (!IS_SPACE(ch)) *buff_ptr++ = ch;
+ if (flag) return true;
+ }
+ if (buff_ptr != buff) POP;
+ return false; // can't read more
+}
+
+ASTGenerator::ASTGenerator() {}
+EvalObj *ASTGenerator::to_float(const string &str) {
+ stringstream ss(str);
+ double val;
+ ss >> val;
+ if (ss.fail() || !ss.eof()) return NULL;
+ return new FloatObj(val);
+}
+
+EvalObj *ASTGenerator::to_int(const string &str) {
+ stringstream ss(str);
+ int val;
+ ss >> val;
+ if (ss.fail() || !ss.eof()) return NULL;
+ return new IntObj(val);
+}
+
+
+EvalObj *ASTGenerator::to_obj(const string &str) {
+ EvalObj *res = NULL;
+ if ((res = ASTGenerator::to_int(str)))
+ return res;
+ if ((res = ASTGenerator::to_float(str)))
+ return res;
+ return new SymObj(str);
+}
+Cons *ASTGenerator::absorb(Tokenizor *tk) {
+ EvalObj **top_ptr = parse_stack;
+ for (;;)
+ {
+ if (top_ptr > parse_stack && *parse_stack)
+ return new Cons(*(top_ptr - 1), empty_list);
+ string token;
+ tk->get_token(token);
+ if (token == "(")
+ *top_ptr++ = NULL; // Make the beginning of a new level
+ else if (token == ")")
+ {
+ Cons *lst = empty_list;
+ while (*(--top_ptr))
+ lst = new Cons(*top_ptr, lst); // Collect the list
+ *top_ptr++ = lst;
+ }
+ else *top_ptr++ = ASTGenerator::to_obj(token);
+ }
+}