115 lines
1.6 KiB
C
115 lines
1.6 KiB
C
/*
|
|
|
|
E ::= T{+T}
|
|
T ::= F{*F}
|
|
F ::= (E)|i
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
|
|
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
|
|
|
|
|
|
typedef enum TokenType {
|
|
INT,
|
|
PLUS,
|
|
MINUS,
|
|
LBRACE,
|
|
RBRACE
|
|
} TokenType;
|
|
|
|
typedef struct _Token {
|
|
TokenType type;
|
|
|
|
int value;
|
|
} Token;
|
|
|
|
|
|
void fatal(const char* message);
|
|
void scan();
|
|
|
|
void e();
|
|
void t();
|
|
void f();
|
|
|
|
|
|
const int LINE_MAX = 1024;
|
|
char *line;
|
|
|
|
int symbol;
|
|
int char_num = 0;
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
|
line = calloc(sizeof(char), LINE_MAX);
|
|
memset(line, 0, LINE_MAX);
|
|
|
|
scan();
|
|
e();
|
|
|
|
if (symbol != '\n') {
|
|
fatal("Syntax invalid");
|
|
}
|
|
|
|
printf("Success\n");
|
|
|
|
free(line);
|
|
return 0;
|
|
}
|
|
|
|
void scan() {
|
|
symbol = getchar();
|
|
if (symbol == '\n')
|
|
line[char_num++] = ' ';
|
|
else
|
|
line[char_num++] = symbol;
|
|
}
|
|
|
|
void e() {
|
|
t();
|
|
while (symbol == '+') {
|
|
scan();
|
|
t();
|
|
}
|
|
}
|
|
|
|
void t() {
|
|
f();
|
|
while (symbol == '*') {
|
|
scan();
|
|
f();
|
|
}
|
|
}
|
|
|
|
void f() {
|
|
if (symbol == '(') {
|
|
scan();
|
|
e();
|
|
if (symbol != ')') {
|
|
fatal("Expected parentheses");
|
|
}
|
|
}
|
|
else if (symbol >= '0' && symbol <= '9') {
|
|
;
|
|
}
|
|
else if (symbol == '\n') {
|
|
fatal("LF too early");
|
|
}
|
|
else {
|
|
fatal("Unexpected symbol");
|
|
}
|
|
scan();
|
|
}
|
|
|
|
void fatal(const char* message) {
|
|
eprintf("\nError at char %d\n%s\n", char_num, line);
|
|
eprintf("%*c\n", char_num, '^');
|
|
eprintf("Message: %s\n", message);
|
|
exit(1);
|
|
}
|