summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miniany/cc.c461
1 files 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 );