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

Commit

Permalink
Introduce resolver
Browse files Browse the repository at this point in the history
* Improve bminor.c readability

* Improve readability of Makefile

* Improve error handling in scanner and parser

* Fix assignment expression parsing issue

* Fix an issue in decl_print()

* Modify printer to directly print to stdout

* Change printer_test() in runtest.sh to use diff

* Add .tmp for testing output to .gitignore

* Create test cases for resolver

* Add test for resolver in runtest.sh

* Create symbol.c and symbol.h

* Create scope.c and scope.h

* Create resolver.c and resolver.h

* Implement decl_resolve()

* Implement stmt_resolve()

* Implement param_list_resolve()

* Implement expr_resolve()

* Add rules for resolver in Makefile

* Add --resolve option in bminor.c

* Fix no prototype warning in hash_table.c
  • Loading branch information
sghuang19 authored Nov 8, 2023
1 parent 160bd09 commit 056e2f9
Show file tree
Hide file tree
Showing 45 changed files with 658 additions and 196 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ token.h
grammar.tab.c
grammar.output

test/**/*.out
test/**/*.out
test/**/*.tmp
64 changes: 44 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,48 +1,65 @@
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
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 \
resolver.o symbol.o scope.o hash_table.o
gcc $^ -o $@

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

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

lex.yy.o: lex.yy.c
gcc -c $^ -o $@
gcc -c $< -o $@

scanner.o: scanner.c token.h
gcc -c $< -o $@

# Parser
parser.o: parser.c
gcc -c $^ -o $@
parser.o: parser.c printer.h
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 $<

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

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

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

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

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

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

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

# Resolver
resolver.o: resolver.c resolver.h
gcc -c $< -o $@

symbol.o: symbol.c symbol.h
gcc -c $< -o $@

scope.o: scope.c scope.h
gcc -c $< -o $@

hash_table.o: hash_table.c hash_table.h
gcc -c $< -o $@

# Tests
test-encoder:
Expand All @@ -57,9 +74,16 @@ test-parser:
test-printer:
./runtest.sh printer

test-resolver:
./runtest.sh resolver

# Cleanup
clean-test:
rm -f ./test/*/*.bminor.out

clean:
rm -f ./test/*/*.bminor.out
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
32 changes: 13 additions & 19 deletions bminor.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "scanner.h"
#include "parser.h"
#include "printer.h"
#include "resolver.h"

void usage(int exit_code)
{
Expand All @@ -21,20 +22,17 @@ int main(int argc, char* argv[])
{
case 1:
usage(EXIT_FAILURE);
break;
case 2:
if (strcmp(argv[1], "--help") == 0)
usage(EXIT_SUCCESS);
else usage(EXIT_FAILURE);
break;
case 3:
option = argv[1];
filename = argv[2];
break;
default:
fprintf(stderr, "Too many arguments.\n");
usage(EXIT_FAILURE);
break;
}

// Open input file
Expand All @@ -47,31 +45,27 @@ int main(int argc, char* argv[])

// Perform the requested operation
if (strcmp(option, "--encode") == 0)
{
if (decode(fp) == 0)
return EXIT_SUCCESS;
}
return decode(fp) == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
else if (strcmp(option, "--scan") == 0)
{
if (scan(fp) == 0)
return EXIT_SUCCESS;
}
return scan(fp) == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
else if (strcmp(option, "--parse") == 0)
return parse(fp) != NULL ? EXIT_SUCCESS : EXIT_FAILURE;
else if (strcmp(option, "--print") == 0)
{
if (parse(fp) != NULL)
return EXIT_SUCCESS;
struct decl* d = parse(fp);
if (d == NULL) return EXIT_FAILURE;
print(d);
return EXIT_SUCCESS;
}
else if (strcmp(option, "--print") == 0)
else if (strcmp(option, "--resolve") == 0)
{
return print_and_compare(filename, fp);
struct decl* d = parse(fp);
if (d == NULL) return EXIT_FAILURE;
return resolve(d);
}
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;
}
49 changes: 42 additions & 7 deletions decl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include <stdio.h>
#include "decl.h"
#include "type.h"
#include "symbol.h"
#include "scope.h"

struct decl* decl_create(char* name, struct type* type, struct expr* value, struct stmt* code, struct decl* next)
{
Expand Down Expand Up @@ -34,9 +36,7 @@ void decl_print(struct decl* d, int indent)
printf("}");
}
else
{
expr_print(d->value);
}
}

