看板 EE_DSnP 關於我們 聯絡資訊
※ 引述《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
WSzc:挖 感謝教授寫這麼詳盡!!! 05/28 20:36