diff --git a/recursive_compiler.c b/recursive_compiler.c new file mode 100644 --- /dev/null +++ b/recursive_compiler.c @@ -0,0 +1,113 @@ +/** + * Ein-Pass-Compiler + * + */ + +#include +#include +#include + +#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; +}