Następujący program implementuje bardzo prosty jednoprzebiegowy kompilator napisany w języku C. Ten kompilator kompiluje wyrażenia zdefiniowane w notacji infiksowej do ONP, a także do asemblera. Kompilator realizuje strategię rekurencyjnego zagłębiania się w wyrażenie. Każde wywołanie funkcji odpowiada napotkaniu symbolu nieterminalnegonależącego do gramatyki języka.
#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; }
Przykład możliwego wyjścia, wygenerowanego podczas wykonania powyższego programu:
Please enter an infix-notated expression with single digits: 3-4*2+2 Compiling to postfix-notated expression: 342*-2+ Compiling to assembly-notated machine code: PUSH 3 PUSH 4 PUSH 2 POP B POP A MUL A, B PUSH A POP B POP A SUB A, B PUSH A PUSH 2 POP B POP A ADD A, B PUSH A