home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 March / VPR9703A.ISO / VPR_DATA / DOGA / SOURCES / POLYEDIT.LZH / ML / SCANNER.C < prev    next >
C/C++ Source or Header  |  1996-06-05  |  15KB  |  834 lines

  1. /*
  2.  *        トークンの切り出し
  3.  *
  4.  *        T.Kobayashi        1993.8.5
  5.  */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <io.h>
  11. #include <sys\stat.h>
  12. #include <assert.h>
  13.  
  14. #include "strclass.h"
  15. #include "scanner.h"
  16. #include "err.h"
  17.  
  18. #include "inlib.h"
  19.  
  20. /*#define static*/
  21.  
  22. #if 0
  23. #define        iskanji( c )    ( ( (c) & 0x80 ) != 0 )
  24. #endif
  25. #define        iskanji( c )    (( 0x80 <= (c) && (c) < 0x9f) || ( 0xe0 <= (c) && (c) < 0xfc))
  26.  
  27. /*    予約語リスト    */
  28. static    char    *ResWord[] = {
  29.         NULL,
  30.         "break",
  31.         "const",
  32.         "continue",
  33.         "do",
  34.         "else",
  35.         "for",
  36.         "function",
  37.         "if",
  38.         "private",
  39.         "return",
  40.         "var",
  41.         "while",
  42.         NULL
  43. };
  44.  
  45. /*    定数リスト    */
  46. int            SysConsts ;
  47. ConstStruct    SysConst[MAX_SYSCONST] ;
  48.  
  49. static    char    *BoolConstName[] = {
  50.         "TRUE",
  51.         "FALSE",
  52.         "ON",
  53.         "OFF",
  54.         NULL
  55. };
  56.  
  57. static    BoolData    BoolConst[] = {
  58.         {TYPE_BOOLEAN,        0,        TRUE},
  59.         {TYPE_BOOLEAN,        0,        FALSE},
  60.         {TYPE_BOOLEAN,        0,        TRUE},
  61.         {TYPE_BOOLEAN,        0,        FALSE},
  62. };
  63.  
  64. static    char    *TypeConstName[] = {
  65.         "NOASSIGN",
  66.         "BOOLEAN",
  67.         "INT",
  68.         "REAL",
  69.         "TYPE",
  70.         "ARRAY",
  71.         "FUNC",
  72.         "OBJECT",
  73.         NULL,
  74. };
  75.  
  76. static    TypeData    TypeConst[] = {
  77.         {TYPE_TYPE,        0,        TYPE_NOASN},
  78.         {TYPE_TYPE,        0,        TYPE_BOOLEAN},
  79.         {TYPE_TYPE,        0,        TYPE_INT},
  80.         {TYPE_TYPE,        0,        TYPE_REAL},
  81.         {TYPE_TYPE,        0,        TYPE_TYPE},
  82.         {TYPE_TYPE,        0,        TYPE_ARRAY},
  83.         {TYPE_TYPE,        0,        TYPE_FUNC},
  84.         {TYPE_TYPE,        0,        TYPE_OBJECT},
  85. };
  86.  
  87. /*    大域変数    */
  88. InputStruct    Input ;
  89. char        *InputFile;
  90. int            InputLine ;
  91.  
  92. static    int        GetChar( void );
  93. static    int        NextChar( void );
  94. static    int        Comment( void );
  95. static    int        isword1( int );
  96. static    int        isword2( int );
  97. static    int        isnum( int );
  98. static    int        ishex( int );
  99. static    void    GetNum( DataStruct*, char* );
  100. static    void    GetString( DataStruct* );
  101.  
  102. #if 0
  103. static    inline    int    strcmp(const char *p1, const char *p2)
  104. {
  105.     while (*p1 == *p2) {
  106.         if (*p1 == '\0') {
  107.             return 0;
  108.         }
  109.         p1++;
  110.         p2++;
  111.     }
  112.     return *p1 - *p2;
  113. }
  114. #endif
  115.  
  116.  
  117. /*    初期化    */
  118. void    ScannerInit()
  119. {
  120.     int        i ;
  121.  
  122.     SysConsts = 0 ;
  123.  
  124.     for( i = 0 ; BoolConstName[i] != NULL ; i++ )
  125.         SetSystemConst( BoolConstName[i], (DataStruct*)&BoolConst[i] );
  126.  
  127.     for( i = 0 ; TypeConstName[i] != NULL ; i++ )
  128.         SetSystemConst( TypeConstName[i], (DataStruct*)&TypeConst[i] );
  129. }
  130.  
  131.  
  132. /*    システム定数の設定    */
  133. void    SetSystemConst( name, c )
  134. char    *name ;
  135. DataStruct    *c ;
  136. {
  137.     extern    void    (*ErrorExec)() ;
  138.  
  139.     if ( SysConsts >= MAX_SYSCONST )
  140.         (*ErrorExec)( "システム定数用バッファが確保できません。" );
  141. #if 0
  142.     SysConst[SysConsts].name = name ;
  143.     SysConst[SysConsts].data = *c ;
  144.     SysConsts ++ ;
  145. #else
  146.     {
  147.         int        i, i1, i2, j;
  148.         i1 = -1;
  149.         i2 = SysConsts;
  150.         while (i1 < i2-1) {
  151.             i = (i1+i2)/2;
  152.             j = strcmp(Input.str, SysConst[i].name);
  153.             if (j == 0) {
  154.                 (*ErrorExec)( "システム定数名が重複しています。" );
  155.             } else if (j < 0) {
  156.                 i2 = i;
  157.             } else {
  158.                 i1 = i;
  159.             }
  160.         }
  161.         if (i2 < SysConsts) {
  162.             for (i = SysConsts; i > i2; --i) {
  163.                 SysConst[i].name = SysConst[i-1].name;
  164.                 SysConst[i].data = SysConst[i-1].data;
  165.             }
  166.         }
  167.         SysConst[i2].name = name ;
  168.         SysConst[i2].data = *c ;
  169.         SysConsts ++ ;
  170.     }
  171. #endif
  172. }
  173.  
  174. /*    ソース入力用バッファの初期化    */
  175. void    FileOpen( name )
  176. char    *name ;
  177. {
  178.     int        size ;
  179.     FILE    *fp ;
  180.     struct stat sbuf ;
  181.  
  182.     if ( name != NULL )
  183.     {
  184.         fp = fopen( name, "rb" );
  185.         if ( fp == NULL )
  186.         {
  187.             ParseError( "ファイル %s がオープンできません。", name );
  188.             return ;
  189.         }
  190.         stat( name, &sbuf );
  191.         Input.buf = MemoryAlloc( sbuf.st_size + 1 );
  192.         size = fread( Input.buf, 1, sbuf.st_size, fp );
  193.         if ( size > sbuf.st_size )
  194.         {
  195.             ParseError( "ファイルサイズが不正です。" );
  196.             return ;
  197.         }
  198.         Input.ptr = Input.buf ;
  199.         Input.last = Input.buf + size ;
  200.         Input.buf[size] = Input.buf[size-1];
  201. #if    0
  202.         printf( "size : %d : %d\n", size, sbuf.st_size );
  203.         Input.buf[size] = 0 ;
  204.         printf( "[%x][%x][%x]\n", Input.buf[sbuf.st_size-3],
  205.                         Input.buf[sbuf.st_size-2], Input.buf[sbuf.st_size-1] );
  206.         printf( "last : [%s]\n", &Input.buf[sbuf.st_size-20] );
  207. #endif
  208.  
  209.         Input.fp = fp ;
  210. #if 0
  211.         if (InputFile != NULL) {
  212.             MemoryFree(InputFile);
  213.         }
  214. #endif
  215.         {
  216.             char *p;
  217.             if ((p = strrchr(name, '\\')) == NULL) {
  218.                 p = name;
  219.             } else {
  220.                 p++;
  221.             }
  222.             InputFile = MemoryAlloc( strlen(p) + 1 );
  223.             if ( InputFile == NULL )
  224.             {
  225.                 ParseError( "メモリが確保できません。(FileOpen)" );
  226.                 return ;
  227.             }
  228.             strcpy( InputFile, p);
  229.         }
  230.     }
  231.     InputLine = 1 ;
  232.     Input.ch = 0 ;
  233.     Input.ch1 = 0 ;
  234.     GetChar();
  235.     GetToken();
  236. }
  237.  
  238. /*    ソース入力終了    */
  239. void    FileClose()
  240. {
  241.     fclose( Input.fp );
  242.     MemoryFree( Input.buf );
  243. #if 0
  244.     InputFile[0] = '\0';
  245. #endif
  246. }
  247.  
  248. /*    1文字入力    */
  249. static    int        GetChar()
  250. {
  251.     /*    既にEOF    */
  252.     if ( Input.ch == EOF )
  253.         return EOF ;
  254.     if ( Input.ch1 == 0 )
  255.     {
  256.         if ( Input.ptr == Input.last )
  257.             Input.ch = EOF ;
  258.         else
  259.             Input.ch = *Input.ptr++ ;
  260.     }
  261.     else
  262.     {
  263.         Input.ch = Input.ch1 ;
  264.         Input.ch1 = 0 ;
  265.     }
  266.     if ( Input.ch == '\n' )
  267.         InputLine ++ ;
  268.     return Input.ch ;
  269. }
  270.  
  271. #ifndef __GNUC__
  272. #define inline
  273. #endif
  274.  
  275. /*    1文字先読み    */
  276. static inline    int        NextChar()
  277. {
  278.     if ( Input.ch1 == 0 )
  279.     {
  280.         if ( Input.ptr == Input.last )
  281.             Input.ch1 = EOF ;
  282.         else
  283.             Input.ch1 = *Input.ptr++ ;
  284.     }
  285.     return Input.ch1 ;
  286. }
  287.  
  288. /*    コメントとスペースの処理    */
  289. static    int        Comment()
  290. {
  291.     do {
  292.         while ( 0 <= Input.ch && Input.ch <= 0x20 )
  293.         {
  294.             GetChar();
  295.         }
  296.  
  297.         while( Input.ch == '/' )
  298.         {
  299.             NextChar();
  300.             switch( Input.ch1 )
  301.             {
  302.                 case '*':    /* */
  303.                     GetChar();        /*    '*'    */
  304.                     do
  305.                     {
  306.                         GetChar();
  307.                         if ( Input.ch == '*' )
  308.                             NextChar();
  309.                     }
  310.                     while( Input.ch != '*' || Input.ch1 != '/' );
  311.                     GetChar();        /*    '/'            */
  312.                     GetChar();        /*    next char    */
  313.                     break ;
  314.                 case '/':    /* 行末までコメント    */
  315.                     do
  316.                     {
  317.                         GetChar();
  318.                     }
  319.                     while( Input.ch != '\n' );
  320.                     GetChar();        /*    next char    */
  321.                     break ;
  322.                 default :
  323.                     return '/' ;
  324.             }
  325.         }
  326.     } while ( 0 <= Input.ch && Input.ch <= 0x20 );
  327.  
  328.     return Input.ch ;
  329. }
  330.  
  331. /*    ワードの1バイト目チェック    */
  332. static inline    int        isword1( c )
  333. int        c ;
  334. {
  335.     return c == '_' || isalpha( c );
  336. }
  337.  
  338. /*    ワードの2バイト目以降チェック    */
  339. static inline     int        isword2( c )
  340. int        c ;
  341. {
  342.     return c == '_' || isalnum( c );
  343. }
  344.  
  345. /*    数字の1バイト目チェック    */
  346. static inline     int        isnum( c )
  347. int        c ;
  348. {
  349.     return isdigit( c ) ;
  350. }
  351.  
  352. /*    16進数のチェック    */
  353. static inline     int        ishex( c )
  354. int        c ;
  355. {
  356. #if 0
  357.     return isdigit( c ) || ( 'a' <= c && c <= 'f' ) || ( 'A' <= c && c <= 'F' ) ;
  358. #endif
  359.     return isxdigit( c );
  360. }
  361.  
  362. /*    数値定数    */
  363. static    void    GetNum( data, buf )
  364. DataStruct    *data ;
  365. char        *buf ;
  366. {
  367.     int        i, flag ;
  368.  
  369.     NextChar();
  370.     if ( Input.ch == '0' && Input.ch1 == 'x' )
  371.     {
  372.         /*    16進数    */
  373.         i = 0 ;
  374.         *buf++ = Input.ch ;
  375.         GetChar();
  376.         *buf++ = Input.ch ;
  377.         GetChar();
  378.         while( ishex( Input.ch ) )
  379.         {
  380.             if ( '0' <= Input.ch && Input.ch <= '9' )
  381.                 i = i * 16 + ( Input.ch - '0' );
  382.             else
  383.                 i = i * 16 + ( tolower( Input.ch ) - 'a' + 10 );
  384.             *buf++ = Input.ch ;
  385.             GetChar();
  386.         }
  387.         data->type = TYPE_INT ;
  388.         data->id.i = i ;
  389.         *buf = '\0' ;
  390.         return ;
  391.     }
  392.     else
  393.     {
  394.         char    str[256], *p = str ;
  395.         flag = TYPE_INT ;
  396.         do
  397.         {
  398.             *p++ = Input.ch ;
  399.             if ( ! isdigit( Input.ch ) )
  400.                 flag = TYPE_REAL ;
  401.             GetChar();
  402.             if ( Input.ch == 'E' || Input.ch == 'e' )
  403.                 NextChar();
  404.         }
  405.         while(
  406.             isnum( Input.ch ) ||
  407.             ( Input.ch == '.' ) ||
  408.             ( ( Input.ch == 'E' || Input.ch == 'e' ) && ( Input.ch1 == '+' || Input.ch1 == '-' ) )
  409.         );
  410.  
  411.         *p = '\0' ;
  412.         strcpy( buf, str );
  413.  
  414.         data->type = flag ;
  415.         if ( flag == TYPE_INT )
  416.             data->id.i = atoi( str );
  417.         else
  418.             data->rd.r = atof( str );
  419.         return ;
  420.     }
  421. }
  422.  
  423. /*    文字列定数    */
  424. static    void    GetString( data )
  425. DataStruct    *data ;
  426. {
  427.     int        ch ;
  428.     int        len ;
  429.     char    str[STRING_CHARS] ;
  430.  
  431.     assert( Input.ch == '\"' );
  432.  
  433.     len = 0 ;
  434.     do
  435.     {
  436.         GetChar();
  437.         switch( Input.ch )
  438.         {
  439.             case '\\':
  440.                 GetChar();
  441.                 switch( Input.ch )
  442.                 {
  443.                     case 'n':
  444.                         ch = '\n' ;
  445.                         break ;
  446.                     case 't':
  447.                         ch = '\t' ;
  448.                         break ;
  449.                     case 'x':        /*  hex  */
  450.                         ch = 0 ;
  451.                         NextChar();
  452.                         while( ishex( Input.ch1 ) )
  453.                         {
  454.                             GetChar();
  455.                             if ( '0' <= Input.ch && Input.ch <= '9' )
  456.                                 ch = ch * 16 + ( Input.ch - '0' );
  457.                             else
  458.                                 ch = ch * 16 + ( tolower( Input.ch ) - 'a' + 10 );
  459.                             NextChar();
  460.                         }
  461.                         break ;
  462.                     case '0': case '1': case '2': case '3':        /*  oct  */
  463.                     case '4': case '5': case '6': case '7':
  464.                         ch = 0 ;
  465.                         NextChar();
  466.                         while( '0' <= Input.ch1 && Input.ch1 <= '7' )
  467.                         {
  468.                             GetChar();
  469.                             ch = ch * 8 + ( Input.ch - '0' );
  470.                             NextChar();
  471.                         }
  472.                         break ;
  473.                     default:
  474.                         ch = Input.ch ;
  475.                 }
  476.                 break ;
  477.             case '\"':
  478.                 GetChar();        /*    next char */
  479.                 Comment();
  480.                 if ( Input.ch == '\"' )
  481.                     continue ;
  482.                 else
  483.                     ch = '\0';
  484.                 break ;
  485.             case EOF:
  486.                 ch = '\0';
  487.                 break ;
  488.             default:
  489.                 ch = Input.ch ;
  490.                 break ;
  491.         }
  492.         if ( len < STRING_CHARS )
  493.             str[len++] = ch ;
  494.         if ( iskanji( ch ) )
  495.         {
  496.             GetChar();
  497.             str[len++] = Input.ch ;
  498.         }
  499.     }
  500.     while( ch != '\0' );
  501.  
  502.     str[len] = '\0' ;
  503.  
  504.     data->type = TYPE_OBJECT ;
  505.     data->od.ptr = (Object*)StringSet( str );
  506.  
  507.     return ;
  508. }
  509.  
  510. /*    トークンの切り出し    */
  511. int        GetToken()
  512. {
  513.     int        i, twochar ;
  514.  
  515.     Comment();
  516.  
  517.     if ( Input.ch == EOF )
  518.     {
  519.         Input.token = SYM_EOF ;
  520.         return SYM_EOF ;
  521.     }
  522.     if ( isnum( Input.ch ) )
  523.     {
  524.         /*    数値定数    */
  525.         Input.token = SYM_CONSTDATA ;
  526.         GetNum( &Input.data, Input.str );
  527.     }
  528.     else if ( Input.ch == '\'' )
  529.     {
  530.         /*    単一文字    */
  531.         Input.token = SYM_CONSTDATA ;
  532.         Input.data.type = TYPE_INT ;
  533.         Input.data.id.i = 0 ;
  534.         GetChar();
  535.         while( Input.ch != '\'' )
  536.         {
  537.             Input.data.id.i = ( Input.data.id.i << 8 ) | Input.ch ;
  538.             GetChar();
  539.         }
  540.         GetChar();
  541.     }
  542.     else if ( Input.ch == '\"' )
  543.     {
  544.         /*    文字列定数    */
  545.         Input.token = SYM_CONSTDATA ;
  546.         GetString( &Input.data );
  547.         strcpy( Input.str, "" );
  548.     }
  549.     else if ( isword1( Input.ch ) )
  550.     {
  551.         /*    ワード切り出し    */
  552.         i = 0 ;
  553.         do
  554.         {
  555.             if ( i < IDENT_CHARS )
  556.             {
  557.                 Input.str[i] = Input.ch ;
  558.                 i++ ;
  559.             }
  560.             GetChar();
  561.         }
  562.         while( isword2( Input.ch ) );
  563.         Input.str[i] = '\0' ;
  564.  
  565.         /*    予約語のチェック    */
  566. #if 0
  567.         for( i = 1 ; ResWord[i] != NULL ; i++ )
  568.         {
  569.             if ( strcmp( Input.str, ResWord[i] ) == 0 )
  570.             {
  571.                 Input.token = SYM_RESERVED + i ;
  572.                 return Input.token ;
  573.             }
  574.         }
  575. #else
  576.         {
  577.             int        i1, i2, j;
  578.             i1 = 0;
  579.             i2 = (sizeof(ResWord)/sizeof(ResWord[0]))-1;
  580.             while (i1 < i2-1) {
  581.                 i = (i1+i2)/2;
  582.                 j = strcmp(Input.str, ResWord[i]);
  583.                 if (j == 0) {
  584.                     Input.token = SYM_RESERVED + i ;
  585.                     return Input.token ;
  586.                 } else if (j < 0) {
  587.                     i2 = i;
  588.                 } else {
  589.                     i1 = i;
  590.                 }
  591.             }
  592.         }
  593.  
  594. #endif
  595. #if 1
  596.         /*    システム定数のチェック    */
  597.         for( i = 0 ; i < SysConsts ; i++ )
  598.         {
  599.             if ( strcmp( Input.str, SysConst[i].name ) == 0 )
  600.             {
  601.                 Input.token = SYM_CONSTDATA ;
  602.                 Input.data = SysConst[i].data ;
  603.                 return Input.token ;
  604.             }
  605.         }
  606. #else
  607.         {
  608.             int        i1, i2, j;
  609.             i1 = -1;
  610.             i2 = SysConsts;
  611.             while (i1 < i2-1) {
  612.                 i = (i1+i2)/2;
  613.                 j = strcmp(Input.str, SysConst[i].name);
  614.                 if (j == 0) {
  615.                     Input.token = SYM_CONSTDATA ;
  616.                     Input.data = SysConst[i].data ;
  617.                     return Input.token ;
  618.                 } else if (j < 0) {
  619.                     i2 = i;
  620.                 } else {
  621.                     i1 = i;
  622.                 }
  623.             }
  624.         }
  625.  
  626. #endif
  627.  
  628.         /*    識別子    */
  629.         Input.token = SYM_IDENT ;
  630.     }
  631.     else
  632.     {
  633.         twochar = FALSE ;
  634.         switch( Input.ch )
  635.         {
  636.             /*    かっこ    */
  637.             case '(':
  638.                 Input.token = SYM_OPEN1 ;
  639.                 break ;
  640.             case ')':
  641.                 Input.token = SYM_CLOSE1 ;
  642.                 break ;
  643.             case '{':
  644.                 Input.token = SYM_OPEN2 ;
  645.                 break ;
  646.             case '}':
  647.                 Input.token = SYM_CLOSE2 ;
  648.                 break ;
  649.             case '[':
  650.                 Input.token = SYM_OPEN3 ;
  651.                 break ;
  652.             case ']':
  653.                 Input.token = SYM_CLOSE3 ;
  654.                 break ;
  655.  
  656.             /*    四則演算&代入    */
  657.             case '+':
  658.                 NextChar();
  659.                 if ( Input.ch1 == '=' )
  660.                 {
  661.                     Input.token = SYM_ASN_PLUS ;
  662.                     twochar = TRUE ;
  663.                 }
  664.                 else if ( Input.ch1 == '+' )
  665.                 {
  666.                     Input.token = SYM_ASN_INC ;
  667.                     twochar = TRUE ;
  668.                 }
  669.                 else
  670.                     Input.token = SYM_PLUS ;
  671.                 break ;
  672.             case '-':
  673.                 NextChar();
  674.                 if ( Input.ch1 == '=' )
  675.                 {
  676.                     Input.token = SYM_ASN_MINUS ;
  677.                     twochar = TRUE ;
  678.                 }
  679.                 else if ( Input.ch1 == '-' )
  680.                 {
  681.                     Input.token = SYM_ASN_DEC ;
  682.                     twochar = TRUE ;
  683.                 }
  684.                 else if ( Input.ch1 == '>' )
  685.                 {
  686.                     Input.token = SYM_REFER ;
  687.                     twochar = TRUE ;
  688.                 }
  689.                 else
  690.                     Input.token = SYM_MINUS ;
  691.                 break ;
  692.             case '.':
  693.                 Input.token = SYM_DOT ;
  694.                 break ;
  695.             case '*':
  696.                 NextChar();
  697.                 if ( Input.ch1 == '=' )
  698.                 {
  699.                     Input.token = SYM_ASN_MULT ;
  700.                     twochar = TRUE ;
  701.                 }
  702.                 else
  703.                     Input.token = SYM_MULT ;
  704.                 break ;
  705.             case '/':
  706.                 NextChar();
  707.                 if ( Input.ch1 == '=' )
  708.                 {
  709.                     Input.token = SYM_ASN_DIVIDE ;
  710.                     twochar = TRUE ;
  711.                 }
  712.                 else
  713.                     Input.token = SYM_DIVIDE ;
  714.                 break ;
  715.             case '%':
  716.                 Input.token = SYM_MOD ;
  717.                 break ;
  718.             case '&':
  719.                 NextChar();
  720.                 if ( Input.ch1 == '=' )
  721.                 {
  722.                     Input.token = SYM_ASN_AND;
  723.                     twochar = TRUE ;
  724.                 }
  725.                 else
  726.                     Input.token = SYM_AND ;
  727.                 break ;
  728.             case '|':
  729.                 NextChar();
  730.                 if ( Input.ch1 == '=' )
  731.                 {
  732.                     Input.token = SYM_ASN_OR ;
  733.                     twochar = TRUE ;
  734.                 }
  735.                 else
  736.                     Input.token = SYM_OR ;
  737.                 break ;
  738.             case '^':
  739.                 NextChar();
  740.                 if ( Input.ch1 == '=' )
  741.                 {
  742.                     Input.token = SYM_ASN_XOR ;
  743.                     twochar = TRUE ;
  744.                 }
  745.                 else
  746.                     Input.token = SYM_XOR ;
  747.                 break ;
  748.             case '!':
  749.                 NextChar();
  750.                 if ( Input.ch1 == '=' )
  751.                 {
  752.                     Input.token = SYM_NOTEQ ;
  753.                     twochar = TRUE ;
  754.                 }
  755.                 else
  756.                     Input.token = SYM_NOT ;
  757.                 break ;
  758.             case '=':
  759.                 NextChar();
  760.                 if ( Input.ch1 == '=' )
  761.                 {
  762.                     Input.token = SYM_EQ ;
  763.                     twochar = TRUE ;
  764.                 }
  765.                 else
  766.                     Input.token = SYM_ASSIGN ;
  767.                 break ;
  768.  
  769.             /*    比較    */
  770.             case '<':
  771.                 NextChar();
  772.                 if ( Input.ch1 == '=' )
  773.                 {
  774.                     Input.token = SYM_LSSEQ ;
  775.                     twochar = TRUE ;
  776.                 }
  777.                 else if ( Input.ch1 == '<' )
  778.                 {
  779.                     Input.token = SYM_LSFT ;
  780.                     twochar = TRUE ;
  781.                 }
  782.                 else
  783.                     Input.token = SYM_LSS ;
  784.                 break ;
  785.             case '>':
  786.                 NextChar();
  787.                 if ( Input.ch1 == '=' )
  788.                 {
  789.                     Input.token = SYM_GTREQ ;
  790.                     twochar = TRUE ;
  791.                 }
  792.                 else if ( Input.ch1 == '>' )
  793.                 {
  794.                     Input.token = SYM_RSFT ;
  795.                     twochar = TRUE ;
  796.                 }
  797.                 else
  798.                     Input.token = SYM_GTR ;
  799.                 break ;
  800.  
  801.             /*    その他    */
  802.             case ',':
  803.                 Input.token = SYM_COMMA ;
  804.                 break ;
  805.             case ';':
  806.                 Input.token = SYM_SEMCLN ;
  807.                 break ;
  808.             case ':':
  809.                 Input.token = SYM_COLON ;
  810.                 break ;
  811.             case '#':
  812.                 Input.token = SYM_PREPROC ;
  813.                 break ;
  814.             case EOF:
  815.                 Input.token = SYM_EOF ;
  816.                 break ;
  817.             default:
  818.                 Input.token = SYM_UNKNOWN ;
  819.                 break ;
  820.         }
  821.         Input.str[0] = Input.ch ;
  822.         if ( twochar )
  823.         {
  824.             GetChar();
  825.             Input.str[1] = Input.ch ;
  826.             Input.str[2] = '\0' ;
  827.         }
  828.         else
  829.             Input.str[1] = '\0' ;
  830.         GetChar();
  831.     }
  832.     return Input.token ;
  833. }
  834.