Skip to content
This repository has been archived by the owner on Jun 28, 2024. It is now read-only.

Commit

Permalink
Introduce printer
Browse files Browse the repository at this point in the history
* Create test cases for printer

* Add printer test in runtest.sh

* Add --print option

* Add rules for printer and other improvements

* Create printer.c

* Define semantic values in lex.yy.l

* Modify parse() to support parsing consecutive files

* Modify parse() to return AST root

* Add actions after reduction in grammar.y

* Add param_list_create() and param_list_print()

* Add expr_create() and expr_print()

* Add type_create() and type_print()

* Add stmt_create() and stmt_print()

* Add decl_create() and decl_print()

* Pass file pointers to decode(), scan(), and parse()

* Modify parse() to take file pointer

* Modify scan() to take file pointer

* Modify decode() to take file pointer

* Move definition of MAX_STRING_LEN

* Add grammar.output to .gitignore
  • Loading branch information
sghuang19 committed Nov 6, 2023
1 parent aaab449 commit 160bd09
Show file tree
Hide file tree
Showing 35 changed files with 1,193 additions and 178 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ bminor
lex.yy.c
token.h
grammar.tab.c
grammar.output

test/**/*.out
36 changes: 30 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
bminor: bminor.c encoder.o scanner.o lex.yy.o parser.o grammar.tab.o
bminor: bminor.c encoder.o scanner.o lex.yy.o parser.o grammar.tab.o printer.o decl.o stmt.o expr.o type.o param_list.o
gcc $^ -o $@

encoder.o: encoder.c
gcc -c $^ -o $@
encoder.o: encoder.c encoder.h
gcc -c $< -o $@

# Scanner
lex.yy.c: lex.yy.l
flex $^

Expand All @@ -13,16 +14,36 @@ lex.yy.o: lex.yy.c
scanner.o: scanner.c token.h
gcc -c $< -o $@

# Parser
parser.o: parser.c
gcc -c $^ -o $@

grammar.tab.c token.h: grammar.y lex.yy.c
bison --defines=token.h $<
#bison -v --defines=token.h $<
#bison --defines=token.h $<
bison -v --defines=token.h $<

grammar.tab.o: grammar.tab.c
gcc -c $^ -o $@

# Printer
printer.o: printer.c
gcc -c $^ -o $@

decl.o: decl.c
gcc -c $^ -o $@

stmt.o: stmt.c
gcc -c $^ -o $@

expr.o: expr.c
gcc -c $^ -o $@

type.o: type.c
gcc -c $^ -o $@

param_list.o: param_list.c
gcc -c $^ -o $@

# Tests
test-encoder:
./runtest.sh encoder
Expand All @@ -33,9 +54,12 @@ test-scanner:
test-parser:
./runtest.sh parser

test-printer:
./runtest.sh printer

