kleiner auffschrischungskurs compilerbau...
committer: Markus Bröker <mbroeker@largo.homelinux.org>
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,8 @@
copy \
function_pointers \
sort \
- min2time
+ min2time \
+ recursive_compiler
.SUFFIXES: .c .cc .asm
@@ -235,6 +236,10 @@
@echo Linking $< ...
@$(CC) -o $@ $<
+recursive_compiler: recursive_compiler.o
+ @echo Linking $< ...
+ @$(CC) -o $@ $<
+
.PHONY: clean uninstall
clean:
new file mode 100644
--- /dev/null
+++ b/recursive_compiler.c
@@ -0,0 +1,113 @@
+/**
+ * Ein-Pass-Compiler
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MODE_POSTFIX 0
+#define MODE_ASSEMBLY 1
+
+char lookahead;
+int pos;
+int compile_mode;
+char expression[20 + 1];
+
+void error ()
+{
+ printf ("Syntaxfehler!\n");
+}
+
+void match (char t)
+{
+ if (lookahead == t) {
+ lookahead = expression[++pos];
+ } else
+ error ();
+}
+
+void digit ()
+{
+ switch (lookahead) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ printf (compile_mode == MODE_POSTFIX ? "%c" : "\tPUSH %c\n", lookahead);
+ match (lookahead);
+ break;
+ default:
+ error ();
+ break;
+ }
+}
+
+void term ()
+{
+ digit ();
+ while (1) {
+ switch (lookahead) {
+ case '*':
+ match ('*');
+ digit ();
+ printf ("%s", compile_mode == MODE_POSTFIX ? "*" : "\tPOP B\n\tPOP A\n\tMUL A, B\n\tPUSH A\n");
+ break;
+ case '/':
+ match ('/');
+ digit ();
+ printf ("%s", compile_mode == MODE_POSTFIX ? "/" : "\tPOP B\n\tPOP A\n\tDIV A, B\n\tPUSH A\n");
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+void expr ()
+{
+ term ();
+ while (1) {
+ switch (lookahead) {
+ case '+':
+ match ('+');
+ term ();
+ printf ("%s", compile_mode == MODE_POSTFIX ? "+" : "\tPOP B\n\tPOP A\n\tADD A, B\n\tPUSH A\n");
+ break;
+ case '-':
+ match ('-');
+ term ();
+ printf ("%s", compile_mode == MODE_POSTFIX ? "-" : "\tPOP B\n\tPOP A\n\tSUB A, B\n\tPUSH A\n");
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+int main (int argc, char **argv)
+{
+ printf ("Bitte geben Sie einen Ausdruck in Infix-Notation ein:\n\n\t");
+ fgets (expression, 20, stdin);
+
+ printf ("\nCompilierter Ausdruck in Postfix-Notation:\n\n\t");
+ compile_mode = MODE_POSTFIX;
+ pos = 0;
+ lookahead = *expression;
+ expr ();
+
+ printf ("\n\nCompilierter Ausdruck in Assemblersprache:\n\n");
+ compile_mode = MODE_ASSEMBLY;
+ pos = 0;
+ lookahead = *expression;
+ expr ();
+
+ return 0;
+}