為什麼這篇Lex, Yacc鄉民發文收入到精華區:因為在Lex, Yacc這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者ric2k1 (Ric)看板EE_DSnP標題Re: [討論] lex 與 yacc時間Wed ...
※ 引述《ric2k1 (Ric)》之銘言:
※ 引述《WSzc (WSzc)》之銘言:
: ※ 引述《ric2k1 (Ric)》之銘言:
: : 其實學期初有在想這個 HW#6 要來教大家用 lex 跟 yacc,
: : 用它們寫會簡單不少... 不過還是來不及教.
: : 有興趣的人可以去 google 一下簡單的 tutorial,
: : 不過請自行 trade-off 學新東西與用 C++ 硬刻的 efforts.
: : 歡迎發問.
: 請問一下 用lex/yacc寫的話
: 是只要留產生出來的執行檔 然後包在CirRead cmd裡頭嗎?
: (就是在CirRead時 會自動去跑lex/yacc的執行檔嗎) 或是別的執行方式?
不是呼叫執行檔哦 (雖然也是可以啦), 是直接呼叫 yacc 產生出來的 function.
yacc parse 的 entry function 叫做 yyparse().
一個簡單的作法是在你的 CirMgr::readCircuit(const string& fileName) 裡頭:
{
extern FILE* yyin;
extern int yyparse();
extern int parseErrorCount;
if (!(yyin = fopen(fileName.c_str(), "r")))
...
if (yyparse() != 0 || parseErrorCount != 0) return false;
fclose(yyOAin);
}
其中 "yyin" 就是在 yyparse() 裏頭用來讀檔的 file pointer.
而 parseErrorCount 則是我自己加的變數, 用在 yacc file 裏頭計算文法錯誤的
次數.
而在你的 .y 檔裡頭, 你必須:
1. extern 在 lex file 裏頭的變數, 如 yylineno.
2. extern global circuit maganger, 如 cirMgr.
3. 宣告一些 external functions 的 prototypes, 如:
int yylex(void);
extern "C" { int cirwrap() { return 1; } }
4. 宣告一些 parse 過程會用到的 global variables (parse 完要記得 reset).
5. 自訂你想要 yyerror(const char *str) 印出來的格式.
void yyerror(const char *str) { ... }
6. 有些 errors 你可以插在 rules 中間檢查, 但有些 errors 則必須利用 yacc
內定的 token "error" 來檢查. (<== 看不懂就算了)
在你的 .l 檔裡頭, 你必須:
1. 宣告一些 global variables, 如 yylineno.
2. 宣告一些 external functions 的 prototypes, 如:
extern "C" { int cirwrap() { return 1; } }
3. 注意 lex 裏頭的字串 (i.e. yytext) 是 temporary 的, 要傳給 yacc 之前,
記得 allocate memory & then copy, 或是改成 string type.
不過 yacc 裏頭 union {} 不能用 string, 所以我用 string*.
另外你要在 src/cir/Makefile 裡加上幾行來讓 lex/yacc 產生 C/C++ files.
基本上 lex/yacc 產生出來的是 .c files,
你可以 mv y.tab.c yourPreferredName.cpp,
或是像我這樣做:
(加在 cir/Makefile 最後面)
LEX = flex
YACC = bison
LEX_FLAG = -Pcir
YACC_FLAG = -d -p cir
cirLex.cpp: cirLex.l
@echo "> lexing: $<"
@$(LEX) $(LEX_FLAG) -o$@ $<
cirParse.cpp: cirParse.y
@echo "> yaccing: $<"
@$(YACC) $(YACC_FLAG) -o $@ $<
注意: 我有改 prefix (成為 cir), 所以我的 .y .l 裡面事實上是用, 如:
cirparse(), cirlineno, cirlex(), etc.
: 另外因為現在還沒有辦法測試ref programe 想請問一下
: error message 像是 Line38: Gate "16GAT" is redefined!!
: 是在CirRead時印 還是CirPrint時印呢?
在 CIRRead 時印啊!
.doc/.pdf 有寫:
Usage: CIRRead <(string fileName)> [-Replace]
Description: Read the circuit from the file "fileName" and store it in the
global variable (e.g. cirMgr). If the circuit has been read, issue an error
"Error: circuit already exists!!" unless the option "-Replace" is issued. In
such case, delete the original circuit, create a new one, and print out the
message "Note: original circuit is replaced...". Note that the original
circuit will be deleted even if the new circuit construction fails. No
warning or error message is needed if "-Replace" is used in the first
construction of the circuit.
: 如果是CirRead的話 有印出error時 還可以做CirPrint的動作嗎?
不行! cirMgr will be NULL.
: 還是他會印出之前的circuit description file呢?
一旦 "-Replace" 下了之後之前的 circuit netlist 就 bye 了!
: 謝謝回答
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.224.47.190
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.21.241