source: libcfa/src/enum.cfa@ b24cbaf

Last change on this file since b24cbaf was 3ac5fd8, checked in by Peter A. Buhr <pabuhr@…>, 13 months ago

first attempt changing end-of-file to an exception

  • 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 ) )
[e49c308]13 abort( "call to fromInt has index %d outside of enumeration range %d-%d.",
[2e6b2a0]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 ) )
[e49c308]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 ) )
[e49c308]28 abort( "call to pred() exceeds enumeration lower bound of %d.", fromInstance( lower ) );
[876739f]29 return pred_unsafe( e );
[0097d08]30 }
[0c327ce]31
[e49c308]32 int Countof( E ) {
[0097d08]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" );
[3ac5fd8]42 if ( eof( is ) ) throwResume ExceptionInst( end_of_file );
[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
[3ac5fd8]61 if ( eof( is ) ) throwResume ExceptionInst( end_of_file );
62
[0097d08]63 for ( c; max ) { // scan columns of the label matix (some columns missing)
[2e6b2a0]64 int args = fmt( is, "%c", &ch ); // read character
[f90c092]65// fprintf( stderr, "fmt args: %d eof: %d\n", args, eof(is) );
[d796be70]66 if ( eof( is ) ) {
[2e6b2a0]67// fprintf( stderr, "Eof1\n" );
68 if ( c == 0 ) return is; // no characters read ?
[d796be70]69 clear( is ); // => read something => reset EOF => detect again on next read
[2e6b2a0]70// fprintf( stderr, "Eof2\n" );
[d796be70]71 break;
72 } // if
[0097d08]73 if ( args != 1 ) throwResume ExceptionInst( missing_data ); // may be unnecessary since reading single character
[d796be70]74
[2e6b2a0]75// printf( "read '%c'\n", ch );
[0097d08]76 for ( r; N ) { // scan enumeration strings for matching character in current column
77// printf( "%d %d %d\n", c, r, lnths[r] );
78 if ( c < lnths[r] ) { // string long enough for this column check ?
79 char match = label( fromInt( r ) )[c]; // optimization
[2e6b2a0]80// printf( "%c '%c'\n", match, ch );
[d796be70]81 // Stop on first match, could be other matches.
[0097d08]82 if ( (match == ch) && (c == 0 || curr == label( fromInt( r ) )[c - 1]) ) {
83// printf( "match %d %d %d '%c' '%c' '%c' '%c' 'c'\n", c, r, lnths[r], match, ch, prev, label( fromInt( r ) )[c - 1] );
84 mcol = c; // matching column
85 prev = curr; // last matching character
86 curr = ch; // current matching character
[2e6b2a0]87 break;
88 } // if
89 } // if
90 } else {
[0097d08]91// fprintf( stderr, "finished mcol: %d ch: '%c' curr: '%c' prev: '%c'\n", mcol, ch, curr, prev );
92 ungetc( ch, is ); // push back last unmatching character
93 if ( mcol == -1 ) throwResume ExceptionInst( missing_data ); // no matching character in first column
94 break;
[2e6b2a0]95 } // for
96// printf( "\n" );
97// } else {
[0097d08]98// fprintf( stderr, "finished2 %d\n", mcol );
[2e6b2a0]99 } // for
[0097d08]100
101 for ( c; N ) { // scan enumeration strings of length "mcol" for match
102 if ( mcol == lnths[c] - 1 ) {
103 char match = label( fromInt( c ) )[mcol]; // optimization
104// printf( "finished1 mcol: %d c: %d lnth: %d match: '%c' curr: '%c' prev: '%c'\n", mcol, c, lnths[c], match, curr, prev );
105 if ( (match == curr) && (mcol == 0 || prev == label( fromInt( c ) )[mcol - 1]) ) {
106 e = fromInt( c );
[2e6b2a0]107 break;
[d796be70]108 } // if
[2e6b2a0]109 } // if
110 } else {
[0097d08]111// fprintf( stderr, "finished3 %d\n", mcol );
112 throwResume ExceptionInst( missing_data ); // no match in this column
[2e6b2a0]113 } // for
[64eeb06]114 return is;
115}
116
[236f133]117forall( ostype & | ostream( ostype ), E | CfaEnum( E ) ) {
[64eeb06]118 ostype & ?|?( ostype & os, E e ) {
119 return os | label( e );
120 }
[b12e4ad]121 OSTYPE_VOID_IMPL( os, E )
[259012e]122}
Note: See TracBrowser for help on using the repository browser.