Serenity Operating System
at hosted 132 lines 4.4 kB view raw
1/* 2 * Copyright (c) 2020, Stephan Unverwerth <s.unverwerth@gmx.de> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "Token.h" 28#include <AK/Assertions.h> 29#include <AK/StringBuilder.h> 30#include <ctype.h> 31 32namespace JS { 33 34const char* Token::name(TokenType type) 35{ 36 switch (type) { 37#define __ENUMERATE_JS_TOKEN(x) \ 38 case TokenType::x: \ 39 return #x; 40 ENUMERATE_JS_TOKENS 41#undef __ENUMERATE_JS_TOKEN 42 default: 43 ASSERT_NOT_REACHED(); 44 return "<Unknown>"; 45 } 46} 47 48const char* Token::name() const 49{ 50 return name(m_type); 51} 52 53double Token::double_value() const 54{ 55 ASSERT(type() == TokenType::NumericLiteral); 56 String value_string(m_value); 57 if (value_string[0] == '0' && value_string.length() >= 2) { 58 if (value_string[1] == 'x' || value_string[1] == 'X') { 59 // hexadecimal 60 return static_cast<double>(strtoul(value_string.characters() + 2, nullptr, 16)); 61 } else if (value_string[1] == 'o' || value_string[1] == 'O') { 62 // octal 63 return static_cast<double>(strtoul(value_string.characters() + 2, nullptr, 8)); 64 } else if (value_string[1] == 'b' || value_string[1] == 'B') { 65 // binary 66 return static_cast<double>(strtoul(value_string.characters() + 2, nullptr, 2)); 67 } else if (isdigit(value_string[1])) { 68 // also octal, but syntax error in strict mode 69 return static_cast<double>(strtoul(value_string.characters() + 1, nullptr, 8)); 70 } 71 } 72 return strtod(value_string.characters(), nullptr); 73} 74 75String Token::string_value() const 76{ 77 ASSERT(type() == TokenType::StringLiteral); 78 StringBuilder builder; 79 for (size_t i = 1; i < m_value.length() - 1; ++i) { 80 if (m_value[i] == '\\' && i + 1 < m_value.length() - 1) { 81 i++; 82 switch (m_value[i]) { 83 case 'b': 84 builder.append('\b'); 85 break; 86 case 'f': 87 builder.append('\f'); 88 break; 89 case 'n': 90 builder.append('\n'); 91 break; 92 case 'r': 93 builder.append('\r'); 94 break; 95 case 't': 96 builder.append('\t'); 97 break; 98 case 'v': 99 builder.append('\v'); 100 break; 101 case '0': 102 builder.append((char)0); 103 break; 104 case '\'': 105 builder.append('\''); 106 break; 107 case '"': 108 builder.append('"'); 109 break; 110 case '\\': 111 builder.append('\\'); 112 break; 113 default: 114 // FIXME: Also parse octal, hex and unicode sequences 115 // should anything else generate a syntax error? 116 builder.append(m_value[i]); 117 } 118 119 } else { 120 builder.append(m_value[i]); 121 } 122 } 123 return builder.to_string(); 124} 125 126bool Token::bool_value() const 127{ 128 ASSERT(type() == TokenType::BoolLiteral); 129 return m_value == "true"; 130} 131 132}