From 4828136228c43e3680984ab7ffc73efa3b26db15 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 22 Aug 2021 16:18:10 +0000 Subject: cc: more structured code --- miniany/cc.c | 461 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 261 insertions(+), 200 deletions(-) diff --git a/miniany/cc.c b/miniany/cc.c index 8d36653..5400305 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -1,115 +1,129 @@ -int col; -int row; +/* scanner */ -int pushback; - -int token; - -int DEBUG_SCANNER; +enum { + S_PLUS = 1, + S_MINUS, + S_STAR, + S_SLASH, + S_SEMICOLON, + S_EQUALS, + S_INT = 10, + S_IDENT, + S_NUM = 20, + S_ERR = 30, + S_EOI = 31 +}; enum { MAX_IDENT_LEN = 20 }; -void pushBack( int c ) +struct Scanner { + int col; + int row; + int c; + int pushback; + int token; + int debug; + int num; + char *ident; +}; + +struct Scanner *createScanner( ) { - pushback = c; + struct Scanner *scanner; + + scanner = (struct Scanner *)malloc( sizeof( struct Scanner ) ); + scanner->col = 0; + scanner->row = 1; + scanner->c = EOF; + scanner->pushback = 0; + scanner->ident = (char *)malloc( MAX_IDENT_LEN + 1 ); + scanner->debug = 0; + + return scanner; } -int getChar( ) -{ - int c; - - if( pushback ) { - c = pushback; - pushback = 0; - return c; +void freeScanner( struct Scanner *scanner ) +{ + free( scanner->ident ); + free( (char *)scanner ); +} + +void pushBack( struct Scanner *scanner ) +{ + scanner->pushback = scanner->c; +} + +int getChar( struct Scanner *scanner ) +{ + if( scanner->pushback ) { + scanner->c = scanner->pushback; + scanner->pushback = 0; + return scanner->c; } - c = getchar( ); - if( c == EOF ) { - return c; + scanner->c = getchar( ); + if( scanner->c == EOF ) { + return scanner->c; } - col++; - if( c == '\n' ) { - col = 0; - row++; + scanner->col++; + if( scanner->c == '\n' ) { + scanner->col = 0; + scanner->row++; } - return c; + + return scanner->c; } -int skipWhite( ) +int skipWhite( struct Scanner *scanner ) { - int c; - - c = getChar( ); - while( isspace( c ) ) { - c = getChar( ); + scanner->c = getChar( scanner ); + while( isspace( scanner->c ) ) { + scanner->c = getChar( scanner ); } - return c; + return scanner->c; } -enum { - S_PLUS = 1, - S_MINUS, - S_STAR, - S_SLASH, - S_SEMICOLON, - S_EQUALS, - S_INT = 10, - S_IDENT, - S_NUM = 20, - S_ERR = 30, - S_EOI = 31 -}; - -void printErrorHeader( ) +void printErrorHeader( struct Scanner *scanner ) { putstring( "Error line " ); - putint( row ); + putint( scanner->row ); putstring( ", pos " ); - putint( col ); + putint( scanner->col ); putstring( ": " ); } -int num; - -void scanNumber( int c ) +void scanNumber( struct Scanner *scanner ) { - num = c - '0'; - c = getChar( ); - while( isdigit( c ) ) { - num = 10 * num + ( c - '0' ); - c = getChar( ); + scanner->num = scanner->c - '0'; + scanner->c = getChar( scanner ); + while( isdigit( scanner->c ) ) { + scanner->num = 10 * scanner->num + ( scanner->c - '0' ); + scanner->c = getChar( scanner ); } - pushBack( c ); + pushBack( scanner ); } -/* c4: no data segment allocation in char array decleration */ -char *ident; -/*char ident[20]; - char ident[MAX_IDENT_LEN]; -*/ - -void scanIdent( int c ) +void scanIdent( struct Scanner *scanner ) { int n; n = 0; - while( isalnum( c ) || ( c == '_' ) ) { - ident[n] = c; + while( isalnum( scanner->c ) || ( scanner->c == '_' ) ) { + scanner->ident[n] = scanner->c; n++; if( n >= MAX_IDENT_LEN - 1 ) { - printErrorHeader( ); + printErrorHeader( scanner ); putstring( "too long identifier" ); putnl( ); exit( EXIT_FAILURE ); } - c = getChar( ); + scanner->c = getChar( scanner ); } - ident[n] = 0; /* c4 doesn't handle '\0' */ - pushBack( c ); + scanner->ident[n] = 0; /* c4 doesn't handle '\0' */ + pushBack( scanner ); } int keyword( char *ident ) @@ -127,57 +141,71 @@ int keyword( char *ident ) } } -int getToken( ) +void scannerPrintState( struct Scanner *scanner ) +{ + putint( scanner->row ); + putchar( '/' ); + putint( scanner->col ); + putstring( ": " ); + putint( scanner->token ); + if( scanner->token == S_NUM ) { + putchar( '(' ); + putint( scanner->num ); + putchar( ')' ); + } + putnl( ); +} + +int getToken( struct Scanner *scanner ) { - int t; int c; - c = skipWhite( ); + c = skipWhite( scanner ); switch( c ) { case EOF: - t = S_EOI; + scanner->token = S_EOI; break; case '+': - t = S_PLUS; + scanner->token = S_PLUS; break; case '-': - t = S_MINUS; + scanner->token = S_MINUS; break; case '*': - t = S_STAR; + scanner->token = S_STAR; break; case '/': - c = getChar( ); + c = getChar( scanner ); if( c == '/' ) { while( c != EOF && c != '\n' ) { - c = getChar( ); + c = getChar( scanner ); } - t = getToken( ); + scanner->token = getToken( scanner ); } else if( c == '*' ) { do { while( c != EOF && c != '*' ) { - c = getChar( ); + c = getChar( scanner ); } - c = getChar( ); + c = getChar( scanner ); } while( c != EOF && c != '/' ); - c = getChar( ); - t = getToken( ); + c = getChar( scanner ); + scanner->token = getToken( scanner ); } else { - pushBack( c ); - t = S_SLASH; + pushBack( scanner ); + scanner->token = S_SLASH; } break; case ';': - t = S_SEMICOLON; + scanner->token = S_SEMICOLON; break; case '=': - t = S_EQUALS; + scanner->token = S_EQUALS; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - scanNumber( c ); - t = S_NUM; + scanNumber( scanner ); + scanner->token = S_NUM; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': @@ -192,15 +220,15 @@ int getToken( ) case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': - scanIdent( c ); - if( ( t = keyword( ident ) ) ) { + scanIdent( scanner ); + if( ( scanner->token = keyword( scanner->ident ) ) ) { } else { - t = S_IDENT; + scanner->token = S_IDENT; } break; default: - t = S_ERR; - printErrorHeader( ); + scanner->token = S_ERR; + printErrorHeader( scanner ); putstring( "unknown token '" ); putchar( c ); putstring( "'" ); @@ -208,76 +236,15 @@ int getToken( ) exit( EXIT_FAILURE ); } - if( DEBUG_SCANNER ) { - putint( row ); - putchar( '/' ); - putint( col ); - putstring( ": " ); - putint( t ); - if( t == S_NUM ) { - putchar( '(' ); - putint( num ); - putchar( ')' ); - } - putnl( ); - } - - return t; -} - -void expect( int must, char *what ) -{ - if( token == must ) { - token = getToken( ); - } else { - printErrorHeader( ); - putstring( what ); - putstring( " expected" ); - putnl( ); - exit( EXIT_FAILURE ); - } -} - -void parseExpression( ) -{ - if( token == S_EOI ) { - printErrorHeader( ); - putstring( "unexpected eof in expression" ); - putnl( ); - exit( EXIT_FAILURE ); - } - - if( token == S_NUM ) { - putstring( "immediate int " ); - putint( num ); - putnl( ); + if( scanner->debug ) { + scannerPrintState( scanner ); } - token = getToken( ); - if( token == S_PLUS ) { - token = getToken( ); - parseExpression( ); - } else if( token == S_MINUS ) { - token = getToken( ); - parseExpression( ); - } else if( token == S_STAR ) { - token = getToken( ); - parseExpression( ); - } else if( token == S_SLASH ) { - token = getToken( ); - parseExpression( ); - } else if( token == S_EOI || token == S_SEMICOLON ) { - return; - } else { - printErrorHeader( ); - putstring( "unexpected token '" ); - putint( token ); - putstring( "' in expression" ); - putnl( ); - exit( EXIT_FAILURE ); - } + return scanner->token; } +/* symbol table */ + struct Symbol { char *name; struct Symbol *next; @@ -300,6 +267,8 @@ void freeSymbol( struct Symbol *sym ) free( (char *)sym ); } +/* scope */ + struct Scope { char *name; struct Symbol *sym; @@ -332,8 +301,6 @@ void freeScope( struct Scope *scope ) free( (char *)scope ); } -struct Scope *global_scope; - struct Symbol *getSymbol( struct Scope *scope, char *name ) { struct Symbol *sym; @@ -359,63 +326,157 @@ void insertSymbol( struct Scope *scope, struct Symbol *sym ) } } -void parseDeclaration( ) +/* parser */ + +struct Parser { + int token; + struct Scanner *scanner; + struct Scope *global_scope; +}; + +struct Parser *createParser( ) +{ + struct Parser *parser; + + parser = (struct Parser *)malloc( sizeof( struct Parser ) ); + parser->scanner = createScanner( ); + parser->global_scope = createScope( "global" ); + + return parser; +} + +void freeParser( struct Parser *parser ) +{ + freeScope( parser->global_scope ); + freeScanner( parser->scanner ); + free( (char *)parser ); +} + +void parserExpect( struct Parser *parser, int must, char *what ) +{ + if( parser->token == must ) { + parser->token = getToken( parser->scanner ); + } else { + printErrorHeader( parser->scanner ); + putstring( what ); + putstring( " expected" ); + putnl( ); + exit( EXIT_FAILURE ); + } +} + +void parseExpression( struct Parser *parser ) +{ + if( parser->token == S_EOI ) { + printErrorHeader( parser->scanner ); + putstring( "unexpected eof in expression" ); + putnl( ); + exit( EXIT_FAILURE ); + } + + if( parser->token == S_NUM ) { + putstring( "immediate int " ); + putint( parser->scanner->num ); + putnl( ); + } + + parser->token = getToken( parser->scanner ); + if( parser->token == S_PLUS ) { + parser->token = getToken( parser->scanner ); + parseExpression( parser ); + } else if( parser->token == S_MINUS ) { + parser->token = getToken( parser->scanner ); + parseExpression( parser ); + } else if( parser->token == S_STAR ) { + parser->token = getToken( parser->scanner ); + parseExpression( parser ); + } else if( parser->token == S_SLASH ) { + parser->token = getToken( parser->scanner ); + parseExpression( parser ); + } else if( parser->token == S_EOI || parser->token == S_SEMICOLON ) { + return; + } else { + printErrorHeader( parser->scanner ); + putstring( "unexpected token '" ); + putint( parser->token ); + putstring( "' in expression" ); + putnl( ); + exit( EXIT_FAILURE ); + } +} + +void parseDeclaration( struct Parser *parser ) { struct Symbol *sym; - expect( S_INT, "int" ); - expect( S_IDENT, "identifier" ); - putstring( "Adding glob: " ); putstring( ident ); putnl( ); - sym = getSymbol( global_scope, ident ); + parserExpect( parser, S_INT, "int" ); + parserExpect( parser, S_IDENT, "identifier" ); + putstring( "Adding glob: " ); putstring( parser->scanner->ident ); putnl( ); + sym = getSymbol( parser->global_scope, parser->scanner->ident ); if( sym == NULL ) { - sym = createSymbol( ident ); - insertSymbol( global_scope, sym ); + sym = createSymbol( parser->scanner->ident ); + insertSymbol( parser->global_scope, sym ); } else { - printErrorHeader( ); - putstring( "duplicate global '" ); - putstring( ident ); + printErrorHeader( parser->scanner ); + putstring( "duplicate global symbol '" ); + putstring( parser->scanner->ident ); putstring( "'" ); putnl( ); exit( EXIT_FAILURE ); } - expect( S_SEMICOLON, ";" ); + parserExpect( parser, S_SEMICOLON, ";" ); } -void parseAssignment( ) +void parseAssignment( struct Parser *parser ) { - token = getToken( ); - expect( S_EQUALS, "=" ); - parseExpression( ); - expect( S_SEMICOLON, ";" ); + struct Symbol *sym; + + parserExpect( parser, S_IDENT, "identifier" ); + sym = getSymbol( parser->global_scope, parser->scanner->ident ); + if( sym == NULL ) { + printErrorHeader( parser->scanner ); + putstring( "unknown symbol '" ); + putstring( parser->scanner->ident ); + putstring( "'" ); + putnl( ); + exit( EXIT_FAILURE ); + } + parserExpect( parser, S_EQUALS, "=" ); + parseExpression( parser ); + parserExpect( parser, S_SEMICOLON, ";" ); } -void parseStatement( ) +void parseStatement( struct Parser *parser ) { - if( token == S_INT ) { - parseDeclaration( ); - } else if( token == S_IDENT ) { - parseAssignment( ); - } else if( token == S_EOI ) { + if( parser->token == S_INT ) { + parseDeclaration( parser ); + } else if( parser->token == S_IDENT ) { + parseAssignment( parser ); + } else if( parser->token == S_EOI ) { return; + } else { + printErrorHeader( parser->scanner ); + putstring( "unexpected token '" ); + putint( parser->token ); + putstring( "'" ); + putnl( ); + exit( EXIT_FAILURE ); } } +/* main */ + int main( int argc, char **argv ) -{ - col = 0; - row = 1; - pushback = 0; - DEBUG_SCANNER = 1; - global_scope = createScope( "global" ); - ident = (char *)malloc( MAX_IDENT_LEN+1 ); - - token = getToken( ); - while( token != S_EOI ) { - parseStatement( ); +{ + struct Parser *parser; + + parser = createParser( ); + parser->scanner->debug = 1; + parser->token = getToken( parser->scanner ); + while( parser->token != S_EOI ) { + parseStatement( parser ); } - - freeScope( global_scope ); - free( (char *)ident ); + freeParser( parser ); exit( EXIT_SUCCESS ); -- cgit v1.2.3-54-g00ecf