compilerlab5 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- compilerlab5-0.1.1.dist-info/METADATA +374 -0
- compilerlab5-0.1.1.dist-info/RECORD +19 -0
- compilerlab5-0.1.1.dist-info/WHEEL +5 -0
- compilerlab5-0.1.1.dist-info/entry_points.txt +7 -0
- compilerlab5-0.1.1.dist-info/licenses/LICENSE +15 -0
- compilerlab5-0.1.1.dist-info/top_level.txt +1 -0
- cpp/__init__.py +2 -0
- cpp/__main__.py +4 -0
- cpp/c_sources/01_lalr_bottom_up.c +23 -0
- cpp/c_sources/02_slr1_parser.c +37 -0
- cpp/c_sources/03_three_address_code.c +33 -0
- cpp/c_sources/04_operator_lexical_analyzer.c +24 -0
- cpp/c_sources/05_shift_reduce_parser.c +21 -0
- cpp/cli.py +19 -0
- cpp/lalr.py +34 -0
- cpp/operator.py +27 -0
- cpp/shift_reduce.py +56 -0
- cpp/slr.py +29 -0
- cpp/tac.py +38 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: compilerlab5
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Five Compiler Design laboratory programs from Experiments 6-10
|
|
5
|
+
Author: Compiler Lab Package
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: compiler-design,lalr,slr,three-address-code,shift-reduce,lexical-analyzer
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
\# compilerlab5
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
A pip-installable package containing five Compiler Design laboratory programs based on \*\*Experiment 6-10.pdf\*\*:
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
1\. LALR bottom-up parser demo
|
|
22
|
+
|
|
23
|
+
2\. SLR(1) parsing demo
|
|
24
|
+
|
|
25
|
+
3\. Three-address code generator
|
|
26
|
+
|
|
27
|
+
4\. Lexical analyzer for operators
|
|
28
|
+
|
|
29
|
+
5\. Shift-reduce parser
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
\## Installation
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
Install the package from PyPI:
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
|
|
43
|
+
python -m pip install compilerlab5
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
After installation, the package can be used from any supported Python environment.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
\## Usage
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
\### 1. LALR Bottom-Up Parser
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
|
|
63
|
+
compilerlab5 lalr
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
Example input:
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
|
|
75
|
+
i+i\*i
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
\### 2. SLR(1) Parser
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
|
|
87
|
+
compilerlab5 slr
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Example input:
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
|
|
99
|
+
dd
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
\### 3. Three-Address Code Generator
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
|
|
111
|
+
compilerlab5 tac
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
Example input:
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
|
|
123
|
+
a+b\*c
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
\### 4. Lexical Analyzer for Operators
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
|
|
135
|
+
compilerlab5 operator
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
Example input:
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
|
|
147
|
+
\+
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
\### 5. Shift-Reduce Parser
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
|
|
159
|
+
compilerlab5 shift-reduce
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
Example input:
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
|
|
171
|
+
id+id\*id
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
\## Individual Commands
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
The individual console commands are also available:
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
|
|
187
|
+
lalr-parser
|
|
188
|
+
|
|
189
|
+
slr-parser
|
|
190
|
+
|
|
191
|
+
tac-generator
|
|
192
|
+
|
|
193
|
+
operator-validator
|
|
194
|
+
|
|
195
|
+
shift-reduce-parser
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
\## Python Module Usage
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
The package can also be executed through Python:
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
|
|
211
|
+
python -m cpp lalr
|
|
212
|
+
|
|
213
|
+
python -m cpp slr
|
|
214
|
+
|
|
215
|
+
python -m cpp tac
|
|
216
|
+
|
|
217
|
+
python -m cpp operator
|
|
218
|
+
|
|
219
|
+
python -m cpp shift-reduce
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
Here, `cpp` is the internal Python package name, while `compilerlab5` is the public PyPI distribution name.
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
\## Local Testing
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
From the project directory:
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
|
|
239
|
+
python -m pip install --upgrade build
|
|
240
|
+
|
|
241
|
+
python -m build
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
Install the generated wheel:
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
|
|
253
|
+
python -m pip install dist/compilerlab5-0.1.1-py3-none-any.whl
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
\## PyPI Publishing
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
Build the package:
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
|
|
269
|
+
python -m build
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
Check the generated distributions:
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
|
|
281
|
+
dir dist
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
Upload the distributions using Twine:
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
|
|
293
|
+
python -m twine upload dist/\*
|
|
294
|
+
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
For PyPI authentication, use the username:
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
```text
|
|
304
|
+
|
|
305
|
+
\_\_token\_\_
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
and a valid PyPI API token as the password.
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
\## Portability
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
The Python package does \*\*not\*\* require GCC or Clang to run the Python implementations.
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
Python is required on the target system.
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
The original C source files from the supplied \*\*Experiment 6-10.pdf\*\* are also included under:
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
```text
|
|
332
|
+
|
|
333
|
+
src/cpp/c\_sources/
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
These source files are included for laboratory/reference purposes.
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
\## Package Information
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
\*\*Distribution name:\*\* `compilerlab5`
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
\*\*Python package/module:\*\* `cpp`
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
\*\*Current version:\*\* `0.1.1`
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
\*\*License:\*\* MIT
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
\## Educational Purpose
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
This is a teaching/laboratory package containing examples for Compiler Design experiments 6-10.
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
The parser examples intentionally follow the structure and terminology of the supplied laboratory material and are intended for educational use rather than as a production compiler toolkit.
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
compilerlab5-0.1.1.dist-info/licenses/LICENSE,sha256=FZMl_KxZ3I8Ajtguk5x4g3NhIXqG-L49BIUpHP5GpX0,659
|
|
2
|
+
cpp/__init__.py,sha256=8EOxaXdnube-I32_fswktrTi6m7XzRy7b33uoC3i1xc,88
|
|
3
|
+
cpp/__main__.py,sha256=EClCwCzb6h6YBpt0hrnG4h0mlNhNePyg_xBNNSVm1os,65
|
|
4
|
+
cpp/cli.py,sha256=sA0xHsvyf8jqxQiDbaH7k8h3VT44p6rJVrh13ruprXI,513
|
|
5
|
+
cpp/lalr.py,sha256=eHsbHIT8AfJxwaL6081iSxwrKHHmQWF_NdvjPT4JZqg,1049
|
|
6
|
+
cpp/operator.py,sha256=BFrpeZt9f3RxNks7OgdqDglF5Oi63enMgB4utyMsymU,1361
|
|
7
|
+
cpp/shift_reduce.py,sha256=DJ6Ab8qflBLtKGFEksOK14sryUoz-yVB10wgujQK-nw,1998
|
|
8
|
+
cpp/slr.py,sha256=nGNTleNHCO70oES3sGHRkZjD8ykGO_IOG2LERC6R17M,724
|
|
9
|
+
cpp/tac.py,sha256=MCs-aYek40GbZgwoehOIjvnKHW2g1-WGoIXh0xlZH4k,1303
|
|
10
|
+
cpp/c_sources/01_lalr_bottom_up.c,sha256=c4NhvcdjpIk48izCpqaZrH-k1ViN2ZWTy_gDD_4WgWw,813
|
|
11
|
+
cpp/c_sources/02_slr1_parser.c,sha256=7KAvuaWvUHYQISWDYwh9Ia3QTs7Ynn1Ybg2WW33Zuf0,1497
|
|
12
|
+
cpp/c_sources/03_three_address_code.c,sha256=ytSSUdpDwtLkAOo9wGSiSazQYjAp7TNTpKHF2mMnFOc,1462
|
|
13
|
+
cpp/c_sources/04_operator_lexical_analyzer.c,sha256=sBkSLiLLkvoSJokqYnGrKIe3qOsLq3shrGCw2Oq7P68,1805
|
|
14
|
+
cpp/c_sources/05_shift_reduce_parser.c,sha256=oORINMK1GUXpLUWnAZr_G_MQEw-lIHAkDV5h2f8KDpQ,1406
|
|
15
|
+
compilerlab5-0.1.1.dist-info/METADATA,sha256=IXf682qJRfKF-zsOdiXcLfDJ03VkSgnfvacViyiltVc,3738
|
|
16
|
+
compilerlab5-0.1.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
17
|
+
compilerlab5-0.1.1.dist-info/entry_points.txt,sha256=UETMSrtoZk72OdIBMaD-RT2t7n4YzH7nQ93T52Jrm2Y,212
|
|
18
|
+
compilerlab5-0.1.1.dist-info/top_level.txt,sha256=st3_n7dR9Y75QOgD4nJcJed-luRnmOMrSoGkUl0VO1I,4
|
|
19
|
+
compilerlab5-0.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cpp
|
cpp/__init__.py
ADDED
cpp/__main__.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
#include <string.h>
|
|
3
|
+
char stack[50]; int top = -1;
|
|
4
|
+
void push(char c) { stack[++top] = c; }
|
|
5
|
+
void pop(int n) { top -= n; }
|
|
6
|
+
int main() {
|
|
7
|
+
char input[50]; int i = 0;
|
|
8
|
+
printf("Enter string (e.g., i+i*i): "); scanf("%49s", input);
|
|
9
|
+
push('$');
|
|
10
|
+
while (input[i] != '\0') {
|
|
11
|
+
if (input[i] == 'i') {
|
|
12
|
+
push('F'); printf("Shift i, Reduce F->i\n");
|
|
13
|
+
stack[top] = 'T'; printf("Reduce T->F\n");
|
|
14
|
+
stack[top] = 'E'; printf("Reduce E->T\n");
|
|
15
|
+
} else if (input[i] == '+' || input[i] == '*') {
|
|
16
|
+
push(input[i]); printf("Shift %c\n", input[i]);
|
|
17
|
+
} else { printf("Rejected\n"); return 0; }
|
|
18
|
+
i++;
|
|
19
|
+
}
|
|
20
|
+
if (top >= 2 && stack[top] == 'E') printf("Accepted by LALR Bottom-Up Parser\n");
|
|
21
|
+
else printf("Rejected\n");
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
#include <string.h>
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
char input[20]; int ip = 0;
|
|
5
|
+
int main() {
|
|
6
|
+
int stateStack[20], top = 0; stateStack[top] = 0;
|
|
7
|
+
printf("Enter input string: "); scanf("%19s", input); strcat(input, "$");
|
|
8
|
+
while (1) {
|
|
9
|
+
int state = stateStack[top]; char symbol = input[ip];
|
|
10
|
+
switch (state) {
|
|
11
|
+
case 0:
|
|
12
|
+
if (symbol == 'c') { stateStack[++top] = 3; ip++; }
|
|
13
|
+
else if (symbol == 'd') { stateStack[++top] = 4; ip++; }
|
|
14
|
+
else { printf("Rejected\n"); return 0; }
|
|
15
|
+
break;
|
|
16
|
+
case 1:
|
|
17
|
+
if (symbol == '$') { printf("Accepted\n"); return 0; }
|
|
18
|
+
printf("Rejected\n"); return 0;
|
|
19
|
+
case 2:
|
|
20
|
+
if (symbol == 'c') { stateStack[++top] = 3; ip++; }
|
|
21
|
+
else if (symbol == 'd') { stateStack[++top] = 4; ip++; }
|
|
22
|
+
else { printf("Rejected\n"); return 0; }
|
|
23
|
+
break;
|
|
24
|
+
case 3:
|
|
25
|
+
/* The supplied experiment omits the full state-3 transition table. */
|
|
26
|
+
printf("Rejected\n"); return 0;
|
|
27
|
+
case 4:
|
|
28
|
+
top--; state = stateStack[top];
|
|
29
|
+
if (state == 0) stateStack[++top] = 2;
|
|
30
|
+
else if (state == 2) stateStack[++top] = 5;
|
|
31
|
+
else { printf("Rejected\n"); return 0; }
|
|
32
|
+
break;
|
|
33
|
+
case 5: printf("Accepted\n"); return 0;
|
|
34
|
+
default: printf("Rejected\n"); return 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
#include <ctype.h>
|
|
3
|
+
#include <string.h>
|
|
4
|
+
char input[50]; int tempCount = 1;
|
|
5
|
+
void printTAC(char op, char a, char b) { printf("t%d = %c %c %c\n", tempCount, a, op, b); tempCount++; }
|
|
6
|
+
int precedence(char c) { if (c=='+'||c=='-') return 1; if(c=='*'||c=='/') return 2; return 0; }
|
|
7
|
+
int main() {
|
|
8
|
+
char opStack[50], valStack[50]; int topOp=-1, topVal=-1;
|
|
9
|
+
printf("Enter expression: "); scanf("%49s", input);
|
|
10
|
+
for (int i=0; input[i]!='\0'; i++) {
|
|
11
|
+
char ch=input[i];
|
|
12
|
+
if (isalnum((unsigned char)ch)) valStack[++topVal]=ch;
|
|
13
|
+
else if (ch=='(') opStack[++topOp]=ch;
|
|
14
|
+
else if (ch==')') {
|
|
15
|
+
while(topOp!=-1 && opStack[topOp]!='(') {
|
|
16
|
+
char op=opStack[topOp--], b=valStack[topVal--], a=valStack[topVal--];
|
|
17
|
+
printTAC(op,a,b); valStack[++topVal]='t'+tempCount-1;
|
|
18
|
+
}
|
|
19
|
+
if(topOp!=-1) topOp--;
|
|
20
|
+
} else {
|
|
21
|
+
while(topOp!=-1 && opStack[topOp]!='(' && precedence(opStack[topOp])>=precedence(ch)) {
|
|
22
|
+
char op=opStack[topOp--], b=valStack[topVal--], a=valStack[topVal--];
|
|
23
|
+
printTAC(op,a,b); valStack[++topVal]='t'+tempCount-1;
|
|
24
|
+
}
|
|
25
|
+
opStack[++topOp]=ch;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
while(topOp!=-1) {
|
|
29
|
+
char op=opStack[topOp--], b=valStack[topVal--], a=valStack[topVal--];
|
|
30
|
+
printTAC(op,a,b); valStack[++topVal]='t'+tempCount-1;
|
|
31
|
+
}
|
|
32
|
+
printf("Final result stored in t%d\n", tempCount-1); return 0;
|
|
33
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
#include <string.h>
|
|
3
|
+
void validateOperator(const char *op) {
|
|
4
|
+
if(strlen(op)==1) {
|
|
5
|
+
switch(op[0]) {
|
|
6
|
+
case '+': case '-': case '*': case '/': case '%': printf("'%s' is a Valid Arithmetic Operator.\n",op); return;
|
|
7
|
+
case '<': case '>': printf("'%s' is a Valid Relational Operator.\n",op); return;
|
|
8
|
+
case '=': printf("'%s' is a Valid Assignment Operator.\n",op); return;
|
|
9
|
+
case '!': printf("'%s' is a Valid Logical NOT Operator.\n",op); return;
|
|
10
|
+
case '&': case '|': case '^': case '~': printf("'%s' is a Valid Bitwise Operator.\n",op); return;
|
|
11
|
+
case '?': case ':': printf("'%s' is a Valid Conditional/Ternary Operator.\n",op); return;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if(strlen(op)==2) {
|
|
15
|
+
if(!strcmp(op,"++")||!strcmp(op,"--")) { printf("'%s' is a Valid Increment/Decrement Operator.\n",op); return; }
|
|
16
|
+
if(!strcmp(op,"==")||!strcmp(op,"!=")||!strcmp(op,"<=")||!strcmp(op,">=")) { printf("'%s' is a Valid Relational Operator.\n",op); return; }
|
|
17
|
+
if(!strcmp(op,"&&")||!strcmp(op,"||")) { printf("'%s' is a Valid Logical Operator.\n",op); return; }
|
|
18
|
+
if(!strcmp(op,"+=")||!strcmp(op,"-=")||!strcmp(op,"*=")||!strcmp(op,"/=")||!strcmp(op,"%=")) { printf("'%s' is a Valid Compound Assignment Operator.\n",op); return; }
|
|
19
|
+
if(!strcmp(op,"<<")||!strcmp(op,">>")) { printf("'%s' is a Valid Bitwise Shift Operator.\n",op); return; }
|
|
20
|
+
}
|
|
21
|
+
if(strlen(op)==3 && (!strcmp(op,"<<=")||!strcmp(op,">>="))) { printf("'%s' is a Valid Compound Bitwise Shift Operator.\n",op); return; }
|
|
22
|
+
printf("'%s' is an INVALID Operator.\n",op);
|
|
23
|
+
}
|
|
24
|
+
int main(){ char input[10]; printf("--- Lexical Analyzer: Operator Validator ---\nEnter a symbol to validate: "); if(scanf("%9s",input)==1) validateOperator(input); return 0; }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
#include <string.h>
|
|
3
|
+
char stack[100], input[100]; int top=-1, ip=0;
|
|
4
|
+
void displayStack(){ for(int i=0;i<=top;i++) printf("%c",stack[i]); }
|
|
5
|
+
void reduce() {
|
|
6
|
+
if(top>=1 && stack[top-1]=='i' && stack[top]=='d'){ stack[top-1]='E'; top--; printf("Reduce: E -> id\n"); return; }
|
|
7
|
+
if(top>=2 && stack[top-2]=='(' && stack[top-1]=='E' && stack[top]==')'){ top-=2; stack[top]='E'; printf("Reduce: E -> (E)\n"); return; }
|
|
8
|
+
if(top>=2 && stack[top-2]=='E' && stack[top-1]=='+' && stack[top]=='E'){ top-=2; stack[top]='E'; printf("Reduce: E -> E+E\n"); return; }
|
|
9
|
+
if(top>=2 && stack[top-2]=='E' && stack[top-1]=='*' && stack[top]=='E'){ top-=2; stack[top]='E'; printf("Reduce: E -> E*E\n"); return; }
|
|
10
|
+
}
|
|
11
|
+
int main(){
|
|
12
|
+
printf("SHIFT-REDUCE PARSER\n--------------------\nGrammar:\nE -> E+E\nE -> E*E\nE -> (E)\nE -> id\n\nEnter input string (use id for identifier): ");
|
|
13
|
+
scanf("%99s",input);
|
|
14
|
+
printf("\n%-15s %-15s %-20s\n","Stack","Input","Action");
|
|
15
|
+
printf("-----------------------------------------------\n");
|
|
16
|
+
while(input[ip]!='\0'){ stack[++top]=input[ip++]; printf("%-15s %-15s Shift %c\n",stack,input+ip,stack[top]); reduce(); }
|
|
17
|
+
while(1){ int oldTop=top; reduce(); if(oldTop==top) break; }
|
|
18
|
+
printf("\nFinal Stack: "); displayStack();
|
|
19
|
+
if(top==0 && stack[0]=='E') printf("\n\nInput string ACCEPTED.\n"); else printf("\n\nInput string REJECTED.\n");
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
cpp/cli.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from . import lalr, slr, tac, operator, shift_reduce
|
|
3
|
+
|
|
4
|
+
COMMANDS = {
|
|
5
|
+
"lalr": lalr.main,
|
|
6
|
+
"slr": slr.main,
|
|
7
|
+
"tac": tac.main,
|
|
8
|
+
"operator": operator.main,
|
|
9
|
+
"shift-reduce": shift_reduce.main,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def main():
|
|
13
|
+
p=argparse.ArgumentParser(prog="cpp", description="Five Compiler Design lab programs")
|
|
14
|
+
p.add_argument("program", nargs="?", choices=COMMANDS, help="Program to run")
|
|
15
|
+
a=p.parse_args()
|
|
16
|
+
if not a.program:
|
|
17
|
+
p.print_help()
|
|
18
|
+
return
|
|
19
|
+
COMMANDS[a.program]()
|
cpp/lalr.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""LALR-style bottom-up parser demo based on the supplied Experiment 6-10 PDF.
|
|
2
|
+
|
|
3
|
+
Grammar demonstrated:
|
|
4
|
+
E -> E+T | T
|
|
5
|
+
T -> T*F | F
|
|
6
|
+
F -> i
|
|
7
|
+
|
|
8
|
+
This is a teaching/demo parser, matching the reduction trace style of the source.
|
|
9
|
+
"""
|
|
10
|
+
def parse(text: str) -> list[str]:
|
|
11
|
+
text = text.strip()
|
|
12
|
+
if not text:
|
|
13
|
+
return ["Rejected"]
|
|
14
|
+
if any(c not in "i+*" for c in text) or text[0] != "i" or text[-1] != "i":
|
|
15
|
+
return ["Rejected"]
|
|
16
|
+
if "++" in text or "**" in text or "+*" in text or "*+" in text:
|
|
17
|
+
return ["Rejected"]
|
|
18
|
+
out=[]
|
|
19
|
+
expect_operand=True
|
|
20
|
+
for c in text:
|
|
21
|
+
if expect_operand:
|
|
22
|
+
if c!="i": return ["Rejected"]
|
|
23
|
+
out += ["Shift i, Reduce F->i", "Reduce T->F", "Reduce E->T"]
|
|
24
|
+
expect_operand=False
|
|
25
|
+
else:
|
|
26
|
+
if c not in "+*": return ["Rejected"]
|
|
27
|
+
out.append(f"Shift {c}")
|
|
28
|
+
expect_operand=True
|
|
29
|
+
out.append("Accepted by LALR Bottom-Up Parser")
|
|
30
|
+
return out
|
|
31
|
+
|
|
32
|
+
def main():
|
|
33
|
+
s=input("Enter string (e.g., i+i*i): ")
|
|
34
|
+
print("\n".join(parse(s)))
|
cpp/operator.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Lexical analyzer for operators, based on the supplied PDF."""
|
|
2
|
+
def validate_operator(op: str) -> str:
|
|
3
|
+
arithmetic={"+","-","*","/","%"}
|
|
4
|
+
relational={"<",">","==","!=","<=",">="}
|
|
5
|
+
assignment={"="}
|
|
6
|
+
logical={"!","&&","||"}
|
|
7
|
+
bitwise={"&","|","^","~"}
|
|
8
|
+
conditional={"?",":"}
|
|
9
|
+
incdec={"++","--"}
|
|
10
|
+
compound={"+=","-=","*=","/=","%="}
|
|
11
|
+
shifts={"<<",">>"}
|
|
12
|
+
compound_shifts={"<<=",">>="}
|
|
13
|
+
if op in arithmetic: return f"'{op}' is a Valid Arithmetic Operator."
|
|
14
|
+
if op in relational: return f"'{op}' is a Valid Relational Operator."
|
|
15
|
+
if op in assignment: return f"'{op}' is a Valid Assignment Operator."
|
|
16
|
+
if op in logical: return f"'{op}' is a Valid Logical Operator."
|
|
17
|
+
if op in bitwise: return f"'{op}' is a Valid Bitwise Operator."
|
|
18
|
+
if op in conditional: return f"'{op}' is a Valid Conditional/Ternary Operator."
|
|
19
|
+
if op in incdec: return f"'{op}' is a Valid Increment/Decrement Operator."
|
|
20
|
+
if op in compound: return f"'{op}' is a Valid Compound Assignment Operator."
|
|
21
|
+
if op in shifts: return f"'{op}' is a Valid Bitwise Shift Operator."
|
|
22
|
+
if op in compound_shifts: return f"'{op}' is a Valid Compound Bitwise Shift Operator."
|
|
23
|
+
return f"'{op}' is an INVALID Operator."
|
|
24
|
+
|
|
25
|
+
def main():
|
|
26
|
+
print("--- Lexical Analyzer: Operator Validator ---")
|
|
27
|
+
print(validate_operator(input("Enter a symbol to validate: ")))
|
cpp/shift_reduce.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Shift-reduce parser based on the supplied PDF.
|
|
2
|
+
|
|
3
|
+
Grammar:
|
|
4
|
+
E -> E+E
|
|
5
|
+
E -> E*E
|
|
6
|
+
E -> (E)
|
|
7
|
+
E -> id
|
|
8
|
+
"""
|
|
9
|
+
def parse(text: str) -> list[tuple[str,str,str]]:
|
|
10
|
+
s=text.strip()
|
|
11
|
+
if not s: return [("", "", "Rejected")]
|
|
12
|
+
tokens=[]
|
|
13
|
+
i=0
|
|
14
|
+
while i<len(s):
|
|
15
|
+
if s.startswith("id",i):
|
|
16
|
+
tokens.append("id"); i+=2
|
|
17
|
+
elif s[i] in "+*()":
|
|
18
|
+
tokens.append(s[i]); i+=1
|
|
19
|
+
else:
|
|
20
|
+
return [("", s[i:], "Rejected")]
|
|
21
|
+
stack=[]; rows=[]
|
|
22
|
+
def reduce_once():
|
|
23
|
+
if len(stack)>=1 and stack[-1]=="id":
|
|
24
|
+
stack[-1]="E"; return "Reduce: E -> id"
|
|
25
|
+
if len(stack)>=3 and stack[-3:] == ["(","E",")"]:
|
|
26
|
+
del stack[-3:]; stack.append("E"); return "Reduce: E -> (E)"
|
|
27
|
+
if len(stack)>=3 and stack[-3:] == ["E","*","E"]:
|
|
28
|
+
del stack[-3:]; stack.append("E"); return "Reduce: E -> E*E"
|
|
29
|
+
if len(stack)>=3 and stack[-3:] == ["E","+","E"]:
|
|
30
|
+
del stack[-3:]; stack.append("E"); return "Reduce: E -> E+E"
|
|
31
|
+
return None
|
|
32
|
+
for idx,tok in enumerate(tokens):
|
|
33
|
+
stack.append(tok)
|
|
34
|
+
rows.append((" ".join(stack)," ".join(tokens[idx+1:]),f"Shift {tok}"))
|
|
35
|
+
# Prefer id/parenthesis reductions immediately, then repeatedly reduce.
|
|
36
|
+
while True:
|
|
37
|
+
act=reduce_once()
|
|
38
|
+
if not act: break
|
|
39
|
+
rows.append((" ".join(stack)," ".join(tokens[idx+1:]),act))
|
|
40
|
+
while True:
|
|
41
|
+
act=reduce_once()
|
|
42
|
+
if not act: break
|
|
43
|
+
rows.append((" ".join(stack),"",act))
|
|
44
|
+
rows.append((" ".join(stack),"","Input string ACCEPTED." if stack==["E"] else "Input string REJECTED."))
|
|
45
|
+
return rows
|
|
46
|
+
|
|
47
|
+
def main():
|
|
48
|
+
print("SHIFT-REDUCE PARSER")
|
|
49
|
+
print("--------------------")
|
|
50
|
+
print("Grammar:")
|
|
51
|
+
print("E -> E+E\nE -> E*E\nE -> (E)\nE -> id\n")
|
|
52
|
+
s=input("Enter input string (use id for identifier): ")
|
|
53
|
+
print("\n{:<15} {:<15} {:<30}".format("Stack","Input","Action"))
|
|
54
|
+
print("-"*65)
|
|
55
|
+
for a,b,c in parse(s):
|
|
56
|
+
print("{:<15} {:<15} {}".format(a,b,c))
|
cpp/slr.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""SLR(1) parsing demo based on the supplied PDF.
|
|
2
|
+
|
|
3
|
+
Grammar:
|
|
4
|
+
S -> CC
|
|
5
|
+
C -> cC | d
|
|
6
|
+
|
|
7
|
+
The implementation mirrors the small state-machine example in the source.
|
|
8
|
+
"""
|
|
9
|
+
def parse(text: str) -> list[str]:
|
|
10
|
+
s=text.strip()
|
|
11
|
+
if not s:
|
|
12
|
+
return ["Rejected"]
|
|
13
|
+
# For S -> CC, C -> cC | d, valid strings are two C strings.
|
|
14
|
+
def consume_c(i):
|
|
15
|
+
while i < len(s) and s[i] == "c":
|
|
16
|
+
i += 1
|
|
17
|
+
if i < len(s) and s[i] == "d":
|
|
18
|
+
return i+1
|
|
19
|
+
return None
|
|
20
|
+
j=consume_c(0)
|
|
21
|
+
if j is not None and j < len(s):
|
|
22
|
+
k=consume_c(j)
|
|
23
|
+
if k == len(s):
|
|
24
|
+
return ["Accepted"]
|
|
25
|
+
return ["Rejected"]
|
|
26
|
+
|
|
27
|
+
def main():
|
|
28
|
+
s=input("Enter input string: ")
|
|
29
|
+
print("\n".join(parse(s)))
|
cpp/tac.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Three-address code generator based on the supplied PDF."""
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
def generate(expr: str) -> list[str]:
|
|
5
|
+
expr=expr.strip()
|
|
6
|
+
if not expr:
|
|
7
|
+
raise ValueError("Expression cannot be empty")
|
|
8
|
+
if not re.fullmatch(r"[A-Za-z0-9()+*/-]+", expr):
|
|
9
|
+
raise ValueError("Only identifiers/numbers, + - * / and parentheses are supported")
|
|
10
|
+
precedence={"+":1,"-":1,"*":2,"/":2}
|
|
11
|
+
ops=[]; vals=[]; out=[]; n=1
|
|
12
|
+
def emit():
|
|
13
|
+
nonlocal n
|
|
14
|
+
op=ops.pop()
|
|
15
|
+
b=vals.pop(); a=vals.pop()
|
|
16
|
+
t=f"t{n}"
|
|
17
|
+
out.append(f"{t} = {a} {op} {b}")
|
|
18
|
+
vals.append(t); n+=1
|
|
19
|
+
for ch in expr:
|
|
20
|
+
if ch.isalnum(): vals.append(ch)
|
|
21
|
+
elif ch=="(": ops.append(ch)
|
|
22
|
+
elif ch==")":
|
|
23
|
+
while ops and ops[-1]!="(": emit()
|
|
24
|
+
if not ops: raise ValueError("Mismatched parentheses")
|
|
25
|
+
ops.pop()
|
|
26
|
+
else:
|
|
27
|
+
while ops and ops[-1]!="(" and precedence[ops[-1]]>=precedence[ch]:
|
|
28
|
+
emit()
|
|
29
|
+
ops.append(ch)
|
|
30
|
+
while ops:
|
|
31
|
+
if ops[-1]=="(": raise ValueError("Mismatched parentheses")
|
|
32
|
+
emit()
|
|
33
|
+
if len(vals)!=1: raise ValueError("Invalid expression")
|
|
34
|
+
out.append(f"Final result stored in {vals[0]}")
|
|
35
|
+
return out
|
|
36
|
+
|
|
37
|
+
def main():
|
|
38
|
+
print("\n".join(generate(input("Enter expression: "))))
|