Blex2.c

[目次 | 関数 | マクロ]

目次

関数一覧

マクロ一覧


   1|/**************************************************************************
   2|*  1. <<< 基本レキシカルアナライザ (BLex2) >>> 
   3|*
   4|* 
   5|*・テキストファイルを半ランダムにアクセスする手段を提供します。
   6|*・BLex2_peek でアクセスし、BLex2_next でファイル・ポインタを進めます。
   7|***************************************************************************/
   8|
   9|#include "mixer_precomp.h"
  10|// #pragma hdrstop ("mixer_precomp")
  11|
  12|#define  STDLIBS_INCLUDE
  13|#define  STDLIBS_INCLUDE_STDLIB_H
  14|#define  STDLIBS_INCLUDE_STRING_H
  15|#include  <ctype.h>
  16|#ifdef  USES_MXP_AUTOINC
  17| #include  "blex2.ah"  /* Auto include header, Look at mixer-... folder */
  18|#endif
  19|
  20|
  21|
  22|
  23| 
  24|/*-------------------------------------------------------------------------*/
  25|/* 2. <<< ◆基本処理 >>> 
  26|/*-------------------------------------------------------------------------*/
  27|
  28|
  29| 
  30|/***************************************************************************
  31|*  3. <<< [BLex2_init] 初期化する >>> 
  32|*【引数】
  33|*  ・BLex2*  m;      基本字句解析
  34|*  ・char*  fname;      読み込むファイル名、または NULL(標準入力)
  35|*  ・char*  buf;        先読みバッファ
  36|*  ・size_t buf_sizeof; buf の大きさ
  37|*【補足】
  38|*・引数の詳細は、BLex2 構造体を参考にしてください。
  39|*・fname を NULL にすると、標準入力から読み込むようになります。
  40|*【内部補足】
  41|*・BLEX2_USE_SIZEOF が定義してあるとバイナリモードになります。
  42|****************************************************************************/
  43|void  BLex2_init( BLex2* m, const char* fname, char* buf,
  44|  size_t buf_sizeof )
  45|{
  46|  #ifdef  BLEX2_USE_SIZEBUF
  47|    if ( fname == NULL )  m->fp = stdin;
  48|    else   m->fp = FileX_open( fname, "rb" );
  49|  #else
  50|    if ( fname == NULL )  m->fp = stdin;
  51|    else   m->fp = FileX_open( fname, "rt" );
  52|  #endif
  53|
  54|  m->buf = buf;
  55|  m->buf_sizeof = (int)buf_sizeof;
  56|  m->buf_n = 0;
  57|
  58|  #ifdef  BLEX2_USE_SIZEBUF
  59|    m->sizeBuf = NULL;
  60|  #endif
  61|
  62|  m->tokenType = BLex2_Token_Unknown;
  63|  m->tokenSize = 0;
  64|
  65|  #ifdef USES_ARRX
  66|    m->recBufF = false;
  67|    m->recF = false;
  68|  #endif
  69|
  70|  #ifdef _CHECKER
  71|    m->stopper = 0;
  72|  #endif
  73|
  74|  #ifdef  BLEX2_USE_PATH
  75|    strcpy( m->path, fname );
  76|  #endif
  77|}
  78|
  79|
  80| 
  81|/***************************************************************************
  82|*  4. <<< [BLex2_finish] 後始末をする >>> 
  83|*【引数】
  84|*  ・BLex2*  m;      基本字句解析
  85|****************************************************************************/
  86|void  BLex2_finish( BLex2* m )
  87|{
  88|  if ( m->fp != stdin )
  89|    fclose( m->fp );
  90|}
  91|
  92|
  93| 
  94|/***************************************************************************
  95|*  5. <<< [BLex2_setSizeBuf] サイズバッファ領域を指定する >>> 
  96|*【補足】
  97|*・改行が 0x0A オンリーの場合の、BLex2_getPos を使うときに必要です。
  98|*・サイズバッファは、バッファ m->buf の各文字がファイル中では
  99|*  何バイトであるかを格納する領域です。
 100|*・サイズは、バッファ(BLex2_init の第4引数)と同じにします。
 101|****************************************************************************/
 102|#ifdef  BLEX2_USE_SIZEBUF
 103|void  BLex2_setSizeBuf( BLex2* m, void* buf, int buf_size )
 104|{
 105|  m->sizeBuf = buf;
 106|  ASSERT( buf_size >= m->buf_sizeof );
 107|}
 108|#endif
 109|
 110|
 111|
 112| 
 113|/***************************************************************************
 114|*  6. <<< [BLex2_peek] 文字を参照する >>> 
 115|*【機能】
 116|*・現在のファイル・ポインタの位置から、offset を足した位置の文字を参照します。
 117|*【補足】
 118|*・ファイル・ポインタの位置は変わりません。
 119|*・ファイルの終端より後を参照したら EOF(-1) 文字を返します。
 120|*・日本語を調べるときは、unsigned char 型かどうかについて注意してください。
 121|****************************************************************************/
 122|int  BLex2_peek( BLex2* m, int offset )
 123|{
 124|  #ifdef _CHECKER
 125|    if ( m->stopper > 1000 )  error();
 126|    m->stopper ++;
 127|  #endif
 128|
 129|  BLex2_fillBuf( m, offset + 1 );
 130|  if ( offset >= m->buf_n )  return  EOF;
 131|  else  return  (int)(unsigned char)m->buf[offset];
 132|}
 133|
 134|
 135| 
 136|/***************************************************************************
 137|*  7. <<< [BLex2_next] ファイル・ポインタを進める >>> 
 138|****************************************************************************/
 139|void  BLex2_next( BLex2* m, int count )
 140|{
 141|  #ifdef _CHECKER
 142|    m->stopper = 0;
 143|  #endif
 144|
 145|  /* 進める量が、バッファサイズより小さい場合、*/
 146|  if ( count < m->buf_n ) {
 147|
 148|    /* 記録状態なら m->recData に記録する */
 149|    #ifdef USES_ARRX
 150|      if ( m->recF ) {
 151|        ArrX  plus;
 152|        ArrX_init( &plus, m->buf, count );
 153|        c_try {
 154|          ArrX_Buf_addCopy( &m->recBuf, &plus );
 155|        }
 156|        c_catch ( Errors_Msg*, msg ) {
 157|          if ( msg->code == ArrX_Err_Full ) {
 158|            Errors_Msg_init( msg, msg->id, BLex2_Err_RecBufFull, msg->file,
 159|              msg->line, "記録バッファが満杯です" );
 160|          }
 161|          c_throw_again();
 162|        } c_end_catch;
 163|      }
 164|    #endif /* USES_ARRX */
 165|
 166|    /* m->buf をスクロールさせる */
 167|    memmove( m->buf, m->buf + count, m->buf_n - count );
 168|    #ifdef  BLEX2_USE_SIZEBUF
 169|      memmove( m->sizeBuf, m->sizeBuf + count, m->buf_n - count );
 170|    #endif
 171|    m->buf_n -= count;
 172|  }
 173|
 174|  /* 進める量が、バッファサイズ以上の場合、*/
 175|  else {
 176|    int  i;
 177|
 178|    /* 記録状態なら m->recData に記録する */
 179|    #ifdef USES_ARRX
 180|      if ( m->recF ) {
 181|        ArrX  plus;
 182|        ArrX_init( &plus, m->buf, m->buf_n );
 183|        ArrX_Buf_addCopy( &m->recBuf, &plus );
 184|        for ( i = 0; i < count - m->buf_n; i++ )
 185|          ArrX_Buf_addChr( &m->recBuf,
 186|                         (unsigned char)fgetc( m->fp ) );
 187|      }
 188|      /* 記録状態でないならファイルポインタを進める */
 189|      else {
 190|        for ( i = 0; i < count - m->buf_n; i++ )
 191|          fgetc( m->fp );
 192|      }
 193|    #else
 194|      for ( i = 0; i < count - m->buf_n; i++ )
 195|        fgetc( m->fp );
 196|    #endif /* USES_ARRX */
 197|    m->buf_n = 0;
 198|  }
 199|}
 200|
 201|
 202| 
 203|/***************************************************************************
 204|*  8. <<< [BLex2_watch] 状態を表示する(デバッグ用) >>> 
 205|****************************************************************************/
 206|#ifdef USES_WATCH
 207|void  BLex2_watch( BLex2* m )
 208|{
 209|  int  i;
 210|
 211|  watch( 0x1001, (int)m->fp );
 212|
 213|  watch( 0x1002, m->buf_sizeof );
 214|  watch( 0x1003, m->buf_n );
 215|  for ( i = 0; i < m->buf_n; i++ )
 216|    watch( 0x2000 + i, m->buf[i] );
 217|}
 218|#endif /* USES_WATCH */
 219|
 220|
 221| 
 222|/*-------------------------------------------------------------------------*/
 223|/* 9. <<< ◆トークン処理 >>> 
 224|/*-------------------------------------------------------------------------*/
 225|
 226|
 227| 
 228|/***************************************************************************
 229|*  10. <<< [BLex2_setToken] 現在のトークンタイプを設定する >>> 
 230|*【引数】
 231|*  ・BLex2*  m;   基本字句解析
 232|*  ・int  type;      トークンタイプ ID
 233|*  ・int  size;      トークンのサイズ(バイト)
 234|*【補足】
 235|*・フェッチ・フェーズで字句解析したトークンのタイプを設定します。
 236|*  BLex2_getTokenBLex2_nextToken 関数に影響します。
 237|*・もう一度この関数を呼び出すことで、トークンタイプを変更することもできます。
 238|****************************************************************************/
 239|void  BLex2_setToken( BLex2* m, int type, int size )
 240|{
 241|  m->tokenType = type;
 242|  m->tokenSize = size;
 243|  BLex2_fillBuf( m, size );
 244|}
 245|
 246|
 247| 
 248|/***************************************************************************
 249|*  11. <<< [BLex2_getToken] トークン文字列を取得する >>> 
 250|*【引数】
 251|*  ・BLex2*  m;   基本字句解析
 252|*  ・char*  s;       トークン文字列を格納する先頭アドレス
 253|*  ・int   s_size;    s の領域のサイズ
 254|****************************************************************************/
 255|void  BLex2_getToken( BLex2* m, char* s, int s_size )
 256|{
 257|  int  size = ( m->tokenSize < s_size  ? m->tokenSize : s_size - 1 );
 258|
 259|  BLex2_fillBuf( m, size );
 260|  memcpy( s, m->buf, size );
 261|  s[size] = '\0';
 262|}
 263|
 264|
 265| 
 266|/***************************************************************************
 267|*  12. <<< [BLex2_nextToken] ファイルポインタを次のトークンに進める >>> 
 268|*【引数】
 269|*  ・BLex2*  m;   基本字句解析
 270|*【補足】
 271|*・BLex2_setToken 関数で設定したトークンのサイズだけファイルポインタを進めます。
 272|****************************************************************************/
 273|void  BLex2_nextToken( BLex2* m )
 274|{
 275|  BLex2_next( m, m->tokenSize );
 276|}
 277|
 278|
 279| 
 280|/*-------------------------------------------------------------------------*/
 281|/* 13. <<< ◆ファイル・ポインタを進める >>> 
 282|/*-------------------------------------------------------------------------*/
 283|
 284|
 285| 
 286|/****************************************************************************
 287|*  14. <<< [BLex2_reset] ファイル・ポインタをファイルの先頭へ戻す >>> 
 288|****************************************************************************/
 289|void  BLex2_reset( BLex2* m )
 290|{
 291|  #ifdef _CHECKER
 292|    m->stopper = 0;
 293|  #endif
 294|
 295|  fseek( m->fp, 0L, SEEK_SET );
 296|
 297|  m->buf_n = 0;
 298|}
 299|
 300|
 301| 
 302|/*******************************************************************
 303|*  15. <<< [BLex2_skipSpcTab] 空白、タブをスキップする >>> 
 304|*  ポインタを移動します
 305|*    返り値 : 改行数
 306|*  条件:バッファの大きさは1以上
 307|*******************************************************************/
 308|int  BLex2_skipSpcTab( BLex2* m )
 309|{
 310|  int  line = 0;
 311|  int  c;
 312|
 313|  for(;;) {
 314|    c = BLex2_peek( m, 0 );
 315|    if ( c == '\n' ) {
 316|      line++;
 317|      break;
 318|    }
 319|    if ( ! isspace( c ) )
 320|      break;
 321|    BLex2_next( m, 1 );
 322|  }
 323|  return  line;
 324|}
 325|
 326|
 327| 
 328|/*******************************************************************
 329|*  16. <<< [BLex2_skipSpcTabRet] 空白、タブ、改行をスキップする >>> 
 330|*【引数】
 331|*  ・BLex2*  m;         基本字句解析
 332|*  ・char*  返り値;        スキップした行数
 333|*******************************************************************/
 334|int  BLex2_skipSpcTabRet( BLex2* m )
 335|{
 336|  int  line = 0;
 337|  int  c;
 338|
 339|  for(;;) {
 340|    c = BLex2_peek( m, 0 );
 341|    if ( c == '\n' )
 342|      line++;
 343|    if ( ! isspace( c ) )
 344|      break;
 345|    BLex2_next( m, 1 );
 346|  }
 347|  return  line;
 348|}
 349|
 350|
 351| 
 352|/***************************************************************************
 353|*  17. <<< [BLex2_nextLine] 次の行までファイル・ポインタを進める >>> 
 354|****************************************************************************/
 355|void  BLex2_nextLine( BLex2* m )
 356|{
 357|  int  c;
 358|
 359|  while ( (c= BLex2_peek( m, 0 )) != '\n'  && c!='\r'  && c!=EOF )
 360|    BLex2_next( m, 1 );
 361|  while ( (c= BLex2_peek( m, 0 )) == '\n'  || c=='\r' )
 362|    BLex2_next( m, 1 );
 363|}
 364|
 365|
 366| 
 367|/***************************************************************************
 368|*  18. <<< [BLex2_nextFor] キーワードに到達するまでファイル・ポインタを進める >>> 
 369|*【補足】
 370|*・BLex_strncmp( m, key ) ==0 になるまでファイル・ポインタを進めます。
 371|\・EOF に到達しても止まります。
 372|****************************************************************************/
 373|void  BLex2_nextFor( BLex2* m, char* key )
 374|{
 375|  while ( BLex2_strncmp( m, key ) != 0 ) {
 376|    if ( BLex2_peek( m, 0 ) == EOF )
 377|      break;
 378|    BLex2_next( m, 1 );
 379|  }
 380|}
 381|
 382|
 383| 
 384|/***************************************************************************
 385|*  19. <<< [BLex2_nextFor2] キーワードに到達するまでファイル・ポインタを進める >>> 
 386|*【補足】
 387|*・BLex_strcmp2( m, key, i_case ) ==0 になるまでファイル・ポインタを進めます。
 388|\・EOF に到達しても止まります。
 389|****************************************************************************/
 390|void  BLex2_nextFor2( BLex2* m, char* key, bool i_case )
 391|{
 392|  while ( BLex2_strncmpEx( m, key, i_case ) != 0 ) {
 393|    if ( BLex2_peek( m, 0 ) == EOF )
 394|      break;
 395|    BLex2_next( m, 1 );
 396|  }
 397|}
 398|
 399|
 400| 
 401|/**************************************************************************
 402|*  20. <<< [BLex2_getPos] 現在のファイルアドレスを取得する >>> 
 403|*【補足】
 404|*・改行が 0x0A オンリーの場合、BLEX2_USE_SIZEBUF を定義して、
 405|*  BLex2_setSizeBuf 関数を呼び出さないと、正しく動きません。
 406|**************************************************************************/
 407|void  BLex2_getPos( BLex2* m, BLex2_Pos* pos )
 408|{
 409|  char*  buf;
 410|  char*  buf_over;
 411|
 412|  /* バッファの末尾のファイル・アドレスを取得する */
 413|  *pos = ftell( m->fp );
 414|
 415|  /* バッファの先頭へ、ファイルアドレスを戻す */
 416|  #ifdef  BLEX2_USE_SIZEBUF
 417|    buf_over = m->sizeBuf + m->buf_n;
 418|    for ( buf = m->sizeBuf; buf < buf_over; buf++ ) {
 419|      (*pos) -= *buf;
 420|    }
 421|  #else
 422|    buf_over = m->buf + m->buf_n;
 423|    for ( buf = m->buf; buf < buf_over; buf++ ) {
 424|      if ( *buf == '\n' )
 425|        (*pos) --;  /* ファイルアドレス2つ分 */
 426|      (*pos) --;
 427|    }
 428|  #endif
 429|}
 430|
 431|
 432| 
 433|/**************************************************************************
 434|*  21. <<< [BLex2_setPos] 現在のファイルアドレスを設定する >>> 
 435|**************************************************************************/
 436|void  BLex2_setPos( BLex2* m, BLex2_Pos* pos )
 437|{
 438|  fseek( m->fp, *pos, SEEK_SET );
 439|  m->buf_n = 0;
 440|BLex2_peek( m, 30 );
 441|}
 442|
 443|
 444| 
 445|/************************************************************************
 446|*  22. <<< [BLex2_Pos_cmp] ファイルアドレスを比較する >>> 
 447|*【機能】
 448|*・2つのファイルポインタの位置関係を調べます。
 449|*【引数】
 450|*  ・BLex2*  m;    基本字句解析
 451|*  ・int  返り値;  0=同じ位置、正=a が b より大きい(下)、負= b が大きい
 452|*************************************************************************/
 453|int  BLex2_Pos_cmp( BLex2_Pos* a, BLex2_Pos* b )
 454|{
 455|  if ( *a > *b )  return  1;
 456|  else if ( *a == *b )  return  0;
 457|  else  return  -1;
 458|}
 459|
 460|
 461| 
 462|/*-------------------------------------------------------------------------*/
 463|/* 23. <<< ◆現在のファイルポインタの位置からデータを比較する >>> 
 464|/*-------------------------------------------------------------------------*/
 465|
 466|
 467| 
 468|/****************************************************************************
 469|*  24. <<< [BLex2_strncmpX] 文字列と比較する >>> 
 470|*【引数】
 471|*  ・BLex2*  m;            基本字句解析
 472|*  ・char*  kword;            比較する文字列
 473|*  ・BLex_FStrnmp  pStrNCmp;  文字列比較判定関数
 474|*  ・int  返り値;             strncmp と同じ
 475|*【補足】
 476|*・kword の文字数だけ比較します。
 477|*・kword の文字数はバッファの大きさを越えないように指定します。
 478|*・strcmp 関数を用いて比較する場合、 BLex2_strncmp 関数を用います。
 479|****************************************************************************/
 480|int  BLex2_strncmpX( BLex2* m, const char* kword, BLex_FStrnmp pStrNCmp )
 481|{
 482|  #ifdef _CHECKER
 483|    if ( (int)strlen( kword ) > m->buf_sizeof )  error();
 484|  #endif
 485|
 486|  BLex2_fillBuf( m, strlen( kword ) );
 487|  return  (*pStrNCmp)( m->buf, kword, strlen( kword ) );
 488|}
 489|
 490|
 491| 
 492|/****************************************************************************
 493|*  25. <<< [BLex2_strncmpEx] 文字列と比較する(拡張)>>> 
 494|*【引数】
 495|*  ・BLex2*  m;  基本字句解析
 496|*  ・char*  kword;  キーワード(書式拡張あり)
 497|*  ・bool  i_case;  大文字小文字の区別 する=true, しない=false
 498|*  ・int 返り値;    0==マッチした, 0 以外=マッチしない
 499|*【機能】
 500|*・i_case の条件の下で、書式を用いた kword と、m のファイルポインタから
 501|*  続く文字列が、一致するかどうか調べます。
 502|*【補足】
 503|*・kword に次の書式を用いることで、あいまいな比較ができます。
 504|*   ・%h : 0個以上の空白かTAB
 505|*   ・%H : 1個以上の空白かTAB
 506|*   ・%n : %h と、0個以上の改行
 507|*   ・%* : 任意の文字列
 508|*   ・%% : % という文字
 509|*【例】
 510|*・key="<%hA%Hhref%h=%*>" は
 511|*  "<A href=index.htm>" とマッチします。
 512|*  "< A  href =index.htm>" とマッチします。
 513|*  "<Ahref=index.htm>" とマッチしません。
 514|****************************************************************************/
 515|int  BLex2_strncmpEx( BLex2* m, const char* kword, bool i_case )
 516|{
 517|  int  k = 0, p = 0, c;
 518|
 519|  for (;;) {
 520|    if ( p >= m->buf_sizeof ) {
 521|      fprintf( stderr, "BLex2_StrCmp2() : buf over" );
 522|      exit(1);
 523|    }
 524|
 525|    c = BLex2_peek( m, p );
 526|
 527|    /* BLex2 からの入力の終了 */
 528|    if ( c == EOF )
 529|      return  -1;
 530|
 531|    /* 特殊文字表現 */
 532|    if ( kword[k] == '%' ) {
 533|      switch ( kword[k+1] ) {
 534|      case 'H':  /* [%H] 1 個以上の空白と TAB をスキップ */
 535|        if ( c != ' ' && c != '\t' ) {
 536|          return false;
 537|        }
 538|        p++;
 539|        c = BLex2_peek( m, p );
 540|        /* case 'h' に続く*/
 541|
 542|      case 'h':  /* [%h] 0 個以上の空白と TAB をスキップ */
 543|        while ( c == ' ' || c == '\t' ) {
 544|          p++;
 545|          c = BLex2_peek( m, p );
 546|        }
 547|        k+=2;
 548|        break;
 549|      case 'n':  /* [%n] 0 個以上の空白と TAB と改行をスキップ */
 550|        while ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) {
 551|          p++;
 552|          c = BLex2_peek( m, p );
 553|        }
 554|        k+=2;
 555|        break;
 556|      case '*':  /* [%*] 任意の文字列をスキップ */
 557|        while ( c != kword[k+2] && c != EOF) {
 558|          p++;
 559|          c = BLex2_peek( m, p );
 560|        }
 561|        k+=3;  p++;
 562|        break;
 563|      default:  /* [% ] その他 */
 564|        k++;
 565|        break;
 566|      }
 567|    }
 568|
 569|    /* キーワード検査の完了 */
 570|    else if ( kword[k] == '\0' ) {
 571|      return  0;
 572|    }
 573|
 574|    /* (メイン)キーワードの1文字判断 */
 575|    else {
 576|      if ( c == kword[k] )  { p++; k++; }
 577|      else if ( ! i_case && toupper(c) == toupper(kword[k]) )  { p++; k++; }
 578|      else  return  -1;
 579|    }
 580|  }
 581|}
 582|
 583|
 584| 
 585|/*******************************************************************
 586|*  26. <<< [BLex2_strfind_ArrX] 文字列集合から一致する要素を返す >>> 
 587|*【機能】
 588|*・現在のファイルポインタの位置からなる文字列が、strs で指定された
 589|*  文字列配列の中のある要素と一致すれば、その要素を返します。
 590|*【引数】
 591|*  ・BLex2*  m;    基本字句解析
 592|*  ・ArrX*  strs;     文字列 char*型集合
 593|*  ・char*  返り値;   一致した要素文字列へのポインタ
 594|*                     見つからない場合は、NULL
 595|*******************************************************************/
 596|#ifdef USES_ARRX
 597|char* BLex2_strfind_ArrX( BLex2* m, ArrX* strs )
 598|{
 599|  char**  i;
 600|  char**  last = (char**)strs->last;
 601|
 602|  for ( i = (char**)strs->first; i != last; i++ )
 603|    if ( BLex2_strncmp( m, *i ) == 0 )
 604|      return  *i;
 605|  return  NULL;
 606|}
 607|#endif /* USES_ARRX */
 608|
 609|
 610| 
 611|/***************************************************************
 612|*  27. <<< [BLex2_isUnsignedDouble] unsigned double 定数か調べる >>> 
 613|*  現在ポイントしている位置から。
 614|*  ただし、符号は付かないものとする。 yacc 向き。
 615|*  空白はスキップしておくこと
 616|*  ポインタは移動しません。
 617|*  条件:バッファの大きさは2以上
 618|***************************************************************/
 619|bool  BLex2_isUnsignedDouble( BLex2* m )
 620|{
 621|  if ( isdigit( BLex2_peek( m, 0 ) ) )  return  true;
 622|  if ( BLex2_peek( m, 0 ) == '.' && isdigit( BLex2_peek( m, 1 ) ) )
 623|    return  true;
 624|  return  false;
 625|}
 626|
 627|
 628| 
 629|/***************************************************************
 630|*  28. <<< [BLex2_isDouble] double 定数か調べる >>> 
 631|*  現在ポイントしている位置から C 言語の double 定数か調べる。
 632|*  空白はスキップしておくこと
 633|*  ポインタは移動しません。
 634|*  条件:バッファの大きさは3以上
 635|***************************************************************/
 636|bool  BLex2_isDouble( BLex2* m )
 637|{
 638|  if ( BLex2_isUnsignedDouble( m ) )  return  true;
 639|
 640|  if ( BLex2_peek( m, 0 ) == '+' || BLex2_peek( m, 0 ) == '-' ) {
 641|    if ( isdigit( BLex2_peek( m, 1 ) ) )  return  true;
 642|    if ( BLex2_peek( m, 1 ) == '.' && isdigit( BLex2_peek( m, 2 ) ) )
 643|      return  true;
 644|  }
 645|  return  false;
 646|}
 647|
 648|
 649| 
 650|/***************************************************************
 651|*  29. <<< [BLex2_getJisIOType] JIS 漢字の IN/OUT コードか調べる >>> 
 652|*【引数】
 653|*  ・BLex2*  m;        基本字句解析
 654|*  ・int  offset;         調べる文字のファイルポインタからのオフセット
 655|*  ・int  返り値;  漢字 IN/OUT コードかどうかの判定(StrX_CodeT 型)
 656|*【補足】
 657|*・返り値は、StrX_getJisIOType 関数を参照。
 658|***************************************************************/
 659|int  BLex2_getJisIOType( BLex2* m, int offset )
 660|{
 661|  BLex2_fillBuf( m, offset + 3 );
 662|  return  StrX_getJisIOType( m->buf + offset );
 663|}
 664|
 665|
 666| 
 667|/***************************************************************
 668|*  30. <<< [BLex2_isHoriLine] 文字による水平線かどうか調べる >>> 
 669|*【引数】
 670|*  ・BLex2*  m;    基本字句解析
 671|*  ・int  ch;         水平線を構成する文字
 672|*  ・int  nCh;        水平線を構成する文字の最小の数
 673|*  ・bool 返り値;     水平線かどうか
 674|*【補足】
 675|*・現在のファイルポインタの位置から行末までに、文字 ch が nCh 個
 676|*  連続していれば、水平線と判定します。
 677|*・返り値は、StrX_getJisIOType 関数を参照。
 678|***************************************************************/
 679|bool  BLex2_isHoriLine( BLex2* m, int ch, int nCh )
 680|{
 681|  int  i;
 682|  int  c;
 683|  int  n = 0;
 684|
 685|  for ( i = 0; i < m->buf_sizeof; i++ ) {
 686|    c = BLex2_peek( m, i );
 687|    if ( c == '\n' )
 688|      return  false;
 689|    if ( c == ch ) {
 690|      n ++;
 691|      if ( n >= nCh )
 692|        return  true;
 693|    }
 694|    else
 695|      n = 0;
 696|  }
 697|  ASSERT( 1 );
 698|  return  false;
 699|}
 700|
 701|
 702| 
 703|/***************************************************************
 704|*  31. <<< [BLex2_strchrInLine] 行の中に指定文字がある位置を返す >>> 
 705|*【引数】
 706|*  ・BLex2*  m;    基本字句解析
 707|*  ・int  ch;         行の中を調べる文字
 708|*  ・bool 返り値;     指定文字がある位置
 709|*【補足】
 710|*・返り値は、現在のファイルポインタからのオフセット値です。
 711|*  文字が見つからない場合、返り値は -1 です。
 712|***************************************************************/
 713|int  BLex2_strchrInLine( BLex2* m, int ch )
 714|{
 715|  int  i;
 716|  int  c;
 717|
 718|  for ( i = 0; i < m->buf_sizeof; i++ ) {
 719|    c = BLex2_peek( m, i );
 720|    if ( c == '\n' )  return  -1;
 721|    if ( c == ch )    return  i;
 722|  }
 723|  ASSERT( 1 );
 724|  return  -1;
 725|}
 726|
 727|
 728| 
 729|/*-------------------------------------------------------------------------*/
 730|/* 32. <<< ◆データを読み込む >>> 
 731|/*-------------------------------------------------------------------------*/
 732|
 733|
 734| 
 735|/***************************************************************************
 736|*  33. <<< [BLex2_read] 1文字読み込む >>> 
 737|*【補足】
 738|*・現在のファイル・ポインタの位置の文字を返して、ファイル・ポインタを1つ進める。
 739|****************************************************************************/
 740|int  BLex2_read( BLex2* m )
 741|{
 742|  int  c;
 743|
 744|  c = BLex2_peek( m, 0 );
 745|  BLex2_next( m, 1 );
 746|  return  c;
 747|}
 748|
 749|
 750| 
 751|/****************************************************************************
 752|*  34. <<< [BLex2_getBySpace] 次のスペースまで読み込む >>> 
 753|*【引数】
 754|*  ・BLex2*  m;  基本字句解析
 755|*  ・char* buf;     読み込んだテキストを格納するアドレス
 756|*  ・int  buf_len;  buf に確保してある領域のサイズ(byte)
 757|*  ・int  返り値;   0=正常, -1=buf_len まで読み込んだ
 758|*【補足】
 759|*・"" で囲まれている場合、スペースではなく " まで読み込みます。ただし、
 760|*  両端の " 文字は取り除かれます。
 761|*・"" で囲まれていない場合、両端の空白は、取り除かれます。
 762|*・スペース以外に termCh 文字も区切り文字としてみなします。
 763|*  もし、スペース以外に区切る必要がないなら、スペース文字を指定します。
 764|*・ファイルポインタは、スペースまたは termCh または " の次まで進みます。
 765|*・buf_len まで読み込んだら、ファイルポインタ fp は、その次まで進みます。
 766|*【例】
 767|*  「  abc def 」なら buf="abc", *fp = 'd' (*1)
 768|*  「  "abc def"X 」なら buf="abc def", *fp = 'X'
 769|*  「  "abc def" X 」なら buf="abc def", *fp = 'X'
 770|*  「  abc" def" X 」なら buf="abc", *fp = 最初の '"'
 771|*  「  abc, def 」で termCh=',' なら buf="abc", *fp = 'd'
 772|*  「  " d,ef"A」で termCh=',' なら buf=" d,ef", *fp = 'A'
 773|* (*1) *fp = 'd' は、ファイル・ポインタが、ファイル中の 'd' の文字まで
 774|*   進んだことを示します。
 775|****************************************************************************/
 776|#if 0
 777|int  BLex2_getBySpace( BLex2* m, char* buf, int buf_len, int termCh )
 778|{
 779|  char*  buf_over = buf + buf_len;
 780|
 781|  /* 先頭の空白を取り除く */
 782|  BLex2_skipSpcTabRet( m );
 783|  if ( BLex2_peek( m, 0 ) == EOF )
 784|    return 0;
 785|
 786|  /* 最初の文字が '"' でないなら、空白または termCh の前まで buf に読み込む */
 787|  /* ファイルポインタは、その空白または termCh まで進む */
 788|  if ( BLex2_peek( m, 0 ) != '"' ) {
 789|    while ( BLex2_peek( m, 0 ) != ' '
 790|         && BLex2_peek( m, 0 ) != termCh
 791|         && BLex2_peek( m, 0 ) != EOF
 792|         && buf < buf_over ) {
 793|      *buf = (char)BLex2_peek( m, 0 );
 794|      buf ++;
 795|      BLex2_next( m, 1 );
 796|    }
 797|    *buf = '\0';
 798|  }
 799|  /* 最初の文字が '"' なら、次の '"' の前まで buf に読み込む */
 800|  else {
 801|    BLex2_next( m, 1 );
 802|    while ( BLex2_peek( m, 0 ) != '"'
 803|         && BLex2_peek( m, 0 ) != EOF
 804|         && buf < buf_over ) {
 805|      *buf = (char)BLex2_peek( m, 0 );
 806|      buf ++;
 807|      BLex2_next( m, 1 );
 808|    }
 809|    *buf = '\0';
 810|  }
 811|
 812|  /* 次の文字(空白、termCh 以外)までファイルポインタを進める */
 813|  while ( BLex2_peek( m, 0 ) == ' '
 814|       || BLex2_peek( m, 0 ) == termCh )
 815|    BLex2_next( m, 1 );
 816|
 817|  return  ( buf < buf_over ? 0 : -1 );
 818|}
 819|#endif
 820|
 821| 
 822|/****************************************************************************
 823|*  35. <<< [BLex2_copyStr] 文字列をコピーする >>> 
 824|*【引数】
 825|*  ・BLex2*  m;        基本字句解析
 826|*  ・char*   buf;         読み込んだ文字列を格納するアドレス
 827|*  ・size_t  buf_size;    buf のメモリサイズ、読み込むサイズ+1(byte)
 828|*【補足】
 829|*・ファイルポインタは進みません。
 830|*・ファイルの最後が区切り文字でなく EOF の場合、文字列を格納して、
 831|*  EOF を返します。
 832|*・最後に '\0' 文字が入ります。
 833|****************************************************************************/
 834|void  BLex2_copyStr( BLex2* m, char* buf, int buf_size )
 835|{
 836|  int  i;
 837|
 838|  BLex2_peek( m, buf_size - 2 );
 839|  for ( i = 0; i < buf_size - 1; i++ ) {
 840|    *buf = BLex2_peek( m, i );
 841|    if ( *buf == EOF )  break;
 842|    buf++;
 843|  }
 844|  *buf = '\0';
 845|}
 846|
 847|
 848| 
 849|/****************************************************************************
 850|*  36. <<< [BLex2_readStr] 文字列を読み込む >>> 
 851|*【引数】
 852|*  ・BLex2*  m;        基本字句解析
 853|*  ・char*   buf;         読み込んだ文字列を格納するアドレス
 854|*  ・size_t  buf_len;     buf に確保してある領域のサイズ(byte)
 855|*  ・char*   terms;       区切り文字を並べた文字列
 856|*  ・int     返り値;      読み込んだ区切り文字、または EOF
 857|*【補足】
 858|*・terms は、たとえば区切り文字がスペースとタブの場合、" \t" とします。
 859|*・両端の空白は、取り除かれます。( "" で囲まれている場合を除く)
 860|*・ファイルポインタは、区切り文字の次に進みます。
 861|*・"" で囲まれている場合、閉じる " の次まで読み込みます。その場合、
 862|*  両端の " 文字は取り除かれて buf に格納します。
 863|*  先頭が " でなければ、途中に " を含んだ文字列を読み込むことが出来ます。
 864|*・ファイルの最後が区切り文字でなく EOF の場合、文字列を格納して、
 865|*  EOF を返します。
 866|*【内部補足】
 867|*・安定したら BLex2_getBySpace を廃止します。
 868|****************************************************************************/
 869|int  BLex2_readStr( BLex2* m, char* buf, size_t buf_len, char* terms )
 870|{
 871|  char*  p = buf;   /* buf 中へのポインタ */
 872|  char*  p_last = buf + buf_len - 1;
 873|  int    c;   /* 処理中の文字 */
 874|
 875|  /* 先頭の空白を取り除く */
 876|  BLex2_skipSpcTabRet( m );
 877|  if ( BLex2_peek( m, 0 ) == EOF )
 878|    return 0;
 879|
 880|  /* 最初の文字が '"' でないなら、区切り文字の直前まで buf に読み込む */
 881|  if ( BLex2_peek( m, 0 ) != '"' ) {
 882|    c = BLex2_read( m );
 883|    while ( strchr( terms, c ) == NULL && c != EOF && p < p_last ) {
 884|      *p = (char)c;  p ++;
 885|      c = BLex2_read( m );
 886|    }
 887|
 888|    /* 末尾の空白を取り除く */
 889|    p --;
 890|    while ( *p == ' ' && p >= buf )  p --;
 891|    p++;
 892|    *p = '\0';
 893|  }
 894|
 895|  /* 最初の文字が '"' なら、次の '"' の直前まで buf に読み込む */
 896|  else {
 897|    BLex2_next( m, 1 );
 898|    c = BLex2_read( m );
 899|    while ( c != '"' && c != EOF && p < p_last ) {
 900|      *p = (char)c;  p ++;
 901|      c = BLex2_read( m );
 902|    }
 903|    *p = '\0';
 904|    if ( c == '"' )  c = BLex2_read( m );
 905|  }
 906|
 907|  return  c;
 908|}
 909|
 910|
 911| 
 912|/**********************************************************************
 913|*  37. <<< [BLex2_copyIdiom2] 現在位置からイディオムをコピーする >>> 
 914|*【引数】
 915|*  ・BLex2*  m;        基本字句解析
 916|*  ・int    nWord;        コピーするイディオムのワード数
 917|*  ・char*  idiom;        イディオムを格納する領域のアドレス
 918|*  ・int  idiom_size;     idiom のメモリサイズ
 919|*  ・int  返り値;         コピーしたワード数
 920|*【補足】
 921|*・ワード数が nWord を超えるイディオムがない場合、nWord より少ない
 922|*  ワード数のイディオムが格納されます。
 923|*・参考: StrX_getIdiom2
 924|***********************************************************************/
 925|int  BLex2_copyIdiom2( BLex2* m, int nWord,
 926|  char* idiom, int idiom_size )
 927|{
 928|  int  i = 0, c;
 929|  int  mWord = nWord;
 930|  char*  idiom_last = idiom + idiom_size - 1;
 931|
 932|  #ifndef  NDEBUG
 933|    c = BLex2_peek( m, 0 );
 934|    ASSERT ( isalpha( c ) || c == '_' || _ismbblead( c ) );
 935|  #endif
 936|
 937|  c = BLex2_peek( m, 0 );
 938|  nWord = 0;
 939|
 940|  while ( nWord < mWord ) {
 941|
 942|    if ( isalpha( c ) || isdigit( c ) || c == '_' ) {
 943|      nWord ++;
 944|      while ( idiom < idiom_last ) {
 945|        *idiom = c;  idiom ++;  i++;  c = BLex2_peek( m, i );
 946|        if ( ! ( isalpha( c ) || isdigit( c ) || c == '_' ) )
 947|          break;
 948|      }
 949|    }
 950|
 951|    /* 英単語の区切り(空白文字)の場合 */
 952|    else if ( c == ' ' ) {
 953|      *idiom = c;  idiom ++;  i++;  c = BLex2_peek( m, i );
 954|    }
 955|
 956|    /* 全角文字の場合 */
 957|    else if ( _ismbblead( c ) ) {
 958|      nWord ++;
 959|      *idiom = c;  idiom++;  i ++;  c = BLex2_peek( m, i );
 960|      *idiom = c;  idiom++;  i ++;  c = BLex2_peek( m, i );
 961|    }
 962|
 963|    /* その他(イディオム区切り文字)の場合 */
 964|    else {
 965|      /* ワードが取得できなかったとき、末尾に加えた */
 966|      /* ワードの区切り空白文字をカットする */
 967|      if ( nWord >= 1 ) {
 968|        do {
 969|          idiom --;
 970|        } while ( *idiom == ' ' );
 971|        idiom ++;
 972|      }
 973|      break;
 974|    }
 975|  }
 976|
 977|  *idiom = '\0';
 978|
 979|  return  nWord;
 980|}
 981|
 982|
 983| 
 984|/************************************************************
 985|*  38. <<< [BLex2_readLine] 行末まで読み込む >>> 
 986|*【引数】
 987|*  ・BLex2*  m;   基本字句解析
 988|*  ・char*  line;    行を格納する領域の先頭アドレス
 989|*  ・int  size;      line のメモリサイズ
 990|*【補足】
 991|*・line に入りきらない部分は、カットされます。
 992|*  その場合でも、ファイルポインタは次の行の先頭に移動します。
 993|************************************************************/
 994|void  BLex2_readLine( BLex2* m, char* line, int size )
 995|{
 996|  char*  p = line;
 997|  char*  p_last = line + size - 1;
 998|  int  c;
 999|
1000|  for (;;) {
1001|    c = BLex2_peek( m, 0 );
1002|    if ( c == EOF || c == '\n' )  break;
1003|    if ( p < p_last ) {
1004|      *p = c;   p++;
1005|    }
1006|    BLex2_next( m, 1 );
1007|  }
1008|  *p = '\0';
1009|}
1010|
1011|
1012|
1013|
1014| 
1015|/************************************************************
1016|*  39. <<< [BLex2_readInt] int 定数を読み込む >>> 
1017|*    返り値 : 読み込んだ値
1018|*  ポインタは int 定数の直後に移動します。
1019|*  条件:バッファの大きさは1以上
1020|************************************************************/
1021|int  BLex2_readInt( BLex2* m )
1022|{
1023|  int  n = 0;
1024|  int  flag = 1;
1025|  int  c;
1026|
1027|  /* マイナスの符号 */
1028|  if ( BLex2_peek( m, 0 ) == '-' ) {
1029|    flag = -1;
1030|    BLex2_next( m, 1 );
1031|  }
1032|  /* 数値 */
1033|  while ( ( c = BLex2_peek( m, 0 ) ) >= '0' && c <= '9' ) {
1034|    n = n * 10 + c - '0';
1035|    BLex2_next( m, 1 );
1036|  }
1037|  return  flag * n;
1038|}
1039|
1040|
1041| 
1042|/************************************************************
1043|*  40. <<< [BLex2_readInt16] int 型 16進数を読み込む >>> 
1044|*    返り値 : 読み込んだ値
1045|*  ポインタは16進数の直後に移動します。
1046|*  条件:バッファの大きさは1以上
1047|************************************************************/
1048|int  BLex2_readInt16( BLex2* m )
1049|{
1050|  int  n = 0;
1051|  int  flag = 1;
1052|  int  c;
1053|
1054|  /* マイナスの符号 */
1055|  if ( BLex2_peek( m, 0 ) == '-' ) {
1056|    flag = -1;
1057|    BLex2_next( m, 1 );
1058|  }
1059|  /* 数値 */
1060|  for (;;) {
1061|    c = BLex2_peek( m, 0 );
1062|    if ( c >= '0' && c <= '9' ) {
1063|      n = n * 16 + c - '0';
1064|      BLex2_next( m, 1 );
1065|    }
1066|    else if ( c >= 'A' && c <= 'F' ) {
1067|      n = n * 16 + c - 'A' + 10;
1068|      BLex2_next( m, 1 );
1069|    }
1070|    else if ( c >= 'a' && c <= 'f' ) {
1071|      n = n * 16 + c - 'a' + 10;
1072|      BLex2_next( m, 1 );
1073|    }
1074|    else
1075|      break;
1076|  }
1077|  return  flag * n;
1078|}
1079|
1080|
1081| 
1082|/***************************************************************
1083|*  41. <<< [BLex2_readDouble] double 定数を読み込む >>> 
1084|*    返り値 : 読み込んだ値
1085|*  ポインタは double 定数の直後に移動します。
1086|*  double 定数でなかったら 0.0 を返します。
1087|*  条件:バッファの大きさは3以上(符号がないなら2以上)
1088|*  注意 : 内部で WordStr255 を使っています。
1089|***************************************************************/
1090|double  BLex2_readDouble( BLex2* m )
1091|{
1092|  if ( ! BLex2_isDouble( m ) ) {
1093|    return  0.0;
1094|  }
1095|  else {
1096|    char*  workStr;
1097|    int  i;
1098|    bool  fDot = false;  /* 小数点を読み込んだか */
1099|    bool  fE = false;  /* 指数記号 E, e を読み込んだか */
1100|    double  n;
1101|    int  c = BLex2_peek( m, 0 );
1102|
1103|    BigStack_start();
1104|    workStr = BigStack_alloc( 256 );
1105|
1106|    for ( i = 0; i < 255; i++ ) {  /* i の判定はループ内に */
1107|      c = BLex2_peek( m, 0 );
1108|
1109|      if ( isdigit( c ) ) ;  /*ok*/
1110|      else if ( c == '.' ) {
1111|        if ( fDot )  break;
1112|        else  fDot = true;  /*ok*/
1113|      }
1114|      else if ( c == 'e' || c == 'E' ) {
1115|        if ( fE )  break;
1116|        else  fE = true;  /*ok*/
1117|      }
1118|      else if ( c == '+' || c == '-' ) {
1119|        if ( i == 0 ) ;  /*ok*/
1120|        else if ( workStr[i-1] == 'e' || workStr[i-1] == 'E' ) ;  /*ok*/
1121|        else  break;
1122|      }
1123|      else
1124|        break;
1125|
1126|      workStr[i] = (char)c;
1127|      BLex2_next( m, 1 );
1128|    }
1129|    workStr[i] = '\0';
1130|    n = atof( workStr );
1131|    BigStack_end();
1132|    return  n;
1133|    /* BLex2 は先読みして fscanf が使えないのでわざわざ取り込んでいます。*/
1134|  }
1135|}
1136|
1137|
1138| 
1139|/***************************************************************
1140|*  42. <<< [BLex2_readCSV] CSV 形式の1項目を読み込む >>> 
1141|*【引数】
1142|*  ・BLex2*  m;     基本字句解析
1143|*  ・char*  buf;       項目を格納するバッファ
1144|*  ・int  buf_maxLen;  buf に格納できる最大のサイズ
1145|*  ・char*  返り値;    buf と同じ
1146|*【補足】
1147|*・ファイルポインタを、読み込む項目の先頭に移動してから呼び出してください。
1148|*・ファイルポインタは、',' または '\n' または EOF に移ります。
1149|*・文字列の先頭または末尾の空白は、そのまま格納します。
1150|*【例】
1151|*・例1: abc,"abc,d""ef",123 (\n) なら buf=[abc], ファイルポインタ = ','
1152|*・例2: "abc,d""ef",123 (\n)     なら buf=[abc,d"ef], ファイルポインタ = ','
1153|*・例3: 123 (\n)                 なら buf=[123], ファイルポインタ = '\n'
1154|***************************************************************/
1155|char*  BLex2_readCSV( BLex2* m, char* buf, int buf_maxLen )
1156|{
1157|  int    c, f;
1158|  char*  buf_over = buf + buf_maxLen;
1159|
1160|  if ( buf >= buf_over )  return  buf;
1161|
1162|  /* , まで読み込む場合 */
1163|  if ( BLex2_peek( m, 0 ) != '"' ) {
1164|    while ( (c= BLex2_peek( m, 0 )) != ','  && c!= '\n' && c!= EOF ) {
1165|      if ( buf < buf_over - 1 )
1166|        *buf++ = (char)c;
1167|      BLex2_next( m, 1 );
1168|    }
1169|  }
1170|  /* "" の間を読み込む場合 */
1171|  else {
1172|    BLex2_next( m, 1 );  /* '"' のスキップ */
1173|    while ( (c= BLex2_peek( m, 0 )) != '"' ||
1174|            (f= ( BLex2_strncmp( m, "\"\"" ) == 0 )) &&
1175|             c != EOF ) {
1176|      if ( buf < buf_over - 1 )
1177|        *buf++ = (char)c;
1178|      BLex2_next( m, ( c=='"' && f ? 2 : 1 ) );
1179|    }
1180|    BLex2_next( m, 1 );  /* '"' のスキップ */
1181|  }
1182|  *buf = '\0';
1183|
1184|  return  buf;
1185|}
1186|
1187|
1188| 
1189|/*-------------------------------------------------------------------------*/
1190|/* 43. <<< ◆記録用バッファを使って読み込む >>> 
1191|/*-------------------------------------------------------------------------*/
1192|
1193|
1194| 
1195|/*******************************************************************
1196|*  44. <<< [BLex2_setRecBuf] 記録用バッファを登録する >>> 
1197|*【引数】
1198|*  ・BLex2*  m;          基本字句解析
1199|*  ・ArrX_Buf*  recBuf;     記録用バッファ
1200|*******************************************************************/
1201|#ifdef USES_ARRX
1202|void  BLex2_setRecBuf( BLex2* m, void* mem, size_t mem_sizeof )
1203|{
1204|  ArrX_Buf_init( &m->recBuf, mem, mem_sizeof );
1205|  m->recBufF = true;
1206|}
1207|#endif /* USES_ARRX */
1208|
1209|
1210| 
1211|/*******************************************************************
1212|*  45. <<< [BLex2_getRecBuf] 記録用バッファを参照する >>> 
1213|*【引数】
1214|*  ・BLex2*  m;          基本字句解析
1215|*  ・ArrX_Buf*  返り値;     記録用バッファ
1216|*******************************************************************/
1217|#ifdef USES_ARRX
1218|ArrX_Buf*  BLex2_getRecBuf( BLex2* m )
1219|{
1220|  return  &m->recBuf;
1221|}
1222|#endif /* USES_ARRX */
1223|
1224|
1225| 
1226|/*******************************************************************
1227|*  46. <<< [BLex2_recToEmpty] 記録用バッファを空にする >>> 
1228|*【補足】
1229|*・この関数を呼び出す前に、BLex2_setRecBuf 関数を用いて記録用
1230|*  バッファを用意してください。
1231|*******************************************************************/
1232|#ifdef USES_ARRX
1233|void  BLex2_recToEmpty( BLex2* m )
1234|{
1235|  #ifdef _CHECKER
1236|    if ( ! m->recBufF )  error();
1237|                /* 記録用バッファが設定されていません */
1238|  #endif
1239|
1240|  ArrX_Buf_toEmpty( &m->recBuf );
1241|}
1242|#endif /* USES_ARRX */
1243|
1244|
1245| 
1246|/*******************************************************************
1247|*  47. <<< [BLex2_recStart] 記録を開始する >>> 
1248|*【機能】
1249|*・BLex2_next するごとに m->recBuf にコピーするようにします。
1250|*【補足】
1251|*・記録を開始する前に、BLex2_setRecBuf 関数を用いて記録用バッファを
1252|*  用意してください。
1253|*・バッファにデータが残っていたら、その続きから記録します。
1254|*  空にするときは、BLex2_recToEmpty 関数を用います。
1255|*******************************************************************/
1256|#ifdef USES_ARRX
1257|void  BLex2_recStart( BLex2* m )
1258|{
1259|  #ifdef _CHECKER
1260|    if ( ! m->recBufF )  error();
1261|                /* 記録用バッファが設定されていません */
1262|  #endif
1263|
1264|  m->recF = true;
1265|}
1266|#endif /* USES_ARRX */
1267|
1268|
1269| 
1270|/*******************************************************************
1271|*  48. <<< [BLex2_recEnd] 記録を終了する >>> 
1272|*【引数】
1273|*  ・BLex2*  m;      基本字句解析
1274|*  ・ArrX_Buf* 返り値;  記録したデータの入ったバッファ
1275|*【補足】
1276|*・記録用バッファの末尾の次に '\0' 文字を付加します。
1277|*  ただし、返り値は、'\0' を含みません。
1278|*******************************************************************/
1279|#ifdef USES_ARRX
1280|ArrX_Buf*  BLex2_recEnd( BLex2* m )
1281|{
1282|  ASSERT( m->recF );
1283|
1284|  m->recF = false;
1285|  ArrX_Buf_addEndOfC( &m->recBuf );
1286|  while ( *((char*)m->recBuf.last - 1) == '\0' )
1287|    m->recBuf.last = (void*)((char*)m->recBuf.last - 1);
1288|
1289|  return  &m->recBuf;
1290|}
1291|
1292|#endif /* USES_ARRX */
1293|
1294|
1295| 
1296|/*-------------------------------------------------------------------------*/
1297|/* 49. <<< ◆言語用処理 >>> 
1298|/*-------------------------------------------------------------------------*/
1299|
1300|
1301| 
1302|/**************************************************************
1303|*  50. <<< [BLex2_isCIdent] C 言語の識別子かどうか判断する >>> 
1304|*【機能】
1305|*・現在のファイル・ポインタの位置から始まるテキストが、英文字
1306|*  または、アンダーライン '_' から始まる C 言語識別子かどうか
1307|*  判断します。
1308|*【補足】
1309|*・現在のファイル・ポインタの位置が空白やタブなどの場合、
1310|*  正しく判断できません。
1311|*・ファイル・ポインタは移動しません。
1312|***************************************************************/
1313|bool  BLex2_isCIdent( BLex2* m )
1314|{
1315|  int  c = BLex2_peek( m, 0 );
1316|
1317|  return  ( (isalpha( c ) || c == '_') && !_ismbblead( c ) );
1318|}
1319|
1320|
1321| 
1322|/**************************************************************************
1323|*  51. <<< [BLex2_readCIdent] C 言語の識別子を読み込む >>> 
1324|*【引数】
1325|*  ・BLex2*  m;         基本字句解析
1326|*  ・char*  ident;         読み込んだ識別子を格納するアドレス
1327|*  ・size_t ident_sizeof;  ident のメモリサイズ
1328|*【補足】
1329|*・ファイル・ポインタは C 言語の識別子の直後に移動します。
1330|**************************************************************************/
1331|void  BLex2_readCIdent( BLex2* m, char* ident, size_t ident_sizeof )
1332|{
1333|  int  c;
1334|  int  len;
1335|
1336|  ASSERT( BLex2_isCIdent( m ) );
1337|
1338|  c = BLex2_peek( m, 0 );
1339|  len = 0;
1340|  do {
1341|    ident[len] = (char)c;  len++;
1342|    BLex2_next( m, 1 );
1343|    c = BLex2_peek( m, 0 );
1344|
1345|  } while ( ( isalpha( c ) || c == '_' || isdigit( c ) ) &&
1346|            !_ismbblead( c ) &&
1347|            len < (int)ident_sizeof - 2 );
1348|
1349|  ident[len] = '\0';
1350|}
1351|
1352|
1353| 
1354|/**************************************************************************
1355|*  52. <<< [BLex2_copyCIdent] C 言語の識別子をコピーする >>> 
1356|*【引数】
1357|*  ・BLex2*  m;         基本字句解析
1358|*  ・char*  ident;         読み込んだ識別子を格納するアドレス
1359|*  ・size_t ident_sizeof;  ident のメモリサイズ
1360|*【補足】
1361|*・ファイル・ポインタは移動しません。
1362|**************************************************************************/
1363|void  BLex2_copyCIdent( BLex2* m, char* ident, size_t ident_sizeof )
1364|{
1365|  int  c;
1366|  int  len;
1367|
1368|  ASSERT( BLex2_isCIdent( m ) );
1369|
1370|  c = BLex2_peek( m, 0 );
1371|  len = 0;
1372|  do {
1373|    ident[len] = (char)c;  len++;
1374|    c = BLex2_peek( m, len );
1375|
1376|  } while ( ( isalpha( c ) || c == '_' || isdigit( c ) ) &&
1377|            !_ismbblead( c ) &&
1378|            len < (int)ident_sizeof - 2 );
1379|
1380|  ident[len] = '\0';
1381|}
1382|
1383|
1384| 
1385|/**************************************************************************
1386|*  53. <<< [BLex2_getCIdentSize] C 言語の識別子のサイズを取得する >>> 
1387|*【引数】
1388|*  ・BLex2*  m;       基本字句解析
1389|*  ・int  返り値;        C 言語の識別子のサイズ(バイト)
1390|*【補足】
1391|*・ファイル・ポインタは移動しません。
1392|**************************************************************************/
1393|int  BLex2_getCIdentSize( BLex2* m )
1394|{
1395|  int  c;
1396|  int  len;
1397|
1398|  ASSERT( BLex2_isCIdent( m ) );
1399|
1400|  c = BLex2_peek( m, 0 );
1401|  len = 0;
1402|  do {
1403|    len++;
1404|    c = BLex2_peek( m, len );
1405|
1406|  } while ( ( isalpha( c ) || c == '_' || isdigit( c ) ) && !_ismbblead( c ) );
1407|
1408|  return  len;
1409|}
1410|
1411|
1412| 
1413|/*******************************************************************
1414|*  54. <<< [BLex2_skipC] 空白、タブ、改行、コメント(C, C++)をスキップ >>> 
1415|*【引数】
1416|*  ・BLex2*  m;         基本字句解析
1417|*  ・char*  返り値;        スキップした行数
1418|*******************************************************************/
1419|int  BLex2_skipC( BLex2* m )
1420|{
1421|  int  lines = 0;
1422|
1423|  lines += BLex2_skipSpcTabRet( m );
1424|  do {
1425|    if ( BLex2_isCComment( m ) )
1426|      lines += BLex2_skipCComment( m );
1427|    if ( BLex2_isCPPComment( m ) ) {
1428|      BLex2_nextLine( m );  lines++;
1429|    }
1430|    lines += BLex2_skipSpcTabRet( m );
1431|  } while ( BLex2_isCComment( m ) || BLex2_isCPPComment( m ) );
1432|
1433|  return  lines;
1434|}
1435|
1436|
1437| 
1438|/*******************************************************************
1439|*  55. <<< [BLex2_skipCLine] 空白、タブ、コメント(C, C++)をスキップ >>> 
1440|*【引数】
1441|*  ・BLex2*  m;         基本字句解析
1442|*  ・char*  返り値;        スキップした行数
1443|*******************************************************************/
1444|#if 0
1445|int  BLex2_skipCLine( BLex2* m )
1446|{
1447|  int  lines = 0;
1448|
1449|  do {
1450|    lines += BLex2_skipSpcTab( m );
1451|    if ( BLex2_isCComment(m) )  lines += BLex2_skipCComment(m);
1452|    if ( BLex2_isCPPComment(m) )  { BLex2_nextLine(m)  lines++; }
1453|  } while ( BLex2_isCComment( m ) || BLex2_isCPPComment( m ) );
1454|  /* 複数行もあり? */
1455|
1456|  return  lines;
1457|}
1458|#endif
1459|
1460|
1461| 
1462|/*******************************************************************
1463|*  56. <<< [BLex2_isCComment] C 言語のコメントか調べる >>> 
1464|*【機能】
1465|*・現在ポイントしている位置が C 言語のコメントの始まりかどうか調べます。
1466|*【補足】
1467|*・C 言語のコメントは /* 〜 */ です。
1468|*******************************************************************/
1469|bool  BLex2_isCComment( BLex2* m )
1470|{
1471|  return ( BLex2_peek( m, 0 ) == '/' &&
1472|           BLex2_peek( m, 1 ) == '*' );
1473|}
1474|
1475|
1476| 
1477|/*******************************************************************
1478|*  57. <<< [BLex2_skipCComment] C 言語のコメントをスキップします >>> 
1479|*【引数】
1480|*  ・BLex2*  m;    基本字句解析
1481|*  ・int  返り値;     スキップ中に改行した行数
1482|*【補足】
1483|*・C 言語のコメントは /* 〜 */ です。
1484|*・現在のファイルポインタの位置を、C 言語のコメントが始まる位置に
1485|*  調節してから呼び出してください。
1486|*・対応するカッコ閉じが無い場合、例外を出します。
1487|*******************************************************************/
1488|int  BLex2_skipCComment( BLex2* m )
1489|{
1490|  int  lines = 0;
1491|
1492|  BLex2_next( m, 2 );
1493|  while ( BLex2_peek( m, 0 ) != '*' || BLex2_peek( m, 1 ) != '/' ) {
1494|    if ( BLex2_peek( m, 0 ) == '\n' )
1495|      lines++;
1496|    BLex2_next( m, 1 );
1497|    if ( BLex2_peek( m, 0 ) == EOF ) {
1498|      error2_0( BLex2_Err_NoCommentEnd,
1499|      "コメントの終端がありません" );
1500|    }
1501|  }
1502|  BLex2_next( m, 2 );
1503|  return  lines;
1504|}
1505|
1506|
1507| 
1508|/*******************************************************************
1509|*  58. <<< [BLex2_skipCCommentNest] ネストして C 言語コメントをスキップ >>> 
1510|*  ポインタを移動します
1511|*    lines : [出力]改行した行数
1512|*    返り値 : 対応するカッコ閉じがあります。(正常)
1513|*             カッコの始まりがないときは false を返します。
1514|*             /**/ ではなく /*/ のときはカッコとみなしません。
1515|*  条件:バッファの大きさは2以上
1516|*******************************************************************/
1517|#if 0
1518|bool  BLex2_skipCCommentNest( BLex2* m, int* lines )
1519|{
1520|  *lines = 0;
1521|  if ( BLex2_isCComment( m ) ) {
1522|    int  level = 1;
1523|    int  c1, c2;
1524|    BLex2_next( m, 2 );
1525|
1526|    while ( level > 0 ) {
1527|      c1 = BLex2_peek( m, 0 );
1528|      c2 = BLex2_peek( m, 1 );
1529|
1530|      if ( c1 != '/' || c2 != '*' )
1531|        level++;
1532|      else if ( c1 != '*' || c2 != '/' )
1533|        level--;
1534|
1535|      if ( BLex2_peek( m, 0 ) == '\n' )
1536|        (*lines)++;
1537|      BLex2_next( m, 1 );
1538|
1539|      if ( c1 == EOF )
1540|        return  false;
1541|    }
1542|    BLex2_next( m, 1 );
1543|    return  true;
1544|  }
1545|  return  false;
1546|}
1547|#endif /* #if 0 */
1548|
1549|
1550| 
1551|/*******************************************************************
1552|*  59. <<< [BLex2_isCPPComment] C++ 言語のコメント // か調べる >>> 
1553|*【引数】
1554|*  ・BLex2*  m;    基本字句解析
1555|*  ・bool  返り値;     C++ 言語のコメントかどうか
1556|*【補足】
1557|*・現在のファイルポインタの位置が、C++ 言語のコメント // かどうか調べます。
1558|*・// コメントをスキップする場合、BLex2_nextLine 関数を用います。
1559|*******************************************************************/
1560|bool  BLex2_isCPPComment( BLex2* m )
1561|{
1562|  return ( BLex2_peek( m, 0 ) == '/' && BLex2_peek( m, 1 ) == '/' );
1563|}
1564|
1565|
1566| 
1567|/********************************************************************
1568|*  60. <<< [BLex2_readHTML] HTML タグの構文解析をする >>> 
1569|*【機能】
1570|*・BLex2 の現在のファイルポインタから始まる HTML タグ('<')を構文解析して
1571|*  属性(サブ・タグ)の値を格納します。
1572|*【引数】
1573|*  ・BLex2*  m;           基本字句解析
1574|*  ・BLex2_HTMLTags*  tags;  HTML タグ・リスト(出力)
1575|*  ・StrX_Mem*  mem;         属性の値を格納するワーク領域
1576|*  ・char**  mem2;           属性の値へのポインタを格納する char* 型配列
1577|*  ・int  返り値;            改行した数
1578|*【補足】
1579|*・ファイルポインタを HTML タグの先頭('<')に移動してから呼び出してください。
1580|*  ファイルポインタは HTML タグ('>')の次に移動します。
1581|*・mem および mem2 の領域は、tags のメンバ変数が参照しています。
1582|*  mem には、タグ名、属性名、属性の値が格納されるので、十分な大きさを
1583|*  与えてください。再びこの関数を呼び出す前に、StrX_Mem_init しないと、
1584|*  そのメモリ領域を食い尽くします。
1585|*・mem2 の配列の要素数は、予想される、読み込むタグの
1586|*  属性の数の2倍より大きくしてください。
1587|********************************************************************/
1588|int  BLex2_readHTML( BLex2* m, BLex2_HTMLTags* tags, StrX_Mem* mem,
1589|  char** mem2, size_t mem2_sizeof )
1590|{
1591|  char*  p;
1592|  char*  p2;
1593|  size_t  size;
1594|  int  prevTerm;   /* 直前の区切り文字 */
1595|  int  attr_m = mem2_sizeof / sizeof(char*) / 2;
1596|  int  nLine = 0;
1597|
1598|  ASSERT( BLex2_peek( m, 0 ) == '<' );
1599|
1600|  c_try {
1601|
1602|    /* メモリ領域を tags にリンクする */
1603|    tags->attr_names = mem2;
1604|    tags->attr_vars = mem2 + attr_m;
1605|    tags->attr_n = 0;
1606|
1607|    /* HTML タグ(メイン)を読み込む */
1608|    p = StrX_Mem_alloc( mem );
1609|    size = StrX_Mem_getLeftSize( mem );
1610|    BLex2_next( m, 1 );
1611|    BLex2_skipSpcTabRet( m );
1612|    prevTerm = BLex2_readStr( m, p, size, " >" );
1613|    p2 = p;
1614|    while ( *p2 != '\0' )
1615|      if ( *p2++ == '\n' )  nLine++;
1616|    _strlwr( p );
1617|    tags->name = p;
1618|
1619|    while ( prevTerm != '>' && tags->attr_n < attr_m ) {
1620|
1621|      if ( prevTerm == ' ' )
1622|        nLine += BLex2_skipSpcTabRet( m );
1623|
1624|      /* HTML 属性(サブ)の名前を読み込む */
1625|      p = StrX_Mem_alloc( mem );
1626|      size = StrX_Mem_getLeftSize( mem );
1627|      prevTerm = BLex2_readStr( m, p, size, "=>" );
1628|      p2 = p;
1629|      while ( *p2 != '\0' )
1630|        if ( *p2++ == '\n' )  nLine++;
1631|      _strlwr( p );
1632|      tags->attr_names[tags->attr_n] = p;
1633|
1634|      /* HTML 属性(サブ)の値を読み込む */
1635|      p = StrX_Mem_alloc( mem );
1636|      size = StrX_Mem_getLeftSize( mem );
1637|      if ( prevTerm == '>' )  /* 値が無いままタグが終了した場合 */
1638|        strcpy( p, "" );
1639|      else {
1640|        prevTerm = BLex2_readStr( m, p, size, " \t\r\n>" );
1641|        if ( prevTerm == '\n' )  nLine++;
1642|      }
1643|      tags->attr_vars[tags->attr_n] = p;
1644|
1645|      tags->attr_n ++;
1646|    }
1647|  }
1648|  c_catch ( Errors_Msg*, msg ) {
1649|    if ( msg->code != StrX_Err_MemEmpty )  c_throw_again();
1650|  } c_end_catch;
1651|
1652|  return  nLine;
1653|}
1654|
1655|
1656| 
1657|/*-------------------------------------------------------------------------*/
1658|/* 61. <<< ◆HTML タグ [BLex2_HTMLTags] >>> 
1659|/*-------------------------------------------------------------------------*/
1660|
1661|
1662| 
1663|/********************************************************************
1664|*  62. <<< [BLex2_HTMLTags_getVar] 属性の値を返す >>> 
1665|*【引数】
1666|*  ・BLex2_HTMLTags*  m;    HTML タグ情報
1667|*  ・char*  attr_name;         属性名(小文字で指定)
1668|*  ・char*  返り値;            属性の値、または NULL
1669|*【補足】
1670|*・attr_name は、小文字で指定しても大文字混在の属性名にヒットします。
1671|*・返り値の文字列は変更しないでください。
1672|********************************************************************/
1673|char*  BLex2_HTMLTags_getVar( BLex2_HTMLTags* m, const char* attr_name )
1674|{
1675|  int  i;
1676|
1677|  #ifndef NDEBUG
1678|    { /* attr_name は、すべて小文字であること */
1679|      const char*  p = attr_name;
1680|      while ( *p != '\0' ) {
1681|        if ( isupper( *p ) )  error();
1682|        p++;
1683|      }
1684|    }
1685|  #endif
1686|
1687|  for ( i = 0; i < m->attr_n; i++ ) {
1688|    if ( strcmp( m->attr_names[i], attr_name ) == 0 )
1689|      return  m->attr_vars[i];
1690|  }
1691|  return  NULL;
1692|}
1693|
1694|
1695| 
1696|/********************************************************************
1697|*  63. <<< [BLex2_HTMLTags_print] BLex2_HTMLTags 型を出力する >>> 
1698|*【補足】
1699|*・データ構造を元に表示するので、取りこんだ通りの出力結果が
1700|*  出るとは限りません。取り込んだ通り出力したいときは、
1701|*  BLex2_recStart 関数などを利用して下さい。
1702|********************************************************************/
1703|void  BLex2_HTMLTags_print( BLex2_HTMLTags* m )
1704|{
1705|  int  i;
1706|
1707|  printf( "<%s", m->name );
1708|
1709|  for ( i = 0; i < m->attr_n; i++ ) {
1710|    printf( " %s=\"%s\"", m->attr_names[i], m->attr_vars[i] );
1711|  }
1712|
1713|  printf( ">" );
1714|}
1715|
1716|
1717| 
1718|/********************************************************************
1719|*  64. <<< [BLex2_HTMLTags_fprint] BLex2_HTMLTags 型を出力する >>> 
1720|********************************************************************/
1721|void  BLex2_HTMLTags_fprint( BLex2_HTMLTags* m, FILE* out )
1722|{
1723|  int  i;
1724|
1725|  _strupr( m->name );
1726|  fprintf( out, "<%s", m->name );
1727|  _strlwr( m->name );
1728|
1729|  for ( i = 0; i < m->attr_n; i++ ) {
1730|    fprintf( out, " %s=\"%s\"", m->attr_names[i], m->attr_vars[i] );
1731|  }
1732|
1733|  fprintf( out, ">" );
1734|}
1735|
1736|
1737| 
1738|/*-------------------------------------------------------------------------*/
1739|/* 65. <<< ◆内部処理 >>> 
1740|/*-------------------------------------------------------------------------*/
1741|
1742|
1743| 
1744|/***************************************************************************
1745|*  66. <<< [BLex2_fillBuf] 先読みバッファに読み込む >>> 
1746|*【内部補足】
1747|*・EOF は、先読みバッファに入れません。
1748|*  0〜255しか表現できないため、EOF の判定は有効バッファサイズで判定しています。
1749|*・BLEX2_USE_SIZEBUF が定義してあって、サイズがぎりぎりだと、
1750|*  オーバーフローする可能性があります。
1751|****************************************************************************/
1752|void  BLex2_fillBuf( BLex2* m, int len )
1753|{
1754|  if ( len > m->buf_sizeof )  len = m->buf_sizeof;
1755|
1756|  if ( len > m->buf_n ) {
1757|    int  i;
1758|
1759|    for ( i = m->buf_n; i < len; i++ ) {
1760|      int  c;
1761|
1762|      c = fgetc( m->fp );
1763|
1764|      #ifdef  BLEX2_BIN_CHKER
1765|        {
1766|          bool  flag = false;
1767|
1768|          /* if ( c == 0xFF )  flag = true; */
1769|          if ( c < ' ' && c != '\n' && c != '\r' &&  c != EOF &&
1770|               c != '\t' && c != 0x1A && c != StrX_SI && c != StrX_SO &&
1771|               c != StrX_ESC )  flag = true;
1772|
1773|          if ( flag ) {
1774|            error2_2( BLex2_Err_BinaryCannotParse,
1775|              "バイナリファイルは読みこめません char=(%d) in %s",
1776|              c, m->path );
1777|          }
1778|        }
1779|      #endif
1780|
1781|      /* バッファに格納する */
1782|      m->buf[i] = (char)c;
1783|      if ( c != EOF ) {
1784|        m->buf_n++;
1785|      }
1786|
1787|      #ifdef  BLEX2_USE_SIZEBUF
1788|      {
1789|        int  c2;
1790|
1791|        ASSERT( m->sizeBuf != NULL );
1792|        m->sizeBuf[i] = 1;
1793|
1794|        /* "\r\n" の場合、"\n" だけにする */
1795|        if ( c == '\r' ) {
1796|          c2 = fgetc( m->fp );
1797|          if ( c2 == '\n' ) {
1798|            m->buf[i] = '\n';
1799|            m->sizeBuf[i] = 2;
1800|          }
1801|          else {
1802|            i++;
1803|            m->buf[i] = (char)c2;
1804|            m->sizeBuf[i] = 1;
1805|            if ( c2 != EOF ) {
1806|              m->buf_n++;
1807|            }
1808|          }
1809|        }
1810|        /* "\n\r" の場合、"\n" だけにする */
1811|        if ( c == '\n' ) {
1812|          c2 = fgetc( m->fp );
1813|          if ( c2 == '\r' ) {
1814|            m->sizeBuf[i] = 2;
1815|          }
1816|          else {
1817|            i++;
1818|            m->buf[i] = (char)c2;
1819|            m->sizeBuf[i] = 1;
1820|            if ( c2 != EOF ) {
1821|              m->buf_n++;
1822|            }
1823|          }
1824|        }
1825|      }
1826|      #endif
1827|    }
1828|  }
1829|}
1830| 
1831|/*-------------------------------------------------------------------------*/
1832|/* 67. <<< ◆行のサブレックス (BLex2_Line) >>> 
1833|/*-------------------------------------------------------------------------*/
1834|
1835|
1836| 
1837|/***************************************************************************
1838|*  68. <<< [BLex2_Line_init] 初期化する >>> 
1839|*【引数】
1840|*  ・BLex2_Line*  m;   行のサブレックス
1841|****************************************************************************/
1842|void  BLex2_Line_init( BLex2_Line* m )
1843|{
1844|  m->lineNum = 1;
1845|  m->column = 1;
1846|  m->bFirst = true;
1847|  /* m->bLast は、フェッチフェーズで決定する */
1848|}
1849|
1850|
1851| 
1852|/***************************************************************************
1853|*  69. <<< [BLex2_Line_fetch] フェッチフェーズ用・フェッチ >>> 
1854|*【引数】
1855|*  ・BLex2_Line*  m;   行のサブレックス
1856|****************************************************************************/
1857|void  BLex2_Line_fetch( BLex2_Line* m, BLex2* lex )
1858|{
1859|  m->bLast = ( BLex2_peek( lex, 1 ) == '\n' );
1860|}
1861|
1862|
1863| 
1864|/***************************************************************************
1865|*  70. <<< [BLex2_Line_nextFetch] ネクストフェーズ用・フェッチ >>> 
1866|*【引数】
1867|*  ・BLex2_Line*  m;   行のサブレックス
1868|****************************************************************************/
1869|void  BLex2_Line_nextFetch( BLex2_Line* m, BLex2* lex )
1870|{
1871|  m->bFirst = ( BLex2_peek( lex, 0 ) == '\n' );
1872|  if ( m->bFirst ) {
1873|    m->lineNum ++;
1874|    m->column = 1;
1875|  }
1876|  else {
1877|    m->column++;
1878|  }
1879|}
1880|
1881|
1882| 
1883|/*-------------------------------------------------------------------------*/
1884|/* 71. <<< ◆括弧のサブレックス (BLex2_Kakko) >>> 
1885|/*-------------------------------------------------------------------------*/
1886|
1887|
1888| 
1889|/***************************************************************************
1890|*  72. <<< [BLex2_Kakko_init] 初期化する >>> 
1891|*【引数】
1892|*  ・BLex2_Kakko*  m;  括弧のサブレックス
1893|*  ・char*  typeStack;    括弧タイプの記録領域
1894|*  ・int  typeStack_m;    typeStack のメモリサイズ
1895|*【補足】
1896|*・typeStack は、括弧の対応関係をチェックするために用います。
1897|*  必要無ければ typeStack=NULL, typeStack_m=0 を指定します。
1898|*  括弧が深すぎる場合、チェックしません。
1899|*  サイズは、BLex2_Kakko_getStackSize 関数で得られた分だけ用意します。
1900|****************************************************************************/
1901|void  BLex2_Kakko_init( BLex2_Kakko* m, int* typeStack,
1902|  int typeStack_m )
1903|{
1904|  m->level = 0;
1905|  m->typeStack = typeStack;
1906|  m->typeStack_m = typeStack_m;
1907|}
1908|
1909|
1910| 
1911|/***************************************************************************
1912|*  73. <<< [BLex2_Kakko_fetch] フェッチ・フェーズ用フェッチ >>> 
1913|*【引数】
1914|*  ・BLex2_Line*  line;   フェッチが済んだ行のサブレックス(または NULL)
1915|*【補足】
1916|*・line を指定すると、括弧対応をミスしている行を検出します。
1917|*  検出しなくてもいい場合は、NULL を指定します。
1918|****************************************************************************/
1919|void  BLex2_Kakko_fetch( BLex2_Kakko* kakko, BLex2* lex, BLex2_Line* line )
1920|{
1921|  int  c = BLex2_peek( lex, 0 );
1922|  if ( c == '(' || c == '{' || c == '[' ) {
1923|    kakko->level ++;
1924|
1925|    /* typeStack に記録する */
1926|    if ( kakko->level * sizeof(int) * 3 <= (unsigned)kakko->typeStack_m ) {
1927|      *kakko->typeStack = c;  kakko->typeStack ++;
1928|      if ( line != NULL ) {
1929|        *kakko->typeStack = line->lineNum;  kakko->typeStack ++;
1930|        *kakko->typeStack = line->column;   kakko->typeStack ++;
1931|      }
1932|      else
1933|        kakko->typeStack += 2;
1934|    }
1935|  }
1936|}
1937|
1938|
1939| 
1940|/***************************************************************************
1941|*  74. <<< [BLex2_Kakko_nextFetch] ネクスト・フェーズ用フェッチ >>> 
1942|****************************************************************************/
1943|void  BLex2_Kakko_nextFetch( BLex2_Kakko* kakko, BLex2* lex, BLex2_Line* line )
1944|{
1945|  int  c = BLex2_peek( lex, 0 );
1946|  if ( c == ')' || c == '}' || c == ']' ) {
1947|    kakko->level --;
1948|
1949|    #ifndef NDEBUG
1950|    if ( kakko->level < 0 ) {
1951|      error2_3( BLex2_Err_TooManyKakkoEnd,
1952|      "'%c' too many from (line=%d, column=%d)", c,
1953|      ( kakko->typeStack == NULL ? -1 : *(kakko->typeStack + 1) ),
1954|      ( kakko->typeStack == NULL ? -1 : *(kakko->typeStack + 2) ) );
1955|    }
1956|    #endif
1957|
1958|    if ( kakko->level * sizeof(int) * 3 < (unsigned)kakko->typeStack_m ) {
1959|      if ( ( c == ')' && *( kakko->typeStack - 3 ) != '(' ) ||
1960|           ( c == '}' && *( kakko->typeStack - 3 ) != '{' ) ||
1961|           ( c == ']' && *( kakko->typeStack - 3 ) != '[' ) ) {
1962|        error2_5 ( BLex2_Err_DefferentKakkoType,
1963|          "括弧の対応関係がおかしい '%c'〜'%c' ファイル:%s 行:%d〜%d",
1964|          *( kakko->typeStack - 3 ), c,
1965|          FileX_getOpenedFName( lex->fp ),
1966|          *( kakko->typeStack - 2 ), line->lineNum );
1967|      }
1968|
1969|      kakko->typeStack -= 3;
1970|    }
1971|  }
1972|}
1973|
1974|
1975| 
1976|/*-------------------------------------------------------------------------*/
1977|/* 75. <<< ◆C言語のコメントのサブレックス (BLex2_CComment) >>> 
1978|/*-------------------------------------------------------------------------*/
1979|
1980|
1981| 
1982|/***************************************************************************
1983|*  76. <<< [BLex2_CComment_init] 初期化する >>> 
1984|*【引数】
1985|*  ・BLex2_CComment*  m;  C言語のコメントのサブレックス
1986|****************************************************************************/
1987|void  BLex2_CComment_init( BLex2_CComment* m )
1988|{
1989|  m->level = 0;
1990|}
1991|
1992|
1993| 
1994|/***************************************************************************
1995|*  77. <<< [BLex2_CComment_fetch] フェッチ・フェーズ用フェッチ >>> 
1996|****************************************************************************/
1997|void  BLex2_CComment_fetch( BLex2_CComment* comnt, BLex2* lex )
1998|{
1999|  int  c1, c2;
2000|
2001|  c1 = BLex2_peek( lex, 0 );
2002|  c2 = BLex2_peek( lex, 1 );
2003|
2004|  /* "/*" */
2005|  if ( c1 == '/' && c2 == '*' ) {
2006|    BLex2_setToken( lex, BLex2_Token_CCommentStart, 2 );
2007|    if ( comnt->level == 0 ) {
2008|      comnt->level ++;
2009|      comnt->type = BLex2_C;
2010|    }
2011|  }
2012|
2013|  /* "*/" */
2014|  else if ( c1 == '*' && c2 == '/' ) {
2015|    BLex2_setToken( lex, BLex2_Token_CCommentEnd, 2 );
2016|  }
2017|
2018|  /* "//" */
2019|  else if ( c1 == '/' && c2 == '/' ) {
2020|    BLex2_setToken( lex, BLex2_Token_CPPCommentStart, 2 );
2021|    if ( comnt->level == 0 ) {
2022|      comnt->level ++;
2023|      comnt->type = BLex2_CPP;
2024|    }
2025|  }
2026|}
2027|
2028|
2029|
2030| 
2031|/***************************************************************************
2032|*  78. <<< [BLex2_CComment_nextFetch] ネクスト・フェーズ用フェッチ >>> 
2033|****************************************************************************/
2034|void  BLex2_CComment_nextFetch( BLex2_CComment* comnt, BLex2* lex )
2035|{
2036|  if ( comnt->level == 0 )  return;
2037|
2038|  if ( comnt->type == BLex2_C &&
2039|       lex->tokenType == BLex2_Token_CCommentEnd ) {
2040|    comnt->level --;
2041|  }
2042|  else if ( comnt->type == BLex2_CPP && BLex2_peek( lex, 0 ) == '\n' ) {
2043|    comnt->level --;
2044|  }
2045|}
2046|
2047|
2048| 
2049|/*-------------------------------------------------------------------------*/
2050|/* 79. <<< ◆C言語の文字列のサブレックス (BLex2_CStr) >>> 
2051|/*-------------------------------------------------------------------------*/
2052|
2053|
2054| 
2055|/***************************************************************************
2056|*  80. <<< [BLex2_CStr_init] 初期化する >>> 
2057|*【引数】
2058|*  ・BLex2_CStr*  m;  C言語の文字列のサブレックス
2059|****************************************************************************/
2060|void  BLex2_CStr_init( BLex2_CStr* m )
2061|{
2062|  m->bInChar = false;
2063|  m->bInStr = false;
2064|  m->bInNow = false;
2065|}
2066|
2067|
2068| 
2069|/***************************************************************************
2070|*  81. <<< [BLex2_CStr_fetch] フェッチ・フェーズ用フェッチ >>> 
2071|****************************************************************************/
2072|void  BLex2_CStr_fetch( BLex2_CStr* m, BLex2* lex )
2073|{
2074|  int  c;
2075|
2076|  c = BLex2_peek( lex, 0 );
2077|
2078|  /* 文字、文字列の中ならエスケープ文字をフェッチ */
2079|  if ( m->bInChar || m->bInStr ) {
2080|    if ( c == '\\' ) {
2081|      c = BLex2_peek( lex, 1 );
2082|      if ( c == '\'' || c == '"' || c == '\\' )
2083|        BLex2_setToken( lex, BLex2_Token_EscChar, 2 );
2084|    }
2085|  }
2086|
2087|  /* 文字、文字列の外なら文字か文字列の開始をフェッチ */
2088|  else {
2089|    if ( c == '\'' ) {
2090|      m->bInChar = true;  m->bInNow = true;
2091|    }
2092|    else if ( c == '"' ) {
2093|      m->bInStr = true;  m->bInNow = true;
2094|    }
2095|  }
2096|}
2097|
2098|
2099| 
2100|/***************************************************************************
2101|*  82. <<< [BLex2_CStr_nextFetch] ネクスト・フェーズ用フェッチ >>> 
2102|****************************************************************************/
2103|void  BLex2_CStr_nextFetch( BLex2_CStr* m, BLex2* lex )
2104|{
2105|  /* 文字か文字列が始まったばかりでなければ... */
2106|  if ( ! m->bInNow ) {
2107|    int  c = BLex2_peek( lex, 0 );
2108|
2109|    /* 文字、文字列の終了をフェッチ */
2110|    if ( m->bInChar && c == '\'' )
2111|      m->bInChar = false;
2112|    else if ( m->bInStr && c == '"' )
2113|      m->bInStr = false;
2114|  }
2115|  m->bInNow = false;
2116|}
2117|
2118|
2119| 
2120|