功能:计算四则运算表达式,支持括号,加减乘除,负数
代码如下:
//#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, LEFT_PAREN_TOKEN, RIGHT_PAREN_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 */
//#parser.c# #include <stdio.h> #include <stdlib.h> #include "token.h" #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; double value = 0.0; int minus_flag = 0; my_get_token(&token); if (token.kind == SUB_OPERATOR_TOKEN) { minus_flag = 1; } else { unget_token(&token); } my_get_token(&token); if (token.kind == NUMBER_TOKEN) { value = token.value; } else if (token.kind == LEFT_PAREN_TOKEN) { value = parse_expression(); my_get_token(&token); if (token.kind != RIGHT_PAREN_TOKEN) { fprintf(stderr, "missing ')' error. "); exit(1); } } else { unget_token(&token); } if (minus_flag) { value = -value; } return value; } 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) { time_t time_start = time(NULL); set_line(line); value = parse_line(); time_t time_end = time(NULL); printf(">>%f,time:%f. ", value, difftime(time_end, time_start)); } return 0; }
//#lexicalanalyzer.c# #include <stdio.h> #include <stdlib.h> #include <ctype.h> #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] != '