귀속 하강 분석법 기반 자체 계산기
//main.cpp
#include
#include
#include "token.h"
#include "lexicalanalyzer.cpp"
#define LINE_BUF_SIZE (1024)
static Token st_look_ahead_token;
static int st_look_ahead_token_exists;
static void
my_get_token(Token *token)
{
if (st_look_ahead_token_exists) {
*token = st_look_ahead_token;
st_look_ahead_token_exists = 0;
} else {
get_token(token);
}
}
static void
unget_token(Token *token)
{
st_look_ahead_token = *token;
st_look_ahead_token_exists = 1;
}
double parse_expression(void);
static double
parse_primary_expression()
{
Token token;
my_get_token(&token);
if (token.kind == NUMBER_TOKEN) {
return token.value;
}
fprintf(stderr, "syntax error.
");
exit(1);
return 0.0; /* make compiler happy */
}
static double
parse_term()
{
double v1;
double v2;
Token token;
v1 = parse_primary_expression();
for (;;) {
my_get_token(&token);
if (token.kind != MUL_OPERATOR_TOKEN
&& token.kind != DIV_OPERATOR_TOKEN) {
unget_token(&token);
break;
}
v2 = parse_primary_expression();
if (token.kind == MUL_OPERATOR_TOKEN) {
v1 *= v2;
} else if (token.kind == DIV_OPERATOR_TOKEN) {
v1 /= v2;
}
}
return v1;
}
double
parse_expression()
{
double v1;
double v2;
Token token;
v1 = parse_term();
for (;;) {
my_get_token(&token);
if (token.kind != ADD_OPERATOR_TOKEN
&& token.kind != SUB_OPERATOR_TOKEN) {
unget_token(&token);
break;
}
v2 = parse_term();
if (token.kind == ADD_OPERATOR_TOKEN) {
v1 += v2;
} else if (token.kind == SUB_OPERATOR_TOKEN) {
v1 -= v2;
} else {
unget_token(&token);
}
}
return v1;
}
double
parse_line(void)
{
double value;
st_look_ahead_token_exists = 0;
value = parse_expression();
return value;
}
int
main(int argc, char **argv)
{
char line[LINE_BUF_SIZE];
double value;
while (fgets(line, LINE_BUF_SIZE, stdin) != NULL) {
set_line(line);
value = parse_line();
printf(">>%f
", value);
}
return 0;
}
//lexicalanalyzer.cpp
#include
#include
#include
#include "token.h"
static char *st_line;
static int st_line_pos;
typedef enum {
INITIAL_STATUS,
IN_INT_PART_STATUS,
DOT_STATUS,
IN_FRAC_PART_STATUS
} LexerStatus;
void
get_token(Token *token)
{
int out_pos = 0;
LexerStatus status = INITIAL_STATUS;
char current_char;
token->kind = BAD_TOKEN;
while (st_line[st_line_pos] != '\0') {
current_char = st_line[st_line_pos];
if ((status == IN_INT_PART_STATUS || status == IN_FRAC_PART_STATUS)
&& !isdigit(current_char) && current_char != '.') {
token->kind = NUMBER_TOKEN;
sscanf(token->str, "%lf", &token->value);
return;
}
if (isspace(current_char)) {
if (current_char == '
') {
token->kind = END_OF_LINE_TOKEN;
return;
}
st_line_pos++;
continue;
}
if (out_pos >= MAX_TOKEN_SIZE-1) {
fprintf(stderr, "token too long.
");
exit(1);
}
token->str[out_pos] = st_line[st_line_pos];
st_line_pos++;
out_pos++;
token->str[out_pos] = '\0';
if (current_char == '+') {
token->kind = ADD_OPERATOR_TOKEN;
return;
} else if (current_char == '-') {
token->kind = SUB_OPERATOR_TOKEN;
return;
} else if (current_char == '*') {
token->kind = MUL_OPERATOR_TOKEN;
return;
} else if (current_char == '/') {
token->kind = DIV_OPERATOR_TOKEN;
return;
} else if (isdigit(current_char)) {
if (status == INITIAL_STATUS) {
status = IN_INT_PART_STATUS;
} else if (status == DOT_STATUS) {
status = IN_FRAC_PART_STATUS;
}
} else if (current_char == '.') {
if (status == IN_INT_PART_STATUS) {
status = DOT_STATUS;
} else {
fprintf(stderr, "syntax error.
");
exit(1);
}
} else {
fprintf(stderr, "bad character(%c)
", current_char);
exit(1);
}
}
}
void
set_line(char *line)
{
st_line = line;
st_line_pos = 0;
}
#if 0
void
parse_line(char *buf)
{
Token token;
set_line(buf);
for (;;) {
get_token(&token);
if (token.kind == END_OF_LINE_TOKEN) {
break;
} else {
printf("kind..%d, str..%s
", token.kind, token.str);
}
}
}
int
main(int argc, char **argv)
{
char buf[1024];
while (fgets(buf, 1024, stdin) != NULL) {
parse_line(buf);
}
return 0;
}
#endif
//token.h
#ifndef TOKEN_H_INCLUDED
#define TOKEN_H_INCLUDED
typedef enum {
BAD_TOKEN,
NUMBER_TOKEN,
ADD_OPERATOR_TOKEN,
SUB_OPERATOR_TOKEN,
MUL_OPERATOR_TOKEN,
DIV_OPERATOR_TOKEN,
END_OF_LINE_TOKEN
} TokenKind;
#define MAX_TOKEN_SIZE (100)
typedef struct {
TokenKind kind;
double value;
char str[MAX_TOKEN_SIZE];
} Token;
void set_line(char *line);
void get_token(Token *token);
#endif /* TOKEN_H_INCLUDED */
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.