• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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