Untitled

 avatar
user_2381398
plain_text
2 years ago
16 kB
2
Indexable
%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <iostream>
using namespace std;
#define Trace(t) printf(t)
#define MAX 256
int yylex(void);
void yyerror(const char *s);


#define MAX 256
#define MAX_TABLE 1024

union u {
    int ival;
    float fval;
    char sval[256];
    int bval;
};


struct content {
    char id[MAX];
    union u value;
    char type[MAX];
    char bigtype[MAX];
};

struct content symbolTable[MAX_TABLE][MAX_TABLE];

int id_total = 0;
int scope = 0;

void copyContent(struct content *dest, struct content src) {
    strcpy(dest->id, src.id);
    strcpy(dest->type, src.type);
    strcpy(dest->bigtype, src.bigtype);

    if (strcmp(src.type, "int") == 0 && strcmp(src.bigtype, "arrays") != 0) {
        dest->value.ival = src.value.ival;
    } else if (strcmp(src.type, "real") == 0 && strcmp(src.bigtype, "arrays") != 0) {
        dest->value.fval = src.value.fval;
    } else if (strcmp(src.type, "str") == 0 && strcmp(src.bigtype, "arrays") != 0) {
        strcpy(dest->value.sval, src.value.sval);
    } else if (strcmp(src.type, "bool") == 0 && strcmp(src.bigtype, "arrays") != 0) {
        dest->value.bval = src.value.bval;
    } else {
        dest->value.ival = src.value.ival;
    }
}

int insert(struct content a){
	bool inSymbolTable = false ;
	for(int i = 0 ; i < id_total; i++){
		if(strcmp(a.id, symbolTable[scope][i].id)==0){
			inSymbolTable = true ;
		}
	}
	/* test output */
			if(strcmp(a.type,"int")==0){
			printf("bigtype:%s id:%s type:%s value:%d\n",a.bigtype,a.id,a.type,a.value.ival);

			}else if(strcmp(a.type,"real")==0){
			printf("bigtype:%s id:%s type:%s value:%f\n",a.bigtype,a.id,a.type,a.value.fval);

			}else if(strcmp(a.type,"str")==0){
			printf("bigtype:%s id:%s type:%s value:%s\n",a.bigtype,a.id,a.type,a.value.sval);

			}else if(strcmp(a.type,"bool")==0){
			printf("bigtype:%s id:%s type:%s value:%d\n",a.bigtype,a.id,a.type,a.value.bval);

			}else if(strcmp(a.type,"bool")==0){
			printf("bigtype:%s id:%s type:%s value:%d\n",a.bigtype,a.id,a.type,a.value.bval);

			}
	printf("--insert--\n");
	
	if (!inSymbolTable){
		copyContent(&symbolTable[scope][id_total], a);
		id_total++;
	}


	return 0;
}
int lookup(char *c){
	for (int i = 0; i <= scope; i++)
	{
		for(int j=0;j<=id_total;j++){
		if (strcmp(c , symbolTable[i][j].id)==0)
		{			
			if(strcmp(symbolTable[i][j].type,"int")==0){
				return symbolTable[i][j].value.ival;
			}else{
				
			}
		}else{
			return -1;
		}
		}
	}
	return -1;
}

int dump() {
    char val[32];  // assuming the string representation won't exceed 32 characters

    for (int i = 0; i <= scope; i++) {
        for (int j = 0; j <= id_total; j++) {
            char* type = symbolTable[i][j].type;
            char* bigtype = symbolTable[i][j].bigtype;
            char* id = symbolTable[i][j].id;

            if (strcmp("arrays", bigtype) == 0) {
                strcpy(val, " ");
            } else {
                if (strcmp("int", type) == 0) {
                    sprintf(val, "%d", symbolTable[i][j].value.ival);
                } else if (strcmp("float", type) == 0) {
                    sprintf(val, "%f", symbolTable[i][j].value.fval);
                } else if (strcmp("str", type) == 0) {
                    strcpy(val, symbolTable[i][j].value.sval);
                } else if (strcmp("bool", type) == 0) {
                    strcpy(val, symbolTable[i][j].value.bval == 0 ? "False" : "True");
                } else if (strcmp("null", type) == 0) {
                    strcpy(val, " ");
                }
            }
            printf("%-*s\t%-*s\t%-*s\t%-*s\t%-*d\n", 10, id, 10, type, 10, bigtype, 10, val, 10, i);
        }
    }
    return 0;
}




%}

%union {
    char* idString;
    int integerValue;
    float floatValue;
    char* strValue;
    bool boolValue;
    char type[MAX];
    char bigtype[MAX];
    int intValue;
    struct content sdec;
    struct content contentValue;
}


