1// Copyright 2019 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/torque/ls/json-parser.h" 6 7#include <cctype> 8#include "src/torque/earley-parser.h" 9 10namespace v8 { 11namespace internal { 12namespace torque { 13 14template <> 15V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<ls::JsonValue>::id = 16 ParseResultTypeId::kJsonValue; 17 18template <> 19V8_EXPORT_PRIVATE const ParseResultTypeId 20 ParseResultHolder<std::pair<std::string, ls::JsonValue>>::id = 21 ParseResultTypeId::kJsonMember; 22 23template <> 24V8_EXPORT_PRIVATE const ParseResultTypeId 25 ParseResultHolder<std::vector<ls::JsonValue>>::id = 26 ParseResultTypeId::kStdVectorOfJsonValue; 27 28template <> 29V8_EXPORT_PRIVATE const ParseResultTypeId 30 ParseResultHolder<std::vector<std::pair<std::string, ls::JsonValue>>>::id = 31 ParseResultTypeId::kStdVectorOfJsonMember; 32 33namespace ls { 34 35using JsonMember = std::pair<std::string, JsonValue>; 36 37template <bool value> 38base::Optional<ParseResult> MakeBoolLiteral( 39 ParseResultIterator* child_results) { 40 return ParseResult{JsonValue::From(value)}; 41} 42 43base::Optional<ParseResult> MakeNullLiteral( 44 ParseResultIterator* child_results) { 45 JsonValue result; 46 result.tag = JsonValue::IS_NULL; 47 return ParseResult{std::move(result)}; 48} 49 50base::Optional<ParseResult> MakeNumberLiteral( 51 ParseResultIterator* child_results) { 52 auto number = child_results->NextAs<std::string>(); 53 double d = std::stod(number.c_str()); 54 return ParseResult{JsonValue::From(d)}; 55} 56 57base::Optional<ParseResult> MakeStringLiteral( 58 ParseResultIterator* child_results) { 59 std::string literal = child_results->NextAs<std::string>(); 60 return ParseResult{JsonValue::From(StringLiteralUnquote(literal))}; 61} 62 63base::Optional<ParseResult> MakeArray(ParseResultIterator* child_results) { 64 JsonArray array = child_results->NextAs<JsonArray>(); 65 return ParseResult{JsonValue::From(std::move(array))}; 66} 67 68base::Optional<ParseResult> MakeMember(ParseResultIterator* child_results) { 69 JsonMember result; 70 std::string key = child_results->NextAs<std::string>(); 71 result.first = StringLiteralUnquote(key); 72 result.second = child_results->NextAs<JsonValue>(); 73 return ParseResult{std::move(result)}; 74} 75 76base::Optional<ParseResult> MakeObject(ParseResultIterator* child_results) { 77 using MemberList = std::vector<JsonMember>; 78 MemberList members = child_results->NextAs<MemberList>(); 79 80 JsonObject object; 81 for (auto& member : members) object.insert(std::move(member)); 82 83 return ParseResult{JsonValue::From(std::move(object))}; 84} 85 86class JsonGrammar : public Grammar { 87 static bool MatchWhitespace(InputPosition* pos) { 88 while (MatchChar(std::isspace, pos)) { 89 } 90 return true; 91 } 92 93 static bool MatchStringLiteral(InputPosition* pos) { 94 InputPosition current = *pos; 95 if (MatchString("\"", ¤t)) { 96 while ( 97 (MatchString("\\", ¤t) && MatchAnyChar(¤t)) || 98 MatchChar([](char c) { return c != '"' && c != '\n'; }, ¤t)) { 99 } 100 if (MatchString("\"", ¤t)) { 101 *pos = current; 102 return true; 103 } 104 } 105 current = *pos; 106 if (MatchString("'", ¤t)) { 107 while ( 108 (MatchString("\\", ¤t) && MatchAnyChar(¤t)) || 109 MatchChar([](char c) { return c != '\'' && c != '\n'; }, ¤t)) { 110 } 111 if (MatchString("'", ¤t)) { 112 *pos = current; 113 return true; 114 } 115 } 116 return false; 117 } 118 119 static bool MatchHexLiteral(InputPosition* pos) { 120 InputPosition current = *pos; 121 MatchString("-", ¤t); 122 if (MatchString("0x", ¤t) && MatchChar(std::isxdigit, ¤t)) { 123 while (MatchChar(std::isxdigit, ¤t)) { 124 } 125 *pos = current; 126 return true; 127 } 128 return false; 129 } 130 131 static bool MatchDecimalLiteral(InputPosition* pos) { 132 InputPosition current = *pos; 133 bool found_digit = false; 134 MatchString("-", ¤t); 135 while (MatchChar(std::isdigit, ¤t)) found_digit = true; 136 MatchString(".", ¤t); 137 while (MatchChar(std::isdigit, ¤t)) found_digit = true; 138 if (!found_digit) return false; 139 *pos = current; 140 if ((MatchString("e", ¤t) || MatchString("E", ¤t)) && 141 (MatchString("+", ¤t) || MatchString("-", ¤t) || true) && 142 MatchChar(std::isdigit, ¤t)) { 143 while (MatchChar(std::isdigit, ¤t)) { 144 } 145 *pos = current; 146 return true; 147 } 148 return true; 149 } 150 151 public: 152 JsonGrammar() : Grammar(&file) { SetWhitespace(MatchWhitespace); } 153 154 Symbol trueLiteral = {Rule({Token("true")})}; 155 Symbol falseLiteral = {Rule({Token("false")})}; 156 Symbol nullLiteral = {Rule({Token("null")})}; 157 158 Symbol decimalLiteral = { 159 Rule({Pattern(MatchDecimalLiteral)}, YieldMatchedInput), 160 Rule({Pattern(MatchHexLiteral)}, YieldMatchedInput)}; 161 162 Symbol stringLiteral = { 163 Rule({Pattern(MatchStringLiteral)}, YieldMatchedInput)}; 164 165 Symbol* elementList = List<JsonValue>(&value, Token(",")); 166 Symbol array = {Rule({Token("["), elementList, Token("]")})}; 167 168 Symbol member = {Rule({&stringLiteral, Token(":"), &value}, MakeMember)}; 169 Symbol* memberList = List<JsonMember>(&member, Token(",")); 170 Symbol object = {Rule({Token("{"), memberList, Token("}")})}; 171 172 Symbol value = {Rule({&trueLiteral}, MakeBoolLiteral<true>), 173 Rule({&falseLiteral}, MakeBoolLiteral<false>), 174 Rule({&nullLiteral}, MakeNullLiteral), 175 Rule({&decimalLiteral}, MakeNumberLiteral), 176 Rule({&stringLiteral}, MakeStringLiteral), 177 Rule({&object}, MakeObject), 178 Rule({&array}, MakeArray)}; 179 180 Symbol file = {Rule({&value})}; 181}; 182 183JsonParserResult ParseJson(const std::string& input) { 184 // Torque needs a CurrentSourceFile scope during parsing. 185 // As JSON lives in memory only, a unknown file scope is created. 186 SourceFileMap::Scope source_map_scope(""); 187 TorqueMessages::Scope messages_scope; 188 CurrentSourceFile::Scope unkown_file(SourceFileMap::AddSource("<json>")); 189 190 JsonParserResult result; 191 try { 192 result.value = (*JsonGrammar().Parse(input)).Cast<JsonValue>(); 193 } catch (TorqueAbortCompilation&) { 194 CHECK(!TorqueMessages::Get().empty()); 195 result.error = TorqueMessages::Get().front(); 196 } 197 return result; 198} 199 200} // namespace ls 201} // namespace torque 202} // namespace internal 203} // namespace v8 204