This repository has been archived by the owner on Dec 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinfix.y
184 lines (156 loc) · 4.29 KB
/
infix.y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
%{
// Benjamin Steenkamer
// CPEG 621 - Lab 1, part 1
#include <stdio.h>
#include <string.h>
#include <math.h>
#define MAX_NUM_VARS 30 // Max number of declared variables allowed
#define MAX_VAR_NAME_LEN 20 // How long a variable name can be
int yylex(void); // Will be generated in lex.yy.c by flex
// Following are defined below in sub-routines section
void yyerror(char *); // Following are defined below in sub-routines section
int var_assignment(char *, int);
int get_var_value(char *);
int create_var(char *);
void print_var_create_error(int);
struct variable {
char name[MAX_VAR_NAME_LEN + 1]; // Allocate space for max var name + \0
int value;
};
struct variable vars[MAX_NUM_VARS]; // Holds declared variables
int num_vars = 0; // Current amount of variables declared
int lineNum = 1; // Used for debugging
%}
%token INTEGER POWER VARIABLE // bison adds these #defines in infix.tab.h for use in flex
// Union defines all possible values a token can have associated with it
// Allow yylval to hold either an integer or a string (for variable name)
%union
{
int val;
char *str;
}
// When %union is used to specify multiple value types, must declare the
// value type of each symbol for which values are used
%type <val> expr INTEGER
%type <str> VARIABLE
// Make grammar unambiguous
// Low to high precedence and associativity within a precedent rank
// https://en.cppreference.com/w/c/language/operator_precedence
%left '+' '-'
%left '*' '/'
%precedence '!' // Unary bitwise not; No associativity b/c it is unary
%right POWER // ** exponent operator
%start infix
%%
infix :
infix statement '\n'
|
;
statement:
expr { printf("=%d\n", $1); }
| VARIABLE '=' expr {
printf("=%d\n", var_assignment($1, $3));
free($1); // Must free the strdup string
}
;
expr :
INTEGER { $$ = $1; } // Default action; don't really need this
| VARIABLE { $$ = get_var_value($1); free($1); }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| '!' expr { $$ = ~$2; }
| expr POWER expr { $$ = (int)pow($1, $3); }
| '(' expr ')' { $$ = $2; } // Will give syntax error for unmatched parens
;
%%
// Called for var_name = value operations
// Searches the array of vars for var_name; if found, assigns value to it and returns assigned value
// If var_name doesn't exist, create var_name in array, assign new value, return assigned value
int var_assignment(char* var_name, int value)
{
// Search vars to see if var_name was already created
int i = 0;
for(i = 0; i < num_vars; i++)
{
if (strcmp(vars[i].name, var_name) == 0)
{
vars[i].value = value;
return vars[i].value; // Return newly assigned value
}
}
// Try to add new var_name to the array
i = create_var(var_name);
if (i >= 0)
{
vars[i].value = value;
return vars[i].value;
}
print_var_create_error(i);
return 0;
}
// Returns the value of the variable
// If variable wasn't declared previously, create it with a value of zero
int get_var_value(char *var_name)
{
int i = 0;
for(i = 0; i < num_vars; i++)
{
if (strcmp(vars[i].name, var_name) == 0)
{
return vars[i].value;
}
}
i = create_var(var_name);
if (i >= 0)
{
return vars[i].value; // This should always be zero
}
print_var_create_error(i);
return 0; // Return 0 even if a new var couldn't be made
}
// Attempts to add a new variable to the vars array
// Returns index of new variable in array if successful
// Returns negative number if there was an error
int create_var(char *var_name)
{
if (num_vars >= MAX_NUM_VARS)
{
return -1;
}
int len = strlen(var_name);
if(len > MAX_VAR_NAME_LEN)
{
return -2;
}
strncpy(vars[num_vars].name, var_name, len);
vars[num_vars].value = 0; // Initialize variable with a value of zero
num_vars++;
return num_vars - 1;
}
// Handle to decode errors and print error message
void print_var_create_error(int error)
{
switch(error)
{
case -1:
yyerror("Max number of variables already declared");
break;
case -2:
yyerror("Variable name exceeds max length");
break;
default:
yyerror("Unknown error code");
}
}
void yyerror(char *s)
{
printf("%s\n", s);
}
int main()
{
memset(vars, 0, sizeof(int) * MAX_NUM_VARS); // Initialize variables to zero
yyparse();
return 0;
}