recursive_compiler.c
author Markus Bröker <mbroeker@largo.dyndns.tv>
Thu, 16 Apr 2009 12:49:11 +0200
changeset 31 c95a6a7e305c
parent 30 d037c433ec3e
child 48 b94d657a9acb
permissions -rw-r--r--
wiki synchronisation committer: Markus Bröker <mbroeker@largo.homelinux.org>

/**
 * Ein-Pass-Compiler
 * Adapted from: http://de.wikipedia.org/wiki/Compiler
 */

#include <stdlib.h>
#include <stdio.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");
    fgets (expression, MAX, 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;
}