Merge pull request #27 from PaytonTurnage/master

Implementation for Preprocessor Defines
This commit is contained in:
Joseph 2014-01-14 07:40:33 -08:00
commit abea0981ae
10 changed files with 158 additions and 13 deletions

12
SYNTAX
View file

@ -78,9 +78,17 @@ Labels must be specified at the beginning of a line or on their own line.
// 4. PREPROCESSOR ///////////////////////////////
//////////////////////////////////////////////////
TVM has a preprocessor that allows other source files to be included with the directive "%include filename.vm"
TVM's preprocessor works similarly to many C compilers and uses the prefix "%".
During preprocessing, the entire included source file is inserted in place of the %include directive in memory.
// I. Include //
%include filename
Pastes all of the contents of filename into the source code before interpretting it.
// II. Define //
%define identifier value
Define a constant so that all instances of the string "identifier" will be replaced by "value".
//////////////////////////////////////////////////
// 5. INSTRUCTION LISTING ////////////////////////

View file

@ -8,6 +8,7 @@ typedef struct tvm_htab_node_s
{
char *key;
int value;
void *valptr;
struct tvm_htab_node_s *next;
} tvm_htab_node_t;
@ -22,6 +23,8 @@ tvm_htab_t* htab_create();
void htab_destroy(tvm_htab_t *htab);
int htab_add(tvm_htab_t *htab, const char *key, int value);
int htab_add_str(tvm_htab_t *htab, const char *key, const void *valptr, int len);
int htab_find(tvm_htab_t *htab, const char *key);
char *htab_find_str(tvm_htab_t *htab, const char *key);
#endif

View file

@ -4,6 +4,8 @@
#define MAX_ARGS 2
#define MAX_TOKENS 4
#include "tvm_htab.h"
typedef struct tvm_lexer_s
{
char **source_lines;
@ -14,6 +16,6 @@ tvm_lexer_t *lexer_create();
void lexer_destroy(tvm_lexer_t *l);
/* Tokenize the character array "source" into lines and tokens */
void lex(tvm_lexer_t *lexer, char *source);
void lex(tvm_lexer_t *lexer, char *source, tvm_htab_t *defines);
#endif

View file

@ -1,6 +1,8 @@
#ifndef TVM_PREPROCESSOR_H_
#define TVM_PREPROCESSOR_H_
int tvm_preprocess(char *src, int *src_len);
#include "tvm_htab.h"
int tvm_preprocess(char *src, int *src_len, tvm_htab_t *defines);
#endif

View file

@ -20,6 +20,8 @@ typedef struct tvm_program_s
int **values;
int num_values;
tvm_htab_t *defines;
tvm_htab_t *label_htab;
} tvm_program_t;

View file

@ -25,6 +25,8 @@ void htab_destroy(tvm_htab_t *htab)
while(node)
{
next = node->next;
if(node->valptr)
free(node->valptr);
free(node->key);
free(node);
node = next;
@ -65,7 +67,13 @@ static void htab_rehash(tvm_htab_t *orig, unsigned int size)
while(node)
{
next = node->next;
htab_add(new, node->key, node->value);
if (node->valptr)
{
htab_add_str(new, node->key, node->valptr, strlen(node->valptr) + 1);
free(node->valptr);
}
else
htab_add(new, node->key, node->value);
free(node->key);
free(node);
node = next;
@ -113,7 +121,26 @@ int htab_add(tvm_htab_t *htab, const char *k, int v)
if((float)++htab->num_nodes / htab->size > HTAB_LOAD_FACTOR)
htab_rehash(htab, htab->num_nodes * 2);
return 0;
return hash;
}
int htab_add_str(tvm_htab_t *htab, const char *key, const void *valptr, int len)
{
int hash = htab_add(htab, key, 0);
int found = 0;
tvm_htab_node_t *node = htab->nodes[hash];
while (node && !found)
{
if (!strcmp(node->key, key))
found = 1;
else
node = node->next;
}
node->valptr = calloc(len, sizeof(char));
memcpy(node->valptr, valptr, len);
return hash;
}
int htab_find(tvm_htab_t *htab, const char *key)
@ -131,3 +158,17 @@ int htab_find(tvm_htab_t *htab, const char *key)
return -1;
}
char *htab_find_str(tvm_htab_t *htab, const char *key)
{
int hash = htab_hash(key, htab->size);
tvm_htab_node_t *node = htab->nodes[hash];
while(node)
{
if(!strcmp(node->key, key))
return node->valptr;
node = node->next;
}
return NULL;
}

