-
-
Notifications
You must be signed in to change notification settings - Fork 134
Open
Description
The state machine based solution is easy-to-understood.
#include <stdio.h>
/**
* An improved version of a comment-removal program, inspired by K&R Exercise 1-23.
*
* This version uses an explicit state machine, which is a more standard and
* extensible pattern for this kind of parsing, while retaining the concise and
* clever style of the original. It also adds support for // line comments.
*/
// State definitions
#define NORMAL 0
#define SAW_SLASH 1 // State: Just saw a '/', might be a comment.
#define IN_BLOCK_COMMENT 2
#define SAW_ASTERISK 3 // State: Inside a block comment, just saw a '*'.
#define IN_LINE_COMMENT 4
#define IN_STRING 5
#define SAW_ESCAPE_IN_STRING 6
#define IN_CHAR 7
#define SAW_ESCAPE_IN_CHAR 8
int main() {
int c;
int state = NORMAL;
while ((c = getchar()) != EOF) {
if (state == NORMAL) {
if (c == '/') {
state = SAW_SLASH;
} else if (c == '"') {
putchar(c);
state = IN_STRING;
} else if (c == '\'') {
putchar(c);
state = IN_CHAR;
} else {
putchar(c);
}
} else if (state == SAW_SLASH) {
if (c == '*') {
state = IN_BLOCK_COMMENT;
} else if (c == '/') {
state = IN_LINE_COMMENT;
} else {
putchar('/'); // It was just a division operator.
putchar(c);
state = NORMAL;
}
} else if (state == IN_BLOCK_COMMENT) {
if (c == '*') {
state = SAW_ASTERISK;
}
} else if (state == SAW_ASTERISK) {
if (c == '/') {
state = NORMAL;
} else if (c != '*') {
state = IN_BLOCK_COMMENT; // False alarm.
}
// if c is '*', stay in this state (e.g. /*******/)
} else if (state == IN_LINE_COMMENT) {
if (c == '\n') {
putchar(c);
state = NORMAL;
}
} else if (state == IN_STRING) {
putchar(c);
if (c == '\\') {
state = SAW_ESCAPE_IN_STRING;
} else if (c == '"') {
state = NORMAL;
}
} else if (state == SAW_ESCAPE_IN_STRING) {
putchar(c);
state = IN_STRING;
} else if (state == IN_CHAR) {
putchar(c);
if (c == '\\') {
state = SAW_ESCAPE_IN_CHAR;
} else if (c == '\'') {
state = NORMAL;
}
} else if (state == SAW_ESCAPE_IN_CHAR) {
putchar(c);
state = IN_CHAR;
}
}
return 0;
}
Metadata
Metadata
Assignees
Labels
No labels