recursive_compiler.c
author Markus Bröker<broeker.markus@googlemail.com>
Sun, 10 Feb 2019 13:17:01 +0100
changeset 173 374a86886bc5
parent 131 b5ad49852adc
permissions -rw-r--r--
LAST-DIGIT-BUG: INCREMENT before LF

/**
 * 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;
}