if (d->code)
Expand All @@ -45,14 +45,49 @@ void decl_print(struct decl* d, int indent)
stmt_print(d->code, indent + 1);
for (i = 0; i < indent; i++)
printf("\t");
printf("}");
printf("}\n");
}
else
printf(";\n");

decl_print(d->next, indent);
}

void decl_resolve(struct decl* d)
{
if (!d) return;

if (scope_lookup_current(d->name))
{
fprintf(stderr, "error: symbol '%s' already declared\n", d->name);
res_errors++;
}
symbol_t kind;
int which;
if (cur_scope->level > 0)
{
kind = SYMBOL_LOCAL;
which = cur_local++;
}
else
{
// Functions don't end with semicolon
printf(";");
kind = SYMBOL_GLOBAL;
which = cur_global++;
}
d->symbol = symbol_create(kind, d->type, d->name, which);
scope_bind(d->name, d->symbol);

printf("\n");
decl_print(d->next, indent);
if (d->type->kind == TYPE_ARRAY)
expr_resolve(d->type->size);

expr_resolve(d->value);
if (d->code)
{
scope_enter();
param_list_resolve(d->type->params);
stmt_resolve(d->code);
scope_exit();
}

decl_resolve(d->next);
}
1 change: 1 addition & 0 deletions decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ struct decl

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);
void decl_resolve(struct decl* d);

#endif
24 changes: 24 additions & 0 deletions expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <stdio.h>
#include "encoder.h"
#include "expr.h"
#include "scope.h"

/* Creating binary nodes by default */

Expand Down Expand Up @@ -291,3 +292,26 @@ void expr_print(const struct expr* e)
break;
}
}

/* Resolving the expression nodes */

void expr_resolve(struct expr* e)
{
if (!e) return;
if (e->kind == EXPR_NAME)
{
e->symbol = scope_lookup(e->name);
if (e->symbol)
resolve_msg(e->symbol);
else
{
printf("Resolve Error | Undefined symbol '%s'\n", e->name);
res_errors++;
}
}
else
{
expr_resolve(e->left);
expr_resolve(e->right);
}
}
4 changes: 4 additions & 0 deletions expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct expr
const char* string_literal;
};

/* Creating non-leaf nodes */
struct expr* expr_create(expr_t kind, struct expr* left, struct expr* right);
struct expr* expr_create_unary(expr_t kind, struct expr* operand);

Expand All @@ -76,4 +77,7 @@ struct expr* expr_create_string_literal(const char* str);
/* Printing the expressions */
void expr_print(const struct expr* e);

/* Resolving the expressions */
void expr_resolve(struct expr* e);

#endif
6 changes: 4 additions & 2 deletions grammar.y
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ extern int yylineno;
extern char *yytext;

void yyerror(const char *s) {
fprintf(stderr, "Error: %s at line %d near '%s'\n", s, yylineno, yytext);
fprintf(stderr, "Parse Error @ %d | %s\n", yylineno, s);
}

struct decl *root = NULL;
%}

%error-verbose

/* Keywords */
%token TOKEN_ARRAY
%token TOKEN_AUTO
Expand Down Expand Up @@ -216,7 +218,7 @@ opt_expr : /* epsilon */ { $$ = NULL; }
expr : expr1
;

expr1 : lval TOKEN_ASSIGN expr1 { expr_create(EXPR_ASSIGN, $1, $3); }
expr1 : lval TOKEN_ASSIGN expr1 { $$ = expr_create(EXPR_ASSIGN, $1, $3); }
| expr2
;

Expand Down
8 changes: 3 additions & 5 deletions hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,15 +309,13 @@ acceptable. Do NOT use for cryptographic purposes.
--------------------------------------------------------------------
*/

static ub4 jenkins_hash(k, length, initval)
register const ub1 *k; /* the key */
register ub4 length; /* the length of the key */
register ub4 initval; /* the previous hash, or an arbitrary value */
static ub4 jenkins_hash(const ub1 *k, ub4 length, ub4 initval)
{
register ub4 a, b, c, len; /* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = initval; /* the previous hash value *//*---------------------------------------- handle most of the key */
c = initval; /* the previous hash value */
/*---------------------------------------- handle most of the key */
while(len >= 12) {
a += (k[0] + ((ub4) k[1] << 8) + ((ub4) k[2] << 16) + ((ub4) k[3] << 24));
b += (k[4] + ((ub4) k[5] << 8) + ((ub4) k[6] << 16) + ((ub4) k[7] << 24));
Expand Down
Loading

0 comments on commit 056e2f9

Please sign in to comment.