aboutsummaryrefslogtreecommitdiff
path: root/parser.cpp
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-06 12:39:39 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-06 12:39:39 +0800
commit9e76d377dad809f4aa3faa700883dbfc9b2fa769 (patch)
tree4baeec32938ea656866b9158b1541af28e7e91d9 /parser.cpp
parent5e5a8ab8b6046dccecf2cbb5a85324bbf42b43de (diff)
vector, literal support!
Diffstat (limited to 'parser.cpp')
-rw-r--r--parser.cpp107
1 files changed, 79 insertions, 28 deletions
diff --git a/parser.cpp b/parser.cpp
index b670f36..cd9eacb 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -9,7 +9,7 @@
using std::stringstream;
static char buff[TOKEN_BUFF_SIZE];
-static EvalObj *parse_stack[PARSE_STACK_SIZE];
+static FrameObj *parse_stack[PARSE_STACK_SIZE];
extern Cons *empty_list;
Tokenizor::Tokenizor() : stream(stdin), buff_ptr(buff), escaping(false) {}
@@ -29,8 +29,11 @@ void Tokenizor::set_stream(FILE *_stream) {
((ch) == ' ' || (ch) == '\t' || IS_NEWLINE(ch))
#define IS_COMMENT(ch) \
((ch) == ';')
+#define IS_LITERAL(ch) \
+ ((ch) == '\'')
#define IS_DELIMITER(ch) \
- (IS_BRACKET(ch) || IS_SPACE(ch) || IS_COMMENT(ch) || IS_QUOTE(ch))
+ (IS_BRACKET(ch) || IS_SPACE(ch) || \
+ IS_COMMENT(ch) || IS_QUOTE(ch))
#define POP \
do { \
@@ -38,6 +41,7 @@ void Tokenizor::set_stream(FILE *_stream) {
ret = string(buff); \
buff_ptr = buff; \
} while (0)
+#define TOP (*(buff_ptr - 1))
bool Tokenizor::get_token(string &ret) {
char ch;
@@ -63,26 +67,35 @@ bool Tokenizor::get_token(string &ret) {
else
{
bool in_quote = buff_ptr != buff && IS_QUOTE(*buff);
- if (buff_ptr != buff &&
- (IS_BRACKET(*buff) ||
- IS_DELIMITER(ch)))
-
+ if (buff_ptr != buff)
{
- if (IS_COMMENT(*buff))
- {
- if (IS_NEWLINE(ch)) buff_ptr = buff;
- else buff_ptr = buff + 1;
- }
- else if (!in_quote)
+ if (buff_ptr - buff == 1 && IS_LITERAL(TOP))
{
POP;
flag = true;
}
- else if (IS_QUOTE(ch))
+ else if ((IS_BRACKET(TOP) || IS_DELIMITER(ch)))
{
- *buff_ptr++ = '\"';
- POP;
- return true; // discard current slash
+ if (IS_COMMENT(*buff))
+ {
+ if (IS_NEWLINE(ch)) buff_ptr = buff;
+ else buff_ptr = buff + 1;
+ }
+ else if (!in_quote) // not in a double-quote
+ {
+ if (!(buff_ptr - buff == 1 && ch == '(' && TOP == '#'))
+ {
+ POP;
+ flag = true;
+ }
+ }
+ else if (IS_QUOTE(ch))
+ {
+ // in a double-quote which is being enclosed
+ *buff_ptr++ = '\"';
+ POP;
+ return true; // prevent duplicate quote sign
+ }
}
}
if (in_quote || !IS_SPACE(ch))
@@ -109,31 +122,69 @@ EvalObj *ASTGenerator::to_obj(const string &str) {
if ((res = RealNumObj::from_string(str))) return res;
if ((res = CompNumObj::from_string(str))) return res;
if ((res = StrObj::from_string(str))) return res;
- return new SymObj(str);
+ return new SymObj(str); // otherwise we assume it a symbol
}
+
+#define TO_EVAL(ptr) \
+ (static_cast<EvalObj*>(ptr))
+#define TO_BRACKET(ptr) \
+ (static_cast<ParseBracket*>(ptr))
+#define IS_BRAKET(ptr) \
+ ((ptr)->is_parse_bracket())
+
Cons *ASTGenerator::absorb(Tokenizor *tk) {
- EvalObj **top_ptr = parse_stack;
+ FrameObj **top_ptr = parse_stack;
for (;;)
{
- if (top_ptr > parse_stack && *parse_stack)
- return new Cons(*(top_ptr - 1), empty_list);
+ if (top_ptr - parse_stack > 1 &&
+ !IS_BRAKET(*(top_ptr - 1)) &&
+ IS_BRAKET(*(top_ptr - 2)))
+ {
+ ParseBracket *bptr = TO_BRACKET(*(top_ptr - 2));
+ if (bptr->btype == 2)
+ {
+ top_ptr -= 2;
+ Cons *lst_cdr = new Cons(TO_EVAL(*(top_ptr + 1)), empty_list);
+ Cons *lst = new Cons(new SymObj("quote"), lst_cdr);
+ lst->next = lst_cdr;
+ lst_cdr->next = NULL;
+ *top_ptr++ = lst;
+ }
+ }
+
+ if (top_ptr > parse_stack && !IS_BRAKET(*parse_stack))
+ return new Cons(TO_EVAL(*(top_ptr - 1)), empty_list);
string token;
if (!tk->get_token(token)) return NULL;
- if (token == "(")
- *top_ptr++ = NULL; // Make the beginning of a new level
+ if (token == "(") // a list
+ *top_ptr++ = new ParseBracket(0);
+ else if (token == "#(") // a vector
+ *top_ptr++ = new ParseBracket(1);
+ else if (token == "\'") // syntatic sugar for quote
+ *top_ptr++ = new ParseBracket(2);
else if (token == ")")
{
+ if (top_ptr == parse_stack)
+ throw NormalError(READ_ERR_UNEXPECTED_RIGHT_BRACKET);
Cons *lst = empty_list;
- while (top_ptr >= parse_stack && *(--top_ptr))
+ while (top_ptr >= parse_stack && !IS_BRAKET(*(--top_ptr)))
{
- Cons *_lst = new Cons(*top_ptr, lst); // Collect the list
+ Cons *_lst = new Cons(TO_EVAL(*top_ptr), lst); // Collect the list
_lst->next = lst == empty_list ? NULL : lst;
lst = _lst;
}
- if (top_ptr < parse_stack)
- throw NormalError(READ_ERR_UNEXPECTED_RIGHT_BRACKET);
- *top_ptr++ = lst;
+ ParseBracket *bptr = TO_BRACKET(*top_ptr);
+ if (bptr->btype == 0)
+ *top_ptr++ = lst;
+ else if (bptr->btype == 1)
+ {
+ VecObj *vec = new VecObj();
+ for (Cons *ptr = lst; ptr != empty_list; ptr = TO_CONS(ptr->cdr))
+ vec->push_back(ptr->car);
+ *top_ptr++ = vec;
+ }
}
- else *top_ptr++ = ASTGenerator::to_obj(token);
+ else
+ *top_ptr++ = ASTGenerator::to_obj(token);
}
}