0、準備工作
token.h檔案
#ifndef token_h
#define token_h
typedef enum tokenkind; // 詞的型別
#define max_token_leng 1000
typedef struct token; // 詞節點的資訊
void get_token(token *token);
#endif // !token_h
1、詞法分析
分割單詞,主要是要識別出數值和加減乘除。這個應該比較容易,就直接上**了。
static char *st_line; // 讀取一行
static int st_line_pos; // 游標,表示解析到的位置
typedef enum lexerstatus;
void get_token(token * token)
if(isspace(st_line[st_line_pos] ))
st_line_pos++;
continue; }
if (token_str_length >= (max_token_leng - 1)) /* 如果詞的大小等於大於最大的設定大小 */
token->str[token_str_length] = st_line[st_line_pos];
token_str_length++;
st_line_pos++;
token->str[token_str_length] = '\0';
if (ch == '+')
else if (ch == '-')
else if (ch == '*')
else if (ch == '/')
else if (isdigit(ch)) // 是數字
else if (status == dot_status)
} else if (ch == '.')
else
} else
} }void set_line(char *line)
2、語法分析
這裡使用了遞迴下降的分析方法。yacc版的計算器曾經使用下面演算法
exp // 表示式規則
:term
|exp add term
|exp sub term
;term //表示式規則
:primary_exp
|term mul primary_exp
|term div primary_exp
;primary_exp // 一元表示式的規則
:double_literal
;1).每個非終結符構造乙個分析函式
2).用前看符號指導產生式規則的選擇
static token st_look_ahead_token;
static int st_look_ahead_token_exists;
static void my_get_token(token * token)
else /* 獲得新的詞 */
} static void unget_token(token *token)
static double parse_primary_expression()
fprintf(stderr, "syntax error");
exit(1);
return 0.0;
} static double parse_term()
v2 = parse_primary_expression(); /* 獲得乘除的詞 */
if (token.kind == mul)
else if (token.kind == div)
}while (1);
return v1;
} double parse_expression()
v2 = parse_term(); /* 獲得加減的詞 */
if (token.kind == add)
else if (token.kind == sub)
else
} while (1);
return v1;
}double parse_line()
3、整合** 檔案analyse.c
#include
#include
#include"token.h"
#include
static char *st_line; // 讀取一行
static int st_line_pos; // 游標,表示解析到的位置
static token st_look_ahead_token;
static int st_look_ahead_token_exists;
static void my_get_token(token * token)
else /* 獲得新的詞 */
} static void unget_token(token *token)
static double parse_primary_expression()
fprintf(stderr, "syntax error");
exit(1);
return 0.0; }
static double parse_term()
v2 = parse_primary_expression(); /* 獲得乘除的詞 */
if (token.kind == mul)
else if (token.kind == div)
}while (1);
return v1; }
double parse_expression()
v2 = parse_term(); /* 獲得加減的詞 */
if (token.kind == add)
else if (token.kind == sub)
else
} while (1);
return v1; }
double parse_line()
typedef enum lexerstatus;
void get_token(token * token)
if (isspace(st_line[st_line_pos]))
st_line_pos++;
continue; }
if (token_str_length >= (max_token_leng - 1)) /* 如果詞的大小等於大於最大的設定大小 */
token->str[token_str_length] = st_line[st_line_pos];
token_str_length++;
st_line_pos++;
token->str[token_str_length] = '\0';
if (ch == '+')
else if (ch == '-')
else if (ch == '*')
else if (ch == '/')
else if (isdigit(ch)) // 是數字
else if (status == dot_status)
} else if (ch == '.')
else
} else
} }
void set_line(char *line)
int main()
return 0; }
——————————————————————我是分界線———————————————
C語言之閱讀順序
problem description 大多數語言是從左向右讀的。但是,在一些語言中,閱讀順序是從右向左讀的。這給語言交流增加了不少的麻煩。現在,請你編寫乙個程式,能夠將一從左到右書寫的文字自動轉成從右向左的順序。input 輸入的第一行是乙個數字n n 100 接下來的有n行的文字,由字母 空格 ...
C語言 之遞迴函式
今天來總結一下關於遞迴函式的使用方面的問題。遞迴函式就是在函式使用的時候自己呼叫自己,層層呼叫,來實現你想要的功能。有兩個最常用的例子,我們來寫一下。1 計算階乘 include int factorial int n 函式宣告 階乘 int main void int a 5 printf d的階...
C語言之遞迴經典問題
目錄 一 十進位制轉換 二 前中序遍歷確定後序遍歷 三 漢諾塔 四 八皇后問題 五 細胞 分治法將原問題劃分為若干個規模較小而結構與原問題相同或相似的子問題,然後分別解決這些子問題,最後合併問題的解即為原問題的解。遞迴很適合實現分治思想,遞迴的邏輯中有兩個重要概念 遞迴邊界和遞迴式。十進位制數遞迴轉...