Calculator, lexer and parser
This commit is contained in:
parent
749c09d78f
commit
329692f2b3
1 changed files with 129 additions and 0 deletions
129
calc.c
Normal file
129
calc.c
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue