本文例子來自於 <> 第二版
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
symbol.c#define nsyms 1024 /* maximum number of symbols */
struct symtab symtab[nsyms];
struct symtab *symlook(char* s);
calc.l#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.y%
%%([0-9]+|([0-9]*\.[0-9]+)([ee][-+]?[0-9]+)?)
[ \t] ; /* ignore white space */
[a-za-z][a-za-z0-9]*
"$"
\n |
. return yytext[0];
%%
%
%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...