YACC 例項分析

2021-07-29 03:10:24 字數 2756 閱讀 9854



本文例子來自於 <> 第二版

lex 負責詞法分析,每次解析出乙個 token。 

一、 token 的型別和值

token 具有型別,在計算器例子中,包括如下型別:

1)、 number     一串數字

2)、 name         乙個名稱

3)、 '+', '-', '*', '/' 等符號

同時 token 具有值,不同型別的 token, 值的含義不一樣,例如, 

'1000':   型別是 number,值是1000

'abc':     型別是 name, 值是 'abc' 

lex 解析出乙個 token 後,將此 token 的值,儲存在 yylval 變數中, 並將型別返回給 yacc。

為了能儲存不同型別的值, yylval  被定義成 union

%union

其中, dval 儲存 number 型別的值,symp 儲存 name 型別的值。

為了儲存 name 型別的值,定義了乙個結構 

struct symtab

其中 name 記錄了「符號」的名稱,而 value 則用於儲存計算結果,後文再介紹。

name 型別的 token,又被稱為 「符號」, 跟我們寫程式的時候定義的變數作用相同。

因此,當 lex遇到數字串的時候,就把數字串的值儲存到 yylval 的 dval 中,並返回 number 型別。遇到字串的時候,根據字串名稱生成 symtab 結構,儲存其名稱,並將結構的位址儲存到 yylval 的 symp 中,並返回 name 型別。遇到 '+', '-' 等符號的時候,則返回該符號的 ascii 碼值。

二、 yacc 中的計算

在「產生式」 或者「規則」部分,通過 $1, $2, $3 的方式,可獲取對應 token 的值,對這些變數的訪問,實際就是對 yylval 的訪問。此時,yacc 已經知道相應 token 的型別了,因此對 number 型別,token 的值就是 yylval.dval, 對 name 型別, token 的值就是  yylval.symp

例如:

statement:  name '=' expression 

expression:

| number

| name

對於 number, $1 對應的就是數值

對於 name, $1->name 就是符號名稱

非終結符號的型別和值

%type expression

三、 附錄: 原始碼

symbol.h

#define nsyms 1024  /* maximum number of symbols */ 

struct symtab symtab[nsyms];

struct symtab *symlook(char* s);

symbol.c

#include "symbol.h"

#include #include #include #include struct symtab *symlook(char* s)

/* is it free */

if(!sp->name)

/* otherwise continue to next */

}yyerror("too many symbols");

exit(1); /* cannot continue */

} /* symlook */

calc.l

%

%%([0-9]+|([0-9]*\.[0-9]+)([ee][-+]?[0-9]+)?)

[ \t] ; /* ignore white space */

[a-za-z][a-za-z0-9]*

"$"

\n |

. return yytext[0];

%%

calc.y
%

%union

%token name

%token number

%left '-' '+'

%left '*' '/'

%nonassoc uminus

%type expression

%%statement_list: statement '\n'

| statement_list statement '\n'

;statement: name '=' expression

| expression

;expression: expression '+' expression

| expression '-' expression

| expression '*' expression

| expression '/' expression

| '-' expression %prec uminus

| '(' expression ')'

| number

| name

| name '(' expression ')' };

%%

Lex與Yacc學習(九)之Yacc語法

本文討論yacc語法的格式並描述可用的各種特徵和選項 yacc語法包括三部分 定義段 規則段和使用者子例程段 定義段.規則段.使用者子例程段.各部分由以兩個百分號開頭的行分開,儘管某乙個部分可以為空,但是前兩部分是必須的,第三部分和前面的百分號可以省略。yacc 語法由符號組成,即語法的 詞 符號是...

Lex與Yacc學習(十)之Yacc庫

每個實現都需要有用的例程庫,在unix系統中,可以通過cc命令列尾端給出 ly標誌 或通過其他系統下的等價物 來包含庫。庫的內容在不同的實現之間是不同的,但總是包括main 和yyerror yacc的所有版本都帶有最小的主程式,該程式對於簡短程式和測試有時是很有用的,它非常簡單,如下所示 main...

用YACC構造簡單語法分析器

課堂實驗題 說明部分 翻譯規則 用c語言編寫的輔助例程 按照yacc的源程式規則由題中所給文法寫出trans.y token digit line expr n expr expr term expr term term term term factor factor factor expr dig...