recursive_compiler.c
author Markus Bröker <mbroeker@largo.dyndns.tv>
Thu, 16 Apr 2009 12:49:04 +0200
changeset 30 d037c433ec3e
child 31 c95a6a7e305c
permissions -rw-r--r--
kleiner auffschrischungskurs compilerbau... 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
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
     3
 *
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
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    12
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    13
char lookahead;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    14
int pos;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    15
int compile_mode;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    16
char expression[20 + 1];
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    17
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    18
void error ()
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    19
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    20
    printf ("Syntaxfehler!\n");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    21
}
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
void match (char t)
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    24
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    25
    if (lookahead == t) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    26
        lookahead = expression[++pos];
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    27
    } else
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    28
        error ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    29
}
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
void digit ()
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    32
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    33
    switch (lookahead) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    34
    case '0':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    35
    case '1':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    36
    case '2':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    37
    case '3':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    38
    case '4':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    39
    case '5':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    40
    case '6':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    41
    case '7':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    42
    case '8':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    43
    case '9':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    44
        printf (compile_mode == MODE_POSTFIX ? "%c" : "\tPUSH %c\n", lookahead);
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    45
        match (lookahead);
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    46
        break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    47
    default:
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    48
        error ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    49
        break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    50
    }
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
void term ()
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    54
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    55
    digit ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    56
    while (1) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    57
        switch (lookahead) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    58
        case '*':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    59
            match ('*');
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    60
            digit ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    61
            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
    62
            break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    63
        case '/':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    64
            match ('/');
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    65
            digit ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    66
            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
    67
            break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    68
        default:
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    69
            return;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    70
        }
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
void expr ()
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    75
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    76
    term ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    77
    while (1) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    78
        switch (lookahead) {
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    79
        case '+':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    80
            match ('+');
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    81
            term ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    82
            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
    83
            break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    84
        case '-':
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    85
            match ('-');
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    86
            term ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    87
            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
    88
            break;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    89
        default:
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    90
            return;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    91
        }
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
int main (int argc, char **argv)
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    96
{
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    97
    printf ("Bitte geben Sie einen Ausdruck in Infix-Notation ein:\n\n\t");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    98
    fgets (expression, 20, stdin);
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
    99
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   100
    printf ("\nCompilierter Ausdruck in Postfix-Notation:\n\n\t");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   101
    compile_mode = MODE_POSTFIX;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   102
    pos = 0;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   103
    lookahead = *expression;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   104
    expr ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   105
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   106
    printf ("\n\nCompilierter Ausdruck in Assemblersprache:\n\n");
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   107
    compile_mode = MODE_ASSEMBLY;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   108
    pos = 0;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   109
    lookahead = *expression;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   110
    expr ();
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   111
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   112
    return 0;
d037c433ec3e kleiner auffschrischungskurs compilerbau...
Markus Bröker <mbroeker@largo.dyndns.tv>
parents:
diff changeset
   113
}