Commit | Line | Data |
---|---|---|
970ed795 EL |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright (c) 2000-2014 Ericsson Telecom AB | |
3 | // All rights reserved. This program and the accompanying materials | |
4 | // are made available under the terms of the Eclipse Public License v1.0 | |
5 | // which accompanies this distribution, and is available at | |
6 | // http://www.eclipse.org/legal/epl-v10.html | |
7 | /////////////////////////////////////////////////////////////////////////////// | |
8 | #include "TokenBuf.hh" | |
9 | #include "../AST.hh" | |
10 | #include "Block.hh" | |
11 | ||
12 | extern void asn1_yyerror(const char *s); | |
13 | #define yyerror asn1_yyerror | |
14 | extern int asn1_yylex(); | |
15 | #define yylex asn1_yylex | |
16 | extern const char *asn1_infile; | |
17 | extern int asn1_yylineno; | |
18 | #define yylineno asn1_yylineno | |
19 | extern int asn1_plineno; | |
20 | #define plineno asn1_plineno | |
21 | extern YYLTYPE asn1_yylloc; | |
22 | #define yylloc asn1_yylloc | |
23 | ||
24 | namespace Asn { | |
25 | ||
26 | using namespace Common; | |
27 | ||
28 | // ================================= | |
29 | // ===== Token | |
30 | // ================================= | |
31 | ||
32 | Token::Token(const Token& p) | |
33 | : Node(p), Location(p), token(p.token) | |
34 | { | |
35 | switch (p.token) { | |
36 | case TOK_UpperIdentifier: | |
37 | case TOK_LowerIdentifier: | |
38 | case TOK_ampUpperIdentifier: | |
39 | case TOK_ampLowerIdentifier: | |
40 | semval.id = p.semval.id->clone(); | |
41 | break; | |
42 | case TOK_Number: | |
43 | semval.i = new int_val_t(*p.semval.i); | |
44 | break; | |
45 | case TOK_CString: | |
46 | semval.str = new string(*p.semval.str); | |
47 | break; | |
48 | case TOK_RealNumber: | |
49 | case TOK_BString: | |
50 | case TOK_HString: | |
51 | semval.value = p.semval.value->clone(); | |
52 | break; | |
53 | case TOK_Block: | |
54 | semval.block = p.semval.block->clone(); | |
55 | default: | |
56 | break; | |
57 | } | |
58 | } | |
59 | ||
60 | bool Token::has_semval(int p_token) | |
61 | { | |
62 | switch (p_token) { | |
63 | case TOK_UpperIdentifier: | |
64 | case TOK_LowerIdentifier: | |
65 | case TOK_ampUpperIdentifier: | |
66 | case TOK_ampLowerIdentifier: | |
67 | case TOK_Number: | |
68 | case TOK_CString: | |
69 | case TOK_RealNumber: | |
70 | case TOK_BString: | |
71 | case TOK_HString: | |
72 | case TOK_Block: | |
73 | return true; | |
74 | default: | |
75 | return false; | |
76 | } | |
77 | } | |
78 | ||
79 | Token::Token(int p_token, const Location& p_loc) | |
80 | : Node(), Location(p_loc), token(p_token) | |
81 | { | |
82 | if (has_semval(p_token)) FATAL_ERROR("Token::Token()"); | |
83 | } | |
84 | ||
85 | Token::Token(int p_token, const YYSTYPE& p_semval, const Location& p_loc) | |
86 | : Node(), Location(p_loc), token(p_token) | |
87 | { | |
88 | switch (p_token) { | |
89 | case TOK_UpperIdentifier: | |
90 | case TOK_LowerIdentifier: | |
91 | case TOK_ampUpperIdentifier: | |
92 | case TOK_ampLowerIdentifier: | |
93 | semval.id = p_semval.id; | |
94 | break; | |
95 | case TOK_Number: | |
96 | semval.i = p_semval.i; | |
97 | break; | |
98 | case TOK_CString: | |
99 | semval.str = p_semval.str; | |
100 | break; | |
101 | case TOK_RealNumber: | |
102 | case TOK_BString: | |
103 | case TOK_HString: | |
104 | semval.value = p_semval.value; | |
105 | break; | |
106 | case TOK_Block: | |
107 | semval.block = p_semval.block; | |
108 | default: | |
109 | break; | |
110 | } | |
111 | } | |
112 | ||
113 | Token::~Token() | |
114 | { | |
115 | switch(token) { | |
116 | case TOK_UpperIdentifier: | |
117 | case TOK_LowerIdentifier: | |
118 | case TOK_ampUpperIdentifier: | |
119 | case TOK_ampLowerIdentifier: | |
120 | delete semval.id; | |
121 | break; | |
122 | case TOK_CString: | |
123 | delete semval.str; | |
124 | break; | |
125 | case TOK_RealNumber: | |
126 | case TOK_BString: | |
127 | case TOK_HString: | |
128 | delete semval.value; | |
129 | break; | |
130 | case TOK_Block: | |
131 | delete semval.block; | |
132 | break; | |
133 | case TOK_Number: | |
134 | delete semval.i; | |
135 | break; | |
136 | default: | |
137 | break; | |
138 | } // switch | |
139 | } | |
140 | ||
141 | Token *Token::clone() const | |
142 | { | |
143 | return new Token(*this); | |
144 | } | |
145 | ||
146 | void Token::set_token(int new_token) | |
147 | { | |
148 | if (new_token != token) { | |
149 | if (has_semval(token) || has_semval(new_token)) | |
150 | FATAL_ERROR("Token::set_token()"); | |
151 | token = new_token; | |
152 | } | |
153 | } | |
154 | ||
155 | void Token::steal_semval(YYSTYPE& p_semval) | |
156 | { | |
157 | switch (token) { | |
158 | case TOK_UpperIdentifier: | |
159 | case TOK_LowerIdentifier: | |
160 | case TOK_ampUpperIdentifier: | |
161 | case TOK_ampLowerIdentifier: | |
162 | p_semval.id = semval.id; | |
163 | break; | |
164 | case TOK_Number: | |
165 | p_semval.i = semval.i; | |
166 | break; | |
167 | case TOK_CString: | |
168 | p_semval.str = semval.str; | |
169 | break; | |
170 | case TOK_RealNumber: | |
171 | case TOK_BString: | |
172 | case TOK_HString: | |
173 | p_semval.value = semval.value; | |
174 | break; | |
175 | case TOK_Block: | |
176 | p_semval.block = semval.block; | |
177 | default: | |
178 | break; | |
179 | } | |
180 | token = '\0'; | |
181 | } | |
182 | ||
183 | void Token::set_loc_info() const | |
184 | { | |
185 | asn1_infile = get_filename(); | |
186 | if(get_lineno() > 0) plineno = get_lineno(); | |
187 | } | |
188 | ||
189 | bool Token::is_literal_id() const | |
190 | { | |
191 | if(token==TOK_UpperIdentifier | |
192 | && semval.id->isvalid_asn_word()) | |
193 | return true; | |
194 | else return false; | |
195 | } | |
196 | ||
197 | bool Token::is_literal_kw() const | |
198 | { | |
199 | switch(token) { | |
200 | case ',': | |
201 | case KW_ABSENT: | |
202 | case KW_ALL: | |
203 | case KW_ANY: | |
204 | case KW_APPLICATION: | |
205 | case KW_AUTOMATIC: | |
206 | case KW_BEGIN: | |
207 | case KW_BY: | |
208 | case KW_CLASS: | |
209 | case KW_COMPONENT: | |
210 | case KW_COMPONENTS: | |
211 | case KW_CONSTRAINED: | |
212 | case KW_CONTAINING: | |
213 | case KW_DEFAULT: | |
214 | case KW_DEFINED: | |
215 | case KW_DEFINITIONS: | |
216 | case KW_ENCODED: | |
217 | case KW_EXCEPT: | |
218 | case KW_EXPLICIT: | |
219 | case KW_EXPORTS: | |
220 | case KW_EXTENSIBILITY: | |
221 | case KW_FROM: | |
222 | case KW_IDENTIFIER: | |
223 | case KW_IMPLICIT: | |
224 | case KW_IMPLIED: | |
225 | case KW_IMPORTS: | |
226 | case KW_INCLUDES: | |
227 | case KW_MAX: | |
228 | case KW_MIN: | |
229 | case KW_OF: | |
230 | case KW_OPTIONAL: | |
231 | case KW_PATTERN: | |
232 | case KW_PDV: | |
233 | case KW_PRESENT: | |
234 | case KW_PRIVATE: | |
235 | case KW_SIZE: | |
236 | case KW_STRING: | |
237 | case KW_SYNTAX: | |
238 | case KW_TAGS: | |
239 | case KW_UNIQUE: | |
240 | case KW_UNIVERSAL: | |
241 | case KW_WITH: | |
242 | return true; | |
243 | default: | |
244 | return false; | |
245 | } // switch token | |
246 | } | |
247 | ||
248 | bool Token::is_ampId() const | |
249 | { | |
250 | if(token==TOK_ampUpperIdentifier | |
251 | || token==TOK_ampLowerIdentifier) | |
252 | return true; | |
253 | else return false; | |
254 | } | |
255 | ||
256 | bool Token::is_id() const | |
257 | { | |
258 | switch(token) { | |
259 | case TOK_UpperIdentifier: | |
260 | case TOK_LowerIdentifier: | |
261 | case TOK_ampUpperIdentifier: | |
262 | case TOK_ampLowerIdentifier: | |
263 | return true; | |
264 | default: | |
265 | return false; | |
266 | } // switch | |
267 | } | |
268 | ||
269 | const char* Token::get_token_name(int p_token) | |
270 | { | |
271 | switch(p_token) { | |
272 | case '\0': return "<end of file or statement>"; | |
273 | case TOK_Assignment: return "::="; | |
274 | case TOK_RangeSeparator: return ".."; | |
275 | case TOK_Ellipsis: return "..."; | |
276 | case TOK_LeftVersionBrackets: return "[["; | |
277 | case TOK_RightVersionBrackets: return "]]"; | |
278 | case '{': return "{"; | |
279 | case '}': return "}"; | |
280 | case '(': return "("; | |
281 | case ')': return ")"; | |
282 | case '[': return "["; | |
283 | case ']': return "]"; | |
284 | case ',': return ","; | |
285 | case '.': return "."; | |
286 | case '-': return "-"; | |
287 | case ':': return ":"; | |
288 | case ';': return ";"; | |
289 | case '@': return "@"; | |
290 | case '|': return "|"; | |
291 | case '!': return "!"; | |
292 | case '^': return "^"; | |
293 | case '<': return "<"; | |
294 | case '>': return ">"; | |
295 | case '\'': return "'"; | |
296 | case '"': return "\""; | |
297 | case KW_ABSENT: return "ABSENT"; | |
298 | case KW_ALL: return "ALL"; | |
299 | case KW_ANY: return "ANY"; | |
300 | case KW_APPLICATION: return "APPLICATION"; | |
301 | case KW_AUTOMATIC: return "AUTOMATIC"; | |
302 | case KW_BEGIN: return "BEGIN"; | |
303 | case KW_BIT: return "BIT"; | |
304 | case KW_BMPString: return "BMPString"; | |
305 | case KW_BOOLEAN: return "BOOLEAN"; | |
306 | case KW_BY: return "BY"; | |
307 | case KW_CHARACTER: return "CHARACTER"; | |
308 | case KW_CHOICE: return "CHOICE"; | |
309 | case KW_CLASS: return "CLASS"; | |
310 | case KW_COMPONENT: return "COMPONENT"; | |
311 | case KW_COMPONENTS: return "COMPONENTS"; | |
312 | case KW_CONSTRAINED: return "CONSTRAINED"; | |
313 | case KW_CONTAINING: return "CONTAINING"; | |
314 | case KW_DEFAULT: return "DEFAULT"; | |
315 | case KW_DEFINED: return "DEFINED"; | |
316 | case KW_DEFINITIONS: return "DEFINITIONS"; | |
317 | case KW_EMBEDDED: return "EMBEDDED"; | |
318 | case KW_ENCODED: return "ENCODED"; | |
319 | case KW_END: return "END"; | |
320 | case KW_ENUMERATED: return "ENUMERATED"; | |
321 | case KW_EXCEPT: return "EXCEPT"; | |
322 | case KW_EXPLICIT: return "EXPLICIT"; | |
323 | case KW_EXPORTS: return "EXPORTS"; | |
324 | case KW_EXTENSIBILITY: return "EXTENSIBILITY"; | |
325 | case KW_EXTERNAL: return "EXTERNAL"; | |
326 | case KW_FALSE: return "FALSE"; | |
327 | case KW_GeneralizedTime: return "GeneralizedTime"; | |
328 | case KW_GeneralString: return "GeneralString"; | |
329 | case KW_GraphicString: return "GraphicString"; | |
330 | case KW_IA5String: return "IA5String"; | |
331 | case KW_FROM: return "FROM"; | |
332 | case KW_IDENTIFIER: return "IDENTIFIER"; | |
333 | case KW_IMPLICIT: return "IMPLICIT"; | |
334 | case KW_IMPLIED: return "IMPLIED"; | |
335 | case KW_IMPORTS: return "IMPORTS"; | |
336 | case KW_INCLUDES: return "INCLUDES"; | |
337 | case KW_INSTANCE: return "INSTANCE"; | |
338 | case KW_INTEGER: return "INTEGER"; | |
339 | case KW_INTERSECTION: return "INTERSECTION"; | |
340 | case KW_ISO646String: return "ISO646String"; | |
341 | case KW_MAX: return "MAX"; | |
342 | case KW_MIN: return "MIN"; | |
343 | case KW_MINUS_INFINITY: return "MINUS-INFINITY"; | |
344 | case KW_NULL: return "NULL"; | |
345 | case KW_NumericString: return "NumericString"; | |
346 | case KW_OBJECT: return "OBJECT"; | |
347 | case KW_ObjectDescriptor: return "ObjectDescriptor"; | |
348 | case KW_OCTET: return "OCTET"; | |
349 | case KW_OF: return "OF"; | |
350 | case KW_OPTIONAL: return "OPTIONAL"; | |
351 | case KW_PATTERN: return "PATTERN"; | |
352 | case KW_PDV: return "PDV"; | |
353 | case KW_PLUS_INFINITY: return "PLUS-INFINITY"; | |
354 | case KW_PRESENT: return "PRESENT"; | |
355 | case KW_PrintableString: return "PrintableString"; | |
356 | case KW_PRIVATE: return "PRIVATE"; | |
357 | case KW_REAL: return "REAL"; | |
358 | case KW_RELATIVE_OID: return "RELATIVE-OID"; | |
359 | case KW_SEQUENCE: return "SEQUENCE"; | |
360 | case KW_SET: return "SET"; | |
361 | case KW_SIZE: return "SIZE"; | |
362 | case KW_STRING: return "STRING"; | |
363 | case KW_SYNTAX: return "SYNTAX"; | |
364 | case KW_T61String: return "T61String"; | |
365 | case KW_TAGS: return "TAGS"; | |
366 | case KW_TeletexString: return "TeletexString"; | |
367 | case KW_TRUE: return "TRUE"; | |
368 | case KW_UNION: return "UNION"; | |
369 | case KW_UNIQUE: return "UNIQUE"; | |
370 | case KW_UNIVERSAL: return "UNIVERSAL"; | |
371 | case KW_UniversalString: return "UniversalString"; | |
372 | case KW_UTCTime: return "UTCTime"; | |
373 | case KW_UTF8String: return "UTF8String"; | |
374 | case KW_VideotexString: return "VideotexString"; | |
375 | case KW_VisibleString: return "VisibleString"; | |
376 | case KW_WITH: return "WITH"; | |
377 | case TOK_UpperIdentifier: return "<upperidentifier>"; | |
378 | case TOK_LowerIdentifier: return "<loweridentifier>"; | |
379 | case TOK_ampUpperIdentifier: return "<&upperidentifier>"; | |
380 | case TOK_ampLowerIdentifier: return "<&loweridentifier>"; | |
381 | case TOK_Number: return "<number>"; | |
382 | case TOK_RealNumber: return "<realnumber>"; | |
383 | case TOK_BString: return "<bstring>"; | |
384 | case TOK_CString: return "<cstring>"; | |
385 | case TOK_HString: return "<hstring>"; | |
386 | case TOK_Block: return "<{block}>"; | |
387 | /* special stuff */ | |
388 | case KW_Block_NamedNumberList: return "<NamedNumberList:>"; | |
389 | case KW_Block_Enumerations: return "<Enumerations:>"; | |
390 | case KW_Block_Assignment: return "<Assignment:>"; | |
391 | case KW_Block_NamedBitList: return "<NamedBitList:>"; | |
392 | case KW_Block_IdentifierList: return "<IdentifierList:>"; | |
393 | case KW_Block_FieldSpecList: return "<FieldSpecList:>"; | |
394 | case KW_Block_ComponentTypeLists: return "<ComponentTypeLists:>"; | |
395 | case KW_Block_AlternativeTypeLists: return "<AlternativeTypeLists:>"; | |
396 | case KW_Block_Type: return "<Type:>"; | |
397 | case KW_Block_Value: return "<Value:>"; | |
398 | case KW_Block_ValueSet: return "<ValueSet:>"; | |
399 | case KW_Block_Object: return "<Object:>"; | |
400 | case KW_Block_ObjectSet: return "<ObjectSet:>"; | |
401 | case KW_Block_SeqOfValue: return "<SeqOfValue:>"; | |
402 | case KW_Block_SetOfValue: return "<SetOfValue:>"; | |
403 | case KW_Block_SequenceValue: return "<SequenceValue:>"; | |
404 | case KW_Block_SetValue: return "<SetValue:>"; | |
405 | case KW_Block_ObjectSetSpec: return "<ObjectSetSpec:>"; | |
406 | case KW_Block_DefinedObjectSetBlock: return "<DefinedObjectSetBlock:>"; | |
407 | case KW_Block_AtNotationList: return "<AtNotationList:>"; | |
408 | case KW_Block_OIDValue: return "<OIDValue:>"; | |
409 | case KW_Block_ROIDValue: return "<ROIDValue:>"; | |
410 | case KW_Block_CharStringValue: return "<CharStringValue:>"; | |
411 | case KW_Block_QuadrupleOrTuple: return "<QuadrupleOrTuple:>"; | |
412 | default: | |
413 | return "<Error! Not a keyword.>"; | |
414 | } // switch token | |
415 | } | |
416 | ||
417 | const Identifier& Token::get_semval_id() const | |
418 | { | |
419 | switch(token) { | |
420 | case TOK_UpperIdentifier: | |
421 | case TOK_LowerIdentifier: | |
422 | case TOK_ampUpperIdentifier: | |
423 | case TOK_ampLowerIdentifier: | |
424 | return *semval.id; | |
425 | default: | |
426 | FATAL_ERROR("Token::get_semval_id()"); | |
427 | } // switch | |
428 | } | |
429 | ||
430 | void Token::create_block(TokenBuf *tb) | |
431 | { | |
432 | if (token != '{' || !tb) FATAL_ERROR("Token::create_block()"); | |
433 | token = TOK_Block; | |
434 | /** \todo set the correct end line/column info */ | |
435 | semval.block = new Block(tb); | |
436 | semval.block->set_location(*this); | |
437 | } | |
438 | ||
439 | void Token::dump(unsigned level) const | |
440 | { | |
441 | switch(token) { | |
442 | case TOK_UpperIdentifier: | |
443 | case TOK_LowerIdentifier: | |
444 | case TOK_ampUpperIdentifier: | |
445 | case TOK_ampLowerIdentifier: | |
446 | semval.id->dump(level); | |
447 | break; | |
448 | case TOK_Number: | |
449 | DEBUG(level, "token: number (%s)", semval.i->t_str().c_str()); | |
450 | break; | |
451 | case TOK_CString: | |
452 | DEBUG(level, "token: cstring (\"%s\")", semval.str->c_str()); | |
453 | break; | |
454 | case TOK_RealNumber: | |
455 | case TOK_BString: | |
456 | case TOK_HString: | |
457 | semval.value->dump(level); | |
458 | break; | |
459 | case TOK_Block: | |
460 | semval.block->dump(level); | |
461 | break; | |
462 | default: | |
463 | DEBUG(level, "%s", get_token_name()); | |
464 | } | |
465 | } | |
466 | ||
467 | // ================================= | |
468 | // ===== TokenBuf | |
469 | // ================================= | |
470 | ||
471 | TokenBuf::TokenBuf() | |
472 | : Node(), filename("<undef>") | |
473 | { | |
474 | tokens=new tokens_t(); | |
475 | } | |
476 | ||
477 | TokenBuf::TokenBuf(tokens_t *p_tokens) | |
478 | : Node(), tokens(p_tokens), filename("<undef>") | |
479 | { | |
480 | if(!p_tokens) | |
481 | FATAL_ERROR("NULL parameter: Asn::TokenBuf::TokenBuf(tokens_t*)"); | |
482 | } | |
483 | ||
484 | TokenBuf::TokenBuf(const TokenBuf& p) | |
485 | : Node(), filename(p.filename) | |
486 | { | |
487 | tokens=new tokens_t(); | |
488 | for(size_t i=0; i<p.tokens->size(); i++) | |
489 | tokens->add((*p.tokens)[i]->clone()); | |
490 | } | |
491 | ||
492 | TokenBuf::~TokenBuf() | |
493 | { | |
494 | delete_tokens(); | |
495 | delete tokens; | |
496 | } | |
497 | ||
498 | void TokenBuf::delete_tokens() | |
499 | { | |
500 | for(size_t i=0; i<tokens->size(); i++) | |
501 | delete (*tokens)[i]; | |
502 | tokens->clear(); | |
503 | } | |
504 | ||
505 | void TokenBuf::reset(const char *p_filename) | |
506 | { | |
507 | delete_tokens(); | |
508 | filename=p_filename; | |
509 | } | |
510 | ||
511 | bool TokenBuf::read_next() | |
512 | { | |
513 | /* if there was an EOF, don't try to read another token */ | |
514 | if(!tokens->empty() && (*tokens)[tokens->size()-1]->get_token()=='\0') | |
515 | return false; | |
516 | int token=yylex(); | |
517 | tokens->add(new Token(token, yylval, Location(filename, yylineno))); | |
518 | return true; | |
519 | } | |
520 | ||
521 | Token*& TokenBuf::get_at(size_t pos) | |
522 | { | |
523 | while(tokens->size()<=pos && read_next()) ; | |
524 | if(pos<tokens->size()) { | |
525 | return (*tokens)[pos]; | |
526 | } | |
527 | else { | |
528 | if(tokens->empty()) | |
529 | FATAL_ERROR("Asn::TokenBuf::get_at()"); | |
530 | return (*tokens)[tokens->size()-1]; | |
531 | } | |
532 | } | |
533 | ||
534 | void TokenBuf::push_front_token(Token *p_token) | |
535 | { | |
536 | if(!p_token) | |
537 | FATAL_ERROR("Asn::TokenBuf::push_front_token()"); | |
538 | tokens->add_front(p_token); | |
539 | } | |
540 | ||
541 | void TokenBuf::push_front_kw_token(int kw) | |
542 | { | |
543 | if(tokens->empty()) | |
544 | FATAL_ERROR("Asn::TokenBuf::push_front_kw_token()"); | |
545 | tokens->add_front(new Token(kw, *(*tokens)[0])); | |
546 | } | |
547 | ||
548 | void TokenBuf::push_back_token(Token *p_token) | |
549 | { | |
550 | if(!p_token) | |
551 | FATAL_ERROR("NULL parameter: Asn::TokenBuf::push_back_token()"); | |
552 | tokens->add(p_token); | |
553 | } | |
554 | ||
555 | void TokenBuf::push_back_kw_token(int kw) | |
556 | { | |
557 | if(tokens->empty()) | |
558 | FATAL_ERROR("Asn::TokenBuf::push_back_kw_token()"); | |
559 | tokens->add(new Token(kw, *(*tokens)[tokens->size() - 1])); | |
560 | } | |
561 | ||
562 | void TokenBuf::move_tokens_from(TokenBuf *tb) | |
563 | { | |
564 | if(!tb) | |
565 | FATAL_ERROR("NULL parameter: Asn::TokenBuf::move_tokens_from()"); | |
566 | size_t insert_pos=tokens->size(); | |
567 | if(!tokens->empty() && (*tokens)[tokens->size()-1]->get_token()=='\0') | |
568 | insert_pos--; | |
569 | size_t num_of_toks=tb->tokens->size(); | |
570 | if(!tb->tokens->empty() && | |
571 | (*tb->tokens)[tb->tokens->size()-1]->get_token()=='\0') | |
572 | num_of_toks--; | |
573 | tokens_t *tmp_tokens=tb->tokens->subvector(0, num_of_toks); | |
574 | tb->tokens->replace(0, num_of_toks); | |
575 | tokens->replace(insert_pos, 0, tmp_tokens); | |
576 | tmp_tokens->clear(); delete tmp_tokens; | |
577 | } | |
578 | ||
579 | Token* TokenBuf::pop_front_token() | |
580 | { | |
581 | Token *token=get_at(0); | |
582 | if(token->get_token()=='{') { | |
583 | token->set_loc_info(); /* report this line if unmatch_error */ | |
584 | /* search the matching '}' */ | |
585 | int blocklevel=1; | |
586 | size_t i; | |
587 | bool unmatch_error=false; | |
588 | for(i=1; blocklevel>0 && !unmatch_error; i++) { | |
589 | switch(get_at(i)->get_token()) { | |
590 | case '{': | |
591 | blocklevel++; | |
592 | break; | |
593 | case '}': | |
594 | blocklevel--; | |
595 | break; | |
596 | case 0: | |
597 | yyerror("Unmatched '{'"); | |
598 | unmatch_error=true; | |
599 | i--; /* EOF is not part of the block */ | |
600 | break; | |
601 | } | |
602 | } | |
603 | /* copy the tokens of the block to a new vector */ | |
604 | tokens_t *tokens_block=tokens->subvector(1, i-1); | |
605 | if(!unmatch_error) /* replace '}' to EOF */ | |
606 | (*tokens_block)[tokens_block->size()-1]->set_token('\0'); | |
607 | else /* clone EOF and add to block */ | |
608 | tokens_block->add(get_at(i)->clone()); | |
609 | /* remove the tokens from their original vector */ | |
610 | tokens->replace(0, i); | |
611 | /* create the new tokenbuf from the tokens of the block */ | |
612 | TokenBuf *tb=new TokenBuf(tokens_block); | |
613 | tb->filename=filename; | |
614 | /* transform the opening '{' to a block-token */ | |
615 | token->create_block(tb); | |
616 | } | |
617 | else { | |
618 | /* remove the first token */ | |
619 | tokens->replace(0, 1); | |
620 | } | |
621 | return token; | |
622 | } | |
623 | ||
624 | int TokenBuf::lex() | |
625 | { | |
626 | Token *token=pop_front_token(); | |
627 | int tmp_tok = token->get_token(); | |
628 | token->set_loc_info(); | |
629 | token->steal_semval(yylval); | |
630 | yylloc.first_line=yylloc.last_line=token->get_lineno(); | |
631 | yylloc.first_column=yylloc.last_column=0; | |
632 | delete token; | |
633 | return tmp_tok; | |
634 | } | |
635 | ||
636 | void TokenBuf::dump(unsigned level) const | |
637 | { | |
638 | DEBUG(level, "Tokens: (%lu pcs.)", (unsigned long) tokens->size()); | |
639 | level++; | |
640 | for(size_t i=0; i<tokens->size(); i++) | |
641 | (*tokens)[i]->dump(level); | |
642 | } | |
643 | ||
644 | } // namespace Asn |