Skip to content

Instantly share code, notes, and snippets.

@matutter
Last active August 29, 2015 14:08
Show Gist options
  • Select an option

  • Save matutter/616a71a3bf24a5904f49 to your computer and use it in GitHub Desktop.

Select an option

Save matutter/616a71a3bf24a5904f49 to your computer and use it in GitHub Desktop.
Flex file, AT-ASM to AT-ROM
/*
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