clean:
rm -f lex.yy.c
rm -f token.h grammar.tab.c grammar.output
rm -f *.o
rm -f ./test/*/*.bminor.out
rm -f bminor
rm -f bminor
23 changes: 19 additions & 4 deletions bminor.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "encoder.h"
#include "scanner.h"
#include "parser.h"
#include "printer.h"

void usage(int exit_code)
{
Expand All @@ -14,8 +15,8 @@ void usage(int exit_code)

int main(int argc, char* argv[])
{
// Parse command line arguments
char* option, * filename;

switch (argc)
{
case 1:
Expand All @@ -36,27 +37,41 @@ int main(int argc, char* argv[])
break;
}

// Open input file
FILE* fp = fopen(filename, "r");
if (fp == NULL)
{
fprintf(stderr, "Failed to open file %s\n", filename);
return EXIT_FAILURE;
}

// Perform the requested operation
if (strcmp(option, "--encode") == 0)
{
if (decode(filename) == 0)
if (decode(fp) == 0)
return EXIT_SUCCESS;
}
else if (strcmp(option, "--scan") == 0)
{
if (scan(filename) == 0)
if (scan(fp) == 0)
return EXIT_SUCCESS;
}
else if (strcmp(option, "--parse") == 0)
{
if (parse(filename) == 0)
if (parse(fp) != NULL)
return EXIT_SUCCESS;
}
else if (strcmp(option, "--print") == 0)
{
return print_and_compare(filename, fp);
}
else
{
fprintf(stderr, "Unknown option '%s'\n", option);
usage(EXIT_FAILURE);
}

//Error message
fprintf(stderr, "Failed to %s file %s\n", option + 2, filename);
return EXIT_FAILURE;
}
58 changes: 58 additions & 0 deletions decl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <stdlib.h>
#include <stdio.h>
#include "decl.h"
#include "type.h"

struct decl* decl_create(char* name, struct type* type, struct expr* value, struct stmt* code, struct decl* next)
{
struct decl* d = malloc(sizeof(*d));
d->name = name;
d->type = type;
d->value = value;
d->code = code;
d->next = next;
return d;
}

void decl_print(struct decl* d, int indent)
{
if (!d) return;
int i;

for (i = 0; i < indent; i++)
printf("\t");
printf("%s: ", d->name);
type_print(d->type);

if (d->value)
{
printf(" = ");
if (d->value->kind == EXPR_LIST)
{
printf("{");
expr_print(d->value);
printf("}");
}
else
{
expr_print(d->value);
}
}

if (d->code)
{
printf(" = {\n");
stmt_print(d->code, indent + 1);
for (i = 0; i < indent; i++)
printf("\t");
printf("}");
}
else
{
// Functions don't end with semicolon
printf(";");
}

printf("\n");
decl_print(d->next, indent);
}
25 changes: 11 additions & 14 deletions decl.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@

#ifndef DECL_H
#define DECL_H

#include "type.h"
#include "stmt.h"
#include "expr.h"
#include <stdio.h>
#include "symbol.h"

struct decl {
char *name;
struct type *type;
struct expr *value;
struct stmt *code;
struct symbol *symbol;
struct decl *next;
struct decl
{
char* name;
struct type* type;
struct expr* value;
struct stmt* code;
struct symbol* symbol;
struct decl* next;
};

struct decl * decl_create( char *name, struct type *type, struct expr *value, struct stmt *code, struct decl *next );
void decl_print( struct decl *d, int indent );
struct decl* decl_create(char* name, struct type* type, struct expr* value, struct stmt* code, struct decl* next);
void decl_print(struct decl* d, int indent);

#endif


25 changes: 8 additions & 17 deletions encoder.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_STRING_LEN 255
#include "encoder.h"

int is_hex(char c)
{
Expand Down Expand Up @@ -199,40 +198,32 @@ int string_encode(const char* s, char* es)
return 0;
}

int decode(const char* filename)
int decode(FILE* fp)
{
FILE* file = fopen(filename, "r");
if (file == NULL)
{
printf("Could not open file %s\n", filename);
return 1;
}

// Find the size of the file
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
if (file_size > (MAX_STRING_LEN * 5 + 2) * sizeof(char))
{
fprintf(stderr, "Invalid string: too long\n");
fclose(file);
fclose(fp);
return 1;
}
rewind(file);
rewind(fp);

// Allocate memory for the file content
// Reserve space for \0
char* file_content = (char*)malloc(file_size + sizeof(char));
if (file_content == NULL)
{
perror("Could not allocate memory");
fclose(file);
fclose(fp);
return 1;
}

// Read the file content into the allocated memory
size_t chars_read = fread(file_content, sizeof(char), file_size, file);
size_t chars_read = fread(file_content, sizeof(char), file_size, fp);
file_content[chars_read] = '\0';
fclose(file);

char s[MAX_STRING_LEN + 1] = { 0 };

Expand Down
7 changes: 6 additions & 1 deletion encoder.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#ifndef ENCODER_H
#define ENCODER_H

#define MAX_STRING_LEN 255

int string_decode(const char* es, char* s);

int string_encode(const char* s, char* es);

int decode(const char* filename);
int decode(FILE *fp);

#endif
Loading

0 comments on commit 160bd09

Please sign in to comment.