Last active
August 29, 2015 14:08
-
-
Save matutter/616a71a3bf24a5904f49 to your computer and use it in GitHub Desktop.
Flex file, AT-ASM to AT-ROM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| Mat Utter 10/27/2014 | |
| compiler design, Confer | |
| */ | |
| /* | |
| line comments begin with a semicolon (';') | |
| a ".msg" precompiler directive is allowed prior to any labels or code. | |
| It may contain a message of up to 70 characters beginning after | |
| the whitespace after the ".msg" tokenlabels begin with '!' and | |
| follow with any non whitespace characters. | |
| Empty labels (i.e., those with only a !) are not permitted | |
| The core (legacy) instructions: | |
| "cmp" requires a single character parameter providedbetween single quotes | |
| "be" (branch if last cmp was equal) | |
| "bne" (branch if last cmp was not equal) | |
| "bra" (branch unconditionally) each require a single label as a parameter | |
| "left" and "right" require no parameters | |
| "draw" requires a single character parameter provided between single quotes | |
| "halt" and "fail" require no parameters | |
| New pseudo instructions are: | |
| "right" followed by an unsigned integer number of times to go right | |
| "left" followed by an unsigned integer number of times to go left | |
| Be sure to submit only a flex file that does everything, or however many files you have bundled in a ZIP file with a Makefile modeled from the "flex lexer example". | |
| */ | |
| %option noyywrap | |
| %{ | |
| ///////////////////// | |
| #define VERBOSE | |
| /* OPCODES */ | |
| #define OPCODE_FAIL 0 | |
| #define OPCODE_HALT 1 | |
| #define OPCODE_CMP 2 | |
| #define OPCODE_BE 3 | |
| #define OPCODE_BNE 4 | |
| #define OPCODE_BRA 5 | |
| #define OPCODE_DRAW 6 | |
| #define OPCODE_LEFT 7 | |
| #define OPCODE_RIGHT 8 | |
| #define OPCODE_LEFTex 9 | |
| #define OPCODE_RIGHTex 10 | |
| #define OPCODE_ldraw 11 | |
| #define OPCODE_rdraw 12 | |
| #define MSG_WORDS 35 | |
| /* requires */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <stdint.h> | |
| #include <string.h> | |
| /* mem defines */ | |
| typedef uint16_t WORD; | |
| WORD * buffer; | |
| int ic = 0x0; | |
| /* Label linker */ | |
| struct LABEL_LINK { | |
| char * label; | |
| int ic; | |
| struct LABEL_LINK * next; | |
| struct LABEL_LINK * back; | |
| }; | |
| struct LABEL_LINK * CONSUMER_ROOT; | |
| struct LABEL_LINK * PROVIDER_ROOT; | |
| #ifdef VERBOSE | |
| char * codename( int i ) | |
| { | |
| switch( i ) | |
| { | |
| case 0: return "FAIL"; | |
| case 1: return "HALT"; | |
| case 2: return "CMP"; | |
| case 3: return "BE"; | |
| case 4: return "BNE"; | |
| case 5: return "BRA"; | |
| case 6: return "DRAW"; | |
| case 7: return "LEFT"; | |
| case 8: return "RIGHT"; | |
| case 9: return "LEFTeX"; | |
| case 10: return "RIGHTeX"; | |
| } | |
| return "LABEL"; | |
| } | |
| char * linkname( int x ) | |
| { | |
| struct LABEL_LINK * l = PROVIDER_ROOT; | |
| while( l->next ) { | |
| if( l->ic == x ) | |
| return l->label; | |
| else | |
| l = l->next; | |
| } | |
| } | |
| #endif | |
| WORD compose_MSG( char *s ) { | |
| while( !isalnum(*s) ) s++; | |
| while(1) | |
| { | |
| if( *(s+1) != 10 ) buffer[ic] = *(s+1) << 8; | |
| if( *s != 10 ) buffer[ic] |= *s; | |
| #ifdef VERBOSE | |
| printf("%c%c",*s,*(s+1)); | |
| #endif | |
| ic++; | |
| if( *s == '\0' || *(s+1) == '\0' ) break; | |
| s+=2; | |
| } | |
| //while( ic < MSG_WORDS ) ic++; | |
| ic = MSG_WORDS; | |
| return ic; | |
| } | |
| WORD compose_OPCHAR( WORD op, char mem ) { | |
| #ifdef VERBOSE | |
| printf("COMPOSE : %s '%c'", codename(op), mem ); | |
| #endif | |
| buffer[ic] = op << 12 | ( mem ); | |
| ic++; | |
| return buffer[ic]; | |
| } | |
| WORD compose_OP_REPEAT( WORD op, int repeat ) | |
| { | |
| #ifdef VERBOSE | |
| printf("COMPOSE : %s %d", codename(op), repeat ); | |
| #endif | |
| while( repeat ) | |
| { | |
| buffer[ic] = op << 12; | |
| ic++; | |
| repeat--; | |
| #ifdef VERBOSE | |
| printf("\n REP : %s(%d)", codename(op), repeat); | |
| #endif | |
| } | |
| } | |
| WORD compose_OPWORD( WORD op, WORD mem) | |
| { | |
| #ifdef VERBOSE | |
| printf("COMPOSE : %s %d", codename(op), mem ); | |
| #endif | |
| buffer[ic] = op << 12 | ( mem ); | |
| ic++; | |
| return buffer[ic]; | |
| } | |
| WORD compose_OP( WORD op ) | |
| { | |
| #ifdef VERBOSE | |
| printf("COMPOSE : %s", codename(op) ); | |
| #endif | |
| buffer[ic] = op << 12; | |
| ic++; | |
| return buffer[ic]; | |
| } | |
| WORD link_OPLABEL( WORD instr, WORD label ) | |
| { | |
| buffer[instr] |= (label-MSG_WORDS); | |
| #ifdef VERBOSE | |
| printf("\nLINK %s \t!%s %x", codename( buffer[instr]>>12 ), linkname(label), buffer[instr] ); | |
| #endif | |
| } | |
| void compose_LINK( char * s, struct LABEL_LINK * link, int unique ) | |
| { | |
| while(1) | |
| /* link is composed do nothing */ | |
| if( unique && link->next && !strcmp( link->label, s ) ) | |
| break; | |
| /* end of list, so create the link */ | |
| else if( !link->next ) | |
| { | |
| link->label = (char *)malloc( sizeof( s ) ); | |
| link->ic = ic; | |
| strcpy( link->label, s ); | |
| link->next = (struct LABEL_LINK *)malloc( sizeof(struct LABEL_LINK) ); | |
| link->next->next = 0x0; | |
| link->next->back = link; | |
| break; | |
| } | |
| /* not this one, check next */ | |
| else | |
| link = link->next; | |
| } | |
| void LINK() | |
| { | |
| #ifdef VERBOSE | |
| int i = 0; | |
| printf("\n%s", "Linking labels..."); | |
| #endif | |
| while( PROVIDER_ROOT->next ) | |
| { | |
| struct LABEL_LINK * CON = CONSUMER_ROOT; | |
| while( CON->next ) | |
| { | |
| #ifdef VERBOSE | |
| i++; | |
| #endif | |
| if( !strcmp( PROVIDER_ROOT->label, CON->label ) ) { | |
| link_OPLABEL( CON->ic, PROVIDER_ROOT->ic ); | |
| if( CON != CONSUMER_ROOT ) | |
| CON->back->next = CON->next; | |
| } | |
| CON = CON->next; | |
| } | |
| PROVIDER_ROOT = PROVIDER_ROOT->next; | |
| } | |
| #ifdef VERBOSE | |
| printf("\nLinked in %d passes. \n", i); | |
| #endif | |
| } | |
| WORD stoi_WORDSAFE( char * s ) | |
| { WORD x = 0; | |
| while( *s != '\0' ) { | |
| x *= 10; | |
| x += *s - '0' ; | |
| s++; | |
| } | |
| return x & 0x0FFF; | |
| } | |
| char * valStr( char * s ) | |
| { | |
| while( !isdigit( *s ) ) s++; | |
| char* ret = s; | |
| while( isdigit( *ret ) ) ret++; | |
| *ret = '\0'; | |
| return s; | |
| } | |
| char * labelFrom( char * s ) | |
| { | |
| while( *s != '!' ) s++; | |
| return s+1; | |
| } | |
| char literalFrom( char * s ) | |
| { | |
| while( *s != '\'' ) s++; | |
| return *(s+1); | |
| } | |
| %} | |
| DIGITS [0-9]+ | |
| ALNUMS [a-zA-Z0-9]+ | |
| ALNUM [a-zA-Z0-9] | |
| SPACE [[:space:]]+ | |
| LITERAL "'"."'" | |
| LABEL "!"[a-zA-Z0-9_@]+ | |
| %% | |
| ;.* { | |
| //printf("COMMENT : %s\n", yytext); | |
| } | |
| "."msg{SPACE}.{1,70} { | |
| //printf("MSG : %s\n", yytext+4); | |
| compose_MSG(yytext+4); | |
| } | |
| {LABEL} { | |
| //printf("LABEL : %s\n", labelFrom(yytext)); | |
| compose_LINK( labelFrom(yytext), PROVIDER_ROOT, 1 ); | |
| } | |
| cmp{SPACE}{LITERAL} { | |
| //printf("cmp : %s\n", yytext); | |
| compose_OPCHAR( OPCODE_CMP, literalFrom( yytext+3 ) ); | |
| } | |
| left{SPACE}+[0-9]+ { | |
| //compose_OPWORD( OPCODE_LEFTex, stoi_WORDSAFE( valStr( yytext+4 ) ) ); | |
| compose_OP_REPEAT( OPCODE_LEFT, stoi_WORDSAFE( valStr( yytext+4 ) ) ); | |
| } | |
| right{SPACE}+[0-9]+ { | |
| //printf("rightEX : %s\n", yytext); | |
| //compose_OPWORD( OPCODE_RIGHTex, stoi_WORDSAFE( valStr( yytext+5 ) ) ); | |
| compose_OP_REPEAT( OPCODE_RIGHT, stoi_WORDSAFE( valStr( yytext+5 ) ) ); | |
| } | |
| left { | |
| //printf("left : %s\n", yytext); | |
| compose_OP(OPCODE_LEFT); | |
| } | |
| right { | |
| //printf("right : %s\n", yytext); | |
| compose_OP(OPCODE_RIGHT); | |
| } | |
| be{SPACE}{LABEL} { | |
| //printf("be : %s\n", yytext); | |
| compose_LINK( labelFrom(yytext), CONSUMER_ROOT, 0 ); | |
| compose_OP(OPCODE_BE); | |
| } | |
| bne{SPACE}{LABEL} { | |
| //printf("bne : %s\n", yytext); | |
| compose_LINK( labelFrom(yytext), CONSUMER_ROOT, 0 ); | |
| compose_OP(OPCODE_BNE); | |
| } | |
| bra{SPACE}{LABEL} { | |
| //printf("bra : %s\n", yytext); | |
| compose_LINK( labelFrom(yytext), CONSUMER_ROOT, 0 ); | |
| compose_OP(OPCODE_BRA); | |
| } | |
| ldraw{SPACE}{LITERAL} { | |
| //printf("drawLEFT : %s\n", yytext); | |
| compose_OP( OPCODE_LEFT ); printf("\n"); | |
| compose_OPCHAR( OPCODE_DRAW, literalFrom( yytext+5 ) ); | |
| } | |
| rdraw{SPACE}{LITERAL} { | |
| //printf("drawRIGHT : %s\n", yytext); | |
| compose_OP( OPCODE_RIGHT ); printf("\n"); | |
| compose_OPCHAR( OPCODE_DRAW, literalFrom( yytext+5 ) ); | |
| } | |
| draw{SPACE}{LITERAL} { | |
| //printf("draw : %s\n", yytext); | |
| compose_OPCHAR( OPCODE_DRAW, literalFrom( yytext+4 ) ); | |
| } | |
| halt{SPACE}* { | |
| //printf("halt : %s\n", yytext); | |
| compose_OP(OPCODE_HALT); | |
| } | |
| fail{SPACE}* { | |
| //printf("fail : %s\n", yytext); | |
| compose_OP(OPCODE_FAIL); | |
| } | |
| {SPACE}* { | |
| #ifdef VERBOSE | |
| printf("\n"); | |
| #endif | |
| } | |
| .+ { | |
| printf("BAD SYMBOL!!! \"%s\"\n LINE %d", yytext, ic); | |
| return 0; | |
| } | |
| %% | |
| int main( int argc, char **argv ) | |
| { | |
| printf("%s\n", "Starting"); | |
| char * filename; | |
| if(argc == 1) { | |
| fprintf(stderr, "no input file given\n"); | |
| exit(EXIT_FAILURE); | |
| } | |
| if(argc > 2) { | |
| fprintf(stderr, "Usage:\t%s <input_file>\n", argv[0]); | |
| exit(EXIT_FAILURE); | |
| } | |
| filename = (char*)malloc(sizeof(char) * (strlen(argv[1]) + 1)); | |
| if(filename == NULL) { | |
| fprintf (stderr, "Error - could not allocate memory sufficient for this application\n"); | |
| exit(EXIT_FAILURE); | |
| } | |
| strcpy(filename, argv[1]); | |
| strcat(filename, ".rom"); | |
| yyin = fopen(argv [1], "r"); | |
| if(yyin != NULL) { | |
| fseek(yyin, 0x0, SEEK_END); | |
| long size = ftell(yyin); | |
| fseek(yyin, 0x0, SEEK_SET); | |
| buffer = (WORD*)malloc( sizeof(WORD) * size ); | |
| memset (buffer,0x0,sizeof(WORD) * size ); | |
| CONSUMER_ROOT = (struct LABEL_LINK *) malloc( sizeof(struct LABEL_LINK) ); | |
| CONSUMER_ROOT->next = 0x0; | |
| PROVIDER_ROOT = (struct LABEL_LINK *) malloc( sizeof(struct LABEL_LINK) ); | |
| PROVIDER_ROOT->next = 0x0; | |
| yylex (); | |
| LINK(); | |
| fclose (yyin); | |
| printf("%s\n", "WRITING BINARY..."); | |
| FILE *ROM; | |
| ROM = fopen(filename,"wb"); | |
| if (!ROM) | |
| { | |
| printf("Unable to open file!"); | |
| return 1; | |
| } | |
| fwrite(buffer, sizeof(WORD), ic, ROM); | |
| fclose(ROM); | |
| } | |
| else { | |
| fprintf(stderr, "Could not open file, \"%s\"\n", argv[1]); | |
| } | |
| free (filename); | |
| free (buffer); | |
| exit(EXIT_SUCCESS); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment