Skip to content

Commit

Permalink
partial (a4): for reduce/reduce conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
SantriptaSharma committed Nov 24, 2023
1 parent 999bde1 commit 09a6944
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 9 deletions.
9 changes: 7 additions & 2 deletions 15_A4.y
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ conditional_expression:
assignment_expression:
conditional_expression
| unary_expression '=' assignment_expression {
if ($1.sym->type.kind == FUNC_T || $1.sym->type.kind == TEMP_T) {
if ($1.sym->type.kind == FUNC_T || $1.sym->is_temp) {
yyerror("functions & temps can't be assigned to");
YYABORT;
}
Expand Down Expand Up @@ -439,6 +439,11 @@ declaration:
break;
}

if ($1 == VOID_T && $$.sym->type.kind != FUNC_T) {
yyerror("void is zero-sized!");
YYABORT;
}

Symbol *existing = SymLookup($$.sym->name);
$$.sym->size = GetSize($$.sym->type);

Expand Down Expand Up @@ -615,7 +620,7 @@ selection_statement:
Emit(Jump(AImm(0)));
}
}
| IF '(' expression ')' marker statement guard ELSE marker statement {
| IF '(' expression ')' marker statement <next_list>{ $$ = MakeList(quads_size); Emit(Jump(AImm(0))); } ELSE marker statement {
if ($3.truelist != NULL) {
Backpatch($3.truelist, $5); Backpatch($3.falselist, $9);
$$ = Merge($6, $7); $$ = Merge($$, $10);
Expand Down
126 changes: 120 additions & 6 deletions 15_A4_translator.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ int GetSize(Type type) {
switch (type.kind)
{
case PRIMITIVE_T:
case TEMP_T:
return Sizes[type.primitive];
break;

Expand All @@ -319,7 +318,72 @@ int GetSize(Type type) {
default:
return size_of_pointer;
break;
}
}
}

char TypeEq(Type t1, Type t2) {
switch (t1.kind) {
Type base1, base2;

case PRIMITIVE_T:
return t1.primitive == t2.primitive;
break;

case PRIMITIVE_PTR:
case ARRAY_PTR:
case ARRAY_T:
base1 = t1.kind == PRIMITIVE_PTR ? prim2type(t1.primitive) : prim2type(t1.array.base);
base2 = t2.kind == PRIMITIVE_PTR ? prim2type(t2.primitive) : prim2type(t2.array.base);

if (t2.kind == PRIMITIVE_PTR || t2.kind == ARRAY_PTR || t2.kind == ARRAY_T)
return TypeEq(base1, base2);
else
return 0;
break;

case FUNC_T:
if (t2.kind != FUNC_T) return 0;

if (t1.func.return_type->primitive != t2.func.return_type->primitive) return 0;

ArgList *arg1 = t1.func.arg_list;
ArgList *arg2 = t2.func.arg_list;

while (arg1 != NULL && arg2 != NULL) {
if (!TypeEq(arg1->elem.decl.type, arg2->elem.decl.type)) return 0;

arg1 = arg1->next;
arg2 = arg2->next;
}

return arg1 == NULL && arg2 == NULL;

default:
return 0;
break;
}
}

// will implicitly allow conversions char <-> int, int <-> pointer, but not char <-> pointer (technically int <-> char just as invalid, but let's allow it)
char TypeCompatible(Type t1, Type t2) {
switch (t1.kind) {
PRIMITIVE_TYPE t;

case PRIMITIVE_T:
return t2.kind == !FUNC_T;
break;

case PRIMITIVE_PTR:
case ARRAY_PTR:
case ARRAY_T:
t = t1.kind == PRIMITIVE_PTR ? t1.primitive : t1.array.base;
return t2.kind != FUNC_T && t != CHAR_T;
break;

default:
return 0;
break;
}
}

void TypeFree(Type *type)
Expand All @@ -335,7 +399,6 @@ static const char *TypeSym[] = {
[PRIMITIVE_T] "PRIM",
[PRIMITIVE_PTR] "PRIM*",
[ARRAY_PTR] "ARR*",
[TEMP_T] "TEMP",
[ARRAY_T] "ARR",
[FUNC_T] "FUNC"
};
Expand All @@ -352,7 +415,6 @@ void TypeDispl(Type t) {

switch (t.kind) {
case PRIMITIVE_T:
case TEMP_T:
printf("%s", PrimitiveSym[t.primitive]);
break;

Expand Down Expand Up @@ -398,7 +460,6 @@ Symbol *SymInit(enum KIND_T kind) {
case PRIMITIVE_T:
case PRIMITIVE_PTR:
case ARRAY_PTR:
case TEMP_T:
sym->size = GetSize(sym->type);
break;

Expand All @@ -412,9 +473,61 @@ Symbol *SymInit(enum KIND_T kind) {
break;
}

sym->is_temp = 0;

return sym;
}

// clone any non-func symbol, doesn't assign a name
Symbol *SymClone(Symbol *sym) {
if (sym->type.kind == FUNC_T) return NULL;

Symbol *clone = malloc(sizeof(*clone));
clone->type = sym->type;
clone->initial_value = sym->initial_value;
clone->size = sym->size;
clone->offset = sym->offset;
clone->is_temp = sym->is_temp;
clone->inner_table = sym->inner_table;
clone->next = NULL;

SymInsert(clone);

return clone;
}

// cast any non-func symbol to a given type, creating and returning a new symbol
Symbol *Cast(Symbol *sym, Type type) {
if (type.kind == FUNC_T) return NULL;
if (TypeEq(sym->type, type)) return sym;

Symbol *new = SymClone(sym);
size_t len = strlen(sym->name) + 16;
new->name = malloc(len);
sprintf((char *) new->name, "__cast[%d]_%s", current_table->temp_count++, sym->name);
new->type = type;
new->size = GetSize(type);
new->is_temp = 1;

SymInsert(new);

Quad q = (Quad) {
.opcode = MOV,
.rd = (Addr) {
.kind = SYMBOL_A,
.sym = new
},
.rs = (Addr) {
.kind = SYMBOL_A,
.sym = sym
}
};

Emit(q);

return new;
}

Symbol *SymLookup(const char *name) {
Symbol *sym = current_table->sym_head;
while (sym) {
Expand Down Expand Up @@ -504,7 +617,8 @@ Symbol *GenTemp()
sprintf(name, "__t_%d_", current_table->temp_count++);

Symbol *sym = SymLookupOrInsert(name);
sym->type.kind = TEMP_T;
sym->type.kind = PRIMITIVE_T;
sym->is_temp = 1;
sym->type.primitive = INT_T;

sym->size = GetSize(sym->type);
Expand Down
7 changes: 6 additions & 1 deletion 15_A4_translator.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ struct _ArgList;

typedef struct _Type {
// needs some kind of types table + hashing mechanism to reuse types, instead of always creating new ones (wont implement for now)
enum KIND_T {PRIMITIVE_PTR, ARRAY_PTR, TEMP_T, PRIMITIVE_T, ARRAY_T, FUNC_T} kind;
enum KIND_T {PRIMITIVE_PTR, ARRAY_PTR, PRIMITIVE_T, ARRAY_T, FUNC_T} kind;
union {
PRIMITIVE_TYPE primitive;
struct {
Expand All @@ -109,6 +109,8 @@ typedef struct _Type {
} Type;

int GetSize(Type type);
char TypeEq(Type t1, Type t2);
char TypeCompatible(Type t1, Type t2);
void TypeFree(Type *type);
void TypeDispl(Type type);

Expand All @@ -118,11 +120,14 @@ typedef struct _Symbol {
int initial_value;
int size;
int offset;
char is_temp;
SymbolTable *inner_table;
struct _Symbol *next;
} Symbol;

Symbol *SymInit(enum KIND_T kind);
Symbol *SymClone(Symbol *sym);
Symbol *Cast(Symbol *sym, Type type);
Symbol *SymLookup(const char *name);
Symbol *SymLookupOrInsert(const char *name);
Symbol *StringLookupOrInsert(const char *str);
Expand Down
29 changes: 29 additions & 0 deletions cex.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
15_A4.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
15_A4.y: warning: reduce/reduce conflict on token ELSE [-Wcounterexamples]
First example: type_specifier declarator $@4 '{' IF '(' expression ')' marker statement • ELSE marker statement '}' $end
First reduce derivation
$accept
↳ translation_unit $end
↳ external_declaration
↳ function_definition
↳ type_specifier declarator $@4 compound_statement
↳ '{' block_item_list '}'
↳ block_item
↳ statement
↳ selection_statement
↳ IF '(' expression ')' marker statement guard ELSE marker statement
↳ •
Second example: type_specifier declarator $@4 '{' IF '(' expression ')' marker IF '(' expression ')' marker statement • guard ELSE marker statement '}' $end
Second reduce derivation
$accept
↳ translation_unit $end
↳ external_declaration
↳ function_definition
↳ type_specifier declarator $@4 compound_statement
↳ '{' block_item_list '}'
↳ block_item
↳ statement
↳ selection_statement
↳ IF '(' expression ')' marker statement guard ELSE marker statement
↳ selection_statement
↳ IF '(' expression ')' marker statement •
14 changes: 14 additions & 0 deletions iftest.nc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
char a;
char b;

int main() {
if (a >= b + 13 || a < 0 ) {
a = 5;
} else if (a > 5) {
b = 10
} else if (b < 1) {
b = a;
} else {
a = a = 1;
}
}

0 comments on commit 09a6944

Please sign in to comment.