/* tokens */

%token DOT COMMA COLON SEMICOLON LP RP LSB RSB LCB RCB PLUS MINUS MULTIPLY DIVIDE MOD COLONEQUALS LT LE GT GE EQ EQUALS NOTEQUALS AND OR NOT

%token ARRAY BOOL CHAR CONST DECREASING DEFAULT TO DO ELSE BEGIN_KEYWORD END EXIT FALSE FOR FUNCTION GET IF ENDIF ENDFOR ENDLOOP INT LOOP OF PUT PROCEDURE REAL RESULT RETURN SKIP STRING THEN TRUE VAR WHEN

%token <idString> IDENTIFIER
%token <floatValue> FLOATVAL
%token <integerValue> INTEGERVAL
%token <strValue> STRINGVAL
%token <integerValue> TRUEVAL
%token <integerValue> FALSEVAL
%token <integerValue> INT_RANGE

%type<sdec> constant_exp 
%type<type> type
%type<contentValue> expression function_invocation bool_expression

%nonassoc LT LE GT EG NE
%nonassoc EQ
%left AND
%left OR
%right NOT
%left PLUS MINUS
%left MULTIPLY DIVIDE MOD

%nonassoc UMINUS

//%type<integerValue> unary_expression


%start program


%%
program:
program_units {Trace("Reducing to [program]\n");}
;


