/*  paragrafo 1.9   pagina 31   esercizio 1.24
    Rileva grossolani errori di sintassi dei programmi in C, per esempio l'incoerenza fra parentesi (tonde, quadre e graffe)
    aperte e chiuse. Non tralascia gli apici e le virgolette, le sequenze di controllo e i commenti.
*/
#include <stdio.h>
#define SI 1
#define NO 0
#define MAXPAR 1000 /* numero massimo di parentesi aperte */

int toggle(int);
int remark_remove(char []);

int main() {
    int c1, c2, i, nl, par_err;
    int car_flag = NO;
    int str_flag = NO;
    int esc_flag = NO;
    char par_vec[MAXPAR];
    char next_from_remark[1];
    
    for (i = 0; i < MAXPAR; ++i)
        par_vec[i] = '\0';
    i = 0;
    nl = 0;
    par_err = 0;
    
    if ((c1 = getchar()) != EOF)
    {
        ++nl;
        while ((c2 = getchar()) != EOF)
        {
/* car_flag e str_flag discriminano se e' o non e' LITERAL */
            if (c1 == '"' && car_flag == NO)
                if (esc_flag == NO)
                    str_flag = toggle(str_flag);
                else
                    esc_flag = NO;
            else if (c1 == '\'' && str_flag == NO)
                if (esc_flag == NO)
                    car_flag = toggle(car_flag);
                else
                    esc_flag = NO;
            else if (c1 == '\\' && (str_flag == SI || car_flag == SI))
                esc_flag = toggle(esc_flag);

                else
                    esc_flag = NO;
/* rimozione dei commenti */
            if (c1 == '/' && c2 == '*' && car_flag == NO && str_flag == NO)
            {
                nl = nl + remark_remove(next_from_remark);
                c1 = next_from_remark[0];
            }
            else
            {
/* verifica delle parentesi */
                if (car_flag == NO && str_flag == NO)
                    if ((c1 == '{' || c1 == '[' || c1 == '(') && par_err == NO)
                    {
                        par_vec[i] = c1;
                        ++i;
                    }
                    else
                        if ((c1 == '}' || c1 == ']' || c1 == ')') && par_err == NO)
                            if (--i < 0)
                                par_err = nl;
                            else
                                if (c1 == '}')
                                    if (par_vec[i] != '{')
                                        par_err = nl;
                                    else
                                        par_vec[i] = '\0';
                                else
                                    if (c1 == ']')
                                        if (par_vec[i] != '[')
                                            par_err = nl;
                                        else
                                            par_vec[i] = '\0';
                                    else
                                        if (c1 == ')')
                                            if (par_vec[i] != '(')
                                                par_err = nl;
                                            else
                                                par_vec[i] = '\0';
                
                putchar(c1);
/* incrementa e scrive i numeri di riga di programma */
                if (c1 == '\n')
                    printf("%3d:: ", ++nl);
                c1 = c2;
            }
        }
    }
    if (c1 != EOF)
        putchar(c1);
    if (c1 != '\n')
        putchar('\n');
    
    if (i < 0)
        printf("TROPPE PARENTESI CHIUSE\n");
    else
        if (i > 0)
            printf("CHIUDERE LE PARENTESI \"%s\"\n", par_vec);
    if (par_err != 0)
        printf("ERRORE DI PARENTESI ALLA RIGA %d\n", par_err);
    if (car_flag == SI)
        printf("APICI DISPARI\n");
    if (str_flag == SI)
        printf("VIRGOLETTE DISPARI\n");
    return 0;
}

int toggle(int status) {
    if (status == NO)
        return SI;
    else
        return NO;
}

int remark_remove(char c[]) {
    int star, slash, newline;
    
    newline = 0;
    if ((star = getchar()) != EOF)
        while ((slash = getchar()) != EOF)
            if (star == '*' && slash == '/')
            {
                c[0] = getchar();
                return newline;
            }
            else
            {
                if (star == '\n')
                    ++newline;
                star = slash;
            }
    c[0] = '\a';
    return newline;
}