Files
compiler-the-translators/src/grammar.y

1665 lines
68 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Syntax Analyzer with Bison (3.8.2) */
/* The Translators - Spring 2025 */
// ----- THIS FILE MUST BE FORMATTED CORRECTLY FOR READABILITY ----- //
// ✏️ FORMATTING RULES:
// 1⃣ Use 4 spaces for indentation.
// 2⃣ Grammar rules (terminals and nonterminals) should always be on their own line.
// 3⃣ Grammar rules and C-blocks should always begin 8 spaces in.
// 4⃣ Rule end-markers (;, |) should always be 4 spaces in.
// 5⃣ C-blocks should always be clearly defined and follow clang formatting rules.
// 6⃣ 1-line if/for/while statements must be wrapped in curly braces.
// 7⃣ Comments should always be above rules
// 8⃣ DO NOT USE TABS. EVER.
// Please ask Scarlett if you are unsure of how to format something. Thanks! 😀
%{
#include "../src/grammar.h"
%}
%union {
int integ;
char* words;
char letter;
void* tn;
}
%locations
%token <integ> ACCESS 801
%type <integ> idlist
%type <tn> assignable
%type <tn> expression
%type <tn> constant
%type <tn> id_or_types
%type <tn> types
%type <tn> sblock
%type <tn> compound_statement
%type <tn> simple_statement
%type <tn> statement_list
%type <integ> argument_list
%type <integ> ablock
%token <words> ID 101
%token <tn> T_INTEGER 201
%token <tn> T_ADDRESS 202
%token <tn> T_BOOLEAN 203
%token <tn> T_CHARACTER 204
%token <tn> T_STRING 205
%token <integ> C_INTEGER 301
%token <tn> C_NULL 302
%token <tn> C_CHARACTER 303
%token <tn> C_STRING 304
%token <tn> C_TRUE 305
%token <tn> C_FALSE 306
%token WHILE 401
%token IF 402
%token THEN 403
%token ELSE 404
%token TYPE 405
%token FUNCTION 406
%token RETURN 407
%token EXTERNAL 408
%token AS 409
%token L_PAREN 501
%token R_PAREN 502
%token L_BRACKET 503
%token R_BRACKET 504
%token L_BRACE 505
%token R_BRACE 506
%token SEMI_COLON 507
%token COLON 508
%token COMMA 509
%token ARROW 510
%token MUL 603
%token DIV 604
%token REM 605
%token ADD 601
%token LESS_THAN 606
%token EQUAL_TO 607
%token AND 610
%token OR 611
%token ASSIGN 608
%token SUB_OR_NEG 602
%token NOT 609
%token DOT 612
%token RESERVE 613
%token RELEASE 614
%token COMMENT 700
%token INCLUDE 901
//precedence order
%left ASSIGN
%left OR
%left AND
%left EQUAL_TO
%left LESS_THAN
%left ADD SUB_OR_NEG
%left MUL DIV REM
%precedence NOT
%precedence UMINUS
%precedence DOT
%precedence RESERVE RELEASE
%%
program:
prototype_or_definition_list
| include_list
| include_list prototype_or_definition_list
;
prototype_or_definition_list:
prototype prototype_or_definition_list
| definition prototype_or_definition_list
| prototype
| definition
| prototype error { yyerrok; }
| definition error { yyerrok; }
;
prototype:
L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID
;
include_list:
include_statement include_list
| include_statement
;
include_statement:
INCLUDE C_STRING
;
definition:
TYPE ID COLON
{
printdebug("Currently see a record definition for %s", $2);
tn = CreateEntry(getAncestor(cur),TYPE_RECORD_TYPE, recprime, $2, CreateRecordInfo(0, cur = CreateScope(cur, 0, 0)));
printdebug("Created a new scope");
} dblock {
setRecSize(look_up(getParent(cur), $2), getRecSize(cur));
setRecOffsetInfo(cur, look_up(getParent(cur),$2));
printdebug("Moving up a scope after seeing a record definition");
cur = getParent(cur);
}
| TYPE ID COLON C_INTEGER ARROW id_or_types
{
printdebug("Currently see a array definition of name %s,storing type %s, of dimensions %d", $2, getName((TableNode*)$6), $4);
CreateEntry(cur,TYPE_ARRAY_TYPE, arrayprim, $2, CreateArrayInfo($4, (TableNode*)$6));
printdebug("%sID: %s, dimensions: %d, typeOfArray: %s", COLOR_GREEN, $2, $4, getName((TableNode*)$6));
}
| function_declaration
| TYPE ID COLON id_or_types ARROW id_or_types
{
printdebug("Currently see a function type definition of name %s,parameter type %s, of return type %s", $2, getName((TableNode*)$4), getName((TableNode*)$6));
CreateEntry(cur,TYPE_FUNCTION_TYPE,funtypeprime,$2,CreateFunctionTypeInfo((TableNode*)$4 ,(TableNode*)$6));
}
| ID {
emit_function_start(table_lookup(cur,$1));
//printf("ID: %s\n", $1);
//printf("Type: %s\n", getType(table_lookup(getAncestor(cur), $1)));
printdebug("see function def rule 1\n");
TableNode *node = table_lookup(getAncestor(cur), $1);
if (node == undefined) {
printdebug("Undefined node declared.");
}else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){
throw_error(ERROR_SYNTAX, "Not a valid function declaration.");
}
else {
printdebug("setting as keyword to true");
setStartLine(node, @1.first_line);
setAsKeyword(node, true);
}
cur = CreateScope(cur, 0, 0);
setFunScope(node, cur);
printdebug("Created a new scope");
} L_PAREN {
TableNode * parameter = getParameter(getTypeEntry(table_lookup(getAncestor(cur), $1)));
//TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1))));
printdebug("type of parameter: %s", getName(parameter));
if (parameter == undefined) {
throw_error(ERROR_TYPE, "Undefined parameter in function definition.");
}else if(getAdInfoType(parameter) != TYPE_RECORD_TYPE){
int type_of_param_type = getAdInfoType(parameter);//this is an enum value defined in symbol_table.h
if( type_of_param_type == TYPE_UNDEFINED
|| type_of_param_type == TYPE_FUNCTION_DECLARATION
|| type_of_param_type == TYPE_ARRAY
|| type_of_param_type == TYPE_PRIMITIVE
|| type_of_param_type == TYPE_ALL_ELSE
|| type_of_param_type == TYPE_SYSTEM_DEFINED
|| type_of_param_type == TYPE_RECORD
|| type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused
throw_error(ERROR_TYPE, "Invalid type (%s) of parameter in function definition.", getAdInfo(parameter));
type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases
}
if(type_of_param_type == TYPE_UNDEFINED){
CreateEntry(cur,type_of_param_type, undefined, NULL, NULL);
// throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");
} else {
if(type_of_param_type == TYPE_FUNCTION_TYPE){
CreateEntry(cur, TYPE_FUNCTION_DECLARATION, parameter,NULL, getAdInfo(parameter));
// throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");
}
if(type_of_param_type == TYPE_ARRAY_TYPE){
CreateEntry(cur, TYPE_ARRAY, parameter,NULL, getAdInfo(parameter));
//throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");
}
if(type_of_param_type == TYPE_PRIMITIVE_TYPE){
CreateEntry(cur, TYPE_PRIMITIVE, parameter,NULL, getAdInfo(parameter))==undefined;
// throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");}
}
}
} else {
printdebug("record found");
for (TableNode* entry = getFirstEntry(getRecList(parameter)); entry!= NULL; entry = getNextEntry(entry)){
int type_of_param_type = getAdInfoType(entry);
if( type_of_param_type == TYPE_UNDEFINED
|| type_of_param_type == TYPE_FUNCTION_TYPE
|| type_of_param_type == TYPE_ARRAY_TYPE
|| type_of_param_type == TYPE_PRIMITIVE_TYPE
|| type_of_param_type == TYPE_ALL_ELSE
|| type_of_param_type == TYPE_SYSTEM_DEFINED
|| type_of_param_type == TYPE_RECORD_TYPE
|| type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused
throw_error(ERROR_TYPE, "Invalid type (%s) of parameter in function definition.", getAdInfo(entry));
type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases
}else{
printdebug("type of parameter correctly being passed in to AS function definition is %s which is valid", getType(entry));
}
if(type_of_param_type == TYPE_UNDEFINED){
printdebug("undefined type of parameter inside record");
CreateEntry(cur,type_of_param_type, undefined, NULL, NULL);
//throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");
} else {
if(type_of_param_type == TYPE_FUNCTION_DECLARATION){
printdebug("function declaration of parameter inside record");
CreateEntry(cur, TYPE_FUNCTION_DECLARATION, getTypeEntry(entry),NULL, getAdInfo(entry));
//throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");
}
if(type_of_param_type == TYPE_ARRAY){
printdebug("array type of parameter inside record");
CreateEntry(cur, TYPE_ARRAY, getTypeEntry(entry),NULL, getAdInfo(entry));
//throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");
}
if(type_of_param_type == TYPE_PRIMITIVE){
printdebug("primitive type of parameter inside record");
CreateEntry(cur, TYPE_PRIMITIVE, getTypeEntry(entry),NULL, getAdInfo(entry));
//throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");}
}
if(type_of_param_type == TYPE_RECORD){
printdebug("record type of parameter inside record");
CreateEntry(cur, TYPE_RECORD, getTypeEntry(entry),NULL, getAdInfo(entry));
//throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");}
}
/*printdebug("creating entry of type %s for function", getType(entry));
CreateEntry(cur, getTypeEntry(entry), "undefined", NULL);*/
}
}
}
//counter = 0;
printdebug("Created a new scope after seeing a function definition");
} idlist R_PAREN ASSIGN sblock {
TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1)));
if ($8 == undefined) {
throw_error(ERROR_TYPE, "Expected %s as return type but got undefined (possibly NULL). Differing return types in function.", getName(expected));
} else if (getAdInfoType(expected)==TYPE_ARRAY_TYPE && $8 == addr){
printdebug("CORRECT RETURN TYPE!!!");
} else if (getAdInfoType(expected)==TYPE_RECORD_TYPE && $8 == addr){
printdebug("CORRECT RETURN TYPE!!!");
}else if ($8 != expected) {
throw_error(ERROR_TYPE, "Expected %s as return type but got %s. Differing return types in function.", getName(expected), getName($8));
} else {
printdebug("CORRECT RETURN TYPE!!!");
}
//printf("Ending ID: %s\n", $1);
//printf("Ending Type: %s\n", getType(table_lookup(getAncestor(cur), $1)));
}
;
function_declaration:
FUNCTION ID COLON ID
{
if(getAdInfoType(table_lookup(cur, $4))==TYPE_FUNCTION_TYPE){
//printf("%s\n",$1);
//printf("%s\n",getName(table_lookup(cur, $4)));
if (CreateEntry(cur,TYPE_FUNCTION_DECLARATION, table_lookup(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false,NULL)) == undefined) {
throw_error(ERROR_TYPE, "Duplicate defination of function in function declaration");
}
}
else{
throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $2);
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false,NULL));
}
emit_function_dec(table_lookup(cur, $2));
}
| EXTERNAL FUNCTION ID COLON ID
{
if(getAdInfoType(look_up(cur, $5))==TYPE_FUNCTION_TYPE){
if (CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false,NULL)) == undefined) {
throw_error(ERROR_TYPE, "Duplicate defination of function in function declaration");
}
}
else{
throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $3);
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false,NULL));
}
}
;
idlist:
ID
{
printdebug("idlist rule 1 ID: %s", $1);
TableNode *entry = getFirstEntry(cur);
while((getName(entry) != getName(undefined))){
entry = getNextEntry(entry);
}
if (entry == NULL){
printdebug("mismatch in number of parameters passed to function");
}
else if(entry->theName == NULL){
addName(entry, $1);
printdebug("name added to entry of type %s is %s in function parameter scope",getType(entry), $1);
} else {
printdebug("undefined types passed in to function scope. Improper.");
addName(entry, $1);
}
printTableNode(entry);
//while (strcmp(getName(entry),"undefined") != 0) {
// entry = getNextEntry(entry);
//}
//if (getNextEntry(entry) == NULL) {
// printdebug("too many parameters at line %d column %d", @1.first_line, @1.first_column);
//}
//addName(entry, $1);
//printdebug("name added to entry is %s", $1);
//printTableNode(entry);
}
COMMA idlist
{
$$ = $4 + 1;
}
| ID
{ printdebug("idlist rule 2 ID: %s", $1);
TableNode *entry = getFirstEntry(cur);
while((getName(entry) != getName(undefined))){
entry = getNextEntry(entry);
}
if (entry == NULL){
printdebug("mismatch in number of parameters passed to function");
}
else if(entry->theName == NULL){
addName(entry, $1);
printdebug("name added to entry of type %s is %s in function parameter scope",getType(entry), $1);
} else {
printdebug("undefined types passed in to function scope. Improper.");
addName(entry, $1);
}
printTableNode(entry);
printdebug("Name of entry is now %s", getName(entry));
printdebug("Type of entry is %s", getType(entry));
printdebug("tag is %d", getAdInfoType(entry));
}
;
sblock:
L_BRACE
{
// emit_label(label_gen());
if (getLine(cur) != 0) {
cur = CreateScope(cur,@1.first_line,@1.first_column);
printdebug("Created a new scope");
} else {
setLineNumber(cur, @1.first_line);
setColumnNumber(cur,@1.first_line);
}
}
statement_list
{
//$<tn>$ = $3;
printdebug("Moving up a scope after seeing sblock");
cur = getParent(cur);
}
R_BRACE
{$$ = $3;}
| L_BRACE
{
if (getLine(cur) != 0) {
cur = CreateScope(cur,@1.first_line,@1.first_column);
printdebug("Created a new scope when seeing an L brace");
} else {
setLineNumber(cur, @1.first_line);
setColumnNumber(cur,@1.first_line);
printdebug("Did not create a new scope when saw L Brace, set line number to %d", @1.first_line);
}
}
dblock
{
printdebug("seen sblock with dblock");
}
statement_list
{
printdebug("Moving up a scope after seeing sblock with dblock");
cur = getParent(cur);
//$<tn>$ = $5;
}
R_BRACE
{$$ = $5;}
;
dblock:
L_BRACKET
{
if (getLine(cur) == 0) {
setLineNumber(cur, @1.first_line);
setColumnNumber(cur,@1.first_line);
printdebug("Did not create a new scope when saw dblock, set line number to %d instead", @1.first_line);
} else{
//cur = CreateScope(cur,@1.first_line,@1.first_column); // <----- What is this?
printdebug("Created a new scope when seeing a dblock");
}
}
declaration_list R_BRACKET
;
declaration_list:
declaration SEMI_COLON declaration_list
| declaration
| error SEMI_COLON { yyerrok; } declaration_list //only perform error recovery once we see semi-colon
;
declaration:
id_or_types COLON ID
{
printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ;
int d = getAdInfoType((TableNode*)$1);
if(d == TYPE_UNDEFINED) {
throw_error(ERROR_TYPE, "Undefined type passed in declaration list");
printdebug("Undefined type passed in declaration list");
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}
else if(d == TYPE_FUNCTION_TYPE) {
printdebug("invalid (function) type passed in declaration list in dblock", @2.first_line, @2.first_column);
d = TYPE_FUNCTION_DECLARATION;
if(CreateEntry(cur,d,(TableNode*)$1,$3,NULL) == undefined){
throw_error(ERROR_TYPE, "Duplicate defination of function in declaration list");
}
}
else if(d == TYPE_ARRAY_TYPE){
printdebug("array variable at line %d and column %d", @2.first_line, @2.first_column);
d = TYPE_ARRAY;
if(CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)) == undefined){
throw_error(ERROR_TYPE, "Duplicate defination of array in declaration list");
}
}
else if(d == TYPE_RECORD_TYPE){
printdebug("record variable at line %d and column %d", @2.first_line, @2.first_column);
d = TYPE_RECORD;
if(CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1))== undefined){
throw_error(ERROR_TYPE, "Duplicate defination of record in declaration list");
}
}
else if(d == TYPE_PRIMITIVE_TYPE){
printdebug("primitive variable at line %d and column %d", @2.first_line, @2.first_column);
d = TYPE_PRIMITIVE;
if(CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)) == undefined){
throw_error(ERROR_TYPE, "Duplicate defination of primitive in declaration list");
}
}else {
throw_error(ERROR_TYPE, "%s is being defined with an undefined type", $3);
CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1));
}
}
;
id_or_types:
ID
{
printdebug("string of id is %s in ID pattern of id_or_type rule.", $1);
$$ = table_lookup(getAncestor(cur), $1);
}
| types
{
printdebug("string of type is %s in types pattern of id_or_type rule.",getName((TableNode*)$1));
$$ = (TableNode*)$1;
}
;
statement_list:
compound_statement statement_list {
if ($1 == undefined && $2 != undefined) {
$$ = $2;
} else if ($1 != undefined && $2 == undefined) {
$$ = $1;
} else if ($1 == $2) {
$$ = $1;
}else if((getAdInfoType((TableNode*)$1) == TYPE_ARRAY_TYPE) && ((TableNode*)$2)==addr){
$$ = $1;
}else if((getAdInfoType((TableNode*)$1) == TYPE_RECORD_TYPE) && ((TableNode*)$2)==addr){
$$ = $1;
}else if(((TableNode*)$1)==addr && (getAdInfoType((TableNode*)$2) == TYPE_ARRAY_TYPE)){
$$ = $2;
}else if(((TableNode*)$1)==addr && (getAdInfoType((TableNode*)$2) == TYPE_RECORD_TYPE)){
$$ = $2;
} else {
printdebug("1 differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
$$ = undefined;
}
}
| compound_statement {
$$ = $1;
}
| simple_statement SEMI_COLON statement_list{
if ($1 == undefined && $3 != undefined) {
$$ = $3;
} else if ($1 != undefined && $3 == undefined) {
$$ = $1;
} else if ($1 == $3) {
$$ = $1;
}else if((getAdInfoType((TableNode*)$1) == TYPE_ARRAY_TYPE) && ((TableNode*)$3)==addr){
$$ = $1;
}else if((getAdInfoType((TableNode*)$1) == TYPE_RECORD_TYPE) && ((TableNode*)$3)==addr){
$$ = $1;
}else if(((TableNode*)$1)==addr && (getAdInfoType((TableNode*)$3) == TYPE_ARRAY_TYPE)){
$$ = $3;
}else if(((TableNode*)$1)==addr && (getAdInfoType((TableNode*)$3) == TYPE_RECORD_TYPE)){
$$ = $3;
} else {
printdebug("2 differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
$$ = undefined;
}
}
| simple_statement SEMI_COLON {
$$ = $1;
}
| error SEMI_COLON { yyerrok; } statement_list { $$ = $4; }
;
compound_statement:
WHILE L_PAREN {
S_Push(TrueList, S_Init(), 0);
S_Push(FalseList, S_Init(), 0);
int *l = calloc(1, sizeof(int));
*l = label_gen();
emit_label(*l);
S_Push(stack, l, 2);
} expression R_PAREN {
emit_label(label_gen());
emit_backpatch(S_Pop(TrueList), getLabel(current));
} sblock {
$$ = $7;
int l = label_gen();
emit_backpatch(S_Pop(FalseList), l);
emit_goto(*(int*)(S_Pop(stack)));
emit_label(l);
}
// IF L_PAREN expression R_PAREN THEN sblock ELSE sblock
| IF L_PAREN {
S_Push(TrueList, S_Init(), 0);
S_Push(FalseList, S_Init(), 0);
}expression R_PAREN THEN {
int l = label_gen();
emit_conditional_jump(E_IF_X_TRUE, l, tn_or_const(NODE, $4));
Stack * t = S_Peek(TrueList);
S_Push(t, current, 1);
emit_goto(0);
t = S_Peek(FalseList);
S_Push(t, current, 1);
emit_label(l);
emit_backpatch(S_Pop(TrueList), getLabel(current));
} sblock ELSE {
// NOTE we are not going back to
int l = label_gen();
emit_backpatch(S_Pop(FalseList), l);
S_Push(stack, S_Init(), 0);
emit_goto(0);
S_Push(S_Peek(stack), current, 1);
emit_label(l);
} sblock {
int l = label_gen();
emit_backpatch(S_Pop(stack), l);
emit_label(l);
if ($8 == undefined && $11 != undefined) {
$$ = $11;
} else if ($8 != undefined && $11 == undefined) {
$$ = $8;
} else if ($8 == $11) {
$$ = $8;
}else if((getAdInfoType((TableNode*)$8) == TYPE_ARRAY_TYPE) && ((TableNode*)$11)==addr){
$$ = $8;
}else if((getAdInfoType((TableNode*)$8) == TYPE_RECORD_TYPE) && ((TableNode*)$11)==addr){
$$ = $8;
}else if(((TableNode*)$8)==addr && (getAdInfoType((TableNode*)$11) == TYPE_ARRAY_TYPE)){
$$ = $11;
}else if(((TableNode*)$8)==addr && (getAdInfoType((TableNode*)$11) == TYPE_RECORD_TYPE)){
$$ = $11;
} else {
printdebug("3 differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
//printf("%s\n", getName((TableNode*)$6));
//printf("%s\n", getName((TableNode*)$8));
$$ = undefined;
}
}
| sblock {
$$ = $1;
}
;
simple_statement:
assignable{
S_Push(TrueList, S_Init(), 0);
S_Push(FalseList, S_Init(), 0);
} ASSIGN expression
{
// ----------------------------------------------------------------------------
if ( getTypeEntry((TableNode*)$4) == boo ) {
emit_label(label_gen());
}
emit_backpatch(S_Pop(TrueList), getLabel(current));
emit_backpatch(S_Pop(FalseList), getLabel(current));
// ----------------------------------------------------------------------------
printdebug("simple statement");
TableNode* node;
if((getAdInfoType((getTypeEntry((TableNode*)$1))) == TYPE_FUNCTION_TYPE)||
(getAdInfoType((getTypeEntry((TableNode*)$1))) == TYPE_ARRAY_TYPE)||
(getAdInfoType((getTypeEntry((TableNode*)$1))) == TYPE_RECORD_TYPE)||
(getAdInfoType((getTypeEntry((TableNode*)$1))) == TYPE_PRIMITIVE_TYPE)){
node = ((TableNode*)$1);
} else {
//printf("%d\n",getAdInfoType((getTypeEntry((TableNode*)$1))));
throw_error(ERROR_TYPE, "Invalid type passed to assignable.");
//printf("%d, %d\n", @1.first_line, @1.first_column);
//printf("%s\n", getType(getTypeEntry((TableNode*)$1)));
//printf("%s\n\n", getType(getTypeEntry((TableNode*)$3)));
node = undefined;
}
if(getAdInfoType(node) == getAdInfoType((TableNode*)$4)){
emit_assignment($1, tn_or_const(NODE, $4));
printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getType(node), getType((TableNode*)$4));
} else if (getTypeEntry(getTypeEntry(node)) == arrayprim && getTypeEntry((TableNode*)$4) == addr) {
emit_assignment($1, tn_or_const(NODE, $4));
printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getType(node), getType((TableNode*)$4));
} else if (getTypeEntry(getTypeEntry(node)) == recprime && getTypeEntry((TableNode*)$4) == addr) {
emit_assignment($1, tn_or_const(NODE, $4));
printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getType(node), getType((TableNode*)$4));
} else {
//printf("%d\n",getAdInfoType((TableNode*)$1));
//printf("%d\n",getAdInfoType((TableNode*)$3));
//printf("%d\n",getAdInfoType((TableNode*)$1));
//printf("%d\n",getAdInfoType((TableNode*)$3));
throw_error(ERROR_TYPE, "Assignable Assign Expression - Object %s of type %s != Object %s of type %s", getName(node), getType(node), getName((TableNode*)$4), getType((TableNode*)$4));
}
$$ = undefined;
}
| RETURN expression {
$$ = getTypeEntry((TableNode*)$2);
emit_return(tn_or_const(NODE,(TableNode*)$2));}
|simple_statement error {yyerrok; yyclearin; printdebug("error in simple statement");}
;
rec_op:
DOT
;
ablock:
L_PAREN{
if (stack == NULL){
stack = S_Init();
}
Stack * t = S_Init();
S_Push(stack, t, 0);
}
argument_list {
} R_PAREN
{
// here
$$ = $3;
printdebug("ablock is %d", $$);
}
;
argument_list:
expression{
TableNode * arg = CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), arg_var_gen(), NULL);
if(getLine(cur)==-2){
if(getTypeEntry(arg) != integ){
throw_error(ERROR_TYPE, "Argument %s of type %s is not of type integer for an array argument", getName(arg), getType(arg));
}
}
// ----------------------------------------------------------------------------
// this is emitting the param withthe wrong TableNode
// We need to fiture out how to get the right one.
Stack * t = S_Peek(stack);
if(t==NULL){
t = S_Init();
S_Push(stack, t, 1);
}
emit_parameter(tn_or_const(NODE,$1));
S_Push(t, current, 1);
emit_detach();
// ----------------------------------------------------------------------------
}
COMMA argument_list
{$$ = $4 + 1;}
| expression
{
TableNode* arg = CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), arg_var_gen(), NULL);
if(getLine(cur)==-2){
if(getTypeEntry(arg) != integ){
throw_error(ERROR_TYPE, "Argument %s of type %s is not of type integer for an array argument", getName(arg), getType(arg));
}
}
emit_parameter(tn_or_const(NODE,$1));
$$ = 1;
printdebug("[ARGUMENT_LIST] argument list is %d", $$);
}
;
// will ALWAYS be a TYPE
expression:
constant
{
printdebug("constant expression");
$$ = (TableNode*)$1;
}
| SUB_OR_NEG expression %prec UMINUS
{
printdebug("negative expression");
if(getTypeEntry((TableNode*)$2) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
emit_unary_op(E_NEG,node,tn_or_const(NODE,$2));
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//result of unary operation
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s is not of type integer and can't be negated", getName((TableNode*)$2), getType((TableNode*)$2));
}
}
| NOT expression
{
printdebug("not expression");
if(getTypeEntry((TableNode*)$2) == boo) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
Stack * t = S_Pop(TrueList);
Stack * f = S_Pop(FalseList);
S_Push(TrueList, f, 0);
S_Push(FalseList, t, 0);
//result of unary operation
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s is not of type Boolean and can't be negated", getName((TableNode*)$2), getType((TableNode*)$2));
}
}
| expression ADD expression
{
printdebug("add expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
emit_binary_op(E_ADD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression SUB_OR_NEG expression
{
printdebug("sub or neg expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
emit_binary_op(E_SUB,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression MUL expression
{
printdebug("multiply expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
emit_binary_op(E_MUL,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression DIV expression
{
printdebug("divide expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
emit_binary_op(E_DIV,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression REM expression
{
printdebug("remainder expression");
if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
emit_binary_op(E_MOD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression AND expression
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
// ----------------------------------------------------------------------------
uint_least8_t b = 0;
emit_assignment(node, tn_or_const(BOOLEAN,&b));
// emit_label(label_gen());
// emit_backpatch(S_Pop(TrueList), getLabel(current));
emit_conditional_jump(E_IF_X_FALSE, 0, tn_or_const(NODE, $1));
Stack * t1 = S_Peek(FalseList);
if(t1==NULL){
t1 = S_Init();
S_Push(FalseList, t1, 1);
}
S_Push(t1, current, 1);
emit_goto(0);
t1 = S_Peek(TrueList);
if(t1==NULL){
t1 = S_Init();
S_Push(TrueList, t1, 1);
}
S_Push(t1, current, 1);
emit_label(label_gen());
emit_backpatch(S_Pop(TrueList), getLabel(current));
emit_conditional_jump(E_IF_X_FALSE, 0, tn_or_const(NODE, $3));
Stack * t = S_Peek(FalseList);
if(t==NULL){
t = S_Init();
S_Push(FalseList, t, 1);
}
S_Push(t, current, 1);
b = 1;
emit_assignment(node, tn_or_const(BOOLEAN,&b));
emit_goto(0);
t = S_Peek(TrueList);
if(t==NULL){
t = S_Init();
S_Push(TrueList, t, 1);
}
S_Push(t, current, 1);
S_Merge(FalseList);
// ----------------------------------------------------------------------------
printdebug("AND");
if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) {
//emit_binary_op(E_AND,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be Boolean", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression OR expression
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
// ----------------------------------------------------------------------------
uint_least8_t b = 1;
emit_assignment(node, tn_or_const(BOOLEAN,&b));
// emit_label(label_gen());
// emit_backpatch(S_Pop(TrueList), getLabel(current));
emit_conditional_jump(E_IF_X_TRUE, 0, tn_or_const(NODE, $1));
Stack * t1 = S_Peek(TrueList);
if(t1==NULL){
t1 = S_Init();
S_Push(TrueList, t1, 1);
}
S_Push(t1, current, 1);
emit_goto(0);
t1 = S_Peek(FalseList);
if(t1==NULL){
t1 = S_Init();
S_Push(FalseList, t1, 1);
}
S_Push(t1, current, 1);
emit_label(label_gen());
emit_backpatch(S_Pop(FalseList), getLabel(current));
emit_conditional_jump(E_IF_X_TRUE, 0, tn_or_const(NODE, $3));
Stack * t = S_Peek(TrueList);
if(t==NULL){
t = S_Init();
S_Push(TrueList, t, 1);
}
S_Push(t, current, 1);
b = 0;
emit_assignment(node, tn_or_const(BOOLEAN,&b));
emit_goto(0);
t = S_Peek(FalseList);
if(t==NULL){
t = S_Init();
S_Push(FalseList, t, 1);
}
S_Push(t, current, 1);
S_Merge(TrueList);
// ----------------------------------------------------------------------------
printdebug("OR");
if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) {
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be Boolean", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression LESS_THAN expression
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
// ----------------------------------------------------------------------------
// emit_label(label_gen());
// emit_backpatch(S_Pop(TrueList), getLabel(current));
emit_binary_op(E_LESS_THAN, node, tn_or_const(NODE,$1), tn_or_const(NODE,$3));
/*
emit_conditional_jump(E_IF_X_TRUE, 0, tn_or_const(NODE, node));
Stack * t = S_Peek(TrueList);
if(t==NULL){
t = S_Init();
S_Push(TrueList, t, 1);
}
S_Push(t, current, 1);
emit_goto(0);
t = S_Peek(FalseList);
if(t==NULL){
t = S_Init();
S_Push(FalseList, t, 1);
}
S_Push(t, current, 1);
*/
// ----------------------------------------------------------------------------
printdebug("less than expression");
if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1)==integ) {
$$ = node;
} else if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1)==boo){
$$ = node;
}else {
$$=undefined;
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression EQUAL_TO expression
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
// ----------------------------------------------------------------------------
emit_binary_op(E_EQUAL_TO, node, tn_or_const(NODE,$1), tn_or_const(NODE,$3));
/*
emit_conditional_jump(E_IF_X_TRUE, 0, tn_or_const(NODE, node));
Stack * t = S_Peek(TrueList);
if(t==NULL){
t = S_Init();
S_Push(TrueList, t, 1);
}
S_Push(t, current, 1);
emit_goto(0);
t = S_Peek(FalseList);
if(t==NULL){
t = S_Init();
S_Push(FalseList, t, 1);
}
S_Push(t, current, 1);
*/
// emit_label(label_gen());
// emit_backpatch(S_Pop(TrueList), getLabel(current));
// ----------------------------------------------------------------------------
printdebug("equals check expression");
if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1) != undefined) {
// emit_binary_op(E_EQUAL_TO, node, tn_or_const(NODE,$1), tn_or_const(NODE,$3));
$$ = node;
} else {
$$ = undefined;
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be the same type", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| assignable
{
$$ = $1;
}
| L_PAREN expression R_PAREN
// TODO: We need to check if we need to backpatch here.
{
printdebug("paren expression. current type is %s",getType((TableNode*)$2));
$$=$2;
}
// TODO: We need to type check this.
| RESERVE ID {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL);
TableNode * n = look_up(cur, $2);
if(getAdInfoType(n) != TYPE_RECORD){
throw_error(ERROR_TYPE, "Invalid Reserve expression with object %s of type %s.",
getName((TableNode*)n), getType((TableNode*)n));
$$=undefined;
}
int v = getRecTotal(getTypeEntry(n));
emit_reserve(node, tn_or_const(INTEGER, &v));
$$ = node;
}
| RELEASE ID {
TableNode * n = look_up(cur, $2);
if(getAdInfoType(n) != TYPE_RECORD){
throw_error(ERROR_TYPE, "Invalid Release expression with object %s of type %s.",
getName((TableNode*)n), getType((TableNode*)n));
$$=undefined;
}
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
//emit release needed here
$$ = node;
}
| RESERVE ID {
cur = CreateScope(cur, -2,-1);
} ablock {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL);
int a = S_Size(S_Peek(stack)) + 1;
emit_push_all(S_Peek(stack));
S_Pop(stack);
emit_function_call(node, a, tn_or_const(NODE, $2));
$$ = node;
TableNode * n = look_up(cur, $2);
if(getAdInfoType(n) != TYPE_ARRAY){
throw_error(ERROR_TYPE, "Invalid Reserve expression with object %s of type %s.",
getName(n), getType(n));
$$=undefined;
}
//doing more complicated type checking in a block
if(getNumArrDim(getTypeEntry(n)) != $4){
throw_error(ERROR_SYNTAX, "expected %d dimensions for this array but got %d", getNumArrDim(getTypeEntry(n)), $4);
$$=undefined;
}
cur = getParent(cur);
/*TableNode * t = getFirstEntry(cur);
TableNode * n = look_up(cur, $2);
if(getAdInfoType(n) == TYPE_ARRAY){
int array_dims = getNumArrDim(getTypeEntry(n));
if ($5 != array_dims) {
throw_error(ERROR_SYNTAX, "expected %d dimensions for this array but got %d", array_dims, $5);
}else{
int traverse = 0;
while(t != NULL && t != undefined && getName(t)[0] != '&'){
t = getNextEntry(t);
}
if(getTypeEntry(t) != integ){
throw_error(ERROR_TYPE, "Arg for an array is not of type integer");
$$= undefined;
}else{
//seen first number
traverse++;
t = getNextEntry(t);
while(traverse<array_dims){
while(t !=NULL && t!=undefined && getName(t)[0]!='&'){
t = getNextEntry(t);
}
if(getTypeEntry(t) != integ){
throw_error(ERROR_TYPE, "Arg for an array is not of type integer");
$$= undefined;
break;
}
traverse++;
t = getNextEntry(t);
}
if(traverse != array_dims){
throw_error(ERROR_TYPE, "Invalid number of arguments for array %s. Expected %d but got %d", getName(n), array_dims, traverse);
$$= undefined;}
}
}
}
*/
}
| RELEASE ID {
cur = CreateScope(cur, -2,-1);
} ablock {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
int a = S_Size(S_Peek(stack)) + 1;
emit_push_all(S_Peek(stack));
S_Pop(stack);
emit_function_call(node, a, tn_or_const(NODE, $2));
$$ = node;
TableNode * n = look_up(cur, $2);
if(getAdInfoType(n) != TYPE_ARRAY){
throw_error(ERROR_TYPE, "Invalid Release expression with object %s of type %s.",
getName(n), getType(n));
$$=undefined;
}
//doing more complicated type checking in a block
if(getNumArrDim(getTypeEntry(n)) != $4){
throw_error(ERROR_SYNTAX, "expected %d dimensions for this array but got %d", getNumArrDim(getTypeEntry(n)), $4);
$$=undefined;
}
cur = getParent(cur);
/*
TableNode * t = getFirstEntry(cur);
TableNode * n = look_up(cur, $2);
if(getAdInfoType(n) == TYPE_ARRAY){
int array_dims = getNumArrDim(getTypeEntry(n));
if ($5 != array_dims) {
throw_error(ERROR_SYNTAX, "expected %d dimensions for this array but got %d", array_dims, $5);
}else{
int traverse = 0;
while(t != NULL && t != undefined && getName(t)[0] != '&'){
t = getNextEntry(t);
}
if(getTypeEntry(t) != integ){
throw_error(ERROR_TYPE, "Arg for an array is not of type integer");
$$= undefined;
}else{
//seen first number
traverse++;
t = getNextEntry(t);
while(traverse<array_dims){
while(t !=NULL && t!=undefined && getName(t)[0]!='&'){
t = getNextEntry(t);
}
if(getTypeEntry(t) != integ){
throw_error(ERROR_TYPE, "Arg for an array is not of type integer");
$$= undefined;
break;
}
traverse++;
t = getNextEntry(t);
}
if(traverse != array_dims){
throw_error(ERROR_TYPE, "Invalid number of arguments for array %s. Expected %d but got %d", getName(n), array_dims, traverse);
$$= undefined;}
}
}
}
*/
}
/*
| RELEASE assignable
{
int d = getAdInfoType((TableNode*)$2);
//commenting out type checks for now since assignable is being resolved to something before reserve is being applied which is tricky
//if(d == TYPE_ARRAY ||d == TYPE_RECORD) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
$$ = node;
// } else {
// throw_error(ERROR_TYPE, "Invalid memOp expression with object %s of type %s.", getName((TableNode*)$2), getType((TableNode*)$2));
// $$=undefined;
// }
}
*/
;
//UPDATED $$ for tablenodes to this point
// prolly right, check back with me later
// add array case
// include type check for ablock in arrays - ablock is always the int of the elements in array/rec
assignable:
ID
{
TableNode* pass = look_up(cur,$1);
if(pass == undefined){
throw_error(ERROR_TYPE, "Undefined variable %s", $1);
}
$$ = pass;
printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getType(pass), getName(pass));
}
| assignable
{
printdebug("%sBeginning rule 2 of assignable.", COLOR_CYAN);
//Creating a dummy scope where we create entries for all the arguments of a function call
//Must also consider that we might be in an array access
cur = CreateScope(cur, -1,-1);
}
//we have to consider emmissions in ablocks
ablock
{
//int type = getAdInfoType(look_up(getParent(cur), getName((TableNode*)$1)));
int type = getAdInfoType(getTypeEntry((TableNode*)$1));
printdebug("%stype is %d", COLOR_PURPLE, type);
printdebug("%s", getName((TableNode*)$1));
if (type == TYPE_FUNCTION_TYPE) {
printdebug("%sEntering function call", COLOR_LIGHTGREEN);
//getting the parameter. The type of assignable is a function type so we need to access the paramater of the type
TableNode *expected = getParameter(getTypeEntry((TableNode*)$1));
//Jump into case where the parameter is a record type
if(getAdInfoType(expected) == TYPE_RECORD_TYPE){
//int argument_size = getRecSize(cur);
int parameter_size = getRecSize(getRecList(expected));
printdebug("argument size is %d\n", $3);
printdebug("parameter size is %d\n", parameter_size);
if ($3 != parameter_size) {
throw_error(ERROR_SYNTAX, "expected %d arguments for this function but got %d", parameter_size, $3);
}else{
TableNode* param_arg_type = getFirstEntry(getRecList(expected));
TableNode* arg_given = getFirstEntry(cur);
while(arg_given != NULL && arg_given != undefined && getName(arg_given)[0]!='&'){
arg_given = getNextEntry(arg_given);
}
if(getTypeEntry(arg_given) != getTypeEntry(param_arg_type)){
throw_error(ERROR_TYPE, "expected %s expression as first argument of a record in function call but got %s", getType(param_arg_type), getType(arg_given));
}
param_arg_type = getNextEntry(param_arg_type);
arg_given = getNextEntry(arg_given);
while(arg_given != NULL && arg_given != undefined && param_arg_type != NULL){
while(arg_given != NULL && getName(arg_given)[0]!='&'){
arg_given = getNextEntry(arg_given);
}
if(getTypeEntry(arg_given) != getTypeEntry(param_arg_type)){
throw_error(ERROR_TYPE, "expected type %s expression as argument of a record in function call but got type %s", getType(param_arg_type), getType(arg_given));
}
arg_given = getNextEntry(arg_given);
param_arg_type = getNextEntry(param_arg_type);
}
}
}else{
TableNode*actual_instance = getFirstEntry(cur);
while(actual_instance != NULL && actual_instance != undefined && getName(actual_instance)[0] !='&'){
actual_instance = getNextEntry(actual_instance);
}
if(actual_instance == NULL){
throw_error(ERROR_TYPE, "Invalid function call. No arguments passed");
break;
}
TableNode *actual = getTypeEntry(actual_instance);
if (expected != actual) {
throw_error(ERROR_TYPE, "expected %s expression in single argument function call but got %s", getType(expected), getName(actual));
}
if ($3 != 1) {
throw_error(ERROR_SYNTAX, "expected 1 argument but got %d", $3); }
printTableNode(getReturn(getTypeEntry((TableNode*)$1)));
}
char* temp = temp_var_gen();
TableNode* typeNode2 = getReturn(getTypeEntry((TableNode*)$1));
int t = -1;
if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){
t = TYPE_PRIMITIVE;
}
else if(getAdInfoType(typeNode2) == TYPE_ARRAY_TYPE){
t = TYPE_ARRAY;
}
else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){
t = TYPE_RECORD;
}
//this may need to be updated to provide the correct name of things
else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
throw_error(ERROR_TYPE, "Undefined type returned by function.");
}
TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL);
//-----------------------------------------------------------------------------
// Please don't touch
// the + 1 is here because I don't detach the last param
int a = S_Size(S_Peek(stack)) + 1;
emit_push_all(S_Peek(stack));
S_Pop(stack);
emit_function_call(node, a, tn_or_const(NODE, $1));
//-----------------------------------------------------------------------------
$$ = node;
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK for function call)
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName(typeNode2), getName((TableNode*)$1));
} else if (type == TYPE_ARRAY_TYPE) {
printdebug("%sEntering array call", COLOR_LIGHTGREEN);
if (getNumArrDim(getTypeEntry((TableNode*)$1)) != $3) {
throw_error(ERROR_SYNTAX, "expected %d arguments for this array but got %d", getNumArrDim(getTypeEntry((TableNode*)$1)), $3);
}
char* temp = temp_var_gen();
TableNode* typeNode2 = getArrType(look_up(getAncestor(cur), getType((TableNode*)$1)));
int t = -1;
if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){
t = TYPE_PRIMITIVE;
}
else if(getAdInfoType(typeNode2) == TYPE_ARRAY_TYPE){
t = TYPE_ARRAY;
}
else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){
t = TYPE_RECORD;
}
else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
throw_error(ERROR_TYPE, "Undefined type stored in array.");
}
TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL);
//TODO: emit assign here
//TODO: emit_array_access(char* node, char* array, ...)
$$ = node;
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getType((TableNode*)$1), getName((TableNode*)$1));
}
cur = getParent(cur);
}
| assignable rec_op ACCESS
{
if(getAdInfoType((TableNode*)$1) != TYPE_ARRAY){
throw_error(ERROR_TYPE, "Invalid type passed to array access");
$$ = undefined;
}else if($3>getNumArrDim(getTypeEntry((TableNode*)$1))){
throw_error(ERROR_TYPE, "Invalid trying to access the size of dimension %d but this array only has %d dimensions", $3, getNumArrDim(getTypeEntry((TableNode*)$1)));
$$ = undefined;
} else{
char* temp = temp_var_gen();
int t = 6;
//emission
// arr._1 ....
$$ = CreateEntry(cur,t, integ, temp, NULL);
}
}
| assignable rec_op ID
{
if(getAdInfoType((TableNode*)$1) != TYPE_RECORD){
throw_error(ERROR_TYPE, "Invalid type passed to record access");
$$ = undefined;
}
else if(undefined != table_lookup(getRecList(getTypeEntry((TableNode*)$1)), $3)) {
TableNode* type = getTypeEntry(table_lookup(getRecList(getTypeEntry((TableNode*)$1)), $3));
char* temp = temp_var_gen();
int t = -1;
if(getAdInfoType(type) == TYPE_PRIMITIVE_TYPE){
t = TYPE_PRIMITIVE;
}
else if(getAdInfoType(type) == TYPE_ARRAY_TYPE){
t = TYPE_ARRAY;
}
else if(getAdInfoType(type) == TYPE_RECORD_TYPE){
t = TYPE_RECORD;
}
else if(getAdInfoType(type) == TYPE_FUNCTION_TYPE){
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
throw_error(ERROR_TYPE, "Undefined type stored in record.");
}
TableNode* node = CreateEntry(cur,t, type, temp, NULL);
// getElementOffset(rec, ID)
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
//emit_field_access(char* node, char* record, $3)
$$=node;
}else{
throw_error(ERROR_TYPE, "Invalid field access %s", $3);
$$=undefined;
}
printdebug("[ASSIGNABLE - RULE 3] record = name: %s | field = %s", getName((TableNode*)($1)), getName((TableNode*)$3));
}
;
constant:
C_STRING
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_ARRAY, stri, temp, NULL);
emit_assignment(node, tn_or_const(STRING,$1));
printdebug("string of C_STRING in constant is %s", $1);
$$ = node;
}
| C_INTEGER
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL);
emit_assignment(node, tn_or_const(INTEGER,&$1));
printdebug("number of C_INTEGER in constant is %d", $1);
$$ = node;
}
| C_NULL
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL);
emit_assignment(node, tn_or_const(ADDRESS,$1));
printdebug("string of C_NULL in constant is NULL");
$$ = node;
}
| C_CHARACTER
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, chara, temp, NULL);
emit_assignment(node, tn_or_const(CHARACTER,&$1));
//printdebug("string of C_CHARACTER in constant is %s",$1);
$$ = node;
}
| C_TRUE
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
uint_least8_t b = 1;
emit_assignment(node, tn_or_const(BOOLEAN,&b));
printdebug("string of C_TRUE in constant is true");
$$ = node;
}
| C_FALSE
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
uint_least8_t b = 0;
emit_assignment(node, tn_or_const(BOOLEAN,&b));
printdebug("string of C_FALSE in constant is false");
$$ = node;
}
;
types:
T_INTEGER
{
$$ = $1;
printdebug("string of T_INTEGER in types is %s",getName((TableNode*)$1));
}
| T_ADDRESS
{
$$ = $1;
printdebug("string of T_ADDRESS in types is %s",getName((TableNode*)$1));
}
| T_CHARACTER
{
$$ = $1;
printdebug("string of T_CHARACTER in types is %s",getName((TableNode*)$1));
}
| T_BOOLEAN
{
$$ = $1;
printdebug("string of T_BOOLEAN in types is %s",getName((TableNode*)$1));
}
;
%%
void throw_error(ErrorType error_type, const char *format, ...) {
int line = yylloc.first_line;
int column = yylloc.first_column;
char * error_name = "";
switch (error_type) {
case ERROR_RUNTIME:
error_name = malloc(strlen("RUNTIME") + 1);
strcpy(error_name, "RUNTIME");
break;
case ERROR_SYNTAX:
error_name = malloc(strlen("SYNTAX") + 1);
strcpy(error_name, "SYNTAX");
break;
case ERROR_TYPE:
error_name = malloc(strlen("TYPE") + 1);
strcpy(error_name, "TYPE");
break;
case ERROR_UNDEFINED:
error_name = malloc(strlen("UNDEFINED") + 1);
strcpy(error_name, "UNDEFINED");
break;
}
if (asc_flag) {
yyerror("");
int needed = snprintf(NULL, 0, " LINE (%d:%d) ** %s ERROR: ", line, column, error_name);
char *error_message = malloc(needed + 1);
snprintf(error_message, needed + 1, " LINE (%d:%d) ** %s ERROR: ", line, column, error_name);
va_list args;
va_start(args, format);
va_list args_copy;
va_copy(args_copy, args);
int needed2 = vsnprintf(NULL, 0, format, args_copy) + 1;
va_end(args_copy);
char *error_message2 = malloc(needed2);
if (error_message2 == NULL) {
fprintf(stderr, "Memory allocation failed\n");
va_end(args);
return;
}
vsnprintf(error_message2, needed2, format, args);
va_end(args);
int total_needed = needed + needed2 + 2;
char *total_error_message = malloc(total_needed);
if (total_error_message == NULL) {
fprintf(stderr, "Memory allocation failed\n");
free(error_message);
free(error_message2);
return;
}
snprintf(total_error_message, total_needed, "%s%s\n", error_message, error_message2);
if (tc_flag) {
insert_code_line(total_error_message, line);
} else {
if (error_type != ERROR_TYPE) {
insert_code_line(total_error_message, line);
}
}
free(error_message);
free(error_message2);
free(total_error_message);
}
}
void yyerror(const char *err) {
int line = yylloc.first_line;
int column = yylloc.first_column;
contains_errors = true;
// Grammar Fallback Case
if (strcmp(err, "syntax error") == 0) {
if (asc_flag != NULL) {
int needed = snprintf(NULL, 0, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n", line, column, yytext);
char *error_message = malloc(needed + 1);
snprintf(error_message, needed + 1, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n", line, column, yytext);
insert_code_line(error_message, line);
}
else {
fprintf(stderr, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token %s\n", line, column, yytext);
}
}
}