%{
#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;
}