#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
// enum 대신 define 활용
#define NUMBER 256
#define PLUS 257
#define STAR 258
#define LPAREN 259
#define RPAREN 260
#define END 261
#define MINUS 262
#define DIV 263
#define ACC 999
// 숫자 저장용
char yytext[100];
// token의 타입
typedef enum
{
// 정수 및 실수
INT,
FLT
} kind;
struct number
{
kind t;
union
{
int i;
float f;
} val;
};
int token;
struct number num;
struct number expression();
struct number term();
struct number factor();
int yylex();
void yyerror();
void lex_error();
void warning();
void main()
{
struct number result;
token = yylex(); // get_token() 대신 yylex() 사용
result = expression();
if (token != END)
yyerror(3);
else
{
if (result.t == INT)
printf("%d \n", result.val.i);
else
printf("%f \n", result.val.f);
}
}
struct number expression()
{
struct number result, tmp_term;
result = term();
while (token == PLUS || token == MINUS)
{
int operation = token;
token = yylex(); // get_token() 대신 yylex() 사용
tmp_term = term();
if (result.t == INT && tmp_term.t == INT)
{
if (operation == PLUS)
result.val.i = result.val.i + tmp_term.val.i;
else
result.val.i = result.val.i - tmp_term.val.i;
}
else
{
if (result.t == INT)
{
warning();
result.val.f = (float)result.val.i;
}
if (tmp_term.t == INT)
{
warning();
tmp_term.val.f = (float)tmp_term.val.i;
}
if (operation == PLUS)
result.val.f = result.val.f + tmp_term.val.f;
else
result.val.f = result.val.f - tmp_term.val.f;
result.t = FLT;
}
}
return result;
}
struct number term()
{
struct number result, tmp_factor;
result = factor();
while (token == STAR || token == DIV)
{
int operation = token;
token = yylex(); // get_token() 대신 yylex() 사용
tmp_factor = factor();
if (result.t == INT && tmp_factor.t == INT)
{
if (operation == STAR)
result.val.i = result.val.i * tmp_factor.val.i;
else
result.val.i = result.val.i / tmp_factor.val.i;
}
else
{
if (result.t == INT)
{
warning();
result.val.f = (float)result.val.i;
}
if (tmp_factor.t == INT)
{
warning();
tmp_factor.val.f = (float)tmp_factor.val.i;
}
if (operation == STAR)
result.val.f = result.val.f * tmp_factor.val.f;
else
result.val.f = result.val.f / tmp_factor.val.f;
result.t = FLT;
}
}
return result;
}
struct number factor()
{
struct number result;
if (token == NUMBER)
{
if (num.t == INT)
{
result.t = INT;
result.val.i = num.val.i;
}
else
{
result.t = FLT;
result.val.f = num.val.f;
}
token = yylex(); // get_token() 대신 yylex() 사용
}
else if (token == LPAREN)
{
token = yylex(); // get_token() 대신 yylex() 사용
result = expression();
if (token == RPAREN)
token = yylex(); // get_token() 대신 yylex() 사용
else
yyerror(2);
}
else
{
yyerror(1);
}
return result;
}
// get_token() 대신 yylex()로 수정
int yylex()
{
static char ch = ' ';
while (ch == ' ' || ch == '\t')
ch = getchar();
int i = 0, isFloat = 0;
if (isdigit(ch) || ch == '.')
{
do
{
if (ch == '.')
{
if (isFloat) // 이미 한번 .을 발견한 경우
lex_error();
isFloat = 1;
}
yytext[i++] = ch;
ch = getchar();
} while (isdigit(ch) || ch == '.');
yytext[i] = 0;
if (isFloat)
{
num.t = FLT;
num.val.f = atof(yytext);
}
else
{
num.t = INT;
num.val.i = atoi(yytext);
}
return (NUMBER);
}
else if (ch == '+')
{
ch = getchar();
return (PLUS);
}
else if (ch == '*')
{
ch = getchar();
return (STAR);
}
else if (ch == '(')
{
ch = getchar();
return (LPAREN);
}
else if (ch == ')')
{
ch = getchar();
return (RPAREN);
}
else if (ch == '-')
{
ch = getchar();
return (MINUS);
}
else if (ch == '/')
{
ch = getchar();
return (DIV);
}
else if (ch == EOF || ch == '\n')
return (END);
else
lex_error();
}
void yyerror(int i)
{
switch (i)
{
case 1:
printf("Error: expected a number or a left parenthesis\n");
break;
case 2:
printf("Error: expected a right parenthesis\n");
break;
case 3:
printf("Error: expected end of input\n");
break;
}
exit(1);
}
void lex_error()
{
printf("Error: bad character\n");
exit(1);
}
void warning()
{
// 혼합연산
printf("Warning: mixed operation with float and int\n");
}
카테고리 없음
댓글