Tôi đang học cách sử dụng flex nhưng tôi nảy ra một câu hỏi mà tôi chưa tìm thấy câu trả lời (ngay cả trong thẩm quyền giải quyết không thể tìm thấy trong ). Giả sử tôi có mã này:
patt1 { do_foo(42 }
patt2 { do_bar();
Điều này có thể hoạt động tốt. Vấn đề là,do_foo
Có thể cần phải nhận một tham số bằng tham chiếu (ví dụ: int) và làm gì đó với nó (thực tế là foo). tất cả những gì tôi có thể nghĩ ra do_foo
Cách duy nhất để tiếp cận biến này là khai báo nó dưới dạng biến toàn cục, nhưng tùy thuộc vào phạm vi mã chạy, có thể có giải pháp khác (sạch hơn, tốt hơn).
Có ý tưởng gì không? Bất kỳ trợ giúp sẽ được đánh giá rất cao.
Cảm ơn trước.
Trong thực tế, máy quét kết quả trông như thế này, bỏ đi nhiều chi tiết chủ yếu liên quan đến quản lý bộ đệm:
int yylex() {
/*Một chút thiết lập */
trong khi (1) {
LÀM {
yy_current_state = next_state(yy_current_state, get_next_char());
} trong khi (has_no_action(yy_current_state));
yy_act = yy_accept[yy_current_state];
chuyển đổi (yy_act) {
trường hợp 1: /* Khối hành động đầu tiên */
phá vỡ;
trường hợp 2: /* Khối hành động thứ hai */
phá vỡ;
/* vân vân. */
}
}
}
Vì vậy, thật dễ dàng để biết các hoạt động đang diễn ra ở đâu và phạm vi của chúng là gì. Để thông tin này hữu ích, bạn cần xem những Hook nào có thể được chèn vào, vì vậy hãy viết lại nó với một số Hook rõ ràng:
YY_DECL {
/*Một số khai báo */
/******** Khối mở đầu *********/
/*Một chút thiết lập */
trong khi (1) {
LÀM {
yy_current_state = next_state(yy_current_state, get_next_char());
} trong khi (has_no_action(yy_current_state));
yy_act = yy_accept[yy_current_state];
chuyển đổi (yy_act) {
trường hợp 1: YY_USER_ACTION /**** Macro do người dùng xác định ****/
/******** Khối hành động đầu tiên **********/
YY_BREAK
trường hợp 2: YY_USER_ACTION
/******** Khối hành động thứ hai **********/
YY_BREAK
/* vân vân. */
}
}
}
Một trong những tính năng thú vị nhất là "khối Overture". Trong tệp đầu vào (f)lex của bạn, nó trông như thế này:
%lựa chọn...
%%
/* Khối mở đầu: các dòng thụt lề trước mẫu đầu tiên */
int locvar = 0;
patt1 { /* khối hành động đầu tiên */ }
patt2 { /* khối hành động thứ hai */ }
Macro có các giá trị mặc định hợp lý:
/* Định nghĩa mặc định của YY_DECL sẽ khác nếu bạn
* yêu cầu một lexer reentrant
*/
#ifndef YY_DECL
int yylex bên ngoài(void);
#define YY_DECL int yylex(void);
#endif
/* Mã được thực thi ở đầu mỗi quy tắc, sau yytext và yyleng
* đã được thiết lập.
*/
#ifndef YY_USER_ACTION
#define YY_USER_ACTION
#endif
/* Đoạn mã được thực thi ở cuối mỗi quy tắc */
#ifndef YY_BREAK
#define YY_BREAK ngắt;
#endif
Đối với mục đích của bạn, điều thú vị nhất trong số này là YY_DECL
.Nếu bạn muốn truyền tham số cho yylex
, bạn có thể sửa đổi nguyên mẫu bằng cách xác định macro này. nếu ở yylex
Các lệnh gọi biến cục bộ cũng cần thiết trong giai đoạn này và bạn có thể khai báo chúng trong khối mở đầu. (Điều này hữu ích hơn đối với các từ vựng "đẩy", nhưng nó có cách sử dụng ngay cả đối với các từ vựng thông thường.)
YY_USER_ACTION
Và YY_BREAK
Macro thậm chí còn chuyên nghiệp hơn. Mặc dù tất cả chúng đều có vẻ hữu ích cho việc gỡ lỗi, nhưng tốt hơn hết bạn nên sử dụng các tiện ích theo dõi tích hợp sẵn của flex. YY_USER_ACTION
Macro này rất hữu ích nếu bạn muốn theo dõi các vị trí cột thay vì chỉ số hàng; bạn có thể tìm thấy các ví dụ về cách sử dụng nó cho mục đích này. YY_BREAK
Để biết gợi ý về trình biên dịch break
tình huống, macro có thể được đặt thành trống (thay vì break
) sau đây trở lại
tuyên bố.
Một macro khác không được chỉ ra trong đoạn mã trên làYY_USER_INIT
, mã này sẽ được hợp nhất vào mã khởi tạo một lần (cũng không được hiển thị ở trên, xin lỗi).
Hầu hết các chức năng này đều được ghi lại trong hướng dẫn sử dụng linh hoạt. YY_DECL
hiện hữuPhần 9 ("Máy quét được tạo") ; YY_USER_ACTION
Và YY_USER_INIT
hiện hữu Phần 13 ("Macro khác") (và một số tính năng khác). (YY_BREAK
được mô tả ở cuối phần này. )
prelude block 是一个 Posix 特性,因此它在 lex
中可用。以及,并记录在 Posix 中(以及 Section 5.2 of the Flex manual ):
Any such input (beginning with a
or within %{
and %}
delimiter lines) appearing at the beginning of the Rules section before any rules are specified shall be written to lex.yy.c
after the declarations of variables for the yylex()
function and before the first line of code in yylex()
. Thus, user variables local to yylex()
can be declared here, as well as application code to execute upon entry to yylex()
.
Tôi là một lập trình viên xuất sắc, rất giỏi!