View file

@ -26,7 +26,7 @@ void lexer_destroy(tvm_lexer_t *lexer)
free(lexer);
}
void lex(tvm_lexer_t *lexer, char *source)
void lex(tvm_lexer_t *lexer, char *source, tvm_htab_t *defines)
{
int i, j;
char *pToken, *pLine = strtok(source, "\n");
@ -60,12 +60,16 @@ void lex(tvm_lexer_t *lexer, char *source)
for(j = 0; (pToken && j < MAX_TOKENS); j++)
{
lexer->tokens[i][j] = (char *)calloc(1, (strlen(pToken) + 1));
strcpy(lexer->tokens[i][j], pToken);
char *token = htab_find_str(defines, pToken);
token = token ? token : pToken;
lexer->tokens[i][j] = (char *)calloc(1, (strlen(token) + 1));
strcpy(lexer->tokens[i][j], token);
pToken = strtok(NULL, " \t,");
}
}
lexer->tokens[i] = NULL;
htab_destroy(defines);
}

View file

@ -3,7 +3,7 @@
#include <string.h>
int tvm_preprocess(char *src, int *src_len)
int tvm_preprocess(char *src, int *src_len, tvm_htab_t *defines)
{
char* pp_directive_delimiter = NULL;
if((pp_directive_delimiter = strstr(src, "%include")))
@ -22,7 +22,7 @@ int tvm_preprocess(char *src, int *src_len)
if(!pFile)
{
printf("Unable to open file \"%s\"\n", filename);
return 0;
return -1;
}
free(temp_str);
@ -48,6 +48,63 @@ int tvm_preprocess(char *src, int *src_len)
*src_len = strlen(src);
return 1;
}
else if((pp_directive_delimiter = strstr(src, "%define ")))
{
char *begin = pp_directive_delimiter;
char *end = strchr(begin, '\n');
if(!end) return 0;
int offset = strlen("%define ");
if(begin + offset >= end)
{
printf("Define missing arguments.\n");
return -1;
}
int length = (end - (begin + offset));
char tempstr[length + 1];
memset(tempstr, 0, length + 1);
memcpy(tempstr, begin + offset, length);
char *keystr = tempstr;
char *valstr = strchr(tempstr, ' ');
/* If there is a value, seperate the key and value
with a null character. */
if(valstr)
{
*valstr = 0;
valstr += 1;
}
if(!keystr || !valstr)
{
printf("Define missing arguments.\n");
return -1;
}
if(htab_find(defines, keystr) < 0)
htab_add_str(defines, keystr, valstr, strlen(valstr) + 1);
else
{
printf("Multiple definitions for %s.\n", keystr);
return -1;
}
/* Remove the define line so it is not processed again. */
size_t new_length = *src_len - (end - begin);
size_t first_block_len = begin - src;
size_t second_block_len = (src + *src_len) - end;
memmove(&src[first_block_len], end, second_block_len);
src = realloc(src, sizeof(char) * new_length);
*src_len = new_length;
return 1;
}
return 0;

View file

@ -8,6 +8,7 @@ tvm_program_t *program_create()
{
tvm_program_t *p = (tvm_program_t *)calloc(1, sizeof(tvm_program_t));
p->label_htab = htab_create();
p->defines = htab_create();
return p;
}
@ -54,10 +55,15 @@ pi_interpret:
tvm_fcopy(source, source_length, pFile);
fclose(pFile);
while(tvm_preprocess(source, &source_length));
int err = 0;
while((err = tvm_preprocess(source, &source_length, p->defines)) > 0);
/* The preprocessor encountered a problem. */
if (err < 0)
return 1;
tvm_lexer_t *lexer_ctx = lexer_create();
lex(lexer_ctx, source);
lex(lexer_ctx, source, p->defines);
free(source);
if(parse_labels(p, (const char ***)lexer_ctx->tokens) != 0) return 1;

View file

@ -0,0 +1,20 @@
%define ONE 1
%define ZERO 0
start:
mov eax, ONE
mov ebx, ZERO
loop: add eax, ebx
add ebx, eax
prn eax
prn ebx
cmp eax, ZERO
jl end
cmp ebx, ZERO
jg loop
end: