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("\"", ¤t)) {
96 45 : while (
97 90 : (MatchString("\\", ¤t) && MatchAnyChar(¤t)) ||
98 90 : MatchChar([](char c) { return c != '"' && c != '\n'; }, ¤t)) {
99 : }
100 10 : if (MatchString("\"", ¤t)) {
101 10 : *pos = current;
102 10 : return true;
103 : }
104 : }
105 41 : current = *pos;
106 41 : if (MatchString("'", ¤t)) {
107 0 : while (
108 0 : (MatchString("\\", ¤t) && MatchAnyChar(¤t)) ||
109 0 : MatchChar([](char c) { return c != '\'' && c != '\n'; }, ¤t)) {
110 : }
111 0 : if (MatchString("'", ¤t)) {
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("-", ¤t);
122 51 : if (MatchString("0x", ¤t) && MatchChar(std::isxdigit, ¤t)) {
123 0 : while (MatchChar(std::isxdigit, ¤t)) {
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("-", ¤t);
135 58 : while (MatchChar(std::isdigit, ¤t)) found_digit = true;
136 51 : MatchString(".", ¤t);
137 51 : while (MatchChar(std::isdigit, ¤t)) found_digit = true;
138 51 : if (!found_digit) return false;
139 6 : *pos = current;
140 18 : if ((MatchString("e", ¤t) || MatchString("E", ¤t)) &&
141 6 : (MatchString("+", ¤t) || MatchString("-", ¤t) || true) &&
142 0 : MatchChar(std::isdigit, ¤t)) {
143 0 : while (MatchChar(std::isdigit, ¤t)) {
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
|