-
Notifications
You must be signed in to change notification settings - Fork 19
/
Lisparser.cpp
86 lines (83 loc) · 2.75 KB
/
Lisparser.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "Ctu.h"
#define BETWEEN(x, a, b) (((x) >= (a)) && ((x) <= (b)))
string nextToken(string &code, int &off) {
auto clen = code.length();
while(off < clen && (code[off] == ' ' || code[off] == '\n' || code[off] == '\t' || code[off] == '\r'))
++off;
auto rlen = clen - off;
auto orig = off;
if(rlen <= 0)
return "";
if(code[off] == '(') {
off++;
return "(";
} else if(code[off] == ')') {
off++;
return ")";
} else if(rlen >= 3 && code[off] == '0' && code[off+1] == 'x') {
int te;
for(te = off + 2; te < clen; ++te) {
if(code[te] == ' ' || code[te] == '\n' || code[te] == '\r' || code[te] == '\t' || code[te] == ')')
break;
assert(BETWEEN(code[te], '0', '9') || BETWEEN(code[te], 'a', 'f') || BETWEEN(code[te], 'A', 'F'));
}
off = te;
return code.substr(orig, off - orig);
} else if(BETWEEN(code[off], '0', '9')) {
int te;
for(te = off + 1; te < clen; ++te) {
if(code[te] == ' ' || code[te] == '\n' || code[te] == '\r' || code[te] == '\t' || code[te] == ')')
break;
assert(BETWEEN(code[te], '0', '9'));
}
off = te;
return code.substr(orig, off - orig);
} else if(code[off] == '"') {
string out = "\""; // Signal to the parser that this should be a String rather than Symbol
for(++off ; off < clen && code[off] != '"'; ++off) {
if(code[off] == '\\') {
} else
out += code[off];
}
assert(code[off++] == '"');
return out;
} else if(BETWEEN(code[off], '!', '\'') || BETWEEN(code[off], '*', '~')) {
int te;
for(te = off + 1; te < clen; ++te) {
if(code[te] == ' ' || code[te] == '\n' || code[te] == '\r' || code[te] == '\t' || code[te] == ')')
break;
assert(BETWEEN(code[off], '!', '\'') || BETWEEN(code[off], '*', '~'));
}
off = te;
return code.substr(orig, off - orig);
}
LOG_ERROR(Lisparser, "Unknown token at offset %i", off);
}
shared_ptr<Atom> parseLisp(string code) {
auto off = 0;
auto cur = make_shared<Atom>();
forward_list<shared_ptr<Atom>> stack;
while(true) {
auto token = nextToken(code, off);
if(token == "")
break;
else if(token == "(") {
auto ne = make_shared<Atom>();
cur->children.push_back(ne);
stack.push_front(cur);
cur = ne;
} else if(token == ")") {
cur = stack.front();
stack.pop_front();
} else if(token[0] == '"')
cur->children.push_back(make_shared<Atom>(String, token.substr(1)));
else if(token.length() >= 3 && token[0] == '0' && token[1] == 'x')
cur->children.push_back(make_shared<Atom>(stoull(token.substr(2), nullptr, 16)));
else if(BETWEEN(token[0], '0', '9'))
cur->children.push_back(make_shared<Atom>(stoull(token, nullptr, 10)));
else
cur->children.push_back(make_shared<Atom>(Symbol, token));
}
assert(stack.empty());
return cur;
}