~zorba-coders/zorba/bug-1189803

« back to all changes in this revision

Viewing changes to src/util/json_parser.cpp

  • Committer: Luis Rodriguez Gonzalez
  • Date: 2013-09-19 14:00:22 UTC
  • mfrom: (11612.1.19 lp_zorba)
  • Revision ID: kuraru@gmail.com-20130919140022-tw41ekb6ey16xbxi
MergedĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
234
234
  return false;
235
235
}
236
236
 
237
 
bool lexer::next( token *t ) {
 
237
bool lexer::next( token *t, bool throw_exceptions ) {
238
238
  while ( true ) {
239
239
    set_cur_loc();
240
240
    char c;
253
253
        //
254
254
        location::line_type const quote_line = cur_loc_.line();
255
255
        location::column_type const quote_col = cur_loc_.column();
256
 
        parse_string( &t->value_ );
 
256
        if ( !parse_string( &t->value_, throw_exceptions ) )
 
257
          return false;
257
258
        t->type_ = token::string;
258
259
        t->loc_.set(
259
260
          cur_loc_.file(), quote_line, quote_col, prev_line_, prev_col_
270
271
      case '6':
271
272
      case '7':
272
273
      case '8':
273
 
      case '9':
274
 
        t->numeric_type_ = parse_number( c, &t->value_ );
 
274
      case '9': {
 
275
        token::numeric_type nt;
 
276
        if ( !(nt = parse_number( c, &t->value_, throw_exceptions )) )
 
277
          return false;
 
278
        t->numeric_type_ = nt;
275
279
        t->type_ = token::number;
276
280
        set_loc_range( &t->loc_ );
277
281
        return true;
278
 
      case 'f': // false
279
 
      case 'n': // null
280
 
      case 't': // true
281
 
        t->type_ = parse_literal( c, &t->value_ );
 
282
      }
 
283
      case 'f':   // false
 
284
      case 'n':   // null
 
285
      case 't': { // true
 
286
        token::type tt;
 
287
        if ( !(tt = parse_literal( c, &t->value_, throw_exceptions )) )
 
288
          return false;
 
289
        t->type_ = tt;
282
290
        set_loc_range( &t->loc_ );
283
291
        return true;
 
292
      }
284
293
      case '[':
285
294
      case '{':
286
295
      case ']':
291
300
        t->loc_ = cur_loc_;
292
301
        return true;
293
302
      default:
294
 
        throw illegal_character( cur_loc_, c );
 
303
        if ( throw_exceptions )
 
304
          throw illegal_character( cur_loc_, c );
 
305
        return false;
295
306
    }
296
307
  } // while
297
308
}
298
309
 
299
 
unicode::code_point lexer::parse_codepoint() {
 
310
bool lexer::parse_codepoint( unicode::code_point *result,
 
311
                             bool throw_exceptions ) {
300
312
  static char const hex_digits[] = "0123456789ABCDEF";
301
313
 
302
314
  char c;
307
319
    unicode::code_point cp = 0;
308
320
    for ( int i = 1; i <= 4; ++i ) {
309
321
      if ( !get_char( &c ) )
310
 
        throw illegal_codepoint( set_cur_loc_end( false ), cp_string );
 
322
        goto error_set_cur_loc_end_false;
311
323
      cp_string += c;
312
324
      if ( !ascii::is_xdigit( c ) )
313
 
        throw illegal_codepoint( set_cur_loc_end(), cp_string );
 
325
        goto error_set_cur_loc_end;
314
326
      c = ascii::to_upper( c );
315
327
      char const *const p = std::strchr( hex_digits, c );
316
328
      assert( p );
319
331
 
320
332
    if ( unicode::is_high_surrogate( cp ) ) {
321
333
      if ( high_surrogate )
322
 
        throw illegal_codepoint( set_cur_loc_end(), cp_string );
 
334
        goto error_set_cur_loc_end;
323
335
      //
324
336
      // It's easier to parse the \u for the low surrogate here rather than
325
337
      // trying to manage state in parse_string().
326
338
      //
327
339
      if ( !get_char( &c ) )
328
 
        throw illegal_codepoint( set_cur_loc_end( false ), cp_string );
 
340
        goto error_set_cur_loc_end_false;
329
341
      cp_string += c;
330
 
      if ( c != '\\' )
331
 
        throw illegal_codepoint( set_cur_loc_end(), cp_string );
332
 
      if ( !get_char( &c ) )
333
 
        throw illegal_codepoint( set_cur_loc_end(), cp_string );
 
342
      if ( c != '\\' || !get_char( &c ) )
 
343
        goto error_set_cur_loc_end;
334
344
      cp_string += c;
335
345
      if ( c != 'u' )
336
 
        throw illegal_codepoint( set_cur_loc_end(), cp_string );
 
346
        goto error_set_cur_loc_end;
337
347
 
338
348
      high_surrogate = cp;
339
349
      continue;
340
350
    }
341
351
    if ( unicode::is_low_surrogate( cp ) ) {
342
352
      if ( !high_surrogate )
343
 
        throw illegal_codepoint( set_cur_loc_end(), cp_string );
344
 
      return unicode::convert_surrogate( high_surrogate, cp );
 
353
        goto error_set_cur_loc_end;
 
354
      *result = unicode::convert_surrogate( high_surrogate, cp );
 
355
      return true;
345
356
    }
346
357
    if ( high_surrogate )
347
 
      throw illegal_codepoint( set_cur_loc_end(), cp_string );
348
 
 
349
 
    return cp;
350
 
  }
 
358
      goto error_set_cur_loc_end;
 
359
 
 
360
    *result = cp;
 
361
    return true;
 
362
  } // while
 
363
 
 
364
error_set_cur_loc_end:
 
365
  if ( throw_exceptions )
 
366
    throw illegal_codepoint( set_cur_loc_end(), cp_string );
 
367
  return false;
 
368
 
 
369
error_set_cur_loc_end_false:
 
370
  if ( throw_exceptions )
 
371
    throw illegal_codepoint( set_cur_loc_end( false ), cp_string );
 
372
  return false;
351
373
}
352
374
 
353
 
token::type lexer::parse_literal( char first_c, token::value_type *value ) {
 
375
token::type lexer::parse_literal( char first_c, token::value_type *value,
 
376
                                  bool throw_exceptions ) {
354
377
  static token::value_type const false_value( "false" );
355
378
  static token::value_type const null_value ( "null"  );
356
379
  static token::value_type const true_value ( "true"  );
366
389
  char c;
367
390
  for ( char const *s = value->c_str(); *++s; ) {
368
391
    if ( !get_char( &c ) )
369
 
      throw illegal_literal( set_cur_loc_end( false ) );
 
392
      goto error_set_cur_loc_end_false;
370
393
    if ( c != *s )
371
 
      throw illegal_literal( set_cur_loc_end() );
 
394
      goto error_set_cur_loc_end;
372
395
  }
373
396
  if ( peek_char( &c ) && (ascii::is_alnum( c ) || c == '_') )
 
397
    goto error_set_cur_loc_end_false;
 
398
 
 
399
  return tt;
 
400
 
 
401
error_set_cur_loc_end:
 
402
  if ( throw_exceptions )
 
403
    throw illegal_literal( set_cur_loc_end() );
 
404
  return token::none;
 
405
 
 
406
error_set_cur_loc_end_false:
 
407
  if ( throw_exceptions )
374
408
    throw illegal_literal( set_cur_loc_end( false ) );
375
 
 
376
 
  return tt;
 
409
  return token::none;
377
410
}
378
411
 
379
412
token::numeric_type lexer::parse_number( char first_c,
380
 
                                         token::value_type *value ) {
 
413
                                         token::value_type *value,
 
414
                                         bool throw_exceptions ) {
 
415
  token::numeric_type numeric_type;
 
416
 
381
417
  value->clear();
382
418
 
383
419
  // <number> ::= [-] <int> [<frac>] [<exp>]
385
421
  if ( c == '-' ) {
386
422
    *value += c;
387
423
    if ( !get_char( &c ) )
388
 
      throw illegal_number( set_cur_loc_end( false ) );
 
424
      goto error_set_cur_loc_end_false;
389
425
  }
390
426
 
391
427
  // <int> := '0' | <1-9> <digit>*
392
428
  if ( !ascii::is_digit( c ) )
393
 
    throw illegal_number( set_cur_loc_end() );
 
429
    goto error_set_cur_loc_end;
394
430
  *value += c;
395
 
  token::numeric_type numeric_type = token::integer;
 
431
  numeric_type = token::integer;
396
432
  if ( c == '0' ) {
397
433
    if ( !peek_char( &c ) )
398
434
      goto done;
 
435
    if ( ascii::is_alnum( c ) )
 
436
      goto error_set_cur_loc_end_false;
399
437
  } else {
400
438
    while ( true ) {
401
439
      if ( !peek_char( &c ) )
402
440
        goto done;
403
441
      if ( ascii::is_alpha( c ) && c != 'e' && c != 'E' )
404
 
        throw illegal_number( set_cur_loc_end( false ) );
 
442
        goto error_set_cur_loc_end_false;
405
443
      if ( !ascii::is_digit( c ) )
406
444
        break;
407
445
      get_char( &c );
414
452
    get_char( &c );
415
453
    *value += c;
416
454
    if ( !get_char( &c ) )
417
 
      throw illegal_number( set_cur_loc_end( false ) );
 
455
      goto error_set_cur_loc_end_false;
418
456
    if ( !ascii::is_digit( c ) )
419
 
      throw illegal_number( set_cur_loc_end() );
 
457
      goto error_set_cur_loc_end;
420
458
    *value += c;
421
459
    numeric_type = token::decimal;
422
460
    while ( true ) {
423
461
      if ( !peek_char( &c ) )
424
462
        goto done;
425
463
      if ( ascii::is_alpha( c ) && c != 'e' && c != 'E' )
426
 
        throw illegal_number( set_cur_loc_end( false ) );
 
464
        goto error_set_cur_loc_end_false;
427
465
      if ( !ascii::is_digit( c ) )
428
466
        break;
429
467
      get_char( &c );
438
476
    get_char( &c );
439
477
    *value += c;
440
478
    if ( !get_char( &c ) )
441
 
      throw illegal_number( set_cur_loc_end( false ) );
 
479
      goto error_set_cur_loc_end_false;
442
480
    if ( c == '+' || c == '-' ) {
443
481
      *value += c;
444
482
      if ( !get_char( &c ) )
445
 
        throw illegal_number( set_cur_loc_end( false ) );
 
483
        goto error_set_cur_loc_end_false;
446
484
    }
447
485
    if ( !ascii::is_digit( c ) )
448
 
      throw illegal_number( set_cur_loc_end() );
 
486
      goto error_set_cur_loc_end;
449
487
    *value += c;
450
488
    numeric_type = token::floating_point;
451
489
    while ( true ) {
452
490
      if ( !peek_char( &c ) )
453
491
        goto done;
454
492
      if ( ascii::is_alpha( c ) )
455
 
        throw illegal_number( set_cur_loc_end( false ) );
 
493
        goto error_set_cur_loc_end_false;
456
494
      if ( !ascii::is_digit( c ) )
457
495
        break;
458
496
      get_char( &c );
462
500
 
463
501
done:
464
502
  return numeric_type;
 
503
 
 
504
error_set_cur_loc_end:
 
505
  if ( throw_exceptions )
 
506
    throw illegal_number( set_cur_loc_end() );
 
507
  return token::non_numeric;
 
508
 
 
509
error_set_cur_loc_end_false:
 
510
  if ( throw_exceptions )
 
511
    throw illegal_number( set_cur_loc_end( false ) );
 
512
  return token::non_numeric;
465
513
}
466
514
 
467
 
void lexer::parse_string( token::value_type *value ) {
 
515
bool lexer::parse_string( token::value_type *value, bool throw_exceptions ) {
468
516
  value->clear();
469
517
  bool got_backslash = false;
470
518
  location start_loc( cur_loc_ );
478
526
    set_cur_loc();
479
527
 
480
528
    char c;
481
 
    if ( !get_char( &c ) )
482
 
      throw unterminated_string( set_loc_end( &start_loc, line_, col_ ) );
 
529
    if ( !get_char( &c ) ) {
 
530
      if ( throw_exceptions )
 
531
        throw unterminated_string( set_loc_end( &start_loc, line_, col_ ) );
 
532
      return false;
 
533
    }
483
534
    if ( got_backslash ) {
484
535
      got_backslash = false;
485
536
      switch ( c ) {
503
554
        case 't':
504
555
          *value += '\t';
505
556
          break;
506
 
        case 'u':
507
 
          utf8::encode( parse_codepoint(), value );
 
557
        case 'u': {
 
558
          unicode::code_point cp;
 
559
          if ( !parse_codepoint( &cp, throw_exceptions ) )
 
560
            return false;
 
561
          utf8::encode( cp, value );
508
562
          break;
 
563
        }
509
564
        default:
510
 
          throw illegal_escape( set_cur_loc_end(), c );
 
565
          if ( throw_exceptions )
 
566
            throw illegal_escape( set_cur_loc_end(), c );
 
567
          return false;
511
568
      }
512
569
      continue;
513
570
    }
517
574
        got_backslash = true;
518
575
        break;
519
576
      case '"':
520
 
        return;
 
577
        return true;
521
578
      default:
522
579
        *value += c;
523
580
    }