helloJSON/fsm.c
2023-06-12 23:59:21 +01:00

168 lines
3.3 KiB
C

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define ARR_LEN(X) (sizeof(X) / sizeof(X[0]))
typedef enum {
START_STATE,
DECIMAL_STATE,
NUM_STATE,
FRACTION_STATE,
EXPONENT_STATE,
EXP_SIGN_STATE,
POWER_STATE,
END_STATE,
INVALID_STATE,
} states;
states handle_start(char input);
states handle_decimal(char input);
states handle_num(char input);
states handle_fraction(char input);
states handle_exponent(char input);
states handle_exp_sign(char input);
states handle_power(char input);
states state_machine(states current, char input);
bool check_number(const char *num);
const char *inputs[] = {
"0000000", // INVALID
"01", // INVALID
"f0", // INVALID
"1f", // INVALID
"1.f", // INVALID
"1.0f", // INVALID
"8987", // VALID
"9.5", // VALID
" 7", // VALID
" 7.8", // VALID
"732.9834e", // INVALID
"732.9834e-", // INVALID
"732.9834e+", // INVALID
"732.9834e-g", // INVALID
"732.9834e-8", // VALID
"732.9834e+8", // VALID
};
int main(int argc, char *argv[]) {
for (int i = 0; i < ARR_LEN(inputs); ++i) {
printf("%s is %s\n", inputs[i],
check_number(inputs[i]) ? "VALID" : "INVALID");
}
return EXIT_SUCCESS;
}
states handle_start(char input) {
if (isspace(input)) {
return START_STATE;
} else if (input == '0') {
return DECIMAL_STATE;
} else if (isdigit(input)) {
return NUM_STATE;
}
return INVALID_STATE;
}
states handle_decimal(char input) {
if (input == '.') {
return FRACTION_STATE;
}
return INVALID_STATE;
}
states handle_num(char input) {
if (isdigit(input)) {
return NUM_STATE;
} else if (input == '.') {
return FRACTION_STATE;
} else if (isspace(input)) {
return END_STATE;
}
return INVALID_STATE;
}
states handle_fraction(char input) {
if (isdigit(input)) {
return FRACTION_STATE;
} else if (isspace(input)) {
return END_STATE;
} else if (input == 'e' || input == 'E') {
return EXPONENT_STATE;
}
return INVALID_STATE;
}
states handle_exponent(char input) {
if (isdigit(input)) {
return POWER_STATE;
} else if (input == '+' || input == '-') {
return EXP_SIGN_STATE;
}
return INVALID_STATE;
}
states handle_exp_sign(char input) {
if (isdigit(input)) {
return POWER_STATE;
}
return INVALID_STATE;
}
states handle_power(char input) {
if (isdigit(input)) {
return POWER_STATE;
} else if (isspace(input)) {
return END_STATE;
}
return INVALID_STATE;
}
states state_machine(states current, char input) {
switch (current) {
case START_STATE:
return handle_start(input);
case DECIMAL_STATE:
return handle_decimal(input);
case NUM_STATE:
return handle_num(input);
case FRACTION_STATE:
return handle_fraction(input);
case EXPONENT_STATE:
return handle_exponent(input);
case EXP_SIGN_STATE:
return handle_exp_sign(input);
case POWER_STATE:
return handle_power(input);
case END_STATE:
case INVALID_STATE:
return current;
}
}
bool check_number(const char *num) {
states current = START_STATE;
for (const char *c = &(num[0]); *c != '\0'; ++c) {
current = state_machine(current, *c);
if (current == INVALID_STATE) {
return false;
}
}
return current == END_STATE || current == NUM_STATE ||
current == FRACTION_STATE || current == POWER_STATE;
}