Parsing file to an intermediate representation.
This commit is contained in:
parent
8ce5ac41b1
commit
5ce1fddc8d
489
src/main.c
489
src/main.c
|
|
@ -1,7 +1,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <time.h>
|
||||
|
|
@ -9,10 +9,27 @@
|
|||
#define BRACKETS_NB_MAX 1024
|
||||
#define DATA_SIZE_MAX 65536
|
||||
|
||||
// The advanced version of operations should always have value = simple version + 1
|
||||
enum operations_t {
|
||||
NONE,
|
||||
MEM_POINTER_ADD,
|
||||
MEM_POINTER_ADD_NB,
|
||||
MEM_POINTER_SUB,
|
||||
MEM_POINTER_SUB_NB,
|
||||
MEM_ADD,
|
||||
MEM_ADD_NB,
|
||||
MEM_SUB,
|
||||
MEM_SUB_NB,
|
||||
JUMP_IF_0,
|
||||
JUMP_IF_NOT_0,
|
||||
PRINT_CHAR,
|
||||
GET_CHAR
|
||||
};
|
||||
|
||||
typedef uint8_t operation_t;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
clock_t start_time, end_time;
|
||||
|
||||
int status = EXIT_FAILURE;
|
||||
|
||||
if(argc != 2)
|
||||
|
|
@ -22,7 +39,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
FILE *program_file = NULL;
|
||||
FILE *stripped_file = NULL;
|
||||
FILE *intermediate_representation_file = NULL;
|
||||
|
||||
program_file = fopen(argv[1], "r");
|
||||
if(program_file == NULL)
|
||||
|
|
@ -31,15 +48,13 @@ int main(int argc, char *argv[])
|
|||
goto end;
|
||||
}
|
||||
|
||||
stripped_file = tmpfile();
|
||||
if(stripped_file == NULL)
|
||||
intermediate_representation_file = tmpfile();
|
||||
if(intermediate_representation_file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error creating tmp file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
start_time = clock();
|
||||
|
||||
// Strip program file
|
||||
while(true)
|
||||
{
|
||||
|
|
@ -52,27 +67,164 @@ int main(int argc, char *argv[])
|
|||
if(err)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(program_file));
|
||||
return EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
operation_t operation = NONE;
|
||||
static operation_t last_operation = NONE;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '>':
|
||||
operation = MEM_POINTER_ADD;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
operation = MEM_POINTER_SUB;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
operation = MEM_ADD;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
operation = MEM_SUB;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
operation = JUMP_IF_0;
|
||||
break;
|
||||
|
||||
case ']':
|
||||
operation = JUMP_IF_NOT_0;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
operation = PRINT_CHAR;
|
||||
break;
|
||||
|
||||
case ',':
|
||||
fputc(c, stripped_file);
|
||||
operation = GET_CHAR;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(operation == NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(operation)
|
||||
{
|
||||
case MEM_POINTER_ADD:
|
||||
case MEM_POINTER_SUB:
|
||||
case MEM_ADD:
|
||||
case MEM_SUB:
|
||||
if(operation == last_operation)
|
||||
{
|
||||
operation++; // Go to advanced version of operation
|
||||
|
||||
if(fseek(intermediate_representation_file, -1, SEEK_CUR))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(fwrite(&operation, sizeof(operation), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
size_t nb = 2;
|
||||
|
||||
if(fwrite(&nb, sizeof(nb), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if(operation + 1 == last_operation)
|
||||
{
|
||||
operation++;
|
||||
|
||||
size_t nb;
|
||||
|
||||
if(fseek(intermediate_representation_file, -sizeof(nb), SEEK_CUR))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(fread(&nb, sizeof(nb), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
nb++;
|
||||
|
||||
if(fseek(intermediate_representation_file, -sizeof(nb), SEEK_CUR))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(fwrite(&nb, sizeof(nb), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fwrite(&operation, sizeof(operation), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case JUMP_IF_0:
|
||||
case JUMP_IF_NOT_0:
|
||||
if(fwrite(&operation, sizeof(operation), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
size_t jump_pos = 0;
|
||||
|
||||
if(fwrite(&jump_pos, sizeof(jump_pos), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PRINT_CHAR:
|
||||
case GET_CHAR:
|
||||
if(fwrite(&operation, sizeof(operation), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
last_operation = operation;
|
||||
}
|
||||
|
||||
if(fclose(program_file) == EOF)
|
||||
|
|
@ -86,162 +238,293 @@ int main(int argc, char *argv[])
|
|||
|
||||
program_file = NULL;
|
||||
|
||||
rewind(stripped_file);
|
||||
|
||||
size_t brackets_pos[BRACKETS_NB_MAX];
|
||||
size_t brackets_correspondances[BRACKETS_NB_MAX];
|
||||
|
||||
// Parse brackets
|
||||
size_t bracket_nb = 0;
|
||||
rewind(intermediate_representation_file);
|
||||
|
||||
while(true)
|
||||
{
|
||||
int c = fgetc(stripped_file);
|
||||
operation_t operation;
|
||||
size_t nb_read = fread(&operation, sizeof(operation), 1, intermediate_representation_file);
|
||||
|
||||
if(c == EOF)
|
||||
if(nb_read != 1)
|
||||
{
|
||||
int err = ferror(stripped_file);
|
||||
|
||||
if(err)
|
||||
if(feof(intermediate_representation_file))
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(stripped_file));
|
||||
goto end;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(c == '[' || c == ']')
|
||||
{
|
||||
brackets_pos[bracket_nb] = ftell(stripped_file);
|
||||
|
||||
if(c == '[')
|
||||
{
|
||||
// Find corresponding closing bracket index
|
||||
size_t corresponding_bracket_nb = bracket_nb;
|
||||
|
||||
for(size_t bracket_index = 1; bracket_index;)
|
||||
{
|
||||
int d = fgetc(stripped_file);
|
||||
|
||||
if(d == EOF)
|
||||
{
|
||||
int err = ferror(stripped_file);
|
||||
|
||||
if(err)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(stripped_file));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Reached EOF before finding closing bracket.");
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if(operation == JUMP_IF_0)
|
||||
{
|
||||
long bracket_pos = ftell(intermediate_representation_file);
|
||||
|
||||
if(bracket_pos == -1)
|
||||
{
|
||||
fprintf(stderr, "Error getting file pointer: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Find corresponding closing bracket index
|
||||
for(size_t bracket_index = 1; bracket_index;)
|
||||
{
|
||||
operation_t operation_search;
|
||||
nb_read = fread(&operation_search, sizeof(operation_search), 1, intermediate_representation_file);
|
||||
|
||||
if(nb_read != 1)
|
||||
{
|
||||
if(feof(intermediate_representation_file))
|
||||
{
|
||||
fprintf(stderr, "Reached end of file before finding closing bracket.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
}
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(d == '[' || d == ']')
|
||||
switch(operation_search)
|
||||
{
|
||||
corresponding_bracket_nb++;
|
||||
case MEM_POINTER_ADD_NB:
|
||||
case MEM_POINTER_SUB_NB:
|
||||
case MEM_ADD_NB:
|
||||
case MEM_SUB_NB:
|
||||
case JUMP_IF_NOT_0:
|
||||
if(fseek(intermediate_representation_file, sizeof(size_t), SEEK_CUR))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(d == '[')
|
||||
if(operation_search == JUMP_IF_0)
|
||||
{
|
||||
bracket_index++;
|
||||
}
|
||||
else if(d == ']')
|
||||
else if(operation_search == JUMP_IF_NOT_0)
|
||||
{
|
||||
bracket_index--;
|
||||
}
|
||||
}
|
||||
|
||||
brackets_correspondances[bracket_nb] = corresponding_bracket_nb;
|
||||
brackets_correspondances[corresponding_bracket_nb] = bracket_nb;
|
||||
long corresponding_bracket_pos = ftell(intermediate_representation_file);
|
||||
|
||||
fseek(stripped_file, brackets_pos[bracket_nb], SEEK_SET);
|
||||
if(corresponding_bracket_pos == -1)
|
||||
{
|
||||
fprintf(stderr, "Error getting file pointer: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
bracket_nb++;
|
||||
if(fseek(intermediate_representation_file, -sizeof(size_t), SEEK_CUR))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
size_t bracket_pos_size_t = (size_t)bracket_pos + sizeof(size_t);
|
||||
|
||||
if(fwrite(&bracket_pos_size_t, sizeof(bracket_pos_size_t), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(fseek(intermediate_representation_file, bracket_pos, SEEK_SET))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
|
||||
size_t corresponding_bracket_pos_size_t = corresponding_bracket_pos;
|
||||
if(fwrite(&corresponding_bracket_pos_size_t, sizeof(corresponding_bracket_pos_size_t), 1, intermediate_representation_file) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error writing file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end_time = clock();
|
||||
switch(operation)
|
||||
{
|
||||
case MEM_POINTER_ADD_NB:
|
||||
case MEM_POINTER_SUB_NB:
|
||||
case MEM_ADD_NB:
|
||||
case MEM_SUB_NB:
|
||||
case JUMP_IF_NOT_0:
|
||||
fseek(intermediate_representation_file, sizeof(size_t), SEEK_CUR);
|
||||
break;
|
||||
|
||||
fprintf(stderr, "Parsing time : %fs\n", (float)(end_time - start_time) / (float)CLOCKS_PER_SEC);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rewind(stripped_file);
|
||||
rewind(intermediate_representation_file);
|
||||
|
||||
// Program memory
|
||||
uint8_t mem[DATA_SIZE_MAX] = {0};
|
||||
size_t mem_pointer = 0;
|
||||
|
||||
size_t bracket_index = 0;
|
||||
|
||||
start_time = clock();
|
||||
size_t nb_read;
|
||||
size_t operand;
|
||||
|
||||
while(true)
|
||||
{
|
||||
int c = fgetc(stripped_file);
|
||||
operation_t operation;
|
||||
nb_read = fread(&operation, sizeof(operation), 1, intermediate_representation_file);
|
||||
|
||||
if(c == EOF)
|
||||
if(nb_read != 1)
|
||||
{
|
||||
int err = ferror(stripped_file);
|
||||
if(feof(intermediate_representation_file))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if(err)
|
||||
switch(operation)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(stripped_file));
|
||||
case MEM_POINTER_ADD:
|
||||
mem_pointer++;
|
||||
break;
|
||||
|
||||
case MEM_POINTER_ADD_NB:
|
||||
nb_read = fread(&operand, sizeof(operand), 1, intermediate_representation_file);
|
||||
if(nb_read != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
goto end;
|
||||
}
|
||||
mem_pointer += operand;
|
||||
break;
|
||||
|
||||
case MEM_POINTER_SUB:
|
||||
mem_pointer--;
|
||||
break;
|
||||
|
||||
case MEM_POINTER_SUB_NB:
|
||||
nb_read = fread(&operand, sizeof(operand), 1, intermediate_representation_file);
|
||||
if(nb_read != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
goto end;
|
||||
}
|
||||
mem_pointer -= operand;
|
||||
break;
|
||||
|
||||
case MEM_ADD:
|
||||
mem[mem_pointer]++;
|
||||
break;
|
||||
|
||||
case MEM_ADD_NB:
|
||||
nb_read = fread(&operand, sizeof(operand), 1, intermediate_representation_file);
|
||||
if(nb_read != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
goto end;
|
||||
}
|
||||
mem[mem_pointer] += operand;
|
||||
break;
|
||||
|
||||
case MEM_SUB:
|
||||
mem[mem_pointer]--;
|
||||
break;
|
||||
|
||||
case MEM_SUB_NB:
|
||||
nb_read = fread(&operand, sizeof(operand), 1, intermediate_representation_file);
|
||||
if(nb_read != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
goto end;
|
||||
}
|
||||
mem[mem_pointer] -= operand;
|
||||
break;
|
||||
|
||||
case JUMP_IF_0:
|
||||
if(mem[mem_pointer] == 0)
|
||||
{
|
||||
nb_read = fread(&operand, sizeof(operand), 1, intermediate_representation_file);
|
||||
if(nb_read != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(fseek(intermediate_representation_file, operand, SEEK_SET))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fseek(intermediate_representation_file, sizeof(size_t), SEEK_CUR))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case JUMP_IF_NOT_0:
|
||||
if(mem[mem_pointer])
|
||||
{
|
||||
nb_read = fread(&operand, sizeof(operand), 1, intermediate_representation_file);
|
||||
if(nb_read != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading file: %d\n", ferror(intermediate_representation_file));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(c == '[' || c == ']')
|
||||
if(fseek(intermediate_representation_file, operand, SEEK_SET))
|
||||
{
|
||||
if(c == '[' ? !mem[mem_pointer] : mem[mem_pointer])
|
||||
{
|
||||
bracket_index = brackets_correspondances[bracket_index];
|
||||
fseek(stripped_file, brackets_pos[bracket_index], SEEK_SET);
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fseek(intermediate_representation_file, sizeof(size_t), SEEK_CUR))
|
||||
{
|
||||
fprintf(stderr, "Error seeking file: %d\n", errno);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
bracket_index++;
|
||||
}
|
||||
else if(c == '>')
|
||||
{
|
||||
mem_pointer++;
|
||||
}
|
||||
else if(c == '<')
|
||||
{
|
||||
mem_pointer--;
|
||||
}
|
||||
else if(c == '+')
|
||||
{
|
||||
mem[mem_pointer]++;
|
||||
}
|
||||
else if(c == '-')
|
||||
{
|
||||
mem[mem_pointer]--;
|
||||
}
|
||||
else if(c == '.')
|
||||
{
|
||||
case PRINT_CHAR:
|
||||
putchar(mem[mem_pointer]);
|
||||
}
|
||||
else if(c == ',')
|
||||
{
|
||||
break;
|
||||
|
||||
case GET_CHAR:
|
||||
mem[mem_pointer] = getchar();
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Invalid operation : %02d\n", operation);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end_time = clock();
|
||||
|
||||
fprintf(stderr, "\nExecution time : %fs\n", (float)(end_time - start_time) / (float)CLOCKS_PER_SEC);
|
||||
|
||||
status = EXIT_SUCCESS;
|
||||
|
||||
end:
|
||||
if(stripped_file != NULL)
|
||||
if(intermediate_representation_file != NULL)
|
||||
{
|
||||
if(fclose(stripped_file))
|
||||
if(fclose(intermediate_representation_file))
|
||||
{
|
||||
fprintf(stderr, "Error closing tmp file: %d\n", errno);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue