ソースを参照

cmData.h/c : Initial debugging and testing of cmDataParser.

master
kpl 11年前
コミット
2e1c77f150
2個のファイルの変更126行の追加111行の削除
  1. 120
    111
      cmData.c
  2. 6
    0
      cmData.h

+ 120
- 111
cmData.c ファイルの表示

@@ -34,6 +34,9 @@ void _cmDataFreeArray( cmData_t* p )
34 34
 
35 35
 void _cmDataFree( cmData_t* p )
36 36
 {
37
+  if( p == NULL )
38
+    return;
39
+
37 40
   if( cmDataIsStruct(p) )
38 41
   {
39 42
     cmData_t* cp = p->u.child;
@@ -2391,9 +2394,12 @@ typedef struct
2391 2394
 cmDtRC_t _cmDpSyntaxErrV( cmDataParserCtx_t* c, const cmChar_t* fmt, va_list vl )
2392 2395
 {
2393 2396
   cmChar_t* s0 = NULL;
2397
+  cmChar_t* s1 = NULL;
2394 2398
   s0 = cmTsVPrintfP(s0,fmt,vl);
2395
-  cmDtRC_t rc = cmErrMsg(&c->p->err,kSyntaxErrDtRC,"Syntax error on line %i. %s",cmLexCurrentLineNumber(c->p->lexH),cmStringNullGuard(s0));
2399
+  s1 = cmMemAllocStrN(cmLexTokenText(c->p->lexH),cmLexTokenCharCount(c->p->lexH));
2400
+  cmDtRC_t rc = cmErrMsg(&c->p->err,kSyntaxErrDtRC,"Syntax error on line %i column:%i token:'%s'. %s",cmLexCurrentLineNumber(c->p->lexH),cmLexCurrentColumnNumber(c->p->lexH),s1,cmStringNullGuard(s0));
2396 2401
   cmMemFree(s0);
2402
+  cmMemFree(s1);
2397 2403
   return rc;
2398 2404
 }
2399 2405
 
@@ -2412,18 +2418,41 @@ cmDtRC_t _cmDpPopStack(  cmDataParserCtx_t* c, cmData_t** pp )
2412 2418
   if((vp = cmStackTop(c->p->stH)) == NULL )
2413 2419
     return _cmDpSyntaxErr(c,"Stack underflow.");
2414 2420
   
2421
+  if( cmStackPop(c->p->stH,1) != kOkStRC )
2422
+    return _cmDpSyntaxErr(c,"Stack pop failed.");
2423
+
2415 2424
   *pp = *(cmData_t**)vp;
2416 2425
 
2426
+  //printf("pop: %p\n",*pp);
2427
+
2417 2428
   return kOkDtRC;
2418 2429
 }
2419 2430
 
2420
-cmDtRC_t _cmDpStoreArrayEle( cmDataParserCtx_t* c, void* dp, unsigned byteCnt )
2431
+cmDtRC_t _cmDpPushStack( cmDataParserCtx_t* c, cmData_t* np )
2421 2432
 {
2422
-  char* vp = cmMemResize(char, c->cnp->u.vp, c->cnp->cnt+byteCnt);
2433
+  //printf("push:%p\n",np);
2434
+
2435
+  // store the current node
2436
+  if( cmStackPush(c->p->stH, &np, 1 ) != kOkStRC )
2437
+     return _cmDpSyntaxErr(c,"Parser stack push failed.");
2438
+ 
2439
+  return kOkDtRC;
2440
+}
2441
+
2442
+cmDtRC_t _cmDpStoreArrayEle( cmDataParserCtx_t* c, void* dp, unsigned eleByteCnt, unsigned tid )
2443
+{
2444
+  if( c->cnp->tid == kVoidPtrDtId )
2445
+    c->cnp->tid = tid;
2446
+  else
2447
+    if( c->cnp->tid != tid )
2448
+      return _cmDpSyntaxErr(c,"Mixed types were detected in an array list.");
2449
+
2450
+  unsigned newByteCnt = (c->cnp->cnt+1)*eleByteCnt;
2451
+  char* vp = cmMemResizeP(char, c->cnp->u.vp, newByteCnt);
2423 2452
   
2424
-  memcpy(vp + c->cnp->cnt,dp,byteCnt);
2453
+  memcpy(vp + c->cnp->cnt*eleByteCnt,dp,eleByteCnt);
2425 2454
   c->cnp->u.vp = vp;
2426
-  c->cnp->cnt += byteCnt;
2455
+  c->cnp->cnt += 1;
2427 2456
   
2428 2457
   c->flags = kValueExpFl | kCommaExpFl;
2429 2458
 
@@ -2432,14 +2461,17 @@ cmDtRC_t _cmDpStoreArrayEle( cmDataParserCtx_t* c, void* dp, unsigned byteCnt )
2432 2461
 
2433 2462
 cmDtRC_t _cmDataParserOpenPair( cmDataParserCtx_t* c )
2434 2463
 {
2464
+  cmDtRC_t rc = kOkDtRC;
2465
+
2435 2466
   assert( c->cnp->tid == kRecordDtId );
2436 2467
 
2468
+  // create a pair with a 'null' value which will be replaced when the pair's value is parsed
2437 2469
   cmData_t* nnp = cmDataAllocNull(NULL);
2438 2470
   cmData_t* pnp = cmDataAllocPairLabelN( c->cnp, cmLexTokenText(c->p->lexH), cmLexTokenCharCount(c->p->lexH), nnp );
2439 2471
 
2440 2472
   // store the current node
2441
-  if( cmStackPush(c->p->stH, &c->cnp, 1 ) != kOkStRC )
2442
-    return _cmDpSyntaxErr(c,"Parser stack push failed.");
2473
+  if((rc = _cmDpPushStack(c,c->cnp)) != kOkDtRC )
2474
+    return rc;
2443 2475
 
2444 2476
   // make the new pair the current node
2445 2477
   c->cnp = pnp;
@@ -2447,7 +2479,7 @@ cmDtRC_t _cmDataParserOpenPair( cmDataParserCtx_t* c )
2447 2479
   // pair openings must be followed by a colon.
2448 2480
   c->flags  = kColonExpFl;
2449 2481
  
2450
-  return kOkDtRC;
2482
+  return rc;
2451 2483
 }
2452 2484
 
2453 2485
 cmDtRC_t _cmDataParserClosePair( cmDataParserCtx_t* c )
@@ -2492,6 +2524,11 @@ cmDtRC_t _cmDpStoreValue( cmDataParserCtx_t* c, cmData_t* np, const cmChar_t* ty
2492 2524
 
2493 2525
     default:
2494 2526
       rc = _cmDpSyntaxErr(c,"A '%s' value was found outside of a valid container.",typeLabel);
2527
+
2528
+      // Free the new data node because it was not attached and will 
2529
+      // otherwise be lost
2530
+      cmDataFree(np);
2531
+      
2495 2532
   }
2496 2533
 
2497 2534
   c->flags |= kCommaExpFl;
@@ -2501,26 +2538,45 @@ cmDtRC_t _cmDpStoreValue( cmDataParserCtx_t* c, cmData_t* np, const cmChar_t* ty
2501 2538
 
2502 2539
 cmDtRC_t _cmDataParserReal( cmDataParserCtx_t* c )
2503 2540
 {
2504
-  cmDtRC_t rc  = kOkDtRC;
2505
-  double   val = cmLexTokenDouble(c->p->lexH);
2541
+  cmDtRC_t rc      = kOkDtRC;
2542
+  bool     floatFl = cmLexTokenIsSinglePrecision(c->p->lexH);
2543
+  double   dval;
2544
+  float    fval;
2506 2545
 
2507
-  if( c->cnp->tid == kVoidPtrDtId )
2508
-    rc = _cmDpStoreArrayEle(c,&val,sizeof(val));
2546
+  if( floatFl )
2547
+    fval = cmLexTokenFloat(c->p->lexH);
2509 2548
   else
2510
-    rc = _cmDpStoreValue(c,cmDataAllocDouble(NULL,val),"real");
2549
+    dval = cmLexTokenDouble(c->p->lexH);
2511 2550
 
2551
+  
2552
+  if( cmDataIsPtr(c->cnp) )
2553
+  {
2554
+    if( floatFl )
2555
+      rc = _cmDpStoreArrayEle(c,&fval,sizeof(fval),kFloatPtrDtId);
2556
+    else
2557
+      rc = _cmDpStoreArrayEle(c,&dval,sizeof(dval),kDoublePtrDtId);
2558
+  }
2559
+  else
2560
+  {
2561
+    cmData_t* np = floatFl ? cmDataAllocFloat(NULL,fval) : cmDataAllocDouble(NULL,dval);
2562
+    rc = _cmDpStoreValue(c,np,"real");
2563
+  }
2512 2564
   return rc;
2513 2565
 }
2514 2566
 
2515 2567
 cmDtRC_t _cmDataParserInt( cmDataParserCtx_t* c )
2516 2568
 {
2517
-  cmDtRC_t rc  = kOkDtRC;
2518
-  int      val = cmLexTokenInt(c->p->lexH);
2569
+  cmDtRC_t rc         = kOkDtRC;
2570
+  int      val        = cmLexTokenInt(c->p->lexH);
2571
+  bool     unsignedFl = cmLexTokenIsUnsigned(c->p->lexH);
2519 2572
 
2520
-  if( c->cnp->tid == kVoidPtrDtId )
2521
-    rc = _cmDpStoreArrayEle(c,&val,sizeof(val));
2573
+  if( cmDataIsPtr(c->cnp) )
2574
+    rc = _cmDpStoreArrayEle(c,&val,sizeof(val),unsignedFl ? kUIntPtrDtId : kIntPtrDtId);
2522 2575
   else
2523
-    rc = _cmDpStoreValue(c,cmDataAllocInt(NULL,val),"int");
2576
+  {
2577
+    cmData_t* np = unsignedFl ? cmDataAllocUInt(NULL,val) : cmDataAllocInt(NULL,val);
2578
+    rc = _cmDpStoreValue(c,np,"int");
2579
+  }
2524 2580
 
2525 2581
   return rc;
2526 2582
 }
@@ -2542,155 +2598,102 @@ cmDtRC_t _cmDataParserString( cmDataParserCtx_t* c )
2542 2598
 
2543 2599
 cmDtRC_t _cmDataParserOpenRecd( cmDataParserCtx_t* c )
2544 2600
 {
2601
+  cmDtRC_t rc = kOkDtRC;
2602
+
2545 2603
   // records are values - so we must be expecting a value
2546 2604
   if( cmIsFlag(c->flags,kValueExpFl) == false )
2547 2605
     return _cmDpSyntaxErr(c,"Unexpected '{'.");
2548 2606
 
2549 2607
   // store the current node
2550
-  if( cmStackPush(c->p->stH, &c->cnp, 1 ) != kOkStRC )
2551
-    return _cmDpSyntaxErr(c,"Parser stack push failed.");
2608
+  if((rc = _cmDpPushStack(c,c->cnp)) != kOkDtRC )
2609
+    return rc;
2552 2610
 
2553 2611
   // alloc a new record and make it the current node
2554
-  if( (c->cnp = cmDataRecdAlloc(c->cnp)) == NULL )
2612
+  if( (c->cnp = cmDataRecdAlloc(NULL)) == NULL )
2555 2613
     return _cmDpSyntaxErr(c,"'recd' allocate failed.");
2556 2614
 
2557 2615
   // new records must be followed by an id token.
2558 2616
   c->flags = kIdExpFl;
2559 2617
 
2560
-  return kOkDtRC;
2618
+  return rc;
2561 2619
 }
2562 2620
 
2563
-cmDtRC_t _cmDataParserCloseRecd( cmDataParserCtx_t* c )
2621
+cmDtRC_t _cmDataParserCloseContainer( cmDataParserCtx_t* c, const cmChar_t* typeLabelStr )
2564 2622
 {
2565 2623
   cmDtRC_t rc;
2566 2624
 
2567
-  // make the parent node the new curren node
2625
+  cmData_t* np = c->cnp;
2626
+
2627
+  // make the parent node the new current node
2568 2628
   if((rc = _cmDpPopStack(c,&c->cnp)) != kOkDtRC )
2569 2629
     return rc;
2570 2630
 
2571
-  switch( c->cnp->tid )
2572
-  {
2573
-    case kPairDtId:
2574
-      // if the parent node is a pair then close it
2575
-      rc = _cmDataParserClosePair(c);
2576
-      break;
2577
-
2578
-    case kListDtId:
2579
-      // parent node is a list - so expect another value
2580
-      c->flags = kValueExpFl;
2581
-      break;
2631
+  return _cmDpStoreValue(c,np,typeLabelStr);
2632
+}
2582 2633
 
2583
-    default:
2584
-      return _cmDpSyntaxErr(c,"'records' may only be contained in other records or heterogenous arrays.");
2585
-      
2586
-  }
2634
+cmDtRC_t _cmDataParserCloseRecd( cmDataParserCtx_t* c )
2635
+{
2636
+  assert( c->cnp->tid == kRecordDtId );
2587 2637
 
2588
-  c->flags |= kCommaExpFl;
2589
-    
2590
-  return rc;
2638
+  return _cmDataParserCloseContainer(c,"record");
2591 2639
 }
2592 2640
 
2593 2641
 cmDtRC_t _cmDataParserOpenList( cmDataParserCtx_t* c )
2594 2642
 {
2643
+  cmDtRC_t rc = kOkDtRC;
2644
+
2595 2645
   // lists are values - so we must be expecting a value
2596 2646
   if( cmIsFlag(c->flags,kValueExpFl) == false )
2597 2647
     return _cmDpSyntaxErr(c,"Unexpected '('.");
2598 2648
 
2599 2649
   // store the current node
2600
-  if( cmStackPush(c->p->stH, &c->cnp, 1 ) != kOkStRC )
2601
-    return _cmDpSyntaxErr(c,"Parser stack push failed.");
2650
+  if((rc = _cmDpPushStack(c,c->cnp)) != kOkDtRC )
2651
+    return rc;
2602 2652
 
2603 2653
   // create a new list
2604
-  if( (c->cnp = cmDataListAlloc(c->cnp)) == NULL )
2654
+  if( (c->cnp = cmDataListAlloc(NULL)) == NULL )
2605 2655
     return _cmDpSyntaxErr(c,"'list' allocate failed.");
2606 2656
 
2607 2657
   // new lists must be followed by a value
2608 2658
   c->flags = kValueExpFl;
2609 2659
 
2610
-  return kOkDtRC;
2660
+  return rc;
2611 2661
 }
2612 2662
 
2613 2663
 cmDtRC_t _cmDataParserCloseList( cmDataParserCtx_t* c )
2614 2664
 {
2615
-  cmDtRC_t rc;
2616
-
2617
-  // make the list's parent the current node
2618
-  if((rc = _cmDpPopStack(c,&c->cnp)) != kOkDtRC )
2619
-    return rc;
2620
-
2621
-  switch( c->cnp->tid )
2622
-  {
2623
-    case kPairDtId:
2624
-      // if the list's parent is a pair then close it
2625
-      rc = _cmDataParserClosePair(c);
2626
-      break;
2627
-
2628
-    case kListDtId:
2629
-      // the list's parent is another list so expect a value
2630
-      c->flags = kValueExpFl;
2631
-      break;
2632
-
2633
-    default:
2634
-      return _cmDpSyntaxErr(c,"'lists' may only be contained in other records or lists.");
2635
-      
2636
-  }
2637
-
2638
-  c->flags |= kCommaExpFl;
2639
-    
2640
-  return rc;
2665
+  assert( c->cnp->tid == kListDtId );
2666
+  return _cmDataParserCloseContainer(c,"list");
2641 2667
 }
2642 2668
 
2643 2669
 cmDtRC_t _cmDataParserOpenArray( cmDataParserCtx_t* c )
2644 2670
 {
2671
+  cmDtRC_t rc = kOkDtRC;
2645 2672
 
2646 2673
   // arrays are values - so we must be expecting a value
2647 2674
   if( cmIsFlag(c->flags,kValueExpFl) == false )
2648 2675
     return _cmDpSyntaxErr(c,"Unexpected '('.");
2649 2676
 
2650 2677
   // store the current node
2651
-  if( cmStackPush(c->p->stH, &c->cnp, 1 ) != kOkStRC )
2652
-    return _cmDpSyntaxErr(c,"Parser stack push failed.");
2678
+  if((rc = _cmDpPushStack(c,c->cnp)) != kOkDtRC )
2679
+    return rc;
2653 2680
 
2654 2681
   // create a new array
2655
-  if( (c->cnp = cmDataSetVoidAllocPtr(c->cnp, NULL, 0 )) == NULL )
2682
+  if( (c->cnp = cmDataVoidAllocPtr(NULL, NULL, 0 )) == NULL )
2656 2683
     return _cmDpSyntaxErr(c,"'array' allocate failed.");
2657 2684
 
2658 2685
   // new arrays must be followed by a value
2659 2686
   c->flags = kValueExpFl;
2660 2687
 
2661
-  return kOkDtRC;
2688
+  return rc;
2662 2689
 
2663 2690
 }
2664 2691
 
2665 2692
 cmDtRC_t _cmDataParserCloseArray( cmDataParserCtx_t* c )
2666 2693
 {
2667
-  cmDtRC_t rc;
2668
-  
2669
-  // make the arrays parent the current node
2670
-  if((rc = _cmDpPopStack(c,&c->cnp)) != kOkDtRC )
2671
-    return rc;
2694
+  assert( cmDataIsPtr(c->cnp) );
2672 2695
 
2673
-  switch( c->cnp->tid )
2674
-  {
2675
-    
2676
-    case kPairDtId:
2677
-      // the arrays parent is a pair - so close it
2678
-      rc = _cmDataParserClosePair(c);
2679
-      break;
2680
-      
2681
-    case kListDtId:
2682
-      // the arrays parent is a list - so expect a value
2683
-      c->flags = kValueExpFl;
2684
-      break;
2685
-
2686
-    default:
2687
-      return _cmDpSyntaxErr(c,"'arrays' may only be contained in other records or lists.");
2688
-      
2689
-  }
2690
-
2691
-  c->flags |= kCommaExpFl;
2692
-    
2693
-  return rc;
2696
+  return _cmDataParserCloseContainer(c,"array");
2694 2697
 }
2695 2698
 
2696 2699
 cmDtRC_t _cmDataParserOnColon( cmDataParserCtx_t* c )
@@ -2726,17 +2729,17 @@ cmDtRC_t cmDataParserExec( cmDataParserH_t h, const cmChar_t* text, cmData_t** p
2726 2729
   cmDataParser_t*   p  = _cmDataParserHandleToPtr(h);
2727 2730
   unsigned          tokenId;
2728 2731
   cmDataParserCtx_t ctx;
2729
-
2730
-  ctx.cnp   = NULL;  // current node ptr
2732
+  cmData_t*         root = cmDataRecdAlloc(NULL);
2733
+  ctx.cnp   = root;
2731 2734
   ctx.p     = p;
2732
-  ctx.flags = kValueExpFl;
2735
+  ctx.flags = kIdExpFl;
2733 2736
 
2734 2737
   if( cmLexSetTextBuffer(p->lexH,text,strlen(text)) != kOkLexRC )
2735 2738
     return cmErrMsg(&p->err,kLexFailDtRC,"The data object lexer failed during reset.");
2736 2739
 
2737 2740
   cmStackClear(p->stH,false);
2738 2741
 
2739
-  while((tokenId = cmLexGetNextToken(p->lexH)) != kEofLexTId )
2742
+  while(rc==kOkDtRC && (tokenId = cmLexGetNextToken(p->lexH)) != kEofLexTId )
2740 2743
   {
2741 2744
     switch(tokenId)
2742 2745
     {
@@ -2745,9 +2748,6 @@ cmDtRC_t cmDataParserExec( cmDataParserH_t h, const cmChar_t* text, cmData_t** p
2745 2748
         break;
2746 2749
 
2747 2750
       case kIntLexTId:      // decimal integer
2748
-        rc = _cmDataParserInt(&ctx);
2749
-        break;
2750
-
2751 2751
       case kHexLexTId:      // hexidecimal integer
2752 2752
         rc = _cmDataParserInt(&ctx);
2753 2753
         break;
@@ -2759,7 +2759,7 @@ cmDtRC_t cmDataParserExec( cmDataParserH_t h, const cmChar_t* text, cmData_t** p
2759 2759
 
2760 2760
       case kLCurlyLexTId:    // a new record is starting
2761 2761
         rc = _cmDataParserOpenRecd(&ctx);
2762
-      break;
2762
+        break;
2763 2763
 
2764 2764
       case kRCurlyLexTId:   // the current record is finished
2765 2765
         rc = _cmDataParserCloseRecd(&ctx);
@@ -2806,7 +2806,13 @@ cmDtRC_t cmDataParserExec( cmDataParserH_t h, const cmChar_t* text, cmData_t** p
2806 2806
 
2807 2807
   if( rc == kOkDtRC )
2808 2808
     *pp = ctx.cnp;
2809
+  else
2810
+  {
2811
+    if( ctx.cnp != root )
2812
+      cmDataUnlinkAndFree(ctx.cnp);
2809 2813
 
2814
+    cmDataUnlinkAndFree(root);
2815
+  }
2810 2816
   return rc;
2811 2817
 }
2812 2818
 
@@ -2913,7 +2919,10 @@ cmDtRC_t cmDataParserTest( cmCtx_t* ctx )
2913 2919
 
2914 2920
   const cmChar_t text[] =
2915 2921
   {
2916
-    "{ f0:1.23 f1:\"hey\" "
2922
+    //0         1         2         3
2923
+    //0123456789012345678901234567890123 
2924
+    "f0:1.23 f1:\"hey\" f2:( a b c ) f3:[ 0f 1f 2f ]"
2925
+    //"f0:1.23 f1:\"hey\""
2917 2926
   };
2918 2927
 
2919 2928
   cmErrSetup(&err,&ctx->rpt,"Data Parser Tester");

+ 6
- 0
cmData.h ファイルの表示

@@ -544,6 +544,12 @@ extern "C" {
544 544
   cmDtRC_t cmDataParserCreate( cmCtx_t* ctx, cmDataParserH_t* hp );
545 545
   cmDtRC_t cmDataParserDestroy( cmDataParserH_t* hp );
546 546
   bool     cmDataParserIsValid( cmDataParserH_t h );
547
+
548
+  // Parse a text representation into a 'record' type. 
549
+  // Note that the text is wrapped with implied curly braces 
550
+  // (e.g. "{ text }").  The contents of the text should therefore
551
+  // fit the record syntax (e.g. the first token should be a 
552
+  // 'pair' label.
547 553
   cmDtRC_t cmDataParserExec(   cmDataParserH_t  h, const cmChar_t* text, cmData_t** pp );
548 554
   //-----------------------------------------------------------------------------
549 555
   

読み込み中…
キャンセル
保存