Calculator, lexer and parser

This commit is contained in:
Imbus 2025-05-23 00:31:37 +02:00
parent 749c09d78f
commit 329692f2b3

129
calc.c Normal file
View file

@ -0,0 +1,129 @@
#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;
}