C程序设计语言 (第二版) 练习 5-20
练习 5-20 扩展dcl程序的功能,使它能够处理包含其他成分的声明,例如带有函数参数类型的声明、带有类似于const限定符的声明等。
注意:代码在win32控制台运行,在不同的IDE环境下,有部分可能需要变更。
IDE工具:Visual Studio 2010
代码块:
# include <ctype.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h> # define MAXTOKEN 100 enum { NAME, PARENS, BRACKETS } ;
enum { ERR_YES, ERR_NO } ; void dcl ( void ) ;
void dirdcl ( void ) ; int gettoken ( void ) ;
int tokentype;
char token[ MAXTOKEN] ;
char name[ MAXTOKEN] ;
char datatype[ MAXTOKEN] ;
char out[ 1000 ] ;
int errtoken = ERR_NO; int main ( ) { while ( gettoken ( ) != EOF ) { strcpy ( datatype, token) ; out[ 0 ] = '\0' ; dcl ( ) ; if ( tokentype != '\n' ) printf ( "syntax error\n" ) ; printf ( "%s: %s %s\n" , name, out, datatype) ; } return 0 ;
} void dcl ( void ) { int ns; for ( ns = 0 ; gettoken ( ) == '*' ; ) ns++ ; dirdcl ( ) ; while ( ns-- > 0 ) strcat ( out, " pointer to" ) ;
} void paramdcl ( void ) ; void dirdcl ( void ) { int type; if ( tokentype == '(' ) { dcl ( ) ; if ( tokentype != ')' ) { printf ( "missing )\n" ) ; errtoken = ERR_YES; } } else if ( tokentype == NAME) strcpy ( name, token) ; else { printf ( "error: expected name or (dcl)\n" ) ; errtoken = ERR_YES; } while ( ( type= gettoken ( ) ) == PARENS || type == BRACKETS || type == '(' ) if ( type == PARENS) strcat ( out, " function returning" ) ; else if ( type == '(' ) { strcat ( out, " function expecting" ) ; paramdcl ( ) ; strcat ( out, " and returning" ) ; } else { strcat ( out, " array" ) ; strcat ( out, token) ; strcat ( out, " of" ) ; }
} void dclspec ( void ) ; void paramdcl ( void ) { do { dclspec ( ) ; } while ( tokentype == ',' ) ; if ( tokentype != ')' ) printf ( "error: missing ) in parameter declaration" ) ;
} int typespecifier ( void ) ;
int typequalifier ( void ) ; void dclspec ( void ) { char temp[ MAXTOKEN] ; temp[ 0 ] = '\0' ; gettoken ( ) ; do { if ( tokentype != NAME) { errtoken = ERR_YES; dcl ( ) ; } else if ( typespecifier ( ) || typequalifier ( ) ) { strcat ( temp, " " ) ; strcat ( temp, token) ; gettoken ( ) ; } else { printf ( "error: unknown type in param list\n" ) ; errtoken = ERR_YES; } } while ( tokentype != ',' && tokentype != ')' ) ; strcat ( out, temp) ; if ( tokentype == ',' ) strcat ( out, "," ) ;
} int compare ( const void * s, const void * t) ; int typespecifier ( void ) { static char * type[ ] = { "char" , "int" , "void" } ; char * pt = token; if ( bsearch ( & pt, type, sizeof ( type) / sizeof ( char * ) , sizeof ( char * ) , compare) == NULL ) return 0 ; return 1 ;
} int typequalifier ( void ) { static char * type[ ] = { "const" , "volatile" } ; char * pt = token; if ( bsearch ( & pt, type, sizeof ( type) / sizeof ( char * ) , sizeof ( char * ) , compare) == NULL ) return 0 ; return 1 ;
} int compare ( const void * s, const void * t) { char * * chs; char * * cht; chs = ( char * * ) s; cht = ( char * * ) t; return strcmp ( * chs, * cht) ;
} int getch ( void ) ;
void ungetch ( int ) ; int gettoken ( void ) { int c; char * p = token; if ( errtoken == ERR_YES) { errtoken = ERR_NO; return tokentype; } while ( ( c = getch ( ) ) == ' ' || c == '\t' ) ; if ( c == '(' ) { if ( ( c = getch ( ) ) == ')' ) { strcpy ( token, "()" ) ; return tokentype = PARENS; } else { ungetch ( c) ; return tokentype = '(' ; } } else if ( c == '[' ) { for ( * p++ = c; ( * p++ = getch ( ) ) != ']' ; ) ; * p = '\0' ; return tokentype = BRACKETS; } else if ( isalpha ( c) ) { for ( * p++ = c; isalnum ( c = getch ( ) ) ; ) * p++ = c; * p = '\0' ; ungetch ( c) ; return tokentype = NAME; } return tokentype = c;
} # define BUFSIZE 100 char buf[ BUFSIZE] ;
int bufp = 0 ; int getch ( void ) { return ( bufp > 0 ) ? buf[ -- bufp] : getchar ( ) ;
} void ungetch ( int c) { if ( bufp >= BUFSIZE) printf ( "ungetch: too many characters\n" ) ; else buf[ bufp++ ] = c;
}