author | Markus Bröker <mbroeker@largo.dyndns.tv> |
Fri, 27 Dec 2013 16:00:09 +0100 | |
changeset 167 | 7c6b221900bf |
parent 131 | b5ad49852adc |
permissions | -rw-r--r-- |
30
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
1 |
/** |
77 | 2 |
* recursive_compiler.c |
3 |
* Adapted from: http://de.wikipedia.org/wiki/Compiler |
|
4 |
* |
|
30
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
5 |
* Ein-Pass-Compiler |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
6 |
*/ |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
7 |
|
48
b94d657a9acb
Policy Inonsistency on many files
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
31
diff
changeset
|
8 |
#include <stdio.h> |
30
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
9 |
#include <stdlib.h> |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
10 |
#include <string.h> |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
11 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
12 |
#define MODE_POSTFIX 0 |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
13 |
#define MODE_ASSEMBLY 1 |
31
c95a6a7e305c
wiki synchronisation
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
30
diff
changeset
|
14 |
#define MAX 20 |
30
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
15 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
16 |
char lookahead; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
17 |
int pos; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
18 |
int compile_mode; |
31
c95a6a7e305c
wiki synchronisation
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
30
diff
changeset
|
19 |
char expression[MAX + 1]; |
30
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
20 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
21 |
void error () |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
22 |
{ |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
23 |
printf ("Syntaxfehler!\n"); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
24 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
25 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
26 |
void match (char t) |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
27 |
{ |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
28 |
if (lookahead == t) { |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
29 |
lookahead = expression[++pos]; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
30 |
} else |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
31 |
error (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
32 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
33 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
34 |
void digit () |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
35 |
{ |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
36 |
switch (lookahead) { |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
37 |
case '0': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
38 |
case '1': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
39 |
case '2': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
40 |
case '3': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
41 |
case '4': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
42 |
case '5': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
43 |
case '6': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
44 |
case '7': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
45 |
case '8': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
46 |
case '9': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
47 |
printf (compile_mode == MODE_POSTFIX ? "%c" : "\tPUSH %c\n", lookahead); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
48 |
match (lookahead); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
49 |
break; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
50 |
default: |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
51 |
error (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
52 |
break; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
53 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
54 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
55 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
56 |
void term () |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
57 |
{ |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
58 |
digit (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
59 |
while (1) { |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
60 |
switch (lookahead) { |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
61 |
case '*': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
62 |
match ('*'); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
63 |
digit (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
64 |
printf ("%s", compile_mode == MODE_POSTFIX ? "*" : "\tPOP B\n\tPOP A\n\tMUL A, B\n\tPUSH A\n"); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
65 |
break; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
66 |
case '/': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
67 |
match ('/'); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
68 |
digit (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
69 |
printf ("%s", compile_mode == MODE_POSTFIX ? "/" : "\tPOP B\n\tPOP A\n\tDIV A, B\n\tPUSH A\n"); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
70 |
break; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
71 |
default: |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
72 |
return; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
73 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
74 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
75 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
76 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
77 |
void expr () |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
78 |
{ |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
79 |
term (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
80 |
while (1) { |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
81 |
switch (lookahead) { |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
82 |
case '+': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
83 |
match ('+'); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
84 |
term (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
85 |
printf ("%s", compile_mode == MODE_POSTFIX ? "+" : "\tPOP B\n\tPOP A\n\tADD A, B\n\tPUSH A\n"); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
86 |
break; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
87 |
case '-': |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
88 |
match ('-'); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
89 |
term (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
90 |
printf ("%s", compile_mode == MODE_POSTFIX ? "-" : "\tPOP B\n\tPOP A\n\tSUB A, B\n\tPUSH A\n"); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
91 |
break; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
92 |
default: |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
93 |
return; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
94 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
95 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
96 |
} |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
97 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
98 |
int main (int argc, char **argv) |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
99 |
{ |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
100 |
printf ("Bitte geben Sie einen Ausdruck in Infix-Notation ein:\n\n\t"); |
131
b5ad49852adc
check for the return values
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
77
diff
changeset
|
101 |
if (fgets (expression, MAX, stdin) == NULL) |
b5ad49852adc
check for the return values
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
77
diff
changeset
|
102 |
return EXIT_FAILURE; |
30
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
103 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
104 |
printf ("\nCompilierter Ausdruck in Postfix-Notation:\n\n\t"); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
105 |
compile_mode = MODE_POSTFIX; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
106 |
pos = 0; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
107 |
lookahead = *expression; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
108 |
expr (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
109 |
|
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
110 |
printf ("\n\nCompilierter Ausdruck in Assemblersprache:\n\n"); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
111 |
compile_mode = MODE_ASSEMBLY; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
112 |
pos = 0; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
113 |
lookahead = *expression; |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
114 |
expr (); |
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
115 |
|
48
b94d657a9acb
Policy Inonsistency on many files
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
31
diff
changeset
|
116 |
return EXIT_SUCCESS; |
30
d037c433ec3e
kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff
changeset
|
117 |
} |