kleiner auffschrischungskurs compilerbau...
authorMarkus Bröker <mbroeker@largo.dyndns.tv>
Thu, 16 Apr 2009 12:49:04 +0200
changeset 30 d037c433ec3e
parent 29 7abf6146898e
child 31 c95a6a7e305c
kleiner auffschrischungskurs compilerbau... committer: Markus Bröker <mbroeker@largo.homelinux.org>
Makefile
recursive_compiler.c
--- 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;
+}