YACC 只是一個(gè)語(yǔ)法分析器,它需要一個(gè)詞法分析器對(duì)其進(jìn)行分析的。如果你想要用 yacc 進(jìn)行語(yǔ)法分析,除了 yacc 自己之外,還需要如下幾個(gè)函數(shù):
1. int yylex();
這個(gè)函數(shù)提供的是語(yǔ)法分析器,它的返回值必須是一個(gè) token,也就是 %token 定義的那些非終結(jié)符對(duì)應(yīng)的編號(hào)(由 yacc 生成,并輸出到 y.tab.h 里,使用的時(shí)候記得在 yylex() 函數(shù)的實(shí)現(xiàn)文件中包含 y.tab.h)。
2. int yyerror(const char* msg);
這個(gè)函數(shù)負(fù)責(zé)在發(fā)現(xiàn)語(yǔ)法錯(cuò)誤的時(shí)候打印錯(cuò)誤信息,它的形式說(shuō)明了一切,我就不多說(shuō)了。
3. int yywrap();
這個(gè)函數(shù)通常是在你使用 flex 生成詞法分析器的時(shí)候需要提供的,我記得是用來(lái)給 flex 設(shè)置調(diào)試信息的開關(guān)。如果其返回真值則關(guān)閉調(diào)試信息,反之,如果返回假值則打開調(diào)試信息。如果你是用自己寫的 yylex(),那么這個(gè)函數(shù)就不需要了。
另外需要注意的是,上面三個(gè)函數(shù)中的 yy 前綴實(shí)際上是與 yacc 中的 yyparse()等函數(shù)的前綴保持一致的。如果你在命令行上使用 -p 選項(xiàng)把 yy 前綴給改了(比如說(shuō),xx),那么以上三個(gè)函數(shù)的前綴也要改掉(xxlex()、xxerror()、xxwrap())。
如果你打算寫一個(gè)語(yǔ)法分析器,并且其詞法非常復(fù)雜,那么最好使用 flex 和 yacc 搭配,用 flex 處理詞法問(wèn)題(雖然 flex 2.5.4 生成的代碼好象有一個(gè)內(nèi)存泄漏錯(cuò)誤,不過(guò)不妨事)。如果詞法很簡(jiǎn)單,那么可以自己寫 yylex() 處理詞法分析。關(guān)于 yylex() 的規(guī)范嘛,請(qǐng)參考 flex 文檔。