Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Programming exercise/challenge Date: Wed, 30 Dec 2020 09:40:30 -0800 Organization: A noiseless patient Spider Lines: 284 Message-ID: <86a6tvur8x.fsf@linuxsc.com> References: <86wnxwkyol.fsf@linuxsc.com> <5fcbb652$0$16505$e4fe514c@textnews.kpn.nl> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="bad9f3398650fdf0e991b5310f5ac4d7"; logging-data="10180"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/77Ul5ZUcHS4VcM8JPpjuNUxxhG/o+oXE=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:szxwD8Lj4AGQ5pbDcopBaUepADw= sha1:8RK/JzzRNLEcXl4vfVVagfw3cvU= Xref: csiph.com comp.lang.c:157908 Sjouke Burry writes: > On 05.12.20 17:25, Tim Rentsch wrote: > >> Prompted by some recent discussion regarding 'goto' statements and >> state machines, I would like to propose a programming exercise. >> (It is perhaps a bit too large to be called an exercise, but not so >> difficult that it deserves the label of challenge. On the other >> hand there are some constraints so maybe challenge is apropos. In >> any case somewhere in between those two bounds.) >> >> Short problem statement: a C program to remove comments from C >> source input. [...] > > If you show yours , maybe some of us will show theirs........ If you have been waiting for me, here it is. This program is basically the same as the one I wrote just before posting the exercise statement, not counting some cosmetic cleanup and a change so comments would be replaced by a single blank. /* uncomment.c - remove comments from C source files */ #include #include typedef unsigned long Count; typedef enum { ALL_GOOD = 0, UNTERMINATED_CHARACTER_LITERAL, UNTERMINATED_STRING, UNTERMINATED_COMMENT, } Status; typedef Status Reader_f( Count ); static Status restart( int ); static Reader_f start, sl, slbs, slsl, slslbs, slst, slstst, slststbs, sq, sqbs, sqbsbs, sqbs__, dq, dqbs, dqbsbs, dqbs__; static Count show_sl_lcs_bs( Count ); static Count show_sl_lcs( Count ); static Count show_lcs( Count ); static int next( void ); static int outc( int ); enum { SQ = '\'', DQ = '\"', SL = '/', STAR = '*', BS = '\\', NL = '\n', SP = ' ', }; /* main */ int main(){ return start(0) == ALL_GOOD ? EXIT_SUCCESS : EXIT_FAILURE; } /* top level */ Status restart( int c ){ return ungetc( c, stdin ), start( 0 ); } Status start( Count n ){ int c = getchar(); return c == SL ? sl( 0 ) : c == DQ ? outc( c ), dq( 0 ) : c == SQ ? outc( c ), sq( 0 ) : c != EOF ? outc( c ), start( 0 ) :/* c == EOF */ ALL_GOOD; } /* slant character - top level */ Status sl( Count n ){ int c = getchar(); return c == SL ? slsl( 0 ) : c == STAR ? slst( 0 ) : c == EOF ? show_sl_lcs( n ), ALL_GOOD : c != BS ? show_sl_lcs( n ), restart( c ) :/* c == BS */ slbs( n ); } Status slbs( Count n ){ int c = getchar(); return c == EOF ? show_sl_lcs_bs( n ), ALL_GOOD : c != NL ? show_sl_lcs_bs( n ), restart( c ) :/* c == NL */ sl( n+1 ); } /* slant character helper functions - show counted line splices */ Count show_sl_lcs_bs( Count n ){ return show_sl_lcs( n ), outc( BS ), 0; } Count show_sl_lcs( Count n ){ return outc( SL ), show_lcs( n ); } Count show_lcs( Count n ){ return n > 0 ? outc( BS ), outc( NL ), show_lcs( n-1 ) : 0; } /* new style C comment - 'slsl' */ Status slsl( Count n ){ int c = getchar(); return c == NL ? outc( c ), start( 0 ) : c == BS ? slslbs( n ) : c == EOF ? outc( NL ), ALL_GOOD : slsl( 0 ); } Status slslbs( Count n ){ int c = getchar(); return c == NL ? slsl( 0 ) : c == EOF ? outc( NL ), ALL_GOOD : c == BS ? slslbs( 0 ) : slsl( 0 ); } /* old style C comment - 'slst' */ Status slst( Count n ){ int c = getchar(); return c == EOF ? outc( NL ), UNTERMINATED_COMMENT : c == NL ? slst( 0 ) : c == STAR ? slstst( 0 ) : slst( 0 ); } Status slstst( Count n ){ int c = getchar(); return c == EOF ? UNTERMINATED_COMMENT : c == NL ? slst( 0 ) : c == SL ? outc( SP ), start( 0 ) : c == STAR ? slstst( 0 ) : c == BS ? slststbs( 0 ) : slst( 0 ); } Status slststbs( Count n ){ int c = getchar(); return c == EOF ? UNTERMINATED_COMMENT : c == NL ? slstst( 0 ) : c == STAR ? slstst( 0 ) : slst( 0 ); } /* character literals - 'sq' */ Status sq( Count n ){ int c = next(); return c == SQ ? start( 0 ) : c == NL ? UNTERMINATED_CHARACTER_LITERAL : c == EOF ? UNTERMINATED_CHARACTER_LITERAL : c == BS ? sqbs( 0 ) : sq( 0 ); } Status sqbs( Count n ){ int c = next(); return c == NL ? sq( 0 ) : c == EOF ? UNTERMINATED_CHARACTER_LITERAL : c == BS ? sqbsbs( 0 ) : sq( 0 ); } Status sqbsbs( Count n ){ int c = next(); return c == NL ? sqbs__( 0 ) : c == EOF ? UNTERMINATED_CHARACTER_LITERAL : c == SQ ? start( 0 ) : c == BS ? sqbs( 0 ) : sq( 0 ); } Status sqbs__( Count n ){ int c = next(); return c == NL ? UNTERMINATED_CHARACTER_LITERAL : c == EOF ? UNTERMINATED_CHARACTER_LITERAL : c == BS ? sqbsbs( 0 ) : sq( 0 ); } /* string literals - 'dq' */ Status dq( Count n ){ int c = next(); return c == DQ ? start( 0 ) : c == NL ? UNTERMINATED_STRING : c == EOF ? UNTERMINATED_STRING : c == BS ? dqbs( 0 ) : dq( 0 ); } Status dqbs( Count n ){ int c = next(); return c == NL ? dq( 0 ) : c == EOF ? UNTERMINATED_STRING : c == BS ? dqbsbs( 0 ) : dq( 0 ); } Status dqbsbs( Count n ){ int c = next(); return c == NL ? dqbs__( 0 ) : c == EOF ? UNTERMINATED_STRING : c == DQ ? start( 0 ) : c == BS ? dqbs( 0 ) : dq( 0 ); } Status dqbs__( Count n ){ int c = next(); return c == NL ? UNTERMINATED_STRING : c == EOF ? UNTERMINATED_STRING : c == BS ? dqbsbs( 0 ) : dq( 0 ); } /* character input */ int next(){ return outc( getchar() ); } /* output */ int outc( int c ){ return c != EOF ? putchar( c ), c : c; }