diff --git a/15_A4.tex b/15_A4.tex index b38aaaf..9c7aedb 100644 --- a/15_A4.tex +++ b/15_A4.tex @@ -16,7 +16,7 @@ \section{Augmenting the Grammar} \begin{itemize} \item We first define our attributed grammar, specifying which attribute is associated with each terminal/non-terminal symbol. The list of attributes is available at the top of the bison file (in the union), with comments. - \item Next, we add + \item Next, we augment the grammar with some symbols, particularly, the marker and the guard symbol, both of which produce only epsilon, but have associated actions or attributes. A description of the action is available in the bison file alongside each rule. \end{itemize} \end{document} diff --git a/15_A4.y b/15_A4.y index a7ec989..7f7c876 100644 --- a/15_A4.y +++ b/15_A4.y @@ -13,12 +13,6 @@ void yyerror(char *s); %} -/* -TODO: go through all rules, make sure no rules just logging remain -TODO: write everything up in assignment pdf -*/ - - %union { // Attribute for all expressions, contains pointers to a symbol, and optional pointers to true/false lists (non-null for bool exprs) ExprAttrib expr; @@ -35,17 +29,22 @@ TODO: write everything up in assignment pdf // A single argument, either a declaration (for params) or an expression (for call args) ArgListElem arg; - + // Attribute for an optional_expression, contains the expression attribute and a flag indicating whether it's present struct _opt_expr { ExprAttrib expr; char has_expr; } opt_expr; + // Attribute for type specifier (int, char, void) tokens, just an enum mapping to INT_T, CHAR_T, VOID_T PRIMITIVE_TYPE type_spec; + // Attribute for statements & guards, contains a pointer to their dangling exit quad addresses QuadList *next_list; + + // Attribute for a marker, contains the number of quads emitted at the time of the marker's reduction size_t quad_index; + // Attribute for constants char *string; int val; } @@ -114,11 +113,11 @@ TODO: write everything up in assignment pdf %% /* auxiliary symbols */ -marker: { $$ = quads_size; } -guard: { $$ = MakeList(quads_size); Emit(Jump(AImm(0))); } +marker: { $$ = quads_size; } // just store the quad index of the next instruction on reduction +guard: { $$ = MakeList(quads_size); Emit(Jump(AImm(0))); } // emit an unconditional jump, and store a next list to be filled in by rules that use guards /* expressions */ -/* TODO: validate types and add implicit conversions, on every operation and assignment */ +/* TODO: validate types and add implicit conversions, on every operation and assignment (wont do) */ constant: INTCONST | CHARCONST @@ -158,7 +157,7 @@ postfix_expression: Emit(IndexRead(ASym($$), ASym($1), ASym($3))); } | postfix_expression '(' argument_expression_list ')' { - // TODO: validate type of params + // TODO: validate type of params (wont do) if ($1.sym->type.kind != FUNC_T) { yyerror("can't call non-function type"); YYABORT; @@ -217,8 +216,6 @@ argument_expression_list: assignment_expression {$$ = MakeArgList(ARG_EXPR($1));} | argument_expression_list ',' assignment_expression {InsertArg($1, ARG_EXPR($3)); $$ = $1;} -// TODO: write out relational actions using dummy keys - unary_expression: postfix_expression | '&' unary_expression { @@ -529,7 +526,7 @@ declaration: yyerror(err); YYABORT; } else if (existing != NULL) { - // TODO: validate signature against existing entry + // TODO: validate signature against existing entry (wont do) SymFree($$.sym); $$.sym = existing; } else { @@ -537,7 +534,7 @@ declaration: } - // TODO: verify types before emitting assignment + // TODO: verify types before emitting assignment (wont do) if ($$.has_init == 1) { Emit(Mov(ASym($$), ASym($$.init))); } @@ -735,12 +732,12 @@ jump_statement: /* TLU */ translation_unit: - external_declaration {log("translation-unit")} - | translation_unit external_declaration {log("translation-unit")} + external_declaration + | translation_unit external_declaration external_declaration: - function_definition {log("external-declaration")} - | declaration {log("external-declaration")} + function_definition + | declaration function_definition: type_specifier declarator { @@ -765,7 +762,7 @@ function_definition: Symbol *existing = SymLookup($2.sym->name, 0); if (existing != NULL) { - // TODO: validate signature against existing entry + // TODO: validate signature against existing entry (wont do) SymFree($2.sym); $2.sym = existing; } else { diff --git a/15_A4_translator.c b/15_A4_translator.c index 302979b..4c7750c 100644 --- a/15_A4_translator.c +++ b/15_A4_translator.c @@ -706,8 +706,6 @@ int main() { InitQuads(); InitTables(); - SymTableDispl(current_table); - yyparse(); SymTableDispl(current_table); diff --git a/15_A4_translator.h b/15_A4_translator.h index 46bda39..5a0bbeb 100644 --- a/15_A4_translator.h +++ b/15_A4_translator.h @@ -7,6 +7,7 @@ extern const unsigned int size_of_pointer; struct _Symbol; +// Struct representing a single address in a 3-address code, either a symbol or an immediate typedef struct _Addr { enum ADDR_KIND {SYMBOL_A, IMMEDIATE} kind; union { @@ -21,6 +22,7 @@ typedef struct _QuadList { struct _QuadList *next; } QuadList; +// Keep track of all true/false/next lists we use so we can free them later (could technically be freed on backpatch but oh well) extern int existing_lists_size, existing_lists_capacity; extern QuadList **existing_lists; @@ -28,24 +30,32 @@ void InitLists(); void AddList(QuadList *list); void DestroyLists(); +// Create a new list with a single element QuadList *MakeList(int ind); +// Insert an element into a list void Insert(QuadList* list, int ind); +// Merge two lists QuadList *Merge(QuadList *list1, QuadList *list2); +// Fill out all jump quads in a list with the given destination void Backpatch(QuadList *list, int dest); +// Free a single list void FreeList(QuadList *list); +// Struct representing a single 3-address instruction typedef struct { enum OPCODE {ADD, SUB, MUL, DIV, MOD, MOV, POS, NEG, ADDR, DEREF, JMP, JIF, JNT, JLT, JGT, JEQ, JNE, JLE, JGE, PAR, CAL, RET, INDR, INDW, PTRW, FN_LABEL} opcode; Addr rs, rt, rd; } Quad; +// Dynamic array of instructions extern int quads_size, quads_capacity; extern Quad *quads; #define AImm(x) ((Addr){IMMEDIATE, .imm = x}) #define ASym(x) ((Addr){SYMBOL_A, .sym = x.sym}) +// Emit a quad void Emit(Quad q); #define Mov(dest, source) ((Quad){MOV, source, AImm(0), dest}) @@ -69,6 +79,7 @@ void Emit(Quad q); #define DerefWrite(dest, source) ((Quad){PTRW, dest, AImm(0), source}) #define FnLabel(label) ((Quad){FN_LABEL, AImm(0), AImm(0), label}) +// Functions for printing a quad & the quads list void DisplayQuad(Quad q); void DisplayQuads(); @@ -83,15 +94,19 @@ typedef struct _SymbolTable { extern SymbolTable glb_table, *current_table; +// Create a new symbol table SymbolTable *Create_SymbolTable(const char *name, enum Scope scope, SymbolTable *parent); +// Free a symbol table void Destroy_SymbolTable(SymbolTable *table); +// Print a symbol table void SymTableDispl(SymbolTable *table); -typedef enum { INT_T, CHAR_T, VOID_T } PRIMITIVE_TYPE; +typedef enum { INT_T, CHAR_T, VOID_T } PRIMITIVE_TYPE; #define prim2type(x) ((Type){.kind = PRIMITIVE_T, .primitive = x}) struct _ArgList; +// Struct representing a type, either a primitive or a pointer (with some extra specialisation) 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, PRIMITIVE_T, ARRAY_T, FUNC_T} kind; @@ -135,6 +150,7 @@ void SymInsert(Symbol *sym); void SymFree(Symbol *sym); void SymDispl(Symbol *sym); +// Struct representing an expression, holds a pointer to a symbol, and optionally true/false lists for boolean expressions typedef struct _ExprAttrib { Symbol *sym; QuadList *truelist, *falselist; @@ -143,6 +159,7 @@ typedef struct _ExprAttrib { #define PURE_EXPR(x) ((ExprAttrib){.sym = x, .truelist = NULL, .falselist = NULL}) #define BOOL_EXPR(x, tl, fl) ((ExprAttrib){.sym = x, .truelist = tl, .falselist = fl}) +// Struct representing a single argument an arglist, can either be an expression (for calls) or a type name pair (for parameters in declarations) typedef struct _ArgListElem { enum {EXPR, DECL} kind; union { @@ -154,6 +171,7 @@ typedef struct _ArgListElem { }; } ArgListElem; +// Struct representing a list of arguments, used for both calls & declarations typedef struct _ArgList { ArgListElem elem; struct _ArgList *next; diff --git a/tex_build/15_A4.pdf b/tex_build/15_A4.pdf index 7b3cbef..10609aa 100644 Binary files a/tex_build/15_A4.pdf and b/tex_build/15_A4.pdf differ