constant_declaration:
CONST IDENTIFIER COLON type COLONEQUALS constant_exp
{
			struct content a;
			strcpy(a.id,$2);
			strcpy(a.bigtype,"conts");
			if(strcmp($6.type,"int")==0){
			strcpy(a.type,"int");
			a.value.ival = $6.value.ival;
			}else if(strcmp($6.type,"real")==0){
			strcpy(a.type,"real");
			a.value.fval = $6.value.fval;
			}else if(strcmp($6.type,"str")==0){
			strcpy(a.type,"str");
			strcpy(a.value.sval,$6.value.sval);
			}else if(strcmp($6.type,"bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = $6.value.bval;
			}else if(strcmp($6.type,"bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = $6.value.bval;
			}
			insert(a);	
		Trace("Reducing to [constant_declaration]\n");
}
| CONST IDENTIFIER COLONEQUALS constant_exp
{
			struct content a;
			strcpy(a.id,$2);
			strcpy(a.bigtype,"conts");
			if(strcmp($4.type, "int")==0){
			strcpy(a.type,"int");
			a.value.ival = $4.value.ival;
			}else if(strcmp($4.type, "real")==0){
			strcpy(a.type,"real");
			a.value.fval = $4.value.fval;
			}else if(strcmp($4.type, "str")==0){
			strcpy(a.type,"str");
			strcpy(a.value.sval,$4.value.sval);
			}else if(strcmp($4.type, "bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = $4.value.bval;
			}else if(strcmp($4.type, "bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = $4.value.bval;	
			}
			insert(a);
		Trace("Reducing to [constant_declaration]\n");
}
| CONST IDENTIFIER COLON type COLONEQUALS MINUS constant_exp
{
			struct content a;
			strcpy(a.id,$2);
			strcpy(a.bigtype,"conts");
			if(strcmp($7.type, "int")==0){
			strcpy(a.type,"int");
			a.value.ival = -$7.value.ival;
			}else if(strcmp($7.type, "real")==0){
			strcpy(a.type,"real");
			a.value.fval = -$7.value.fval;
			}else{
				// Add error handling for non-numeric types.
				printf("Error: Cannot apply unary minus to non-numeric type.\n");
				YYERROR;
			}
			insert(a);	
		Trace("Reducing to [constant_declaration]\n");
}
| CONST IDENTIFIER COLONEQUALS MINUS constant_exp
{
			struct content a;
			strcpy(a.id,$2);
			strcpy(a.bigtype,"conts");
			if(strcmp($5.type, "int")==0){
			strcpy(a.type,"int");
			a.value.ival = -$5.value.ival;
			}else if(strcmp($5.type, "real")==0){
			strcpy(a.type,"real");
			a.value.fval = -$5.value.fval;
			}else{
				// Add error handling for non-numeric types.
				printf("Error: Cannot apply unary minus to non-numeric type.\n");
				YYERROR;
			}
			insert(a);
		Trace("Reducing to [constant_declaration]\n");
}
;

variables_declaration:
    VAR IDENTIFIER COLON type COLONEQUALS constant_exp
    {
			struct content a;
			strcpy(a.id,$2);
			strcpy(a.bigtype,"var");
			if(strcmp($6.type, "int")==0){
			strcpy(a.type,"int");
			a.value.ival = $6.value.ival;
			}else if(strcmp($6.type, "real")==0){
			strcpy(a.type,"real");
			a.value.fval = $6.value.fval;
			}else if(strcmp($6.type, "str")==0){
			strcpy(a.type,"str");
			strcpy(a.value.sval,$6.value.sval);
			}else if(strcmp($6.type, "bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = $6.value.bval;
			}else if(strcmp($6.type, "bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = $6.value.bval;
			}
			insert(a);
    Trace("Reducing to [constant_declaration]\n");
	} 
    | VAR IDENTIFIER COLONEQUALS constant_exp
    {
    		struct content a;
			strcpy(a.id,$2);
			strcpy(a.bigtype,"var");
			if(strcmp($4.type, "int")==0){
			strcpy(a.type,"int");
			a.value.ival = $4.value.ival;
			}else if(strcmp($4.type, "real")==0){
			strcpy(a.type,"real");
			a.value.fval = $4.value.fval;
			}else if(strcmp($4.type, "str")==0){
			strcpy(a.type,"str");
			strcpy(a.value.sval,$4.value.sval);
			}else if(strcmp($4.type, "bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = $4.value.bval;
			}else if(strcmp($4.type, "bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = $4.value.bval;
			}
			insert(a);
    	Trace("Reducing to [constant_declaration]\n");
	}
    | VAR IDENTIFIER COLON type
    {
    	struct content a;
			strcpy(a.id,$2);
			strcpy(a.bigtype,"var");
			if(strcmp($4, "int")==0){
			strcpy(a.type,"int");
			a.value.ival = 0;
			}else if(strcmp($4, "real")==0){
			strcpy(a.type,"real");
			a.value.fval = 0;
			}else if(strcmp($4, "str")==0){
			strcpy(a.type,"str");
			strcpy(a.value.sval,"NULL");
			}else if(strcmp($4, "bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = 0;
			}else if(strcmp($4, "bool")==0){
			strcpy(a.type,"bool");
			a.value.bval = 0;
			}
			insert(a);
    	Trace("Reducing to [constant_declaration]\n");
	}
    ;


arrays_declaration:
VAR IDENTIFIER COLON ARRAY INT_RANGE OF type 
{ 
		struct content a;
		strcpy(a.id,$2);
		strcpy(a.bigtype,"array");
		if(strcmp($7,"int")==0){
			strcpy(a.type,"int");
		}else if(strcmp($7,"real")==0){
			strcpy(a.type,"real");
		}else if(strcmp($7,"str")==0){
			strcpy(a.type,"str");
		}else if(strcmp($7,"bool")==0){
			strcpy(a.type,"bool");
		}
		insert(a);
		Trace("Reducing to [arrays_declaration]\n");
}
;


program_units: program_unit
             | program_units program_unit
             ;

program_unit: constant_declaration
            | variables_declaration
            | arrays_declaration
            | function_expression
            | procedure_expression
            | statements
            | loop
            ;


statements:
    blocks
    | simple
    | if_statement
    ;

blocks:
BEGIN_KEYWORD program_units END
;

simple:
    IDENTIFIER COLONEQUALS INTEGERVAL
    | IDENTIFIER COLONEQUALS function_invocation
    | IDENTIFIER COLONEQUALS IDENTIFIER PLUS INTEGERVAL
    | IDENTIFIER COLONEQUALS IDENTIFIER PLUS IDENTIFIER
    | PUT signed_expression
    | GET IDENTIFIER
    | RESULT expression
    | EXIT
    | EXIT WHEN bool_expression
    | SKIP
    | EXIT WHEN IDENTIFIER EQUALS IDENTIFIER
    ;



signed_expression:
    MINUS IDENTIFIER
    | IDENTIFIER
    | STRINGVAL
    | INTEGERVAL
    | FLOATVAL
    | bool_expression
    | parenthesized_stringval
    ;

parenthesized_stringval:
    LP STRINGVAL RP
    ;


expression:
    INTEGERVAL{
	strcpy($$.type, "int");
	$$.value.ival = $1;
	}
    | IDENTIFIER{
        $$ = lookup($1);
        struct content a;
        strcpy(a.id,$1);
        a.value.ival = $$;
        insert(a);
    }
    | MINUS INTEGERVAL{
		$$=-$2;
	}
    | function_invocation{
    	$$ = $1; 
	} 
    | expression PLUS expression{
		$$ = $1 + $3;
	}
    | expression MINUS expression{
		$$ = $1 - $3;
	}
    | expression MULTIPLY expression{
		$$ = $1 * $3;
	}
    | expression DIVIDE expression{
		$$ = $1 / $3;
	}
    | expression MOD expression{
		$$ = $1 % $3;
	}
    | expression LT expression
    | expression LE expression
    | expression EQUALS expression
    | expression EG expression
    | expression GT expression
    | expression NOTEQUALS expression
    | expression NOT expression
    | expression AND expression
    | expression OR expression
    ;


function_expression:
    FUNCTION IDENTIFIER LP formal_arguments RP COLON type program_units END{scope--;} IDENTIFIER
    {
    	struct content a;
    	strcpy(a.id,$2);
    	strcpy(a.bigtype,"func");
    	strcpy(a.type,$7);
    	a.value.ival = 0;
    	insert(a);
    	scope++;
        Trace("Reducing to [function_expression]\n");
    }
    
    ;


procedure_expression:
	PROCEDURE IDENTIFIER LP formal_arguments RP program_units END{scope--;} IDENTIFIER
	{
		struct content a;
		strcpy(a.id,$2);
		strcpy(a.bigtype,"func");
		a.value.ival = 0;
		insert(a);
		scope++;
		Trace("Redcing to [procedure_exprssion]\n");
	}

;

formal_arguments:
 formal_arguments COMMA formal_argument
    | formal_argument
    |
    ;
   
formal_argument: IDENTIFIER COLON type{
	struct content b;
	strcpy(b.id, $1);
	strcpy(b.bigtype,"func");
	strcpy(b.type,$3);
	b.value.ival = 0;
	insert(b);
  	Trace("Reducing to [formal_argument]\n");
};

if_statement:
IF bool_expression THEN program_units ENDIF {Trace("Reducing to [if_statement]\n");}
| IF bool_expression THEN program_units ELSE program_units ENDIF {Trace("Reducing to [if_statement]\n");}
;

bool_expression:
    TRUEVAL{
    	strcpy($$.type, "bool");
		$$.value.bval = 1;
	} 
    | FALSEVAL{
    	strcpy($$.type, "bool");
		$$.value.bval = 0;
	} 
    | expression LT expression
    | expression LE expression
    | expression EQ expression
    | expression GE expression
    | expression GT expression
    | expression NE expression
    | NOT bool_expression{
    	strcpy($$.type, "bool");
    	$$.value.bval = !$2.value.bval;
	} 
    | bool_expression AND bool_expression
    | bool_expression OR bool_expression
    | LP bool_expression RP { $$ = $2; }
    ;


function_invocation:
IDENTIFIER LP expressions RP {
		struct content a ;
    	strcpy(a.id,$1);
    	a.value.ival = lookup($1);
    	insert(a);
    	$$ = a.value.ival;
	Trace("Reducing to [function_invocation]\n");
}
|IDENTIFIER LP RP {
		struct content a ;
   	 	strcpy(a.id,$1);
   	 	a.value.ival = lookup($1);
   	 	insert(a);
   	 	$$ = a.value.ival;
	Trace("Reducing to [function_invocation]\n");
}
;


expressions:
expression
| expressions COMMA expression
;

loop:
LOOP program_units ENDLOOP {Trace("Reducing to [loop]\n");}
|LOOP ENDLOOP {Trace("Reducing to [loop]\n");}
|FOR opt_decreasing IDENTIFIER COLON constant_exp DOT DOT constant_exp program_units_or_empty ENDFOR {Trace("Reducing to [loop]\n");}
;

program_units_or_empty:
      program_units
    |
    ;

opt_decreasing:
    DECREASING
    |
    ;
    
constant_exp:
INTEGERVAL
		{
			strcpy($$.type, "int");
			$$.value.ival = $1;
		}
| STRINGVAL
		{
			strcpy($$.type, "str");
			strcpy($$.value.sval, $1);
		}
| FLOATVAL
		{
			strcpy($$.type, "real");
			$$.value.fval = $1;
		}
| TRUEVAL
		{
			strcpy($$.type, "bool");
			$$.value.bval = 1;
		}
| FALSEVAL
		{
			strcpy($$.type, "bool");
			$$.value.bval = 0;
		}
| IDENTIFIER
    {
        $$ = lookup($1);
        struct content a;
        strcpy(a.id,$1);
        a.value.ival = $$;
        insert(a);
    }
;

type: STRING
		{
			strcpy($$,"str");
		}
   | BOOL
   		{
   			strcpy($$,"bool");
		}
   | REAL
   		{
   			strcpy($$,"real");
		}
   | INT
   		{
   			strcpy($$,"int");
		}
   ;

%%
#include "lex.yy.c"
void yyerror(const char *msg)
{
  fprintf(stderr, "%s\n", msg);
}
int main(int argc, char *argv[])
{
  if(yyparse()){
    yyerror("Parsing error !");
  }
return 0;
}