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_getToken、BLex2_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|