11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/torque/ls/json-parser.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <cctype>
81cb0ef41Sopenharmony_ci#include "src/torque/earley-parser.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_cinamespace v8 {
111cb0ef41Sopenharmony_cinamespace internal {
121cb0ef41Sopenharmony_cinamespace torque {
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_citemplate <>
151cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<ls::JsonValue>::id =
161cb0ef41Sopenharmony_ci    ParseResultTypeId::kJsonValue;
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_citemplate <>
191cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE const ParseResultTypeId
201cb0ef41Sopenharmony_ci    ParseResultHolder<std::pair<std::string, ls::JsonValue>>::id =
211cb0ef41Sopenharmony_ci        ParseResultTypeId::kJsonMember;
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_citemplate <>
241cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE const ParseResultTypeId
251cb0ef41Sopenharmony_ci    ParseResultHolder<std::vector<ls::JsonValue>>::id =
261cb0ef41Sopenharmony_ci        ParseResultTypeId::kStdVectorOfJsonValue;
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_citemplate <>
291cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE const ParseResultTypeId
301cb0ef41Sopenharmony_ci    ParseResultHolder<std::vector<std::pair<std::string, ls::JsonValue>>>::id =
311cb0ef41Sopenharmony_ci        ParseResultTypeId::kStdVectorOfJsonMember;
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_cinamespace ls {
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciusing JsonMember = std::pair<std::string, JsonValue>;
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_citemplate <bool value>
381cb0ef41Sopenharmony_cibase::Optional<ParseResult> MakeBoolLiteral(
391cb0ef41Sopenharmony_ci    ParseResultIterator* child_results) {
401cb0ef41Sopenharmony_ci  return ParseResult{JsonValue::From(value)};
411cb0ef41Sopenharmony_ci}
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_cibase::Optional<ParseResult> MakeNullLiteral(
441cb0ef41Sopenharmony_ci    ParseResultIterator* child_results) {
451cb0ef41Sopenharmony_ci  JsonValue result;
461cb0ef41Sopenharmony_ci  result.tag = JsonValue::IS_NULL;
471cb0ef41Sopenharmony_ci  return ParseResult{std::move(result)};
481cb0ef41Sopenharmony_ci}
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_cibase::Optional<ParseResult> MakeNumberLiteral(
511cb0ef41Sopenharmony_ci    ParseResultIterator* child_results) {
521cb0ef41Sopenharmony_ci  auto number = child_results->NextAs<std::string>();
531cb0ef41Sopenharmony_ci  double d = std::stod(number.c_str());
541cb0ef41Sopenharmony_ci  return ParseResult{JsonValue::From(d)};
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_cibase::Optional<ParseResult> MakeStringLiteral(
581cb0ef41Sopenharmony_ci    ParseResultIterator* child_results) {
591cb0ef41Sopenharmony_ci  std::string literal = child_results->NextAs<std::string>();
601cb0ef41Sopenharmony_ci  return ParseResult{JsonValue::From(StringLiteralUnquote(literal))};
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_cibase::Optional<ParseResult> MakeArray(ParseResultIterator* child_results) {
641cb0ef41Sopenharmony_ci  JsonArray array = child_results->NextAs<JsonArray>();
651cb0ef41Sopenharmony_ci  return ParseResult{JsonValue::From(std::move(array))};
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_cibase::Optional<ParseResult> MakeMember(ParseResultIterator* child_results) {
691cb0ef41Sopenharmony_ci  JsonMember result;
701cb0ef41Sopenharmony_ci  std::string key = child_results->NextAs<std::string>();
711cb0ef41Sopenharmony_ci  result.first = StringLiteralUnquote(key);
721cb0ef41Sopenharmony_ci  result.second = child_results->NextAs<JsonValue>();
731cb0ef41Sopenharmony_ci  return ParseResult{std::move(result)};
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_cibase::Optional<ParseResult> MakeObject(ParseResultIterator* child_results) {
771cb0ef41Sopenharmony_ci  using MemberList = std::vector<JsonMember>;
781cb0ef41Sopenharmony_ci  MemberList members = child_results->NextAs<MemberList>();
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  JsonObject object;
811cb0ef41Sopenharmony_ci  for (auto& member : members) object.insert(std::move(member));
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  return ParseResult{JsonValue::From(std::move(object))};
841cb0ef41Sopenharmony_ci}
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ciclass JsonGrammar : public Grammar {
871cb0ef41Sopenharmony_ci  static bool MatchWhitespace(InputPosition* pos) {
881cb0ef41Sopenharmony_ci    while (MatchChar(std::isspace, pos)) {
891cb0ef41Sopenharmony_ci    }
901cb0ef41Sopenharmony_ci    return true;
911cb0ef41Sopenharmony_ci  }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  static bool MatchStringLiteral(InputPosition* pos) {
941cb0ef41Sopenharmony_ci    InputPosition current = *pos;
951cb0ef41Sopenharmony_ci    if (MatchString("\"", &current)) {
961cb0ef41Sopenharmony_ci      while (
971cb0ef41Sopenharmony_ci          (MatchString("\\", &current) && MatchAnyChar(&current)) ||
981cb0ef41Sopenharmony_ci          MatchChar([](char c) { return c != '"' && c != '\n'; }, &current)) {
991cb0ef41Sopenharmony_ci      }
1001cb0ef41Sopenharmony_ci      if (MatchString("\"", &current)) {
1011cb0ef41Sopenharmony_ci        *pos = current;
1021cb0ef41Sopenharmony_ci        return true;
1031cb0ef41Sopenharmony_ci      }
1041cb0ef41Sopenharmony_ci    }
1051cb0ef41Sopenharmony_ci    current = *pos;
1061cb0ef41Sopenharmony_ci    if (MatchString("'", &current)) {
1071cb0ef41Sopenharmony_ci      while (
1081cb0ef41Sopenharmony_ci          (MatchString("\\", &current) && MatchAnyChar(&current)) ||
1091cb0ef41Sopenharmony_ci          MatchChar([](char c) { return c != '\'' && c != '\n'; }, &current)) {
1101cb0ef41Sopenharmony_ci      }
1111cb0ef41Sopenharmony_ci      if (MatchString("'", &current)) {
1121cb0ef41Sopenharmony_ci        *pos = current;
1131cb0ef41Sopenharmony_ci        return true;
1141cb0ef41Sopenharmony_ci      }
1151cb0ef41Sopenharmony_ci    }
1161cb0ef41Sopenharmony_ci    return false;
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  static bool MatchHexLiteral(InputPosition* pos) {
1201cb0ef41Sopenharmony_ci    InputPosition current = *pos;
1211cb0ef41Sopenharmony_ci    MatchString("-", &current);
1221cb0ef41Sopenharmony_ci    if (MatchString("0x", &current) && MatchChar(std::isxdigit, &current)) {
1231cb0ef41Sopenharmony_ci      while (MatchChar(std::isxdigit, &current)) {
1241cb0ef41Sopenharmony_ci      }
1251cb0ef41Sopenharmony_ci      *pos = current;
1261cb0ef41Sopenharmony_ci      return true;
1271cb0ef41Sopenharmony_ci    }
1281cb0ef41Sopenharmony_ci    return false;
1291cb0ef41Sopenharmony_ci  }
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  static bool MatchDecimalLiteral(InputPosition* pos) {
1321cb0ef41Sopenharmony_ci    InputPosition current = *pos;
1331cb0ef41Sopenharmony_ci    bool found_digit = false;
1341cb0ef41Sopenharmony_ci    MatchString("-", &current);
1351cb0ef41Sopenharmony_ci    while (MatchChar(std::isdigit, &current)) found_digit = true;
1361cb0ef41Sopenharmony_ci    MatchString(".", &current);
1371cb0ef41Sopenharmony_ci    while (MatchChar(std::isdigit, &current)) found_digit = true;
1381cb0ef41Sopenharmony_ci    if (!found_digit) return false;
1391cb0ef41Sopenharmony_ci    *pos = current;
1401cb0ef41Sopenharmony_ci    if ((MatchString("e", &current) || MatchString("E", &current)) &&
1411cb0ef41Sopenharmony_ci        (MatchString("+", &current) || MatchString("-", &current) || true) &&
1421cb0ef41Sopenharmony_ci        MatchChar(std::isdigit, &current)) {
1431cb0ef41Sopenharmony_ci      while (MatchChar(std::isdigit, &current)) {
1441cb0ef41Sopenharmony_ci      }
1451cb0ef41Sopenharmony_ci      *pos = current;
1461cb0ef41Sopenharmony_ci      return true;
1471cb0ef41Sopenharmony_ci    }
1481cb0ef41Sopenharmony_ci    return true;
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci public:
1521cb0ef41Sopenharmony_ci  JsonGrammar() : Grammar(&file) { SetWhitespace(MatchWhitespace); }
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  Symbol trueLiteral = {Rule({Token("true")})};
1551cb0ef41Sopenharmony_ci  Symbol falseLiteral = {Rule({Token("false")})};
1561cb0ef41Sopenharmony_ci  Symbol nullLiteral = {Rule({Token("null")})};
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  Symbol decimalLiteral = {
1591cb0ef41Sopenharmony_ci      Rule({Pattern(MatchDecimalLiteral)}, YieldMatchedInput),
1601cb0ef41Sopenharmony_ci      Rule({Pattern(MatchHexLiteral)}, YieldMatchedInput)};
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  Symbol stringLiteral = {
1631cb0ef41Sopenharmony_ci      Rule({Pattern(MatchStringLiteral)}, YieldMatchedInput)};
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  Symbol* elementList = List<JsonValue>(&value, Token(","));
1661cb0ef41Sopenharmony_ci  Symbol array = {Rule({Token("["), elementList, Token("]")})};
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci  Symbol member = {Rule({&stringLiteral, Token(":"), &value}, MakeMember)};
1691cb0ef41Sopenharmony_ci  Symbol* memberList = List<JsonMember>(&member, Token(","));
1701cb0ef41Sopenharmony_ci  Symbol object = {Rule({Token("{"), memberList, Token("}")})};
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  Symbol value = {Rule({&trueLiteral}, MakeBoolLiteral<true>),
1731cb0ef41Sopenharmony_ci                  Rule({&falseLiteral}, MakeBoolLiteral<false>),
1741cb0ef41Sopenharmony_ci                  Rule({&nullLiteral}, MakeNullLiteral),
1751cb0ef41Sopenharmony_ci                  Rule({&decimalLiteral}, MakeNumberLiteral),
1761cb0ef41Sopenharmony_ci                  Rule({&stringLiteral}, MakeStringLiteral),
1771cb0ef41Sopenharmony_ci                  Rule({&object}, MakeObject),
1781cb0ef41Sopenharmony_ci                  Rule({&array}, MakeArray)};
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  Symbol file = {Rule({&value})};
1811cb0ef41Sopenharmony_ci};
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ciJsonParserResult ParseJson(const std::string& input) {
1841cb0ef41Sopenharmony_ci  // Torque needs a CurrentSourceFile scope during parsing.
1851cb0ef41Sopenharmony_ci  // As JSON lives in memory only, a unknown file scope is created.
1861cb0ef41Sopenharmony_ci  SourceFileMap::Scope source_map_scope("");
1871cb0ef41Sopenharmony_ci  TorqueMessages::Scope messages_scope;
1881cb0ef41Sopenharmony_ci  CurrentSourceFile::Scope unkown_file(SourceFileMap::AddSource("<json>"));
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  JsonParserResult result;
1911cb0ef41Sopenharmony_ci  try {
1921cb0ef41Sopenharmony_ci    result.value = (*JsonGrammar().Parse(input)).Cast<JsonValue>();
1931cb0ef41Sopenharmony_ci  } catch (TorqueAbortCompilation&) {
1941cb0ef41Sopenharmony_ci    CHECK(!TorqueMessages::Get().empty());
1951cb0ef41Sopenharmony_ci    result.error = TorqueMessages::Get().front();
1961cb0ef41Sopenharmony_ci  }
1971cb0ef41Sopenharmony_ci  return result;
1981cb0ef41Sopenharmony_ci}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci}  // namespace ls
2011cb0ef41Sopenharmony_ci}  // namespace torque
2021cb0ef41Sopenharmony_ci}  // namespace internal
2031cb0ef41Sopenharmony_ci}  // namespace v8
204