]> git.saurik.com Git - cycript.git/blob - trash/Parser.mm
eb441efa108581c5c360ab469a2d816ccc3be37e
[cycript.git] / trash / Parser.mm
1 struct CYExpression {
2 };
3
4 struct CYToken {
5 virtual const char *Text() const = 0;
6 };
7
8 struct CYTokenPrefix :
9 virtual CYToken
10 {
11 };
12
13 struct CYTokenInfix :
14 virtual CYToken
15 {
16 virtual unsigned Precedence() const = 0;
17 };
18
19 struct CYTokenPostfix :
20 virtual CYToken
21 {
22 };
23
24 struct CYTokenAssignment :
25 virtual CYToken
26 {
27 };
28
29 struct CYTokenAccess :
30 virtual CYToken
31 {
32 };
33
34 struct CYTokenLiteral :
35 CYExpression,
36 virtual CYToken
37 {
38 };
39
40 struct CYTokenString :
41 CYTokenLiteral
42 {
43 };
44
45 struct CYTokenNumber :
46 CYTokenLiteral
47 {
48 };
49
50 struct CYTokenWord :
51 virtual CYToken
52 {
53 };
54
55 struct CYTokenIdentifier :
56 CYExpression,
57 CYTokenWord
58 {
59 const char *word_;
60
61 virtual const char *Text() const {
62 return word_;
63 }
64 };
65
66 struct CYTokenColon :
67 CYToken
68 {
69 };
70
71 struct CYTokenComma :
72 CYToken
73 {
74 };
75
76 struct CYTokenSemi :
77 CYToken
78 {
79 };
80
81 struct CYTokenQuestion :
82 CYToken
83 {
84 };
85
86 std::set<const char *, CStringMapLess> OperatorWords_;
87
88 struct CYParser {
89 FILE *fin_;
90 FILE *fout_;
91
92 size_t capacity_;
93 char *data_;
94
95 size_t offset_;
96 size_t size_;
97
98 CYPool pool_;
99
100 CYParser(FILE *fin, FILE *fout) :
101 fin_(fin),
102 fout_(fout),
103 capacity_(1024),
104 data_(reinterpret_cast<char *>(malloc(capacity_))),
105 offset_(0),
106 size_(0)
107 {
108 }
109
110 ~CYParser() {
111 // XXX: this will not deconstruct in constructor failures
112 free(data_);
113 }
114
115 bool ReadLine(const char *prompt) {
116 offset_ = 0;
117 data_[capacity_ - 1] = ~'\0';
118
119 start:
120 if (fout_ != NULL) {
121 fputs(prompt, fout_);
122 fputs(" ", fout_);
123 fflush(fout_);
124 }
125
126 if (fgets(data_, capacity_, fin_) == NULL)
127 return false;
128
129 check:
130 if (data_[capacity_ - 1] != '\0') {
131 size_ = strlen(data_);
132 if (size_ == 0)
133 goto start;
134 if (data_[size_ - 1] == '\n') {
135 --size_;
136 goto newline;
137 }
138 } else if (data_[capacity_ - 2] == '\n') {
139 size_ = capacity_ - 2;
140 newline:
141 data_[size_] = '\0';
142 } else {
143 size_t capacity(capacity_ * 2);
144 char *data(reinterpret_cast<char *>(realloc(data_, capacity)));
145 _assert(data != NULL);
146 data_ = data;
147 size_ = capacity_ - 1;
148 capacity_ = capacity;
149 fgets(data_ + size_, capacity_ - size_, fin_);
150 goto check;
151 }
152
153 return true;
154 }
155
156 _finline void ScanRange(const CYRange &range) {
157 while (range[data_[offset_]])
158 ++offset_;
159 }
160
161 CYToken *ParseToken(const char *prompt) {
162 char next;
163
164 do {
165 if (offset_ == size_ && (prompt == NULL || !ReadLine(prompt)))
166 return false;
167 next = data_[offset_++];
168 } while (next == ' ' || next == '\t');
169
170 CYTokenType type;
171 size_t index(offset_ - 1);
172
173 if (WordStartRange_[next]) {
174 ScanRange(WordEndRange_);
175 type = CYTokenWord;
176 } else if (next == '.') {
177 char after(data_[offset_]);
178 if (after >= '0' && after <= '9')
179 goto number;
180 goto punctuation;
181 } else if (next >= '0' && next <= '9') {
182 number:
183 ScanRange(NumberRange_);
184 type = CYTokenLiteral;
185 } else if (PunctuationRange_[next]) {
186 punctuation:
187 ScanRange(PunctuationRange_);
188 type = CYTokenPunctuation;
189 } else if (next == '"' || next == '\'') {
190 for (;;) {
191 char after(data_[offset_++]);
192 if (after == '\\') {
193 after = data_[offset_++];
194 _assert(after != '\0');
195 if (after == 'u') {
196 offset_ += 4;
197 _assert(offset_ < size_);
198 }
199 } else if (after == next)
200 break;
201 }
202
203 type = CYTokenLiteral;
204 } else if (next == '(' || next == '{' || next == '[') {
205 type = CYTokenOpen;
206 } else if (next == ')' || next == '}' || next == ']') {
207 type = CYTokenClose;
208 } else if (next == ';') {
209 type = CYTokenSemiColon;
210 } else {
211 printf(":( %u\n", next);
212 _assert(false);
213 }
214
215 char *value(pool_(data_ + index, offset_ - index));
216
217 if (type == CYTokenWord && OperatorWords_.find(value) != OperatorWords_.end())
218 type = CYTokenPunctuation;
219
220 CYToken *token(new(pool_) CYToken());
221 token->type_ = type;
222 token->value_ = value;
223 token->next_ = token;
224 token->prev_ = &token->next_;
225 return token;
226 }
227
228 CYToken *ParseExpression(const char *prompt) {
229 CYToken *token(ParseToken(prompt));
230 return token;
231 }
232 };