1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lexer.h"
17 #include <cmath>
18 #include <climits>
19 #include <cstdlib>
20 #include "mpl_logging.h"
21 #include "debug_info.h"
22 #include "mir_module.h"
23 #include "securec.h"
24 #include "utils.h"
25
26 namespace maple {
HexCharToDigit(char c)27 int32 HexCharToDigit(char c)
28 {
29 int32 ret = utils::ToDigit<16, int32>(c);
30 return (ret != INT32_MAX ? ret : 0);
31 }
32
Char2num(char c)33 static uint8 Char2num(char c)
34 {
35 uint8 ret = utils::ToDigit<16>(c);
36 DEBUG_ASSERT(ret != UINT8_MAX, "not a hex value");
37 return ret;
38 }
39
40 // Read (next) line from the MIR (text) file, and return the read
41 // number of chars.
42 // if the line is empty (nothing but a newline), returns 0.
43 // if EOF, return -1.
44 // The trailing new-line character has been removed.
ReadALine()45 int MIRLexer::ReadALine()
46 {
47 if (airFile == nullptr) {
48 line = "";
49 return -1;
50 }
51
52 curIdx = 0;
53 if (!std::getline(*airFile, line)) { // EOF
54 line = "";
55 airFile = nullptr;
56 currentLineSize = 0;
57 return -1;
58 }
59
60 RemoveReturnInline(line);
61 currentLineSize = line.length();
62 return currentLineSize;
63 }
64
ReadALineByMirQueue()65 int MIRLexer::ReadALineByMirQueue()
66 {
67 if (mirQueue.empty()) {
68 line = "";
69 return -1;
70 }
71 curIdx = 0;
72 line = mirQueue.front();
73 RemoveReturnInline(line);
74 currentLineSize = line.length();
75 mirQueue.pop();
76 return currentLineSize;
77 }
78
MIRLexer(MIRModule & mod)79 MIRLexer::MIRLexer(MIRModule &mod)
80 : module(mod), seenComments(mod.GetMPAllocator().Adapter()), keywordMap(mod.GetMPAllocator().Adapter())
81 {
82 // initialize keywordMap
83 keywordMap.clear();
84 #define KEYWORD(STR) \
85 { \
86 std::string str; \
87 str = #STR; \
88 keywordMap[str] = TK_##STR; \
89 }
90 #include "keywords.def"
91 #undef KEYWORD
92 }
93
PrepareForFile(const std::string & filename)94 void MIRLexer::PrepareForFile(const std::string &filename)
95 {
96 // open MIR file
97 airFileInternal.open(filename);
98 CHECK_FATAL(airFileInternal.is_open(), "cannot open MIR file %s\n", &filename);
99
100 airFile = &airFileInternal;
101 // try to read the first line
102 if (ReadALine() < 0) {
103 lineNum = 0;
104 } else {
105 lineNum = 1;
106 }
107 module.GetDbgInfo()->UpdateMsg(lineNum, line.c_str());
108 kind = TK_invalid;
109 }
110
PrepareForString(const std::string & src)111 void MIRLexer::PrepareForString(const std::string &src)
112 {
113 SetMirQueue(src);
114 if (ReadALineByMirQueue() < 0) {
115 lineNum = 0;
116 } else {
117 lineNum = 1;
118 }
119 module.GetDbgInfo()->UpdateMsg(lineNum, line.c_str());
120 kind = TK_invalid;
121 }
122
GenName()123 void MIRLexer::GenName()
124 {
125 uint32 startIdx = curIdx;
126 char c = GetNextCurrentCharWithUpperCheck();
127 char cp = GetCharAt(curIdx - 1);
128 if (c == '@' && (cp == 'h' || cp == 'f')) {
129 // special pattern for exception handling labels: catch or finally
130 c = GetNextCurrentCharWithUpperCheck();
131 }
132 while (utils::IsAlnum(c) || c < 0 || c == '_' || c == '$' || c == ';' || c == '/' || c == '|' || c == '.' ||
133 c == '?' || c == '@') {
134 c = GetNextCurrentCharWithUpperCheck();
135 }
136 name = line.substr(startIdx, curIdx - startIdx);
137 }
138
139 // get the constant value
GetConstVal()140 TokenKind MIRLexer::GetConstVal()
141 {
142 bool negative = false;
143 int valStart = curIdx;
144 char c = GetCharAtWithUpperCheck(curIdx);
145 if (c == '-') {
146 c = GetNextCurrentCharWithUpperCheck();
147 TokenKind tk = GetSpecialFloatConst();
148 if (tk != TK_invalid) {
149 return tk;
150 }
151 negative = true;
152 }
153 const uint32 lenHexPrefix = 2;
154 if (line.compare(curIdx, lenHexPrefix, "0x") == 0) {
155 curIdx += lenHexPrefix;
156 return GetHexConst(valStart, negative);
157 }
158 uint32 startIdx = curIdx;
159 while (isdigit(c)) {
160 c = GetNextCurrentCharWithUpperCheck();
161 }
162 char cs = GetCharAtWithUpperCheck(startIdx);
163 if (!isdigit(cs) && c != '.') {
164 return TK_invalid;
165 }
166 if (c != '.' && c != 'f' && c != 'F' && c != 'e' && c != 'E') {
167 curIdx = startIdx;
168 return GetIntConst(valStart, negative);
169 }
170 return GetFloatConst(valStart, startIdx, negative);
171 }
172
GetSpecialFloatConst()173 TokenKind MIRLexer::GetSpecialFloatConst()
174 {
175 constexpr uint32 lenSpecFloat = 4;
176 constexpr uint32 lenSpecDouble = 3;
177 if (line.compare(curIdx, lenSpecFloat, "inff") == 0 &&
178 !utils::IsAlnum(GetCharAtWithUpperCheck(curIdx + lenSpecFloat))) {
179 curIdx += lenSpecFloat;
180 theFloatVal = -INFINITY;
181 return TK_floatconst;
182 }
183 if (line.compare(curIdx, lenSpecDouble, "inf") == 0 &&
184 !utils::IsAlnum(GetCharAtWithUpperCheck(curIdx + lenSpecDouble))) {
185 curIdx += lenSpecDouble;
186 theDoubleVal = -INFINITY;
187 return TK_doubleconst;
188 }
189 if (line.compare(curIdx, lenSpecFloat, "nanf") == 0 &&
190 !utils::IsAlnum(GetCharAtWithUpperCheck(curIdx + lenSpecFloat))) {
191 curIdx += lenSpecFloat;
192 theFloatVal = -NAN;
193 return TK_floatconst;
194 }
195 if (line.compare(curIdx, lenSpecDouble, "nan") == 0 &&
196 !utils::IsAlnum(GetCharAtWithUpperCheck(curIdx + lenSpecDouble))) {
197 curIdx += lenSpecDouble;
198 theDoubleVal = -NAN;
199 return TK_doubleconst;
200 }
201 return TK_invalid;
202 }
203
GetHexConst(uint32 valStart,bool negative)204 TokenKind MIRLexer::GetHexConst(uint32 valStart, bool negative)
205 {
206 char c = GetCharAtWithUpperCheck(curIdx);
207 if (!isxdigit(c)) {
208 name = line.substr(valStart, curIdx - valStart);
209 return TK_invalid;
210 }
211 uint64 tmp = static_cast<uint32>(HexCharToDigit(c));
212 c = GetNextCurrentCharWithUpperCheck();
213 while (isxdigit(c)) {
214 tmp = (tmp << k16BitShift) + static_cast<uint32>(HexCharToDigit(c));
215 c = GetNextCurrentCharWithUpperCheck();
216 }
217 theIntVal = static_cast<int64>(static_cast<uint64>(tmp));
218 if (negative) {
219 theIntVal = -theIntVal;
220 }
221 theFloatVal = static_cast<float>(theIntVal);
222 theDoubleVal = static_cast<double>(theIntVal);
223 if (negative && theIntVal == 0) {
224 theFloatVal = -theFloatVal;
225 theDoubleVal = -theDoubleVal;
226 }
227 name = line.substr(valStart, curIdx - valStart);
228 return TK_intconst;
229 }
230
GetIntConst(uint32 valStart,bool negative)231 TokenKind MIRLexer::GetIntConst(uint32 valStart, bool negative)
232 {
233 auto negOrSelf = [negative](uint64 val) { return negative ? ~val + 1 : val; };
234
235 theIntVal = HexCharToDigit(GetCharAtWithUpperCheck(curIdx));
236
237 uint64 radix = theIntVal == 0 ? 8 : 10;
238
239 char c = GetNextCurrentCharWithUpperCheck();
240
241 for (theIntVal = negOrSelf(theIntVal); isdigit(c); c = GetNextCurrentCharWithUpperCheck()) {
242 theIntVal = (theIntVal * radix) + negOrSelf(HexCharToDigit(c));
243 }
244
245 if (c == 'u' || c == 'U') { // skip 'u' or 'U'
246 c = GetNextCurrentCharWithUpperCheck();
247 if (c == 'l' || c == 'L') {
248 c = GetNextCurrentCharWithUpperCheck();
249 }
250 }
251
252 if (c == 'l' || c == 'L') {
253 c = GetNextCurrentCharWithUpperCheck();
254 if (c == 'l' || c == 'L' || c == 'u' || c == 'U') {
255 ++curIdx;
256 }
257 }
258
259 name = line.substr(valStart, curIdx - valStart);
260
261 if (negative) {
262 theFloatVal = static_cast<float>(static_cast<int64>(theIntVal));
263 theDoubleVal = static_cast<double>(static_cast<int64>(theIntVal));
264
265 if (theIntVal == 0) {
266 theFloatVal = -theFloatVal;
267 theDoubleVal = -theDoubleVal;
268 }
269 } else {
270 theFloatVal = static_cast<float>(theIntVal);
271 theDoubleVal = static_cast<double>(theIntVal);
272 }
273
274 return TK_intconst;
275 }
276
GetFloatConst(uint32 valStart,uint32 startIdx,bool negative)277 TokenKind MIRLexer::GetFloatConst(uint32 valStart, uint32 startIdx, bool negative)
278 {
279 char c = GetCharAtWithUpperCheck(curIdx);
280 if (c == '.') {
281 c = GetNextCurrentCharWithUpperCheck();
282 }
283 while (isdigit(c)) {
284 c = GetNextCurrentCharWithUpperCheck();
285 }
286 bool doublePrec = true;
287 if (c == 'e' || c == 'E') {
288 c = GetNextCurrentCharWithUpperCheck();
289 if (!isdigit(c) && c != '-' && c != '+') {
290 name = line.substr(valStart, curIdx - valStart);
291 return TK_invalid;
292 }
293 if (c == '-' || c == '+') {
294 c = GetNextCurrentCharWithUpperCheck();
295 }
296 while (isdigit(c)) {
297 c = GetNextCurrentCharWithUpperCheck();
298 }
299 }
300 if (c == 'f' || c == 'F') {
301 doublePrec = false;
302 c = GetNextCurrentCharWithUpperCheck();
303 }
304 if (c == 'l' || c == 'L') {
305 MIR_ERROR("warning: not yet support long double\n");
306 ++curIdx;
307 }
308
309 std::string floatStr = line.substr(startIdx, curIdx - startIdx);
310 // get the float constant value
311 if (!doublePrec) {
312 int eNum = sscanf_s(floatStr.c_str(), "%e", &theFloatVal);
313 CHECK_FATAL(eNum == 1, "sscanf_s failed");
314
315 if (negative) {
316 theFloatVal = -theFloatVal;
317 }
318 theIntVal = static_cast<int>(theFloatVal);
319 theDoubleVal = static_cast<double>(theFloatVal);
320 if (negative && fabs(theFloatVal) <= 1e-6) {
321 theDoubleVal = -theDoubleVal;
322 }
323 name = line.substr(valStart, curIdx - valStart);
324 return TK_floatconst;
325 } else {
326 int eNum = sscanf_s(floatStr.c_str(), "%le", &theDoubleVal);
327 CHECK_FATAL(eNum == 1, "sscanf_s failed");
328
329 if (negative) {
330 theDoubleVal = -theDoubleVal;
331 }
332 theIntVal = static_cast<int>(theDoubleVal);
333 theFloatVal = static_cast<float>(theDoubleVal);
334 if (negative && fabs(theDoubleVal) <= 1e-15) {
335 theFloatVal = -theFloatVal;
336 }
337 name = line.substr(valStart, curIdx - valStart);
338 return TK_doubleconst;
339 }
340 }
341
GetTokenWithPrefixDollar()342 TokenKind MIRLexer::GetTokenWithPrefixDollar()
343 {
344 // token with prefix '$'
345 char c = GetCharAtWithUpperCheck(curIdx);
346 if (utils::IsAlpha(c) || c == '_' || c == '$') {
347 GenName();
348 return TK_gname;
349 } else {
350 // for error reporting.
351 const uint32 printLength = 2;
352 name = line.substr(curIdx - 1, printLength);
353 return TK_invalid;
354 }
355 }
356
GetTokenWithPrefixPercent()357 TokenKind MIRLexer::GetTokenWithPrefixPercent()
358 {
359 // token with prefix '%'
360 char c = GetCharAtWithUpperCheck(curIdx);
361 if (isdigit(c)) {
362 int valStart = curIdx - 1;
363 theIntVal = HexCharToDigit(c);
364 c = GetNextCurrentCharWithUpperCheck();
365 while (isdigit(c)) {
366 theIntVal = (theIntVal * 10) + HexCharToDigit(c); // 10 for decimal
367 DEBUG_ASSERT(theIntVal >= 0, "int value overflow");
368 c = GetNextCurrentCharWithUpperCheck();
369 }
370 name = line.substr(valStart, curIdx - valStart);
371 return TK_preg;
372 }
373 if (utils::IsAlpha(c) || c == '_' || c == '$') {
374 GenName();
375 return TK_lname;
376 }
377 if (c == '%' && utils::IsAlpha(GetCharAtWithUpperCheck(curIdx + 1))) {
378 ++curIdx;
379 GenName();
380 return TK_specialreg;
381 }
382 return TK_invalid;
383 }
384
GetTokenWithPrefixAmpersand()385 TokenKind MIRLexer::GetTokenWithPrefixAmpersand()
386 {
387 // token with prefix '&'
388 char c = GetCurrentCharWithUpperCheck();
389 if (utils::IsAlpha(c) || c == '_') {
390 GenName();
391 return TK_fname;
392 }
393 // for error reporting.
394 constexpr uint32 printLength = 2;
395 name = line.substr(curIdx - 1, printLength);
396 return TK_invalid;
397 }
398
GetTokenWithPrefixAtOrCircumflex(char prefix)399 TokenKind MIRLexer::GetTokenWithPrefixAtOrCircumflex(char prefix)
400 {
401 // token with prefix '@' or `^`
402 char c = GetCurrentCharWithUpperCheck();
403 if (utils::IsAlnum(c) || c < 0 || c == '_' || c == '@' || c == '$' || c == '|') {
404 GenName();
405 if (prefix == '@') {
406 return TK_label;
407 }
408 return TK_prntfield;
409 }
410 return TK_invalid;
411 }
412
GetTokenWithPrefixExclamation()413 TokenKind MIRLexer::GetTokenWithPrefixExclamation()
414 {
415 // token with prefix '!'
416 char c = GetCurrentCharWithUpperCheck();
417 if (utils::IsAlpha(c)) {
418 GenName();
419 return TK_typeparam;
420 }
421 // for error reporting.
422 const uint32 printLength = 2;
423 name = line.substr(curIdx - 1, printLength);
424 return TK_invalid;
425 }
426
GetTokenWithPrefixQuotation()427 TokenKind MIRLexer::GetTokenWithPrefixQuotation()
428 {
429 if (GetCharAtWithUpperCheck(curIdx + 1) == '\'') {
430 theIntVal = GetCharAtWithUpperCheck(curIdx);
431 constexpr uint32 hexLength = 2;
432 curIdx += hexLength;
433 return TK_intconst;
434 }
435 return TK_invalid;
436 }
437
GetTokenWithPrefixDoubleQuotation()438 TokenKind MIRLexer::GetTokenWithPrefixDoubleQuotation()
439 {
440 uint32 startIdx = curIdx;
441 uint32 shift = 0;
442 // for \", skip the \ to leave " only internally
443 // and also for the pair of chars \ and n become '\n' etc.
444 char c = GetCurrentCharWithUpperCheck();
445 while ((c != 0) && (c != '\"' || GetCharAtWithLowerCheck(curIdx - 1) == '\\')) {
446 if (GetCharAtWithLowerCheck(curIdx - 1) == '\\') {
447 shift++;
448 switch (c) {
449 case '"':
450 line[curIdx - shift] = c;
451 break;
452 case '\\':
453 line[curIdx - shift] = c;
454 // avoid 3rd \ in \\\ being treated as an escaped one
455 line[curIdx] = 0;
456 break;
457 case 'a':
458 line[curIdx - shift] = '\a';
459 break;
460 case 'b':
461 line[curIdx - shift] = '\b';
462 break;
463 case 't':
464 line[curIdx - shift] = '\t';
465 break;
466 case 'n':
467 line[curIdx - shift] = '\n';
468 break;
469 case 'v':
470 line[curIdx - shift] = '\v';
471 break;
472 case 'f':
473 line[curIdx - shift] = '\f';
474 break;
475 case 'r':
476 line[curIdx - shift] = '\r';
477 break;
478 // support hex value \xNN
479 case 'x': {
480 const uint32 hexShift = 4;
481 const uint32 hexLength = 2;
482 uint8 c1 = Char2num(GetCharAtWithLowerCheck(curIdx + 1));
483 uint8 c2 = Char2num(GetCharAtWithLowerCheck(curIdx + hexLength));
484 uint32 cNew = (c1 << hexShift) + c2;
485 line[curIdx - shift] = cNew;
486 curIdx += hexLength;
487 shift += hexLength;
488 break;
489 }
490 // support oct value \NNN
491 case '0':
492 case '1':
493 case '2':
494 case '3':
495 case '4':
496 case '5':
497 case '6':
498 case '7':
499 case '8':
500 case '9': {
501 const uint32 octShift1 = 3;
502 const uint32 octShift2 = 6;
503 const uint32 octLength = 3;
504 DEBUG_ASSERT(curIdx + octLength < line.size(), "index out of range");
505 uint32 cNew = (static_cast<unsigned char>(GetCharAtWithLowerCheck(curIdx + 1) - '0') << octShift2) +
506 (static_cast<unsigned char>(GetCharAtWithLowerCheck(curIdx + 2) - '0') << octShift1) +
507 static_cast<unsigned char>(GetCharAtWithLowerCheck(curIdx + 3) - '0');
508 line[curIdx - shift] = cNew;
509 curIdx += octLength;
510 shift += octLength;
511 break;
512 }
513 default:
514 line[curIdx - shift] = '\\';
515 --shift;
516 line[curIdx - shift] = c;
517 break;
518 }
519 } else if (shift) {
520 line[curIdx - shift] = c;
521 }
522 c = GetNextCurrentCharWithUpperCheck();
523 }
524 if (c != '\"') {
525 return TK_invalid;
526 }
527 // for empty string
528 if (startIdx == curIdx) {
529 name = "";
530 } else {
531 name = line.substr(startIdx, curIdx - startIdx - shift);
532 }
533 ++curIdx;
534 return TK_string;
535 }
536
GetTokenSpecial()537 TokenKind MIRLexer::GetTokenSpecial()
538 {
539 --curIdx;
540 char c = GetCharAtWithLowerCheck(curIdx);
541 if (utils::IsAlpha(c) || c < 0 || c == '_') {
542 GenName();
543 TokenKind tk = keywordMap[name];
544 switch (tk) {
545 case TK_nanf:
546 theFloatVal = NAN;
547 return TK_floatconst;
548 case TK_nan:
549 theDoubleVal = NAN;
550 return TK_doubleconst;
551 case TK_inff:
552 theFloatVal = INFINITY;
553 return TK_floatconst;
554 case TK_inf:
555 theDoubleVal = INFINITY;
556 return TK_doubleconst;
557 default:
558 return tk;
559 }
560 }
561 MIR_ERROR("error in input file\n");
562 return TK_eof;
563 }
564
LexToken()565 TokenKind MIRLexer::LexToken()
566 {
567 // skip spaces
568 char c = GetCurrentCharWithUpperCheck();
569 while (c == ' ' || c == '\t') {
570 c = GetNextCurrentCharWithUpperCheck();
571 }
572 // check end of line
573 while (c == 0 || c == '#') {
574 if (c == '#') { // process comment contents
575 seenComments.push_back(line.substr(curIdx + 1, currentLineSize - curIdx - 1));
576 }
577 if (needFile) {
578 if (ReadALine() < 0) {
579 return TK_eof;
580 }
581 } else {
582 if (ReadALineByMirQueue() < 0) {
583 return TK_eof;
584 }
585 }
586 ++lineNum; // a new line read.
587 module.GetDbgInfo()->UpdateMsg(lineNum, line.c_str());
588 // skip spaces
589 c = GetCurrentCharWithUpperCheck();
590 while (c == ' ' || c == '\t') {
591 c = GetNextCurrentCharWithUpperCheck();
592 }
593 }
594 char curChar = c;
595 ++curIdx;
596 switch (curChar) {
597 case '\n':
598 return TK_newline;
599 case '(':
600 return TK_lparen;
601 case ')':
602 return TK_rparen;
603 case '{':
604 return TK_lbrace;
605 case '}':
606 return TK_rbrace;
607 case '[':
608 return TK_lbrack;
609 case ']':
610 return TK_rbrack;
611 case '<':
612 return TK_langle;
613 case '>':
614 return TK_rangle;
615 case '=':
616 return TK_eqsign;
617 case ',':
618 return TK_coma;
619 case ':':
620 return TK_colon;
621 case '*':
622 return TK_asterisk;
623 case '.':
624 if (GetCharAtWithUpperCheck(curIdx) == '.') {
625 const uint32 lenDotdot = 2;
626 curIdx += lenDotdot;
627 return TK_dotdotdot;
628 }
629 // fall thru for .9100 == 0.9100
630 [[clang::fallthrough]];
631 case '0':
632 case '1':
633 case '2':
634 case '3':
635 case '4':
636 case '5':
637 case '6':
638 case '7':
639 case '8':
640 case '9':
641 case '-':
642 --curIdx;
643 return GetConstVal();
644 case '$':
645 return GetTokenWithPrefixDollar();
646 case '%':
647 return GetTokenWithPrefixPercent();
648 case '&':
649 return GetTokenWithPrefixAmpersand();
650 case '@':
651 case '^':
652 return GetTokenWithPrefixAtOrCircumflex(curChar);
653 case '!':
654 return GetTokenWithPrefixExclamation();
655 case '\'':
656 return GetTokenWithPrefixQuotation();
657 case '\"':
658 return GetTokenWithPrefixDoubleQuotation();
659 default:
660 return GetTokenSpecial();
661 }
662 }
663
NextToken()664 TokenKind MIRLexer::NextToken()
665 {
666 kind = LexToken();
667 return kind;
668 }
669
GetTokenString() const670 std::string MIRLexer::GetTokenString() const
671 {
672 std::string temp;
673 switch (kind) {
674 case TK_gname: {
675 temp = "$";
676 temp.append(name);
677 return temp;
678 }
679 case TK_lname:
680 case TK_preg: {
681 temp = "%";
682 temp.append(name);
683 return temp;
684 }
685 case TK_specialreg: {
686 temp = "%%";
687 temp.append(name);
688 return temp;
689 }
690 case TK_label: {
691 temp = "@";
692 temp.append(name);
693 return temp;
694 }
695 case TK_prntfield: {
696 temp = "^";
697 temp.append(name);
698 return temp;
699 }
700 case TK_intconst: {
701 temp = std::to_string(theIntVal);
702 return temp;
703 }
704 case TK_floatconst: {
705 temp = std::to_string(theFloatVal);
706 return temp;
707 }
708 case TK_doubleconst: {
709 temp = std::to_string(theDoubleVal);
710 return temp;
711 }
712 // misc.
713 case TK_newline: {
714 temp = "\\n";
715 return temp;
716 }
717 case TK_lparen: {
718 temp = "(";
719 return temp;
720 }
721 case TK_rparen: {
722 temp = ")";
723 return temp;
724 }
725 case TK_lbrace: {
726 temp = "{";
727 return temp;
728 }
729 case TK_rbrace: {
730 temp = "}";
731 return temp;
732 }
733 case TK_lbrack: {
734 temp = "[";
735 return temp;
736 }
737 case TK_rbrack: {
738 temp = "]";
739 return temp;
740 }
741 case TK_langle: {
742 temp = "<";
743 return temp;
744 }
745 case TK_rangle: {
746 temp = ">";
747 return temp;
748 }
749 case TK_eqsign: {
750 temp = "=";
751 return temp;
752 }
753 case TK_coma: {
754 temp = ",";
755 return temp;
756 }
757 case TK_dotdotdot: {
758 temp = "...";
759 return temp;
760 }
761 case TK_colon: {
762 temp = ":";
763 return temp;
764 }
765 case TK_asterisk: {
766 temp = "*";
767 return temp;
768 }
769 case TK_string: {
770 temp = "\"";
771 temp.append(name);
772 temp.append("\"");
773 return temp;
774 }
775 default:
776 temp = "invalid token";
777 return temp;
778 }
779 }
780 } // namespace maple
781