閱讀《自製程式語言》之遞迴下降

2021-08-15 13:55:58 字數 4061 閱讀 2054

書中舉了乙個例子來說明語法分析中的下降遞迴,還是計算器。

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語言之遞迴經典問題

目錄 一 十進位制轉換 二 前中序遍歷確定後序遍歷 三 漢諾塔 四 八皇后問題 五 細胞 分治法將原問題劃分為若干個規模較小而結構與原問題相同或相似的子問題,然後分別解決這些子問題,最後合併問題的解即為原問題的解。遞迴很適合實現分治思想,遞迴的邏輯中有兩個重要概念 遞迴邊界和遞迴式。十進位制數遞迴轉...