/**
* recursive_compiler.c
* Adapted from: http://de.wikipedia.org/wiki/Compiler
*
* Ein-Pass-Compiler
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MODE_POSTFIX 0
#define MODE_ASSEMBLY 1
#define MAX 20
char lookahead;
int pos;
int compile_mode;
char expression[MAX + 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");
if (fgets (expression, MAX, stdin) == NULL)
return EXIT_FAILURE;
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 EXIT_SUCCESS;
}