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>
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
30
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     1
/**
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     2
 * Ein-Pass-Compiler
31
c95a6a7e305c wiki synchronisation
Markus Bröker <mbroeker@largo.dyndns.tv>
parents: 30
diff changeset
     3
 * Adapted from: http://de.wikipedia.org/wiki/Compiler
30
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     4
 */
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     5
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     6
#include <stdlib.h>
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     7
#include <stdio.h>
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     8
#include <string.h>
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     9
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    10
#define MODE_POSTFIX   0
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    11
#define MODE_ASSEMBLY  1
31
c95a6a7e305c wiki synchronisation
Markus Bröker <mbroeker@largo.dyndns.tv>
parents: 30
diff changeset
    12
#define MAX           20
30
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    13
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    14
char lookahead;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    15
int pos;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    16
int compile_mode;
31
c95a6a7e305c wiki synchronisation
Markus Bröker <mbroeker@largo.dyndns.tv>
parents: 30
diff changeset
    17
char expression[MAX + 1];
30
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    18
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    19
void error ()
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    20
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    21
    printf ("Syntaxfehler!\n");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    22
}
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    23
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    24
void match (char t)
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    25
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    26
    if (lookahead == t) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    27
        lookahead = expression[++pos];
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    28
    } else
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    29
        error ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    30
}
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    31
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    32
void digit ()
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    33
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    34
    switch (lookahead) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    35
    case '0':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    36
    case '1':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    37
    case '2':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    38
    case '3':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    39
    case '4':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    40
    case '5':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    41
    case '6':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    42
    case '7':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    43
    case '8':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    44
    case '9':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    45
        printf (compile_mode == MODE_POSTFIX ? "%c" : "\tPUSH %c\n", lookahead);
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    46
        match (lookahead);
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    47
        break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    48
    default:
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    49
        error ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    50
        break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    51
    }
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    52
}
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    53
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    54
void term ()
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    55
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    56
    digit ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    57
    while (1) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    58
        switch (lookahead) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    59
        case '*':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    60
            match ('*');
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    61
            digit ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    62
            printf ("%s", compile_mode == MODE_POSTFIX ? "*" : "\tPOP B\n\tPOP A\n\tMUL A, B\n\tPUSH A\n");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    63
            break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    64
        case '/':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    65
            match ('/');
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    66
            digit ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    67
            printf ("%s", compile_mode == MODE_POSTFIX ? "/" : "\tPOP B\n\tPOP A\n\tDIV A, B\n\tPUSH A\n");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    68
            break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    69
        default:
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    70
            return;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    71
        }
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    72
    }
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    73
}
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    74
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    75
void expr ()
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    76
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    77
    term ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    78
    while (1) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    79
        switch (lookahead) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    80
        case '+':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    81
            match ('+');
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    82
            term ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    83
            printf ("%s", compile_mode == MODE_POSTFIX ? "+" : "\tPOP B\n\tPOP A\n\tADD A, B\n\tPUSH A\n");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    84
            break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    85
        case '-':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    86
            match ('-');
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    87
            term ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    88
            printf ("%s", compile_mode == MODE_POSTFIX ? "-" : "\tPOP B\n\tPOP A\n\tSUB A, B\n\tPUSH A\n");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    89
            break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    90
        default:
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    91
            return;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    92
        }
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    93
    }
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    94
}
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    95
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    96
int main (int argc, char **argv)
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    97
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    98
    printf ("Bitte geben Sie einen Ausdruck in Infix-Notation ein:\n\n\t");
31
c95a6a7e305c wiki synchronisation
Markus Bröker <mbroeker@largo.dyndns.tv>
parents: 30
diff changeset
    99
    fgets (expression, MAX, stdin);
30
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   100
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   101
    printf ("\nCompilierter Ausdruck in Postfix-Notation:\n\n\t");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   102
    compile_mode = MODE_POSTFIX;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   103
    pos = 0;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   104
    lookahead = *expression;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   105
    expr ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   106
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   107
    printf ("\n\nCompilierter Ausdruck in Assemblersprache:\n\n");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   108
    compile_mode = MODE_ASSEMBLY;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   109
    pos = 0;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   110
    lookahead = *expression;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   111
    expr ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   112
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   113
    return 0;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   114
}