1-24 chk_paren.c

テーブルだらけだなぁ、なんか。

/*
 * P42 演習1-24
 *   カッコ、中カッコ、大カッコのつりあいがとれていないといった
 *   プログラムの基本的な構文エラーのチェックを行うプログラムを書け。
 *   引用符・2重引用符・コメントなどの処理も忘れないこと。(このプログラム
 *   を完全に汎用的にしようとすると、これを書くのは難しくなる。)
 *
 *         2007/06/17 arikui
 */


#include <stdio.h>

#define PAREN   0
#define BRACE   1
#define BRACKET 2
#define NUM_OF_KINDS_OF_PAREN 3

#define NUM_OF_CHARSET 128

#define TRUE  1
#define FALSE 0

#define BUFF_EMPTY  -64

int buff = BUFF_EMPTY;

int readchar(void){
    int c;
    if (buff == BUFF_EMPTY){
        c = getchar();
    }else{
        c = buff;
        buff = BUFF_EMPTY;
    }
    return c;
}

void unreadchar(int c){
    buff = c;
}



void flush_comment_rest(int print_p){
    int c, t;
    
    while((c = readchar()) != EOF){
        if (print_p) putchar(c);
        if (c == '*'){
            t = readchar();
            if (t == '/') break;
            else unreadchar(t);
        }
    }
    
    if (c == EOF) unreadchar(c);
}


void flush_quotation_rest(int print_p, int q){
    int c;
    while((c = readchar()) != EOF){
        if (print_p) putchar(c);
        if (c == '\\'){
            c = readchar();
            if (c == EOF) break;
            if (print_p) putchar(c);
        }else if (c == q) break;
    }
    
    if (c == EOF) unreadchar(c);
}



int main(void){
    int c, t, i, fl_error, count[NUM_OF_KINDS_OF_PAREN] = {0};
    int paren_index_table[NUM_OF_CHARSET] = {0};
    char *index_paren_desc_table[NUM_OF_KINDS_OF_PAREN];
    
    paren_index_table['('] = paren_index_table[')'] = PAREN;
    paren_index_table['{'] = paren_index_table['}'] = BRACE;
    paren_index_table['['] = paren_index_table[']'] = BRACKET;
    
    index_paren_desc_table[PAREN] = "parenthesis";
    index_paren_desc_table[BRACE] = "brace";
    index_paren_desc_table[BRACKET] = "bracket";
    
    
    while((c = readchar()) != EOF){
        if (c == '\\'){
            if ((t = readchar()) == EOF) unreadchar(t);
        }else if (c == '\'' || c == '"'){
            flush_quotation_rest(FALSE, c);
        }else if (c == '/'){
            t = readchar();
            if (t == '*') flush_comment_rest(FALSE);
                else unreadchar(t);
        }else if (c == '(' || c == '{' || c == '['){
            ++count[paren_index_table[c]];
        }else if (c == ')' || c == '}' || c == ']'){
            --count[paren_index_table[c]];
        }
    }
    
    
    for(fl_error = FALSE, i = 0; i < NUM_OF_KINDS_OF_PAREN; ++i){
        if (count[i] != 0){
            printf("Syntax error: %s not balanced -- left %s %d\n",
                   index_paren_desc_table[i],
                   index_paren_desc_table[i],
                   count[i]);
            fl_error = TRUE;
        }
    }
    
    if (!fl_error) printf("Syntax OK\n");
    return 0;
}