Page 34
Write a program to check a C program for rudimentary syntax errors like unbalanced parentheses, brackets and braces. Don't forget about quotes, both single and double, escape sequences, and comments. (This program is hard if you do it in full generality.)
#include <stdio.h>
#include <stdbool.h>
/* Parentheses ()
* Brackets []
* Braces {}
* Single quotes ''
* Double quotes ""
* Escape sequences \c
* Single line comments /*
* Multiline comments /* */
int main()
{
int c, prev_c, prev_prev_c;
int paren_level = 0;
int bracket_level = 0;
int brace_level = 0;
bool in_sglquote = false;
bool in_dblquote = false;
bool in_singleline_comment = false;
bool in_multiline_comment = false;
while ((c = getchar()) != EOF) {
bool in_quote = in_sglquote || in_dblquote;
bool is_esc = prev_c == '\\' && prev_prev_c != '\\';
if (in_singleline_comment) {
if (c == '\n') {
in_singleline_comment = false;
}
} else if (in_multiline_comment) {
if (prev_c == '*' && c == '/') {
in_multiline_comment = false;
}
} else if (!is_esc) {
if (!in_quote) {
if (c == '(') {
paren_level++;
} else if (c == ')') {
paren_level--;
} else if (c == '[') {
bracket_level++;
} else if (c == ']') {
bracket_level--;
} else if (c == '{') {
brace_level++;
} else if (c == '}') {
brace_level--;
} else if (prev_c == '/' && c == '/') {
in_singleline_comment = true;
} else if (prev_c == '/' && c == '*') {
in_multiline_comment = true;
}
}
if (c == '\'' && !in_dblquote) {
in_sglquote = !in_sglquote;
} else if (c == '"' && !in_sglquote) {
in_dblquote = !in_dblquote;
}
}
prev_prev_c = prev_c;
prev_c = c;
}
int exit_code = 0;
if (paren_level != 0) {
printf("%d mismatched parens!\n", paren_level);
exit_code++;
}
if (bracket_level != 0) {
printf("%d mismatched brackets!\n", bracket_level);
exit_code++;
}
if (brace_level != 0) {
printf("%d mismatched braces!\n", brace_level);
exit_code++;
}
if (in_sglquote) {
printf("Unterminated single quote!\n");
exit_code++;
}
if (in_dblquote) {
printf("Unterminated double quote!\n");
exit_code++;
}
/* No need to complain about single line comment */
if (in_multiline_comment) {
printf("Unterminated multiline comment!\n");
exit_code++;
}
return exit_code;
}