作者ric2k1 (Ric)
看板EE_DSnP
标题Re: [讨论] lex 与 yacc
时间Thu May 28 01:33:11 2009
※ 引述《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
1F:推 WSzc:挖 感谢教授写这麽详尽!!! 05/28 20:36