Parser?!



  • Hallo,

    ich arbeite gerade an einem TR/Matheprogramm und wüsste gernen ob mir jmd helfen könnte.
    Mein Tr soll Kettenrechnungen durchführen können.

    Einziges Problem: Die Vorrangregel von / und *.

    Ich hab schon einen Algo entworfen der diese Form (3 Zahlen, zwei Rechenzeichen) in einer Schleife berechnet.

    3+5/4

    (dann nächstes scanf und if anweisungen)

    Einziges Porblem was ich nicht bedacht habe:

    Was ist wenn als nächstes eine weiteres / oder * kommt haben diese wieder Vorrang.

    Es würde ja gehen nur ich weiss ja nicht wieviele werte eingelesen werden.

    Bitte dringend um Hilfe, wäre sehr nett.

    Thx



  • Beim Parsen würde ich über binäre Bäume gehen. Eine halbwegs brauchbare Implementierung in C kannst Du unter http://www.staff.ncl.ac.uk/d.j.wilkinson/software/meparse.tgz finden.



  • hallo muhi,

    hier ein kleiner Compiler, der eigentlich genau das tut was du brauchst:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #define MODE_POSTFIX    0
    #define MODE_ASSEMBLY   1
    
    char    lookahead;
    int     pos;
    int     compile_mode;
    char    expression[20+1];
    
    void error()
    {
            printf("Syntax error!\n");
    }
    
    void match( char t )
    {
            if( lookahead == t )
            {
                    pos++;
                    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':
                            if( compile_mode == MODE_POSTFIX )
                                    printf("%c", lookahead);
                            else
                                    printf("\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("Please enter an infix-notated expression with single digits:\n\n\t");
            scanf("%20s", expression);
    
            printf("\nCompiling to postfix-notated expression:\n\n\t");   
            compile_mode = MODE_POSTFIX;
            pos = 0;
            lookahead = *expression;
            expr();
    
            printf("\n\nCompiling to assembly-notated machine code:\n\n");        
            compile_mode = MODE_ASSEMBLY;
            pos = 0;
            lookahead = *expression;
            expr();
    
            return 0;
    }
    

Anmelden zum Antworten