/* * Starting point for COMP1721 Cavy assignment * Andrew Taylor (andrewt@cse.unsw.edu.au) September 2005 */ #include #include #include #include "cavy_syntax.h" /* * This function compiles a few Cavy(0) programs * You will need to make major changes to it */ char *source_filename; char *code_filename = "code.asm"; FILE *code_stream; void usage(void); void compile_program(void); void compile_statement(void); void emit_system_call(int which); token *expect(token_type expected_type); static char *myname; int main(int argc, char *argv[]) { myname = strrchr(argv[0], '/'); if (myname == NULL) myname = argv[0]; else myname++; if (argc == 1) { source_filename = ""; open_lexical_analysis(stdin); } else if (argc == 2) { source_filename = argv[1]; FILE *f = fopen(argv[1], "r"); if (f == NULL) { fprintf(stderr, "%s: cannot open file: %s\n", argv[0], source_filename); exit(1); } open_lexical_analysis(f); } else usage(); if ((code_stream = fopen(code_filename, "w")) == NULL) { fprintf(stderr, "%s: cannot open file: %s\n", argv[0], code_filename); exit(1); } compile_program(); return 0; } void usage(void) { fprintf(stderr, "Usage: %s \n", myname); exit(1); } /* * Compile a program. * Note this is a partial incorrect implementation. * You will need to do much more */ void compile_program(void) { /* get tokens until we reach the curly brace starting the main method */ for (;;) { token *t = get_token(); if (t->type == T_EOF || t->type == T_LEFT_BRACE) break; } while (view_token(0)->type != T_EOF) compile_statement(); emit_system_call(0); } /* * Compile a single statement * Note this is a partial incorrect implementation. * You will need to do much more */ void compile_statement(void) { token *t = get_token(); if (t->type == T_RIGHT_BRACE || t->type == T_EOF) return; if (t->type == T_CHAR) { /* * declarations are ignored by this program * you will need to do more */ expect(T_IDENTIFIER); } else if (t->type == T_PUTI || t->type == T_PUTC) { /* this handles only some put_c() & put_i() calls correctly */ expect(T_LEFT_PARENTHESIS); token *argument = get_token(); expect(T_RIGHT_PARENTHESIS); if (argument->type == T_CONSTANT) fprintf(code_stream, "\tLDI R26, %d\n", argument->int_value); else fprintf(code_stream, "\tMOV R26, R16\n"); if (t->type == T_PUTI) emit_system_call(1); else emit_system_call(3); } else if (t->type == T_IDENTIFIER) { /* very naive handling of assignment statement */ expect(T_ASSIGNMENT); token *righthand = expect(T_CONSTANT); fprintf(code_stream, "\tLDI R16, %d\n", righthand->int_value); } expect(T_SEMICOLON); /* all statements finish with a semi-colon */ } void emit_system_call(int which) { fprintf(code_stream, "\tLDI R24, %d\n", which); fprintf(code_stream, "\tLDI R31, 0x70\n"); fprintf(code_stream, "\tLDI R30, 0x00\n"); fprintf(code_stream, "\tICALL\n"); } /* * Get the next token and check that it is of the specified type, * if not print an error message and exit. The token is returned. */ token * expect(token_type expected_type) { token *next = get_token(); if (next->type != expected_type) { printf("%s:%d: Syntax error - expected %s found %s\n", source_filename, next->line_number, token_type_to_string(expected_type), token_type_to_string(next->type)); exit(1); } return next; }