summaryrefslogtreecommitdiff
path: root/miniany/cc.c
diff options
context:
space:
mode:
Diffstat (limited to 'miniany/cc.c')
-rw-r--r--miniany/cc.c101
1 files changed, 78 insertions, 23 deletions
diff --git a/miniany/cc.c b/miniany/cc.c
index c630a8f..e977bc9 100644
--- a/miniany/cc.c
+++ b/miniany/cc.c
@@ -25,6 +25,8 @@ enum {
S_MORE,
S_MORE_OR_EQUALS,
S_INT = 50,
+ S_CHAR,
+ S_VOID,
S_IF,
S_ELSE,
S_WHILE,
@@ -50,7 +52,7 @@ struct Scanner {
void scannerPrintErrorHeader( struct Scanner *scanner )
{
putnl( );
- putstring( "Error line " );
+ putstring( "; ERROR: line " );
putint( scanner->row );
putstring( ", pos " );
putint( scanner->col );
@@ -163,6 +165,12 @@ void scanIdent( struct Scanner *scanner )
int keyword( char *ident )
{
switch( ident[0] ) {
+ case 'c':
+ if( strcmp( ident, "char" ) == 0 ) {
+ return S_CHAR;
+ }
+ break;
+
case 'd':
if( strcmp( ident, "do" ) == 0 ) {
return S_DO;
@@ -189,6 +197,12 @@ int keyword( char *ident )
}
break;
+ case 'v':
+ if( strcmp( ident, "void" ) == 0 ) {
+ return S_VOID;
+ }
+ break;
+
case 'w':
if( strcmp( ident, "while" ) == 0 ) {
return S_WHILE;
@@ -330,16 +344,24 @@ int getToken( struct Scanner *scanner )
/* symbol table */
+enum {
+ SYMBOL_CLASS_VARIABLE,
+ SYMBOL_CLASS_FUNCTION
+};
+
struct Symbol {
- char *name;
- struct Symbol *next;
+ int class; /* class SYMBOL_CLASS_XXX */
+ char *name; /* name of the symbol */
+ int type; /* type of variable when type is SYMBOL_CLASS_VARIABLE */
+ struct Symbol *next; /* pointer to next symbol */
};
-struct Symbol *createSymbol( char *s )
+struct Symbol *createSymbol( int class, char *s )
{
struct Symbol *sym;
sym = (struct Symbol *)malloc( sizeof ( struct Symbol ) );
+ sym->class = class;
sym->name = strdup( s );
sym->next = NULL;
@@ -586,11 +608,19 @@ void putlow8reg( struct Generator *generator, int reg )
}
-void genAddGlob( struct Generator *generator, char *ident )
+void genAddGlob( struct Generator *generator, struct Symbol *sym )
{
- putstring( ident );
+ putstring( sym->name );
putstring( ": " );
- putstring( "dd $0" );
+ switch( sym->type ) {
+ case S_INT:
+ putstring( "dd $0" );
+ break;
+
+ case S_CHAR:
+ putstring( "db $0" );
+ break;
+ }
putnl( );
}
@@ -988,7 +1018,9 @@ void genEpilogue( struct Compiler *compiler )
putstring( "hlt" ); putnl( );
sym = compiler->parser->global_scope->sym;
while( sym != NULL ) {
- genAddGlob( compiler->generator, sym->name );
+ if( sym->class == SYMBOL_CLASS_VARIABLE ) {
+ genAddGlob( compiler->generator, sym );
+ }
sym = sym->next;
}
putstring( "putint_string_fmt:" ); putnl( );
@@ -1180,17 +1212,38 @@ struct ASTnode *parseExpression( struct Parser *parser, int level )
return left;
}
-void parseDeclaration( struct Compiler *compiler )
+int parseType( struct Compiler *compiler )
+{
+ struct Parser *parser;
+ int type;
+
+ parser = compiler->parser;
+ if( parser->token == S_INT || parser->token == S_CHAR || parser->token == S_VOID ) {
+ type = parser->token;
+ parser->token = getToken( parser->scanner );
+ } else {
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "type expected" );
+ putnl( );
+ exit( EXIT_FAILURE );
+ }
+
+ return type;
+}
+
+void parseVariableDeclaration( struct Compiler *compiler )
{
struct Parser *parser;
struct Symbol *sym;
+ int type;
parser = compiler->parser;
- parserExpect( parser, S_INT, "int" );
+ type = parseType( compiler );
parserExpect( parser, S_IDENT, "identifier" );
sym = getSymbol( parser->global_scope, parser->scanner->ident );
if( sym == NULL ) {
- sym = createSymbol( parser->scanner->ident );
+ sym = createSymbol( SYMBOL_CLASS_VARIABLE, parser->scanner->ident );
+ sym->type = type;
insertSymbol( parser->global_scope, sym );
} else {
scannerPrintErrorHeader( parser->scanner );
@@ -1338,7 +1391,7 @@ void parseWhile( struct Compiler *compiler )
putstring( "jmp " ); putstring( label2 ); putnl( );
putstring( label1 ); putchar( ':' ); putnl( );
if( parser->debug ) {
- putstring( "; fi" ); putnl( );
+ putstring( "; end while" ); putnl( );
}
free( label2 );
free( label1 );
@@ -1359,6 +1412,9 @@ void parseDo( struct Compiler *compiler )
putstring( label1 ); putchar( ':' ); putnl( );
parseStatementBlock( compiler );
parserExpect( parser, S_WHILE, "while" );
+ if( parser->debug ) {
+ putstring( "; end do, while <cond>" ); putnl( );
+ }
parserExpect( parser, S_LPAREN, "(" );
node = parseExpression( parser, 0 );
generateFromAST( compiler->generator, node, NOREG );
@@ -1375,8 +1431,8 @@ void parseStatement( struct Compiler *compiler )
struct Parser *parser;
parser = compiler->parser;
- if( parser->token == S_INT ) {
- parseDeclaration( compiler );
+ if( parser->token == S_INT || parser->token == S_CHAR ) {
+ parseVariableDeclaration( compiler );
} else if( parser->token == S_IDENT ) {
parseAssignment( compiler );
} else if( parser->token == S_PUTINT ) {
@@ -1415,22 +1471,22 @@ void parseFunctionDeclaration( struct Compiler *compiler )
{
struct Parser *parser;
struct Symbol *sym;
+ int type;
parser = compiler->parser;
- if( parser->token == S_IDENT ) {
- if( strcmp( parser->scanner->ident, "void" ) != 0 ) {
- scannerPrintErrorHeader( parser->scanner );
- putstring( "expected void as return value of a function declaration" );
- putnl( );
- exit( EXIT_FAILURE );
- }
+ type = parseType( compiler );
+ if( type != S_VOID ) {
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "expected void as return value of a function declaration" );
+ putnl( );
+ exit( EXIT_FAILURE );
}
parserExpect( parser, S_IDENT, "identifier" );
sym = getSymbol( parser->global_scope, parser->scanner->ident );
if( sym == NULL ) {
- sym = createSymbol( parser->scanner->ident );
+ sym = createSymbol( SYMBOL_CLASS_FUNCTION, parser->scanner->ident );
insertSymbol( parser->global_scope, sym );
} else {
scannerPrintErrorHeader( parser->scanner );
@@ -1450,7 +1506,6 @@ void parseFunctionDeclaration( struct Compiler *compiler )
putstring( parser->scanner->ident ); putchar( ':' ); putnl( );
putstring( "push ebp" ); putnl( );
putstring( "mov ebp, esp" ); putnl( );
- parser->token = getToken( compiler->parser->scanner );
parserExpect( parser, S_LPAREN, "(" );
parserExpect( parser, S_RPAREN, ")" );
parseStatementBlock( compiler );