-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.cpp
108 lines (89 loc) · 1.97 KB
/
parser.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "parser.h"
#include <sstream>
#include <list>
#include <stdexcept>
#include <cstdlib>
namespace
{
typedef std::list<std::string> Tokens;
const Atom* atom(const std::string& token)
{
char* endptr;
int i = std::strtol(token.c_str(), &endptr, 10);
if(*endptr == 0)
{
return new Integer(i);
}
double r = std::strtod(token.c_str(), &endptr);
if(*endptr == 0)
{
return new Real(r);
}
return new Symbol(token);
}
const Atom* readFrom(Tokens::const_iterator& cur, Tokens::const_iterator end)
{
if(cur == end)
{
throw std::runtime_error("unexpected EOF while reading");
}
std::string token = *cur++;
if(token == "(")
{
std::list<const Atom*> atoms;
for(;;)
{
if(*cur == ")")
{
++cur;
break;
}
atoms.push_back(readFrom(cur, end));
}
const Node* node = Node::getNull();
for(std::list<const Atom*>::reverse_iterator i = atoms.rbegin(); i != atoms.rend(); ++i)
{
node = new Node(*i, node);
}
return node;
}
if(token == ")")
{
throw std::runtime_error("unexpected");
}
return atom(token);
}
Tokens tokenize(const std::string& program)
{
std::stringstream ss;
for(std::string::const_iterator i = program.begin(); i != program.end(); ++i)
{
if(*i == '(')
{
ss << " ( ";
}
else if(*i == ')')
{
ss << " ) ";
}
else
{
ss << *i;
}
}
ss << " ";
Tokens tokens;
std::string token;
while((ss >> token).good())
{
tokens.push_back(token);
}
return tokens;
}
} // end of anonymous namespace
const Atom* parse(const std::string& program)
{
Tokens tokens = tokenize(program);
Tokens::const_iterator begin = tokens.begin();
return readFrom(begin, tokens.end());
}