CPlay/calc.c
2025-08-18 14:59:16 +02:00

114 lines
2.4 KiB
C

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
typedef enum { TOKEN_INT, TOKEN_PLUS, TOKEN_MUL, TOKEN_DIV, TOKEN_LPAREN, TOKEN_RPAREN, TOKEN_EOF } TokenType;
typedef struct {
TokenType type;
int value;
} Token;
const char *input;
size_t pos;
Token current_token;
void skip_whitespace() {
while (isspace(input[pos])) pos++;
}
Token get_next_token() {
skip_whitespace();
char ch = input[pos];
if (ch == '\0')
return (Token){TOKEN_EOF, 0};
if (isdigit(ch)) {
int val = 0;
while (isdigit(input[pos])) {
val = val * 10 + (input[pos++] - '0');
}
return (Token){TOKEN_INT, val};
}
pos++;
switch (ch) {
case '+': return (Token){TOKEN_PLUS, 0};
case '*': return (Token){TOKEN_MUL, 0};
case '/': return (Token){TOKEN_DIV, 0};
case '(': return (Token){TOKEN_LPAREN, 0};
case ')': return (Token){TOKEN_RPAREN, 0};
default: fprintf(stderr, "Unexpected character: %c\n", ch); exit(1);
}
}
void eat(TokenType type) {
if (current_token.type == type) {
current_token = get_next_token();
} else {
fprintf(stderr, "Unexpected token\n");
exit(1);
}
}
int expr();
int factor() {
Token tok = current_token;
if (tok.type == TOKEN_INT) {
eat(TOKEN_INT);
return tok.value;
} else if (tok.type == TOKEN_LPAREN) {
eat(TOKEN_LPAREN);
int result = expr();
eat(TOKEN_RPAREN);
return result;
} else {
fprintf(stderr, "Expected integer or '('\n");
exit(1);
}
}
int term() {
int result = factor();
while (current_token.type == TOKEN_MUL) {
eat(TOKEN_MUL);
result *= factor();
}
while (current_token.type == TOKEN_DIV) {
eat(TOKEN_DIV);
result /= factor();
}
return result;
}
int expr() {
int result = term();
while (current_token.type == TOKEN_PLUS) {
eat(TOKEN_PLUS);
result += term();
}
return result;
}
int main() {
char buffer[256];
printf("Enter expression: ");
fgets(buffer, sizeof(buffer), stdin);
input = buffer;
pos = 0;
current_token = get_next_token();
int result = expr();
if (current_token.type != TOKEN_EOF) {
fprintf(stderr, "Unexpected extra input\n");
return 1;
}
printf("Result = %d\n", result);
return 0;
}