LCOV - code coverage report
Current view: top level - src/torque/ls - json-parser.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 84 84.5 %
Date: 2019-04-17 Functions: 17 20 85.0 %

          Line data    Source code
       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             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : namespace torque {
      13             : 
      14             : template <>
      15             : V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<ls::JsonValue>::id =
      16             :     ParseResultTypeId::kJsonValue;
      17             : 
      18             : template <>
      19             : V8_EXPORT_PRIVATE const ParseResultTypeId
      20             :     ParseResultHolder<std::pair<std::string, ls::JsonValue>>::id =
      21             :         ParseResultTypeId::kJsonMember;
      22             : 
      23             : template <>
      24             : V8_EXPORT_PRIVATE const ParseResultTypeId
      25             :     ParseResultHolder<std::vector<ls::JsonValue>>::id =
      26             :         ParseResultTypeId::kStdVectorOfJsonValue;
      27             : 
      28             : template <>
      29             : V8_EXPORT_PRIVATE const ParseResultTypeId
      30             :     ParseResultHolder<std::vector<std::pair<std::string, ls::JsonValue>>>::id =
      31             :         ParseResultTypeId::kStdVectorOfJsonMember;
      32             : 
      33             : namespace ls {
      34             : 
      35             : using JsonMember = std::pair<std::string, JsonValue>;
      36             : 
      37             : template <bool value>
      38           3 : base::Optional<ParseResult> MakeBoolLiteral(
      39             :     ParseResultIterator* child_results) {
      40           6 :   return ParseResult{JsonValue::From(value)};
      41             : }
      42             : 
      43           1 : base::Optional<ParseResult> MakeNullLiteral(
      44             :     ParseResultIterator* child_results) {
      45           1 :   JsonValue result;
      46           1 :   result.tag = JsonValue::IS_NULL;
      47           3 :   return ParseResult{std::move(result)};
      48             : }
      49             : 
      50           6 : base::Optional<ParseResult> MakeNumberLiteral(
      51             :     ParseResultIterator* child_results) {
      52           6 :   auto number = child_results->NextAs<std::string>();
      53          12 :   double d = std::stod(number.c_str());
      54          18 :   return ParseResult{JsonValue::From(d)};
      55             : }
      56             : 
      57           5 : base::Optional<ParseResult> MakeStringLiteral(
      58             :     ParseResultIterator* child_results) {
      59           5 :   std::string literal = child_results->NextAs<std::string>();
      60          20 :   return ParseResult{JsonValue::From(StringLiteralUnquote(literal))};
      61             : }
      62             : 
      63           4 : base::Optional<ParseResult> MakeArray(ParseResultIterator* child_results) {
      64           8 :   JsonArray array = child_results->NextAs<JsonArray>();
      65          12 :   return ParseResult{JsonValue::From(std::move(array))};
      66             : }
      67             : 
      68           5 : base::Optional<ParseResult> MakeMember(ParseResultIterator* child_results) {
      69           5 :   JsonMember result;
      70           5 :   std::string key = child_results->NextAs<std::string>();
      71          10 :   result.first = StringLiteralUnquote(key);
      72           5 :   result.second = child_results->NextAs<JsonValue>();
      73          15 :   return ParseResult{std::move(result)};
      74             : }
      75             : 
      76           4 : base::Optional<ParseResult> MakeObject(ParseResultIterator* child_results) {
      77             :   using MemberList = std::vector<JsonMember>;
      78           8 :   MemberList members = child_results->NextAs<MemberList>();
      79             : 
      80             :   JsonObject object;
      81           9 :   for (auto& member : members) object.insert(std::move(member));
      82             : 
      83          16 :   return ParseResult{JsonValue::From(std::move(object))};
      84             : }
      85             : 
      86          28 : class JsonGrammar : public Grammar {
      87          64 :   static bool MatchWhitespace(InputPosition* pos) {
      88          81 :     while (MatchChar(std::isspace, pos)) {
      89             :     }
      90          64 :     return true;
      91             :   }
      92             : 
      93          51 :   static bool MatchStringLiteral(InputPosition* pos) {
      94          51 :     InputPosition current = *pos;
      95          51 :     if (MatchString("\"", &current)) {
      96          45 :       while (
      97          90 :           (MatchString("\\", &current) && MatchAnyChar(&current)) ||
      98          90 :           MatchChar([](char c) { return c != '"' && c != '\n'; }, &current)) {
      99             :       }
     100          10 :       if (MatchString("\"", &current)) {
     101          10 :         *pos = current;
     102          10 :         return true;
     103             :       }
     104             :     }
     105          41 :     current = *pos;
     106          41 :     if (MatchString("'", &current)) {
     107           0 :       while (
     108           0 :           (MatchString("\\", &current) && MatchAnyChar(&current)) ||
     109           0 :           MatchChar([](char c) { return c != '\'' && c != '\n'; }, &current)) {
     110             :       }
     111           0 :       if (MatchString("'", &current)) {
     112           0 :         *pos = current;
     113           0 :         return true;
     114             :       }
     115             :     }
     116             :     return false;
     117             :   }
     118             : 
     119          51 :   static bool MatchHexLiteral(InputPosition* pos) {
     120          51 :     InputPosition current = *pos;
     121          51 :     MatchString("-", &current);
     122          51 :     if (MatchString("0x", &current) && MatchChar(std::isxdigit, &current)) {
     123           0 :       while (MatchChar(std::isxdigit, &current)) {
     124             :       }
     125           0 :       *pos = current;
     126           0 :       return true;
     127             :     }
     128             :     return false;
     129             :   }
     130             : 
     131          51 :   static bool MatchDecimalLiteral(InputPosition* pos) {
     132          51 :     InputPosition current = *pos;
     133             :     bool found_digit = false;
     134          51 :     MatchString("-", &current);
     135          58 :     while (MatchChar(std::isdigit, &current)) found_digit = true;
     136          51 :     MatchString(".", &current);
     137          51 :     while (MatchChar(std::isdigit, &current)) found_digit = true;
     138          51 :     if (!found_digit) return false;
     139           6 :     *pos = current;
     140          18 :     if ((MatchString("e", &current) || MatchString("E", &current)) &&
     141           6 :         (MatchString("+", &current) || MatchString("-", &current) || true) &&
     142           0 :         MatchChar(std::isdigit, &current)) {
     143           0 :       while (MatchChar(std::isdigit, &current)) {
     144             :       }
     145           0 :       *pos = current;
     146           0 :       return true;
     147             :     }
     148             :     return true;
     149             :   }
     150             : 
     151             :  public:
     152         868 :   JsonGrammar() : Grammar(&file) { SetWhitespace(MatchWhitespace); }
     153             : 
     154          28 :   Symbol trueLiteral = {Rule({Token("true")})};
     155          28 :   Symbol falseLiteral = {Rule({Token("false")})};
     156          28 :   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          42 :   Symbol* elementList = List<JsonValue>(&value, Token(","));
     166          70 :   Symbol array = {Rule({Token("["), elementList, Token("]")})};
     167             : 
     168          28 :   Symbol member = {Rule({&stringLiteral, Token(":"), &value}, MakeMember)};
     169          28 :   Symbol* memberList = List<JsonMember>(&member, Token(","));
     170          70 :   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             : 
     183          14 : JsonParserResult 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          14 :   SourceFileMap::Scope source_map_scope;
     187          28 :   CurrentSourceFile::Scope unkown_file(SourceFileMap::AddSource("<json>"));
     188             : 
     189             :   JsonParserResult result;
     190             :   try {
     191          38 :     result.value = (*JsonGrammar().Parse(input)).Cast<JsonValue>();
     192           4 :   } catch (TorqueError& error) {
     193             :     result.error = error;
     194             :   }
     195          14 :   return result;
     196             : }
     197             : 
     198             : }  // namespace ls
     199             : }  // namespace torque
     200             : }  // namespace internal
     201       59454 : }  // namespace v8

Generated by: LCOV version 1.10