1
1
#include " GraphQLGrammar.h"
2
2
3
+ #include < tao/pegtl/contrib/unescape.hpp>
4
+
3
5
#include < graphqlparser/Ast.h>
4
6
5
7
#include < memory>
6
- #include < iostream>
7
8
#include < stack>
8
9
#include < tuple>
9
- # include < codecvt >
10
- #include < locale >
10
+
11
+ #include < cstdio >
11
12
12
13
namespace facebook {
13
14
namespace graphql {
@@ -26,7 +27,7 @@ struct parser_state
26
27
std::unique_ptr<ast::SelectionSet> selectionSet;
27
28
28
29
std::string enumValue;
29
- std::ostringstream stringBuffer;
30
+ std::string stringBuffer;
30
31
31
32
std::unique_ptr<ast::Name> name;
32
33
std::unique_ptr<ast::Name> aliasName;
@@ -222,16 +223,10 @@ struct build_ast<grammar::escaped_unicode>
222
223
template <typename _Input>
223
224
static void apply (const _Input& in, parser_state& state)
224
225
{
225
- std::wstring source;
226
- std::wstring_convert<std::codecvt_utf8_utf16<wchar_t >, wchar_t > utf8conv;
227
- std::istringstream encoded (in.string ());
228
- uint32_t wch;
229
-
230
- // Skip past the first 'u' character
231
- encoded.seekg (1 );
232
- encoded >> std::hex >> wch;
233
- source.push_back (static_cast <wchar_t >(wch));
234
- state.stringBuffer << utf8conv.to_bytes (source);
226
+ if (!unescape::utf8_append_utf32 (state.stringBuffer , unescape::unhex_string<uint32_t >(in.begin () + 1 , in.end ())))
227
+ {
228
+ throw parse_error (" invalid escaped unicode code point" , in);
229
+ }
235
230
}
236
231
};
237
232
@@ -246,40 +241,39 @@ struct build_ast<grammar::escaped_char>
246
241
switch (ch)
247
242
{
248
243
case ' "' :
249
- state.stringBuffer << ' "' ;
244
+ state.stringBuffer += ' "' ;
250
245
break ;
251
246
252
247
case ' \\ ' :
253
- state.stringBuffer << ' \\ ' ;
248
+ state.stringBuffer += ' \\ ' ;
254
249
break ;
255
250
256
251
case ' /' :
257
- state.stringBuffer << ' /' ;
252
+ state.stringBuffer += ' /' ;
258
253
break ;
259
254
260
255
case ' b' :
261
- state.stringBuffer << ' \b ' ;
256
+ state.stringBuffer += ' \b ' ;
262
257
break ;
263
258
264
259
case ' f' :
265
- state.stringBuffer << ' \f ' ;
260
+ state.stringBuffer += ' \f ' ;
266
261
break ;
267
262
268
263
case ' n' :
269
- state.stringBuffer << ' \n ' ;
264
+ state.stringBuffer += ' \n ' ;
270
265
break ;
271
266
272
267
case ' r' :
273
- state.stringBuffer << ' \r ' ;
268
+ state.stringBuffer += ' \r ' ;
274
269
break ;
275
270
276
271
case ' t' :
277
- state.stringBuffer << ' \t ' ;
272
+ state.stringBuffer += ' \t ' ;
278
273
break ;
279
274
280
275
default :
281
- state.stringBuffer << ' \\ ' << ch;
282
- break ;
276
+ throw parse_error (" invalid escaped character sequence" , in);
283
277
}
284
278
}
285
279
};
@@ -290,7 +284,7 @@ struct build_ast<grammar::string_quote_character>
290
284
template <typename _Input>
291
285
static void apply (const _Input& in, parser_state& state)
292
286
{
293
- state.stringBuffer << in.peek_char ();
287
+ state.stringBuffer += in.peek_char ();
294
288
}
295
289
};
296
290
@@ -301,7 +295,7 @@ struct build_ast<grammar::block_escape_sequence>
301
295
template <typename _Input>
302
296
static void apply (const _Input& in, parser_state& state)
303
297
{
304
- state.stringBuffer << R"bq( """)bq" ;
298
+ state.stringBuffer . append ( R"bq( """)bq" ) ;
305
299
}
306
300
};
307
301
@@ -311,7 +305,7 @@ struct build_ast<grammar::block_quote_character>
311
305
template <typename _Input>
312
306
static void apply (const _Input& in, parser_state& state)
313
307
{
314
- state.stringBuffer << in.peek_char ();
308
+ state.stringBuffer += in.peek_char ();
315
309
}
316
310
};
317
311
@@ -321,13 +315,12 @@ struct build_ast<grammar::string_value>
321
315
template <typename _Input>
322
316
static void apply (const _Input& in, parser_state& state)
323
317
{
324
- auto parsedValue = state.stringBuffer . str ( );
318
+ auto parsedValue = std::move ( state.stringBuffer );
325
319
std::unique_ptr<char [], ast::CDeleter> value (reinterpret_cast <char *>(malloc (parsedValue.size () + 1 )));
326
320
327
321
memmove (value.get (), parsedValue.data (), parsedValue.size ());
328
322
value[parsedValue.size ()] = ' \0 ' ;
329
323
state.value .push (std::unique_ptr<ast::Value>(new ast::StringValue (get_location (in), value.release ())));
330
- state.stringBuffer .str (" " );
331
324
}
332
325
};
333
326
@@ -1096,11 +1089,23 @@ std::unique_ptr<ast::Node> parseString(const char* text)
1096
1089
return std::unique_ptr<ast::Node>(document.release ());
1097
1090
}
1098
1091
1099
- std::unique_ptr<ast::Node> parseFile (FILE* file)
1092
+ std::unique_ptr<ast::Node> parseFile (const char * fileName)
1093
+ {
1094
+ parser_state state;
1095
+ std::unique_ptr<ast::Document> document;
1096
+ file_input<> in (fileName);
1097
+
1098
+ state.document = &document;
1099
+ parse<grammar::document, build_ast>(std::move (in), std::move (state));
1100
+
1101
+ return std::unique_ptr<ast::Node>(document.release ());
1102
+ }
1103
+
1104
+ std::unique_ptr<ast::Node> parseInput ()
1100
1105
{
1101
1106
parser_state state;
1102
1107
std::unique_ptr<ast::Document> document;
1103
- file_input <> in (file , " GraphQL" );
1108
+ cstream_input <> in (stdin, 1024 * 1024 , " GraphQL" );
1104
1109
1105
1110
state.document = &document;
1106
1111
parse<grammar::document, build_ast>(std::move (in), std::move (state));
0 commit comments