source: libcfa/src/enum.cfa @ d6c5faa

Last change on this file since d6c5faa was 5f210c0, checked in by JiadaL <j82liang@…>, 4 months ago

Change enum pos to signed int to avoid underflow; operator on enum will not have range check (but succ and pred still have range check

  • Property mode set to 100644
File size: 4.3 KB
RevLine 
[c333ed2]1#include "enum.hfa"
[85855b0]2#include "fstream.hfa"
[6d2b3dc]3#include <string.h>
[c333ed2]4
[03ac869]5#pragma GCC visibility push(default)
6
[0c327ce]7forall( E | Serial( E ) ) {
[5f210c0]8        E fromInt( int i ) {
[0097d08]9                E upper = upperBound();
10                E lower = lowerBound();
11                // It is okay to overflow as overflow will be theoretically caught by the other bound
[2e6b2a0]12                if ( i < fromInstance( lower ) || i > fromInstance( upper ) )
13                        abort( "call to fromInt has index %d outside enumeration range %d-%d",
14                                   i, fromInstance( lower ), fromInstance( upper ) );
[0097d08]15                return fromInt_unsafe( i );
16        }
[0c327ce]17
[0097d08]18        E succ( E e ) {
19                E upper = upperBound();
[2e6b2a0]20                if ( fromInstance( e ) >= fromInstance( upper ) )
21                        abort( "call to succ() exceeds enumeration upper bound of %d", fromInstance( upper ) );
[0097d08]22                return succ_unsafe(e);
23        }
[0c327ce]24
[0097d08]25        E pred( E e ) {
26                E lower = lowerBound();
[876739f]27                if ( fromInstance( e ) <= fromInstance(lower ) )
[2e6b2a0]28                        abort( "call to pred() exceeds enumeration lower bound of %d", fromInstance( lower ) );
[876739f]29                return pred_unsafe( e );
[0097d08]30        }
[0c327ce]31
[0097d08]32        int Countof( __attribute__((unused)) E e ) {
33                E upper = upperBound();
34                E lower = lowerBound();
[0c327ce]35                return fromInstance( upper ) + fromInstance( lower ) + 1;
[0097d08]36        }
[0c327ce]37}
38
[0097d08]39forall( istype & | istream( istype ), E | CfaEnum( E ) | Serial( E ) )
[64eeb06]40istype & ?|?( istype & is, E & e ) {
[2e6b2a0]41//      fprintf( stderr, "here0\n" );
[64eeb06]42        if ( eof( is ) ) throwResume ExceptionInst( missing_data );
[d287f3e]43
[d796be70]44        // Match longest input enumerator string to enumerator labels, where enumerator names are unique.
45
[0097d08]46        int N = countof( E ), lnths[N], max = 0;
[2e6b2a0]47//      printf( "N %d\n", N );
[0097d08]48        int r = 0;
[f90c092]49        // for ( s; E : r; 0~@ ) {
[0097d08]50        for ( s; E ) {                                                                          // scan string rows gathering lengths
51                lnths[r] = strlen( label( s ) );
52                if ( lnths[r] > max ) max = lnths[r];
53//              fprintf( stderr, "%s %d %d\n", label( s ), lnths[r], max );
54                r += 1;
[6d2b3dc]55        } // for
[d287f3e]56
[0097d08]57        int mcol = -1;                                                                          // last match column
[2e6b2a0]58        char ch, curr = '\0', prev = '\0';
59
60        fmt( is, " " );                                                                         // skip optional whitespace
[0097d08]61        for ( c; max ) {                                                                        // scan columns of the label matix (some columns missing)
[2e6b2a0]62                int args = fmt( is, "%c", &ch );                                // read character
[f90c092]63//              fprintf( stderr, "fmt args: %d eof: %d\n", args, eof(is) );
[d796be70]64          if ( eof( is ) ) {
[2e6b2a0]65//                      fprintf( stderr, "Eof1\n" );
66                        if ( c == 0 ) return is;                                        // no characters read ?
[d796be70]67                        clear( is );                                                            // => read something => reset EOF => detect again on next read
[2e6b2a0]68//                      fprintf( stderr, "Eof2\n" );
[d796be70]69                        break;
70                } // if
[0097d08]71          if ( args != 1 ) throwResume ExceptionInst( missing_data ); // may be unnecessary since reading single character
[d796be70]72
[2e6b2a0]73//              printf( "read '%c'\n", ch );
[0097d08]74                for ( r; N ) {                                                                  // scan enumeration strings for matching character in current column
75//                      printf( "%d %d %d\n", c, r, lnths[r] );
76                        if ( c < lnths[r] ) {                                           // string long enough for this column check ?
77                                char match = label( fromInt( r ) )[c];  // optimization
[2e6b2a0]78//                              printf( "%c '%c'\n", match, ch );
[d796be70]79                                // Stop on first match, could be other matches.
[0097d08]80                                if ( (match == ch) && (c == 0 || curr == label( fromInt( r ) )[c - 1]) ) {
81//                                      printf( "match %d %d %d '%c' '%c' '%c' '%c' 'c'\n", c, r, lnths[r], match, ch, prev, label( fromInt( r ) )[c - 1] );
82                                        mcol = c;                                                       // matching column
83                                        prev = curr;                                            // last matching character
84                                        curr = ch;                                                      // current matching character
[2e6b2a0]85                                        break;
86                                } // if
87                        } // if
88                } else {
[0097d08]89//                      fprintf( stderr, "finished mcol: %d ch: '%c' curr: '%c' prev: '%c'\n", mcol, ch, curr, prev );
90                        ungetc( ch, is );                                                       // push back last unmatching character
91                        if ( mcol == -1 ) throwResume ExceptionInst( missing_data ); // no matching character in first column
92                        break;
[2e6b2a0]93                } // for
94//              printf( "\n" );
95//      } else {
[0097d08]96//              fprintf( stderr, "finished2 %d\n", mcol );
[2e6b2a0]97        } // for
[0097d08]98
99        for ( c; N ) {                                                                          // scan enumeration strings of length "mcol" for match
100                if ( mcol == lnths[c] - 1 ) {
101                        char match = label( fromInt( c ) )[mcol];       // optimization
102//                      printf( "finished1 mcol: %d c: %d lnth: %d match: '%c' curr: '%c' prev: '%c'\n", mcol, c, lnths[c], match, curr, prev );
103                        if ( (match == curr) && (mcol == 0 || prev == label( fromInt( c ) )[mcol - 1]) ) {
104                                e = fromInt( c );
[2e6b2a0]105                                break;
[d796be70]106                        } // if
[2e6b2a0]107                } // if
108        } else {
[0097d08]109//              fprintf( stderr, "finished3 %d\n", mcol );
110                throwResume ExceptionInst( missing_data );              // no match in this column
[2e6b2a0]111        } // for
[64eeb06]112        return is;
113}
114
[236f133]115forall( ostype & | ostream( ostype ), E | CfaEnum( E ) ) {
[64eeb06]116        ostype & ?|?( ostype & os, E e ) {
117                return os | label( e );
118        }
[b12e4ad]119        OSTYPE_VOID_IMPL( os, E )
[259012e]120}
Note: See TracBrowser for help on using the repository browser.