InggrisPerancisSpanyol

Ad


favorit OnWorks

freebsd-lex - Online di Cloud

Jalankan freebsd-lex di penyedia hosting gratis OnWorks melalui Ubuntu Online, Fedora Online, emulator online Windows, atau emulator online MAC OS

Ini adalah perintah freebsd-lex yang dapat dijalankan di penyedia hosting gratis OnWorks menggunakan salah satu dari beberapa workstation online gratis kami seperti Ubuntu Online, Fedora Online, emulator online Windows atau emulator online MAC OS

PROGRAM:

NAMA


flex, lex - generator penganalisis leksikal cepat

RINGKASAN


melenturkan [-bcdfhilnpstvwBFILTV78+? -C[aefFmr] -keluaran -Pawalan -Kerangka] [--Tolong --Versi: kapan]
[nama file ...]

GAMBARAN


Panduan ini menjelaskan melenturkan, alat untuk menghasilkan program yang melakukan pencocokan pola
pada teks. Manual ini mencakup bagian tutorial dan referensi:

Deskripsi Produk
gambaran singkat tentang alat ini

Beberapa Contoh Sederhana

Format File Masukan

Pola
ekspresi reguler yang diperluas yang digunakan oleh flex

Bagaimana Input Dicocokkan
aturan untuk menentukan apa yang telah dicocokkan

tindakan
bagaimana menentukan apa yang harus dilakukan ketika suatu pola dicocokkan

Pemindai yang Dihasilkan
rincian mengenai pemindai yang dihasilkan flex;
cara mengontrol sumber input

Kondisi Awal
memperkenalkan konteks ke dalam pemindai Anda, dan
mengelola "pemindai mini"

Beberapa Buffer Masukan
cara memanipulasi beberapa sumber input; bagaimana caranya?
pindai dari string alih-alih file

Aturan akhir file
aturan khusus untuk mencocokkan akhir input

Makro Lain-lain
ringkasan makro yang tersedia untuk tindakan

Nilai Tersedia Untuk Pengguna
ringkasan nilai yang tersedia untuk tindakan

Berinteraksi Dengan Yacc
menghubungkan pemindai fleksibel bersama dengan parser yacc

Opsi
flex opsi baris perintah, dan "%option"
Direktif

Pertimbangan Kinerja
bagaimana membuat pemindai Anda berjalan secepat mungkin

Menghasilkan Pemindai C++
fasilitas (eksperimental) untuk menghasilkan C++
kelas pemindai

Inkompatibilitas Dengan Lex Dan POSIX
bagaimana flex berbeda dari AT&T lex dan POSIX lex
standar

Diagnostik
pesan kesalahan yang dihasilkan oleh flex (atau pemindai
itu menghasilkan) yang artinya mungkin tidak jelas

File
file yang digunakan oleh flex

Kekurangan / Bug
masalah yang diketahui dengan flex

Lihat Juga
dokumentasi lainnya, alat terkait

Pengarang
termasuk informasi kontak

DESKRIPSI


melenturkan adalah alat untuk menghasilkan pemindai: program yang mengenali pola leksikal dalam teks.
melenturkan membaca file input yang diberikan, atau input standarnya jika tidak ada nama file yang diberikan, untuk a
deskripsi pemindai untuk menghasilkan. Deskripsinya berupa pasangan beraturan
ekspresi dan kode C, disebut aturan. melenturkan menghasilkan sebagai output file sumber C, lex.yy.c,
yang mendefinisikan rutinitas yylex(). File ini dikompilasi dan ditautkan dengan -II perpustakaan untuk
menghasilkan yang dapat dieksekusi. Ketika executable dijalankan, ia menganalisis inputnya untuk kejadian
dari ekspresi reguler. Setiap kali menemukannya, ia mengeksekusi kode C yang sesuai.

BEBERAPA SEDERHANA CONTOH


Pertama beberapa contoh sederhana untuk mendapatkan rasa bagaimana seseorang menggunakan melenturkan. Berikut ini melenturkan
input menentukan pemindai yang setiap kali menemukan string "nama pengguna" akan menggantikan
dengan nama login pengguna:

%%
nama pengguna printf("%s", getlogin() );

Secara default, teks apa pun tidak cocok dengan a melenturkan pemindai disalin ke output, jadi jaringan
efek pemindai ini adalah menyalin file inputnya ke outputnya dengan setiap kemunculan
"nama pengguna" diperluas. Dalam input ini, hanya ada satu aturan. "nama pengguna" adalah belt hold
dan "printf" adalah tindakan. "%%" menandai awal dari aturan.

Berikut contoh sederhana lainnya:

%{
int jumlah_baris = 0, jumlah_karakter = 0;
%}

%%
\n ++jumlah_baris; ++ jumlah_karakter;
. ++ jumlah_karakter;

%%
utama()
{
yylex();
printf( "# baris = %d, # karakter = %d\n",
jumlah_baris, jumlah_karakter );
}

Pemindai ini menghitung jumlah karakter dan jumlah baris dalam inputnya (itu
tidak menghasilkan keluaran selain laporan akhir penghitungan). Baris pertama menyatakan
dua global, "num_lines" dan "num_chars", yang dapat diakses keduanya di dalam yylex() dan dalam
itu utama() rutin dideklarasikan setelah "%%" kedua. Ada dua aturan, satu yang cocok
baris baru ("\n") dan menambah jumlah baris dan jumlah karakter, dan yang
cocok dengan karakter apa pun selain baris baru (ditunjukkan dengan ekspresi reguler ".").

Contoh yang agak lebih rumit:

/* pemindai untuk mainan seperti bahasa Pascal */

%{
/* membutuhkan ini untuk panggilan ke atof() di bawah */
#termasuk
%}

angka [0-9]
ID [az][a-z0-9]*

%%

{DIGIT}+ {
printf( "Bilangan bulat: %s (%d)\n", yytext,
atoi( yyteks ) );
}

{DIGIT}+"."{DIGIT}* {
printf( "Sebuah float: %s (%g)\n", yytext,
atof( yyteks ) );
}

jika|maka|mulai|akhir|prosedur|fungsi {
printf("Kata kunci: %s\n", yytext );
}

{ID} printf( "Pengidentifikasi: %s\n", yytext );

"+"|"-"|"*"|"/" printf( "Operator: %s\n", yytext );

"{"[^}\n]*"}" /* menghabiskan komentar satu baris */

[ \t\n]+ /* menghabiskan spasi */

. printf("Karakter tidak dikenal: %s\n", yytext );

%%

utama (argc, argv)
int argumen;
karakter **argv;
{
++argv, --argc; /* lewati nama program */
jika ( argc > 0 )
yyin = fopen( argv[0], "r" );
lain
yyin = stdin;

yylex();
}

Ini adalah awal dari pemindai sederhana untuk bahasa seperti Pascal. Ini mengidentifikasi
berbagai jenis token dan melaporkan apa yang telah dilihatnya.

Detail dari contoh ini akan dijelaskan pada bagian berikut.

FORMAT OF THE INPUT FILE


Grafik melenturkan file input terdiri dari tiga bagian, dipisahkan oleh garis dengan hanya %% di dalamnya:

definisi
%%
aturan
%%
kode pengguna

Grafik definisi bagian berisi deklarasi sederhana nama definisi untuk menyederhanakan
spesifikasi pemindai, dan deklarasi awal kondisi, yang dijelaskan dalam
bagian selanjutnya.

Definisi nama memiliki bentuk:

definisi nama

"Nama" adalah kata yang dimulai dengan huruf atau garis bawah ('_') diikuti dengan nol atau
lebih banyak huruf, angka, '_', atau '-' (tanda hubung). Definisi diambil untuk memulai dari yang pertama
karakter non-spasi mengikuti nama dan berlanjut ke akhir baris. Itu
definisi selanjutnya dapat dirujuk menggunakan "{name}", yang akan diperluas ke
"(definisi)". Sebagai contoh,

angka [0-9]
ID [az][a-z0-9]*

mendefinisikan "DIGIT" sebagai ekspresi reguler yang cocok dengan satu digit, dan "ID" menjadi a
ekspresi reguler yang cocok dengan huruf diikuti oleh nol atau lebih huruf atau angka. SEBUAH
referensi selanjutnya ke

{DIGIT}+"."{DIGIT}*

identik dengan

([0-9])+"."([0-9])*

dan cocok dengan satu atau lebih digit diikuti dengan '.' diikuti oleh angka nol atau lebih.

Grafik aturan bagian dari melenturkan input berisi serangkaian aturan bentuk:

tindakan pola

di mana pola harus tidak diindentasi dan aksi harus dimulai pada baris yang sama.

Lihat di bawah untuk penjelasan lebih lanjut tentang pola dan tindakan.

Akhirnya, bagian kode pengguna hanya disalin ke lex.yy.c kata demi kata. Digunakan untuk
rutinitas pendamping yang memanggil atau dipanggil oleh pemindai. Kehadiran bagian ini
adalah opsional; jika hilang, yang kedua %% dalam file input juga dapat dilewati.

Di bagian definisi dan aturan, setiap bertakuk teks atau teks terlampir di %{ dan %} is
disalin kata demi kata ke output (dengan %{} dihapus). %{} harus muncul tanpa indentasi
pada baris sendiri.

Di bagian aturan, teks indentasi atau %{} apa pun yang muncul sebelum aturan pertama dapat digunakan
untuk mendeklarasikan variabel yang lokal ke rutin pemindaian dan (setelah deklarasi)
kode yang akan dieksekusi setiap kali rutinitas pemindaian dimasukkan. Indentasi lainnya atau
%{} teks di bagian aturan masih disalin ke output, tetapi artinya tidak baik-
didefinisikan dan mungkin menyebabkan kesalahan waktu kompilasi (fitur ini hadir untuk POSIX
kepatuhan; lihat di bawah untuk fitur lain seperti itu).

Di bagian definisi (tetapi tidak di bagian aturan), komentar yang tidak diindentasi (yaitu, a
baris yang dimulai dengan "/*") juga disalin kata demi kata ke output hingga "*/" berikutnya.

POLA


Pola dalam input ditulis menggunakan serangkaian ekspresi reguler yang diperluas. Ini
adalah:

x cocok dengan karakter 'x'
. karakter apa pun (byte) kecuali baris baru
[xyz] sebuah "kelas karakter"; dalam hal ini polanya
cocok dengan 'x', 'y', atau 'z'
[abj-oZ] sebuah "kelas karakter" dengan rentang di dalamnya; pertandingan
an 'a', a 'b', huruf apa saja dari 'j' sampai 'o',
atau 'Z'
[^AZ] "kelas karakter yang dinegasikan", yaitu, karakter apa pun
tapi mereka yang ada di kelas. Dalam hal ini, apapun
karakter KECUALI huruf besar.
[^AZ\n] karakter apa pun KECUALI huruf besar atau
baris baru
r* nol atau lebih r, di mana r adalah ekspresi reguler apa pun
r+ satu atau lebih r
R? nol atau satu r (yaitu, "r opsional")
r{2,5} di mana saja dari dua hingga lima r
r{2,} dua atau lebih r
r{4} tepat 4 r's
{name} perluasan dari definisi "nama"
(Lihat di atas)
"[xyz]\" duh"
string literal: [xyz]"foo
\X jika X adalah 'a', 'b', 'f', 'n', 'r', 't', atau 'v',
kemudian interpretasi ANSI-C dari \x.
Jika tidak, 'X' literal (digunakan untuk melarikan diri
operator seperti '*')
\0 karakter NUL (kode ASCII 0)
\123 karakter dengan nilai oktal 123
\x2a karakter dengan nilai heksadesimal 2a
(r) cocok dengan r; tanda kurung digunakan untuk menimpa
prioritas (lihat di bawah)

rs ekspresi reguler r diikuti oleh
ekspresi reguler s; disebut "penggabungan"

r|s baik r atau s

r/s an r tetapi hanya jika diikuti oleh s. Itu
teks yang cocok dengan s disertakan saat menentukan
apakah aturan ini adalah "pertandingan terlama",
tetapi kemudian dikembalikan ke input sebelumnya
tindakan tersebut dijalankan. Jadi aksinya saja
melihat teks yang cocok dengan r. Tipe ini
dari pola disebut konteks trailing".
(Ada beberapa kombinasi r/s yang melenturkan
tidak bisa cocok dengan benar; lihat catatan di
Bagian Kekurangan / Bug di bawah ini tentang
"konteks trailing berbahaya".)
^r an r, tetapi hanya di awal baris (yaitu,
ketika baru mulai memindai, atau tepat setelah a
baris baru telah dipindai).
r$ an r, tetapi hanya di akhir baris (yaitu, just
sebelum baris baru). Setara dengan "r/\n".

Perhatikan bahwa gagasan flex tentang "baris baru" persis
apa pun yang digunakan kompiler C untuk mengkompilasi flex
menafsirkan '\n' sebagai; khususnya, pada beberapa DOS
sistem Anda harus menyaring \r di
masukan sendiri, atau secara eksplisit gunakan r/\r\n untuk "r$".

r an r, tetapi hanya dalam kondisi awal s (lihat
di bawah ini untuk diskusi tentang kondisi awal)
R
sama, tetapi dalam salah satu kondisi awal s1,
s2, atau s3
<*>r an r dalam kondisi awal apa pun, bahkan yang eksklusif.

< > file akhir
< >
end-of-file ketika dalam kondisi start s1 atau s2

Perhatikan bahwa di dalam kelas karakter, semua operator ekspresi reguler kehilangan spesialnya
artinya kecuali escape ('\') dan operator kelas karakter, '-', ']', dan, pada
awal kelas, '^'.

Ekspresi reguler yang tercantum di atas dikelompokkan menurut prioritas, dari yang tertinggi
didahulukan di atas hingga terendah di bawah. Mereka yang dikelompokkan bersama memiliki persamaan
hak lebih tinggi. Sebagai contoh,

foo|bar*

sama dengan

(foo)|(ba(r*))

karena operator '*' memiliki prioritas lebih tinggi daripada penggabungan, dan penggabungan lebih tinggi
dari pergantian ('|'). Oleh karena itu pola ini cocok antara string "foo" or itu
string "ba" diikuti oleh nol atau lebih r. Untuk mencocokkan "foo" atau "bar" nol atau lebih, gunakan:

foo|(bilah)*

dan untuk mencocokkan nol-atau-lebih "foo"'s-or-"bar":

(foo|bilah)*

Selain karakter dan rentang karakter, kelas karakter juga dapat berisi
kelas karakter ekspresi. Ini adalah ekspresi yang terlampir di dalam [: dan :] pembatas
(yang dengan sendirinya harus muncul di antara '[' dan ']' dari kelas karakter; lainnya
elemen dapat terjadi di dalam kelas karakter juga). Ekspresi yang valid adalah:

[:alnum:] [:alpha:] [:kosong:]
[:cntrl:] [:digit:] [:grafik:]
[:bawah:] [:cetak:] [:punct:]
[:spasi:] [:atas:] [:xdigit:]

Semua ekspresi ini menunjuk satu set karakter yang setara dengan yang sesuai
standar C adalahXXX fungsi. Sebagai contoh, [:alum:] menunjuk karakter-karakter yang
nomor isal() mengembalikan true - yaitu, alfabet atau numerik apa pun. Beberapa sistem tidak menyediakan
kosong(), jadi definisi fleksibel [:kosong:] sebagai kosong atau tab.

Misalnya, kelas karakter berikut semuanya setara:

[[:alnum:]]
[[:alfa:][:digit:]]
[[:alfa:]0-9]
[a-zA-Z0-9]

Jika pemindai Anda peka huruf besar/kecil ( -i bendera), lalu [:atas:] dan [:lebih rendah:] adalah
setara dengan [:alfa:].

Beberapa catatan tentang pola:

- Kelas karakter yang dinegasikan seperti contoh "[^AZ]" di atas akan pertandingan a garis baru
kecuali "\n" (atau urutan pelarian yang setara) adalah salah satu karakter secara eksplisit
hadir di kelas karakter yang dinegasikan (misalnya, "[^AZ\n]"). Ini tidak seperti berapa banyak
alat ekspresi reguler lainnya memperlakukan kelas karakter yang dinegasikan, tetapi sayangnya
inkonsistensi secara historis mengakar. Mencocokkan baris baru berarti a
pola seperti [^"]* dapat mencocokkan seluruh input kecuali ada kutipan lain di
memasukkan.

- Aturan dapat memiliki paling banyak satu contoh konteks tambahan (operator '/' atau
operator '$'). Kondisi awal, '^', dan "< >" pola hanya dapat terjadi pada
awal pola, dan, serta dengan '/' dan '$', tidak dapat dikelompokkan
di dalam tanda kurung. A '^' yang tidak muncul di awal aturan atau '$'
yang tidak terjadi pada akhir aturan kehilangan sifat khususnya dan adalah
diperlakukan sebagai karakter normal.

Berikut ini adalah ilegal:

foo/bar$
foo batang

Perhatikan bahwa yang pertama, dapat ditulis "foo/bar\n".

Berikut ini akan mengakibatkan '$' atau '^' diperlakukan sebagai karakter normal:

foo|(batang$)
foo|^bar

Jika yang diinginkan adalah "foo" atau bar-diikuti-oleh-baris baru, berikut ini bisa jadi
digunakan (tindakan '|' khusus dijelaskan di bawah):

foo |
bar$ /* tindakan ada di sini */

Trik serupa akan berfungsi untuk mencocokkan foo atau bilah di awal baris.

BAGAIMANA THE INPUT IS COCOK


Saat pemindai yang dihasilkan dijalankan, pemindai akan menganalisis inputnya untuk mencari string yang cocok
salah satu polanya. Jika menemukan lebih dari satu kecocokan, dibutuhkan yang paling cocok
teks (untuk aturan konteks tambahan, ini termasuk panjang bagian akhir, genap
meskipun kemudian akan dikembalikan ke input). Jika menemukan dua atau lebih kecocokan dari
panjang yang sama, aturan yang tercantum pertama di melenturkan file masukan dipilih.

Setelah kecocokan ditentukan, teks yang sesuai dengan kecocokan (disebut token) is
tersedia di penunjuk karakter global yyteks, dan panjangnya di dunia
bilangan bulat yyleng. Grafik tindakan sesuai dengan pola yang cocok kemudian dieksekusi (lebih
deskripsi rinci tindakan berikut), dan kemudian input yang tersisa dipindai untuk
pertandingan lain.

Jika tidak ada kecocokan yang ditemukan, maka kegagalan memerintah dieksekusi: karakter berikutnya dalam input
dianggap cocok dan disalin ke output standar. Jadi, hukum yang paling sederhana melenturkan
masukan adalah:

%%

yang menghasilkan pemindai yang hanya menyalin inputnya (satu karakter pada satu waktu) ke
output.

Perhatikan bahwa yyteks dapat didefinisikan dalam dua cara yang berbeda: baik sebagai karakter petunjuk atau sebagai
sebuah karakter Himpunan. Anda dapat mengontrol definisi mana melenturkan menggunakan dengan memasukkan salah satu dari
arahan khusus % penunjuk or %Himpunan di bagian (definisi) pertama dari kelenturan Anda
memasukkan. Standarnya adalah % penunjuk, kecuali jika Anda menggunakan -l opsi kompatibilitas lex, di mana
kasus yyteks akan menjadi array. Keuntungan menggunakan % penunjuk jauh lebih cepat
pemindaian dan tidak ada buffer overflow saat mencocokkan token yang sangat besar (kecuali jika Anda kehabisan
memori dinamis). Kerugiannya adalah Anda dibatasi dalam bagaimana tindakan Anda bisa
memodifikasi yyteks (lihat bagian berikutnya), dan telepon ke hapus () fungsi menghancurkan
menyajikan isi dari yyteks, yang bisa menjadi sakit kepala porting yang cukup besar saat bergerak
antara berbeda lex versi.

Keuntungan dari %Himpunan adalah bahwa Anda kemudian dapat memodifikasi yyteks sepuasnya, dan
panggilan ke hapus () jangan hancurkan yyteks (Lihat di bawah). Selanjutnya, yang ada lex program
terkadang akses yyteks secara eksternal menggunakan deklarasi formulir:
karakter eksternal yytext[];
Definisi ini salah bila digunakan dengan % penunjuk, tapi benar untuk %Himpunan.

%Himpunan mendefinisikan yyteks menjadi sebuah array dari YYLMAX karakter, yang defaultnya cukup
nilai besar. Anda dapat mengubah ukuran hanya dengan #define'ing YYLMAX ke nilai yang berbeda di
bagian pertama Anda melenturkan memasukkan. Seperti disebutkan di atas, dengan % penunjuk yytext tumbuh
dinamis untuk mengakomodasi token besar. Sementara ini berarti Anda % penunjuk pemindai bisa
mengakomodasi token yang sangat besar (seperti mencocokkan seluruh blok komentar), ingatlah
bahwa setiap kali pemindai harus mengubah ukuran yyteks itu juga harus memindai ulang seluruh token dari
awalnya, jadi mencocokkan token semacam itu bisa terbukti lambat. yyteks saat ini tidak tidak
tumbuh secara dinamis jika panggilan ke hapus () menghasilkan terlalu banyak teks yang didorong kembali; sebagai gantinya,
hasil kesalahan run-time.

Perhatikan juga bahwa Anda tidak dapat menggunakan %Himpunan dengan kelas pemindai C++ (the c ++ pilihan; Lihat di bawah).

TINDAKAN


Setiap pola dalam aturan memiliki tindakan yang sesuai, yang dapat berupa pernyataan C arbitrer apa pun.
Pola berakhir pada karakter spasi putih pertama yang tidak diloloskan; sisa baris
adalah tindakannya. Jika tindakannya kosong, maka ketika polanya cocok dengan token input
dibuang begitu saja. Misalnya, berikut adalah spesifikasi untuk program yang menghapus
semua kemunculan "zap me" dari inputnya:

%%
"tegur aku"

(Ini akan menyalin semua karakter lain di input ke output karena mereka akan dicocokkan
dengan aturan default.)

Berikut adalah program yang mengompresi beberapa kosong dan tab menjadi satu kosong, dan
membuang spasi yang ditemukan di akhir baris:

%%
[ \t]+ putchar( ' ' );
[ \t]+$ /* abaikan token ini */

Jika aksi berisi '{', maka aksi terbentang hingga keseimbangan '}' ditemukan, dan
tindakan dapat melintasi beberapa garis. melenturkan tahu tentang string C dan komentar dan tidak akan
tertipu oleh kawat gigi yang ditemukan di dalamnya, tetapi juga memungkinkan tindakan untuk memulai %{ dan akan
anggap tindakan sebagai semua teks hingga yang berikutnya %} (terlepas dari kawat gigi biasa
di dalam tindakan).

Tindakan yang hanya terdiri dari bilah vertikal ('|') berarti "sama dengan tindakan untuk selanjutnya
aturan." Lihat di bawah untuk ilustrasi.

Tindakan dapat mencakup kode C arbitrer, termasuk kembali pernyataan untuk mengembalikan nilai ke
rutinitas apa pun yang disebut yylex(). Tiap kali yylex() disebut itu terus diproses
token dari tempat terakhir ditinggalkan hingga mencapai akhir file atau dieksekusi
sebuah pengembalian.

Tindakan bebas untuk dimodifikasi yyteks kecuali untuk memanjangkannya (menambahkan karakter ke nya
akhir--ini akan menimpa karakter selanjutnya dalam aliran input). Namun ini tidak
terapkan saat menggunakan %Himpunan (Lihat di atas); dalam hal itu, yyteks dapat dimodifikasi secara bebas dalam bentuk apa pun
cara.

Tindakan bebas untuk dimodifikasi yyleng kecuali mereka tidak boleh melakukannya jika tindakan itu juga termasuk
penggunaan lagi() (Lihat di bawah).

Ada sejumlah arahan khusus yang dapat dimasukkan dalam suatu tindakan:

- ECHO menyalin teks yy ke keluaran pemindai.

- MULAI diikuti dengan nama kondisi awal menempatkan pemindai di
kondisi awal yang sesuai (lihat di bawah).

- MENOLAK mengarahkan pemindai untuk melanjutkan ke aturan "terbaik kedua" yang cocok
input (atau awalan dari input). Aturan dipilih seperti yang dijelaskan di atas dalam
"Bagaimana Input Dicocokkan", dan yyteks dan yyleng diatur dengan tepat. Mungkin
baik menjadi salah satu yang cocok dengan teks sebanyak aturan yang dipilih awalnya tetapi datang
nanti di melenturkan file input, atau yang cocok dengan lebih sedikit teks. Misalnya,
berikut akan menghitung kata-kata dalam input dan memanggil rutin spesial()
setiap kali "frob" terlihat:

int jumlah_kata = 0;
%%

katak khusus(); MENOLAK;
[^ \t\n]+ ++jumlah_kata;

Tanpa MENOLAK, setiap "frob" di input tidak akan dihitung sebagai kata, karena
pemindai biasanya hanya menjalankan satu tindakan per token. beberapa REJECT adalah
diperbolehkan, masing-masing menemukan pilihan terbaik berikutnya untuk aturan yang sedang aktif. Untuk
contoh, ketika pemindai berikut memindai token "abcd", itu akan menulis:
"abcdabcaba" ke output:

%%
a |
ab |
abc |
ECHO abcd; MENOLAK;
.|\n /* memakan semua karakter yang tidak cocok */

(Tiga aturan pertama berbagi tindakan keempat karena mereka menggunakan khusus '|'
tindakan.) MENOLAK adalah fitur yang sangat mahal dalam hal pemindai
pertunjukan; jika digunakan dalam Apa pun tindakan pemindai itu akan melambat semua of
pencocokan pemindai. Lebih-lebih lagi, MENOLAK tidak dapat digunakan dengan -Lih or -CF
pilihan (lihat di bawah).

Perhatikan juga bahwa tidak seperti tindakan khusus lainnya, MENOLAK adalah cabang; kode
segera mengikutinya dalam aksi akan tidak dieksekusi.

- lagi() memberi tahu pemindai bahwa lain kali itu cocok dengan aturan, yang sesuai
tandanya harus ditambahkan ke nilai saat ini dari yyteks daripada menggantinya.
Misalnya diberi input "mega-kludge" berikut akan menulis "mega-mega-
kludge" ke output:

%%
mega-ECHO; lagi();
lumpur ECHO;

"mega-" pertama dicocokkan dan digaungkan ke output. Kemudian "kludge" cocok, tapi
"mega-" sebelumnya masih berkeliaran di awal yyteks sehingga ECHO
untuk aturan "kludge" sebenarnya akan menulis "mega-kludge".

Dua catatan tentang penggunaan lagi(). Pertama, lagi() tergantung pada nilai yyleng
mencerminkan ukuran token saat ini dengan benar, jadi Anda tidak boleh memodifikasi yyleng jika Anda
sedang menggunakan lagi(). Kedua, kehadiran lagi() dalam tindakan pemindai memerlukan a
penalti kinerja kecil dalam kecepatan pencocokan pemindai.

- yless(n) mengembalikan semua kecuali yang pertama n karakter token saat ini kembali ke
aliran input, di mana mereka akan dipindai ulang ketika pemindai mencari yang berikutnya
cocok. yyteks dan yyleng disesuaikan dengan tepat (misalnya, yyleng sekarang akan
sama dengan n ). Misalnya, pada input "foobar" berikut ini akan ditulis
"foobarbar":

%%
foobar gema; tanpa kamu(3);
[az]+ ECHO;

Argumen dari 0 sampai tanpa kamu akan menyebabkan seluruh string input saat ini dipindai
lagi. Kecuali Anda telah mengubah cara pemindai selanjutnya akan memproses inputnya
(menggunakan MULAI, misalnya), ini akan menghasilkan loop tanpa akhir.

Perhatikan bahwa tanpa kamu adalah makro dan hanya dapat digunakan dalam file input fleksibel, bukan dari yang lain
file sumber.

- hapus (c) menempatkan karakter c kembali ke aliran input. Ini akan menjadi yang berikutnya
karakter dipindai. Tindakan berikut akan mengambil token saat ini dan menyebabkannya
untuk dipindai ulang terlampir dalam tanda kurung.

{
di aku;
/* Salin yytext karena unput() membuang yytext */
char *yycopy = strdup(yytext );
hapus( ')' );
untuk ( i = yyleng - 1; i >= 0; --i )
unput(yycopy[i] );
unput( '(');
gratis(yycopy );
}

Perhatikan bahwa karena setiap hapus () menempatkan karakter yang diberikan kembali pada awal dari
aliran input, mendorong senar harus dilakukan dari belakang ke depan.

Masalah potensial yang penting saat menggunakan hapus () apakah itu jika Anda menggunakan % penunjuk (The
default), panggilan ke hapus () menghancurkan isi dari yyteks, dimulai dari yang paling kanan
karakter dan melahap satu karakter ke kiri dengan setiap panggilan. Jika Anda membutuhkan nilai
dari yytext dipertahankan setelah panggilan ke hapus () (seperti pada contoh di atas), Anda juga harus
salin dulu di tempat lain, atau buat pemindai Anda menggunakan %Himpunan sebagai gantinya (lihat Bagaimana Inputnya?
cocok).

Akhirnya, perhatikan bahwa Anda tidak dapat mengembalikan EOF untuk mencoba menandai aliran input dengan
akhir file.

- memasukkan() membaca karakter berikutnya dari aliran input. Sebagai contoh, berikut ini
adalah salah satu cara untuk memakan komentar C:

%%
"/*" {
ke dalam c;

untuk ( ; ; )
{
while ( (c = input()) != '*' &&
c!= EOF)
; /* makan teks komentar */

jika ( c == '*' )
{
sementara ( (c = input()) == '*' )
;
jika ( c == '/' )
merusak; /* menemukan akhir */
}

jika ( c == EOF )
{
error("EOF dalam komentar");
break;
}
}
}

(Perhatikan bahwa jika pemindai dikompilasi menggunakan C++, kemudian memasukkan() malah dirujuk
sebagai masukan yy(), untuk menghindari bentrokan nama dengan C + + aliran dengan nama
memasukkan.)

- YY_FLUSH_BUFFER membilas buffer internal pemindai sehingga lain kali
pemindai mencoba mencocokkan token, pertama-tama akan mengisi ulang buffer menggunakan YY_INPUT
(lihat Pemindai yang Dihasilkan, di bawah). Tindakan ini adalah kasus khusus dari yang lainnya
umum yy_flush_buffer() fungsi, dijelaskan di bawah ini di bagian Multiple Input
Buffer.

- yyterminate() dapat digunakan sebagai pengganti pernyataan kembali dalam suatu tindakan. Dia
menghentikan pemindai dan mengembalikan 0 ke pemanggil pemindai, yang menunjukkan "semua"
selesai". Secara default, yyterminate() juga dipanggil ketika end-of-file adalah
ditemui. Ini adalah makro dan dapat didefinisikan ulang.

THE DIHASILKAN PEMINDAI


Output dari melenturkan adalah file lex.yy.c, yang berisi pemindaian rutin yylex(), a
jumlah tabel yang digunakan olehnya untuk mencocokkan token, dan sejumlah rutinitas tambahan dan
makro. Secara default, yylex() dideklarasikan sebagai berikut:

ke dalam yylex()
{
... berbagai definisi dan tindakan di sini ...
}

(Jika lingkungan Anda mendukung prototipe fungsi, maka itu akan menjadi "int yylex( void )".)
Definisi ini dapat diubah dengan mendefinisikan makro "YY_DECL". Misalnya, Anda bisa
menggunakan:

#define YY_DECL float lexscan( a, b ) float a, b;

untuk memberi nama pemindaian rutin pemindaian lex, mengembalikan pelampung, dan mengambil dua pelampung sebagai
argumen. Perhatikan bahwa jika Anda memberikan argumen untuk pemindaian rutin menggunakan K&R-style/non-
deklarasi fungsi prototipe, Anda harus mengakhiri definisi dengan titik koma (;).

Kapan saja yylex() dipanggil, ia memindai token dari file input global kamu (yang
default ke stdin). Itu berlanjut hingga mencapai akhir file (pada titik mana
itu mengembalikan nilai 0) atau salah satu tindakannya mengeksekusi a kembali pernyataan.

Jika pemindai mencapai akhir file, panggilan berikutnya tidak ditentukan kecuali jika: kamu
diarahkan ke file input baru (dalam hal ini pemindaian berlanjut dari file itu), atau
kamu mulai ulang() disebut. kamu mulai ulang() mengambil satu argumen, a FILE * penunjuk (yang dapat berupa
nihil, jika Anda sudah mengatur YY_INPUT untuk memindai dari sumber selain yin), dan inisialisasi
kamu untuk memindai dari file itu. Pada dasarnya tidak ada perbedaan antara hanya
menugaskan kamu ke file input baru atau menggunakan kamu mulai ulang() untuk melakukannya; yang terakhir tersedia
untuk kompatibilitas dengan versi sebelumnya dari melenturkan, dan karena dapat digunakan untuk beralih
masukan file di tengah pemindaian. Itu juga dapat digunakan untuk membuang arus
masukan buffer, dengan memanggilnya dengan argumen kamu; tapi lebih baik menggunakan YY_FLUSH_BUFFER
(Lihat di atas). Perhatikan bahwa kamu mulai ulang() tidak tidak setel ulang kondisi awal ke AWAL (Lihat
Kondisi Mulai, di bawah).

If yylex() berhenti memindai karena menjalankan a kembali pernyataan dalam salah satu tindakan, the
pemindai kemudian dapat dipanggil lagi dan akan melanjutkan pemindaian di tempat yang ditinggalkannya.

Secara default (dan untuk tujuan efisiensi), pemindai menggunakan pembacaan blok daripada
sederhana dapatkan() panggilan untuk membaca karakter dari yyin Sifat cara mendapatkan inputnya bisa
dikendalikan dengan mendefinisikan YY_INPUT makro. Urutan panggilan YY_INPUT adalah
"YY_INPUT(buf,hasil,ukuran_maks)". Tindakannya adalah menempatkan hingga ukuran_maks karakter dalam
susunan karakter buf dan kembali dalam variabel integer mengakibatkan baik jumlah
karakter dibaca atau YY_NULL konstan (0 pada sistem Unix) untuk menunjukkan EOF. Standarnya
YY_INPUT membaca dari penunjuk file global "yyin".

Contoh definisi YY_INPUT (di bagian definisi file input):

%{
#define YY_INPUT(buf,hasil,max_size) \
{\
int c = getchar(); \
hasil = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \
}
%}

Definisi ini akan mengubah pemrosesan input menjadi satu karakter pada satu waktu.

Ketika pemindai menerima indikasi akhir file dari YY_INPUT, pemindai kemudian memeriksa
bungkus() fungsi. Jika bungkus() mengembalikan false (nol), maka diasumsikan bahwa fungsi
telah maju dan mengatur kamu untuk menunjuk ke file input lain, dan pemindaian berlanjut. Jika
ia mengembalikan nilai true (bukan nol), lalu pemindai berhenti, mengembalikan 0 ke pemanggilnya. Catatan
bahwa dalam kedua kasus, kondisi awal tetap tidak berubah; itu benar tidak kembali ke AWAL.

Jika Anda tidak menyediakan versi Anda sendiri dari yywrap(), maka Anda harus menggunakan %pilihan
bungkus kado (dalam hal ini pemindai berperilaku seolah-olah bungkus() dikembalikan 1), atau Anda harus
berhubungan dengan -II untuk mendapatkan versi default rutin, yang selalu mengembalikan 1.

Tiga rutinitas tersedia untuk pemindaian dari buffer dalam memori daripada file:
yy_scan_string(), yy_scan_bytes(), dan yy_scan_buffer(). Lihat pembahasannya di bawah ini
di bagian Multiple Input Buffer.

Pemindai menulis ECHO keluaran ke kamu global (default, stdout), yang mungkin
didefinisikan ulang oleh pengguna hanya dengan menugaskannya ke yang lain FILE penunjuk.

MULAI KONDISI


melenturkan menyediakan mekanisme untuk mengaktifkan aturan bersyarat. Setiap aturan yang polanya adalah
diawali dengan " " hanya akan aktif ketika pemindai dalam kondisi mulai bernama
"sc". Sebagai contoh,

[^"]* { /* memakan tubuh senar ... */
...
}

akan aktif hanya ketika pemindai dalam kondisi start "STRING", dan

\. { /* menangani pelarian ... */
...
}

akan aktif hanya ketika kondisi start saat ini adalah "INITIAL", "STRING", atau
"MENGUTIP".

Kondisi awal dideklarasikan di bagian definisi (pertama) dari input menggunakan
garis tidak berindentasi yang dimulai dengan salah satu dari %s or %x diikuti dengan daftar nama. Mantan
menyatakan termasuk kondisi awal, yang terakhir eksklusif kondisi awal. Sebuah awal
kondisi diaktifkan menggunakan MULAI tindakan. Sampai selanjutnya MULAI tindakan dijalankan,
aturan dengan kondisi awal yang diberikan akan aktif dan aturan dengan kondisi awal lainnya
akan tidak aktif. Jika kondisi awal adalah inklusif, lalu aturan tanpa awal
kondisi sama sekali juga akan aktif. Jika memang eksklusif, kemudian hanya aturan yang memenuhi syarat dengan
kondisi awal akan aktif. Seperangkat aturan bergantung pada awal eksklusif yang sama
kondisi menggambarkan pemindai yang independen dari aturan lain di melenturkan
memasukkan. Karena itu, kondisi awal eksklusif memudahkan untuk menentukan "mini-
pemindai" yang memindai bagian input yang secara sintaksis berbeda dari yang lain
(misalnya, komentar).

Jika perbedaan antara kondisi awal inklusif dan eksklusif masih sedikit
samar-samar, inilah contoh sederhana yang menggambarkan hubungan antara keduanya. Sekumpulan dari
aturan:

%s contoh
%%

untuk melakukan_sesuatu();

bilah sesuatu_else();

adalah setara dengan

%x contoh
%%

untuk melakukan_sesuatu();

bar something_else();

Tanpa kualifikasi, bar pola dalam contoh kedua tidak akan
aktif (yaitu, tidak cocok) ketika dalam kondisi awal contoh. Jika kita baru saja menggunakan
Untuk memenuhi syarat bar, meskipun, maka itu hanya akan aktif di contoh dan tidak di AWAL, sementara
pada contoh pertama aktif di keduanya, karena pada contoh pertama contoh awal
kondisi adalah termasuk (%S) kondisi awal.

Perhatikan juga bahwa penentu kondisi awal khusus <*> cocok dengan setiap kondisi awal.
Jadi, contoh di atas juga bisa ditulis;

%x contoh
%%

untuk melakukan_sesuatu();

<*>bar something_else();

Aturan default (untuk ECHO karakter yang tidak cocok) tetap aktif dalam kondisi awal. Dia
setara dengan:

<*>.|\n ECHO;

MULAI(0) kembali ke keadaan semula di mana hanya aturan tanpa kondisi awal yang
aktif. Status ini juga dapat disebut sebagai kondisi awal "INITIAL", jadi
MULAI(AWAL) adalah setara dengan MULAI(0). (Kurung di sekitar kondisi awal
nama tidak diperlukan tetapi dianggap gaya yang baik.)

MULAI tindakan juga dapat diberikan sebagai kode indentasi di awal bagian aturan.
Misalnya, berikut ini akan menyebabkan pemindai memasuki kondisi awal "KHUSUS":
kapan saja yylex() disebut dan variabel global masuk_khusus adalah benar:

int enter_khusus;

%x KHUSUS
%%
jika ( masukkan_khusus )
MULAI(KHUSUS);

bla bla bla
... aturan lainnya menyusul...

Untuk mengilustrasikan penggunaan kondisi awal, berikut adalah pemindai yang menyediakan dua perbedaan:
interpretasi string seperti "123.456". Secara default itu akan memperlakukannya sebagai tiga token,
bilangan bulat "123", sebuah titik ('.'), dan bilangan bulat "456". Tetapi jika string didahului
sebelumnya di baris dengan string "berharap-mengambang" itu akan memperlakukannya sebagai token tunggal, the
bilangan floating-point 123.456:

%{
#termasuk
%}
%s mengharapkan

%%
harapkan-mengambang BEGIN(mengharapkan);

[0-9]+"."[0-9]+ {
printf( "menemukan pelampung, = %f\n",
atof( yyteks ) );
}
\n {
/* itu akhir baris, jadi
* kita membutuhkan "nomor harapan" lain
* sebelum kita mengenali lagi
* angka
*/
MULAI(AWAL);
}

[0-9]+ {
printf( "menemukan bilangan bulat, = %d\n",
atoi( yyteks ) );
}

"." printf("menemukan titik\n");

Berikut adalah pemindai yang mengenali (dan membuang) komentar C sambil mempertahankan hitungan
saluran masukan saat ini.

%x komentar
%%
int jumlah_baris = 1;

"/*" MULAI(komentar);

[^*\n]* /* makan apa saja yang bukan '*' */
"*"+[^*/\n]* /* makan '* tidak diikuti oleh '/'s */
\n ++baris_num;
"*"+"/" MULAI(AWAL);

Pemindai ini mengalami sedikit kesulitan untuk mencocokkan teks sebanyak mungkin dengan setiap aturan.
Secara umum, ketika mencoba untuk menulis pemindai berkecepatan tinggi, cobalah untuk mencocokkan sebanyak mungkin dalam
setiap aturan, karena ini adalah kemenangan besar.

Perhatikan bahwa nama kondisi awal benar-benar nilai integer dan dapat disimpan seperti itu.
Dengan demikian, di atas dapat diperpanjang dengan cara berikut:

%x komentar fo
%%
int jumlah_baris = 1;
int penelepon_komentar;

"/*" {
comment_caller = AWAL;
MULAI(komentar);
}

...

"/*" {
comment_caller = foo;
MULAI(komentar);
}

[^*\n]* /* makan apa saja yang bukan '*' */
"*"+[^*/\n]* /* makan '* tidak diikuti oleh '/'s */
\n ++baris_num;
"*"+"/" BEGIN(pemanggil_komentar);

Selanjutnya, Anda dapat mengakses kondisi awal saat ini menggunakan nilai integer YY_START
makro. Misalnya, tugas di atas untuk komentar_penelepon malah bisa ditulis

comment_caller = YY_START;

Flex menyediakan YYSTATE sebagai alias untuk YY_START (karena itulah yang digunakan oleh AT&T lex).

Perhatikan bahwa kondisi awal tidak memiliki ruang nama sendiri; %s dan %x mendeklarasikan nama
dengan cara yang sama seperti #define.

Terakhir, berikut adalah contoh cara mencocokkan string kutipan gaya-C menggunakan awalan eksklusif
kondisi, termasuk urutan pelarian yang diperluas (tetapi tidak termasuk memeriksa string
itu terlalu lama):

%x str

%%
karakter string_buf[MAX_STR_CONST];
karakter *string_buf_ptr;

\" string_buf_ptr = string_buf;BEGIN(str);

\" { /* melihat kutipan penutup - semua selesai */
MULAI(AWAL);
*string_buf_ptr = '\0';
/* mengembalikan tipe token konstanta string dan
* nilai untuk pengurai
*/
}

\n {
/* error - konstanta string yang tidak diakhiri */
/* menghasilkan pesan kesalahan */
}

\\[0-7]{1,3} {
/* urutan escape oktal */
int hasil;

(void) sscanf( yytext + 1, "%o", &hasil );

jika ( hasil > 0xff )
/* error, konstanta di luar batas */

*string_buf_ptr++ = hasil;
}

\\[0-9]+ {
/* menghasilkan kesalahan - urutan pelarian yang buruk; sesuatu
* seperti '\48' atau '\0777777'
*/
}

\\n *string_buf_ptr++ = '\n';
\\t *string_buf_ptr++ = '\t';
\\r *string_buf_ptr++ = '\r';
\\b *string_buf_ptr++ = '\b';
\\f *string_buf_ptr++ = '\f';

\\(.|\n) *string_buf_ptr++ = yytext[1];

[^\\\n\"]+ {
char *yptr = yyteks;

sementara ( *yptr )
*string_buf_ptr++ = *yptr++;
}

Seringkali, seperti dalam beberapa contoh di atas, Anda akhirnya menulis banyak aturan
semua didahului oleh kondisi awal yang sama. Flex membuat ini sedikit lebih mudah dan lebih bersih
dengan memperkenalkan gagasan tentang kondisi awal cakupan. Lingkup kondisi awal dimulai dengan:

{

dimana SC adalah daftar satu atau lebih kondisi awal. Di dalam lingkup kondisi awal,
setiap aturan secara otomatis memiliki awalan diterapkan padanya, sampai a '}' yang cocok dengan
mulanya '{'. Jadi, misalnya,

{
"\\n" mengembalikan '\n';
"\\r" mengembalikan '\r';
"\\f" mengembalikan '\f';
"\\0" mengembalikan '\0';
}

setara dengan:

"\\n" mengembalikan '\n';
"\\r" mengembalikan '\r';
"\\f" mengembalikan '\f';
"\\0" mengembalikan '\0';

Cakupan kondisi awal mungkin bersarang.

Tiga rutinitas tersedia untuk memanipulasi tumpukan kondisi awal:

membatalkan yy_push_state(int status_baru)
mendorong kondisi awal saat ini ke atas tumpukan kondisi awal dan
beralih ke status_baru seolah-olah Anda telah menggunakan MULAI status_baru (ingat awal itu
nama kondisi juga bilangan bulat).

membatalkan yy_pop_state()
memunculkan bagian atas tumpukan dan beralih ke sana melalui MULAI.

int yy_top_state()
mengembalikan bagian atas tumpukan tanpa mengubah isi tumpukan.

Tumpukan kondisi awal tumbuh secara dinamis sehingga tidak memiliki batasan ukuran bawaan. Jika
memori habis, eksekusi program dibatalkan.

Untuk menggunakan tumpukan kondisi awal, pemindai Anda harus menyertakan a %pilihan tumpukan direktif (lihat
Opsi di bawah).

GANDA INPUT BUFFER


Beberapa pemindai (seperti yang mendukung file "include") memerlukan pembacaan dari beberapa
aliran masukan. Sebagai melenturkan pemindai melakukan buffering dalam jumlah besar, seseorang tidak dapat mengontrol di mana
input berikutnya akan dibaca hanya dengan menulis YY_INPUT yang sensitif terhadap
konteks pemindaian. YY_INPUT hanya dipanggil ketika pemindai mencapai ujung penyangganya,
yang mungkin lama setelah memindai pernyataan seperti "termasuk" yang membutuhkan
mengalihkan sumber masukan.

Untuk merundingkan masalah-masalah semacam ini, melenturkan menyediakan mekanisme untuk membuat dan beralih
antara beberapa buffer input. Buffer input dibuat dengan menggunakan:

YY_BUFFER_STATE yy_create_buffer( FILE *file, ukuran int )

yang membutuhkan FILE pointer dan ukuran dan membuat buffer yang terkait dengan file yang diberikan
dan cukup besar untuk dipegang ukuran karakter (bila ragu, gunakan YY_BUF_SIZE untuk ukuran).
Ini mengembalikan YY_BUFFER_STATE menangani, yang kemudian dapat diteruskan ke rutinitas lain (lihat
di bawah). NS YY_BUFFER_STATE type adalah penunjuk ke buram struktur yy_buffer_state
struktur, sehingga Anda dapat dengan aman menginisialisasi variabel YY_BUFFER_STATE ke ((YY_BUFFER_STATE) 0)
jika Anda mau, dan juga merujuk ke struktur buram untuk mendeklarasikan input dengan benar
buffer dalam file sumber selain pemindai Anda. Perhatikan bahwa FILE penunjuk ke dalam
panggilan untuk yy_buat_buffer hanya digunakan sebagai nilai kamu dilihat oleh YY_INPUT; jika Anda
mendefinisikan kembali YY_INPUT jadi tidak digunakan lagi kamu, maka Anda dapat dengan aman melewati nol FILE petunjuk
untuk yy_buat_buffer. Anda memilih buffer tertentu untuk dipindai menggunakan:

batal yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )

mengganti buffer input pemindai sehingga token berikutnya akan datang dari penyangga_baru. Note
bahwa yy_switch_to_buffer() dapat digunakan oleh yywrap() untuk mengatur semuanya agar dapat dilanjutkan
memindai, alih-alih membuka file baru dan menunjuk kamu di itu. Perhatikan juga bahwa beralih
sumber input melalui salah satu dari yy_switch_to_buffer() or bungkus() tidak tidak mengubah awal
kondisi.

batal yy_delete_buffer( buffer YY_BUFFER_STATE )

digunakan untuk merebut kembali penyimpanan yang terkait dengan buffer. ( penyangga bisa nihil, di mana
jika rutin tidak melakukan apa-apa.) Anda juga dapat menghapus konten buffer saat ini
menggunakan:

batal yy_flush_buffer( buffer YY_BUFFER_STATE )

Fungsi ini membuang konten buffer, jadi saat pemindai mencoba untuk
cocokkan token dari buffer, pertama-tama akan mengisi buffer lagi menggunakan YY_INPUT.

yy_baru_buffer() adalah alias untuk yy_buat_buffer(), disediakan untuk kompatibilitas dengan
C++ menggunakan yang baru dan hapus untuk membuat dan menghancurkan objek dinamis.

Akhirnya, YY_CURRENT_BUFFER pengembalian makro a YY_BUFFER_STATE menangani arus
penyangga.

Berikut adalah contoh penggunaan fitur ini untuk menulis pemindai yang diperluas meliputi:
file (yang < > fitur dibahas di bawah):

/* status "termasuk" digunakan untuk mengambil nama
* dari file yang disertakan
*/
%x termasuk

%{
#tentukan MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE sertakan_stack[MAX_INCLUDE_DEPTH];
int sertakan_stack_ptr = 0;
%}

%%
termasuk BEGIN(termasuk);

[az]+ ECHO;
[^az\n]*\n? GEMA;

[ \t]* /* makan spasi */
[^ \t\n]+ { /* mendapat nama file yang disertakan */
jika ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
fprintf( stderr, "Termasuk terlalu dalam bersarang" );
keluar( 1 );
}

sertakan_stack[sertakan_stack_ptr++] =
YY_CURRENT_BUFFER;

yyin = fopen( yyteks, "r" );

jika ( !yyin )
kesalahan(...);

yy_beralih_ke_buffer(
yy_buat_buffer( yyin, YY_BUF_SIZE ) );

MULAI(AWAL);
}

< > {
jika ( --include_stack_ptr < 0 )
{
yyterminate();
}

lain
{
yy_hapus_buffer( YY_CURRENT_BUFFER );
yy_beralih_ke_buffer(
sertakan_tumpukan[sertakan_tumpukan_ptr] );
}
}

Tiga rutinitas tersedia untuk menyiapkan buffer input untuk memindai string dalam memori
bukannya file. Semuanya membuat buffer input baru untuk memindai string, dan
kembalikan yang sesuai YY_BUFFER_STATE handle (yang harus Anda hapus dengan
yy_hapus_buffer() ketika selesai dengan itu). Mereka juga beralih ke buffer baru menggunakan
yy_switch_to_buffer(), jadi panggilan berikutnya untuk yylex() akan mulai memindai string.

yy_scan_string(konst tangki *str)
memindai string yang diakhiri NUL.

yy_scan_bytes(konst tangki *byte, int len)
scan len byte (termasuk kemungkinan NUL) mulai dari lokasi byte.

Perhatikan bahwa kedua fungsi ini membuat dan memindai a salinan dari string atau byte. (Ini
mungkin diinginkan, karena yylex() memodifikasi konten buffer yang sedang dipindai.) Anda
dapat menghindari penyalinan dengan menggunakan:

yy_scan_buffer(karakter *basis, ttt_ukuran_t ukuran)
yang memindai di tempat buffer mulai dari mendasarkan, yang terdiri dari ukuran byte,
dua byte terakhir di antaranya harus be YY_END_OF_BUFFER_CHAR (ASCII NUL). Dua yang terakhir ini
byte tidak dipindai; dengan demikian, pemindaian terdiri dari: dasar[0] melalui dasar[ukuran-2],
inklusif.

Jika Anda gagal mengatur mendasarkan dengan cara ini (yaitu, lupakan dua yang terakhir
YY_END_OF_BUFFER_CHAR byte), maka yy_scan_buffer() mengembalikan pointer nihil sebagai gantinya
membuat buffer input baru.

Tipe ttt_ukuran_t adalah tipe integral di mana Anda dapat memberikan ekspresi integer
mencerminkan ukuran buffer.

AKHIR-FILE ATURAN


Aturan khusus "< >" menunjukkan tindakan yang harus diambil ketika file akhir adalah
ditemui dan yywrap() mengembalikan bukan nol (yaitu, menunjukkan tidak ada file lebih lanjut untuk diproses).
Tindakan harus selesai dengan melakukan salah satu dari empat hal:

- menugaskan kamu ke file input baru (dalam versi flex sebelumnya, setelah melakukan
tugas Anda harus memanggil tindakan khusus YY_BARU_FILE; ini tidak lagi
diperlukan);

- melaksanakan a kembali penyataan;

- mengeksekusi spesial yyterminate() tindakan;

- atau, beralih ke buffer baru menggunakan yy_switch_to_buffer() seperti yang ditunjukkan pada contoh
atas.

< > aturan tidak boleh digunakan dengan pola lain; mereka mungkin hanya memenuhi syarat dengan daftar
dari kondisi awal. Jika tidak memenuhi syarat < > aturan diberikan, itu berlaku untuk semua awal
kondisi yang belum memiliki < > tindakan. Untuk menentukan < > aturan hanya untuk
kondisi awal awal, gunakan

< >

Aturan ini berguna untuk menangkap hal-hal seperti komentar tertutup. Sebuah contoh:

%x kutipan
%%

...aturan lain untuk menangani kutipan...

< > {
error("kutipan tidak terputus");
yyterminate();
}
< > {
jika ( *++daftar file )
yyin = fopen( *daftar file, "r" );
lain
yyterminate();
}

LAIN-LAIN MAKROS


makro YY_USER_ACTION dapat didefinisikan untuk memberikan tindakan yang selalu dieksekusi
sebelum tindakan aturan yang cocok. Misalnya, #define'd bisa memanggil rutinitas
untuk mengonversi teks yy menjadi huruf kecil. Kapan YY_USER_ACTION dipanggil, variabel yy_bertindak
memberikan jumlah aturan yang cocok (aturan diberi nomor dimulai dengan 1). Misalkan kamu
ingin membuat profil seberapa sering setiap aturan Anda cocok. Berikut ini akan melakukan
menipu:

#define YY_USER_ACTION ++ctr[yy_act]

dimana ctr adalah array untuk menampung jumlah aturan yang berbeda. Perhatikan bahwa makro
YY_NUM_RULES memberikan jumlah total aturan (termasuk aturan default, bahkan jika Anda menggunakan
-S), jadi pernyataan yang benar untuk ctr adalah:

int ctr[YY_NUM_RULES];

makro YY_USER_INIT dapat didefinisikan untuk memberikan tindakan yang selalu dieksekusi sebelumnya
pemindaian pertama (dan sebelum inisialisasi internal pemindai selesai). Sebagai contoh,
itu bisa digunakan untuk memanggil rutin untuk membaca di tabel data atau membuka file logging.

makro yy_set_interaktif(is_interaktif) dapat digunakan untuk mengontrol apakah arus
penyangga dianggap interaktif. Buffer interaktif diproses lebih lambat, tetapi
harus digunakan ketika sumber input pemindai memang interaktif untuk menghindari masalah karena
menunggu untuk mengisi buffer (lihat pembahasan -I bendera di bawah). Nilai bukan nol dalam
doa makro menandai buffer sebagai interaktif, nilai nol sebagai non-interaktif.
Perhatikan bahwa penggunaan penggantian makro ini %pilihan interaktif , %pilihan selalu-interaktif or
%pilihan tidak pernah-interaktif (lihat Opsi di bawah). yy_set_interaktif() harus dipanggil terlebih dahulu
untuk mulai memindai buffer yang (atau tidak) dianggap interaktif.

makro yy_set_bol(at_bol) dapat digunakan untuk mengontrol apakah pemindaian buffer saat ini
konteks untuk pencocokan token berikutnya dilakukan seolah-olah di awal baris. Bukan nol
argumen makro membuat aturan berlabuh dengan

makro YY_AT_BOL() mengembalikan true jika token berikutnya yang dipindai dari buffer saat ini akan
memiliki '^' aturan aktif, salah jika tidak.

Dalam pemindai yang dihasilkan, semua tindakan dikumpulkan dalam satu pernyataan sakelar besar dan
dipisahkan menggunakan YY_BREAK, yang dapat didefinisikan ulang. Secara default, ini hanyalah "istirahat", untuk
pisahkan setiap tindakan aturan dari aturan berikut. Mendefinisikan ulang YY_BREAK memungkinkan, untuk
contoh, pengguna C++ untuk #mendefinisikan YY_BREAK untuk tidak melakukan apa-apa (sambil sangat berhati-hati bahwa setiap
aturan diakhiri dengan "istirahat" atau "kembali"!) untuk menghindari penderitaan dari pernyataan yang tidak dapat dijangkau
peringatan di mana karena tindakan aturan berakhir dengan "kembali", YY_BREAK tidak dapat diakses.

NILAI TERSEDIA UNTUK THE PENGGUNA


Bagian ini merangkum berbagai nilai yang tersedia bagi pengguna dalam tindakan aturan.

- tangki *yyteks memegang teks token saat ini. Ini dapat dimodifikasi tetapi tidak
diperpanjang (Anda tidak dapat menambahkan karakter sampai akhir).

Jika arahan khusus %Himpunan muncul di bagian pertama pemindai
deskripsi, maka yyteks malah dideklarasikan tangki yyteks[YYLMAX], dimana YYLMAX adalah
definisi makro yang dapat Anda definisikan ulang di bagian pertama jika Anda tidak menyukai
nilai default (umumnya 8KB). Menggunakan %Himpunan menghasilkan pemindai yang agak lambat,
tetapi nilai yyteks menjadi kebal terhadap panggilan ke memasukkan() dan hapus(), yang
berpotensi menghancurkan nilainya ketika yyteks adalah penunjuk karakter. Lawan dari
%Himpunan is % penunjuk, yang merupakan default.

Anda tidak dapat menggunakan %Himpunan saat membuat kelas pemindai C++ (the -+ bendera).

- int yyleng memegang panjang token saat ini.

- FILE *yyin adalah file yang secara default melenturkan membaca dari. Ini mungkin didefinisikan ulang tetapi
melakukannya hanya masuk akal sebelum pemindaian dimulai atau setelah EOF selesai
ditemui. Mengubahnya di tengah pemindaian akan menghasilkan hasil yang tidak terduga
sejak melenturkan buffer inputnya; menggunakan kamu mulai ulang() sebagai gantinya. Setelah pemindaian berakhir
karena akhir file telah terlihat, Anda dapat menetapkan kamu di file input baru dan
kemudian panggil pemindai lagi untuk melanjutkan pemindaian.

- membatalkan mulai ulang( FILE *file baru ) dapat dipanggil untuk menunjuk kamu di file masukan baru.
Peralihan ke file baru segera (setiap input buffered-up sebelumnya adalah
hilang). Perhatikan panggilan itu kamu mulai ulang() dengan kamu sebagai argumen dengan demikian membuang
buffer input saat ini dan terus memindai file input yang sama.

- FILE *kamu adalah file yang ECHO tindakan dilakukan. Itu dapat ditugaskan kembali oleh
pengguna.

- YY_CURRENT_BUFFER mengembalikan a YY_BUFFER_STATE menangani ke buffer saat ini.

- YY_START mengembalikan nilai integer yang sesuai dengan kondisi awal saat ini.
Anda selanjutnya dapat menggunakan nilai ini dengan MULAI untuk kembali ke kondisi awal itu.

ANTARMUKA DENGAN YACC


Salah satu kegunaan utama dari melenturkan adalah sebagai pendamping yacc pembuat parser. yacc pengurai
berharap untuk memanggil rutinitas bernama yylex() untuk menemukan token input berikutnya. Rutinitasnya adalah
seharusnya mengembalikan jenis token berikutnya serta memasukkan nilai terkait apa pun
global yylval. Untuk menggunakan melenturkan dengan ya, satu menentukan -d pilihan untuk yacc untuk menginstruksikan
itu untuk menghasilkan file y.tab.h mengandung definisi dari semua %token muncul di
yacc memasukkan. File ini kemudian dimasukkan ke dalam melenturkan pemindai. Misalnya, jika salah satu dari
token adalah "TOK_NUMBER", bagian dari pemindai mungkin terlihat seperti:

%{
#sertakan "y.tab.h"
%}

%%

[0-9]+ yylval = atoi( yytext ); kembali TOK_NUMBER;

PILIHAN


melenturkan memiliki opsi berikut:

-B, --cadangan
Hasilkan informasi cadangan untuk lex.cadangan. Ini adalah daftar status pemindai
yang memerlukan pencadangan dan karakter input tempat mereka melakukannya. Dengan menambahkan
aturan seseorang dapat menghapus status cadangan. Jika semua status cadangan dihilangkan
dan -Lih or -CF digunakan, pemindai yang dihasilkan akan berjalan lebih cepat (lihat -p bendera).
Hanya pengguna yang ingin memeras setiap siklus terakhir dari pemindai mereka yang perlu khawatir
tentang opsi ini. (Lihat bagian tentang Pertimbangan Kinerja di bawah.)

-c adalah opsi tidak melakukan apa-apa dan tidak digunakan lagi yang disertakan untuk kepatuhan POSIX.

-D, --debug
membuat pemindai yang dihasilkan berjalan masuk men-debug mode. Kapanpun sebuah pola dikenali
dan global yy_flex_debug bukan nol (yang merupakan default), pemindai akan
menulis ke stderr garis bentuk:

--accepting rule pada baris 53 ("teks yang cocok")

Nomor baris mengacu pada lokasi aturan dalam file yang mendefinisikan pemindai
(yaitu, file yang diumpankan ke flex). Pesan juga dihasilkan ketika
pemindai mencadangkan, menerima aturan default, mencapai akhir buffer inputnya (atau
menemukan NUL; pada titik ini, keduanya terlihat sama sejauh pemindai
bersangkutan), atau mencapai end-of-file.

-F, --penuh
menentukan cepat pemindai. Tidak ada kompresi tabel yang dilakukan dan stdio dilewati. Itu
hasilnya besar tapi cepat. Opsi ini setara dengan -Bdk (Lihat di bawah).

-H, --membantu
menghasilkan ringkasan "bantuan" dari fleksibel opsi untuk stdout dan kemudian keluar. -? dan
--membantu adalah sinonim untuk -H.

-Saya, --tidak peka huruf besar-kecil
menginstruksikan melenturkan untuk menghasilkan case-insensitive pemindai. Kasus surat yang diberikan
dalam melenturkan pola input akan diabaikan, dan token dalam input akan dicocokkan
terlepas dari kasus. Teks yang cocok diberikan dalam yyteks akan memiliki kasus yang diawetkan
(yaitu, itu tidak akan dilipat).

-aku, --lex-kompat
menyalakan kompatibilitas maksimum dengan AT&T asli lex penerapan. Catatan
bahwa ini tidak berarti penuh kesesuaian. Penggunaan opsi ini memerlukan biaya
sejumlah besar kinerja, dan itu tidak dapat digunakan dengan -+, -F, -F, -Cf,
or -CF pilihan. Untuk detail tentang kompatibilitas yang diberikannya, lihat bagian
"Inkompatibilitas Dengan Lex Dan POSIX" di bawah ini. Opsi ini juga menghasilkan nama
YY_FLEX_LEX_COMPAT menjadi #define'd di pemindai yang dihasilkan.

-n adalah opsi lain yang tidak melakukan apa-apa dan tidak digunakan lagi yang disertakan hanya untuk kepatuhan POSIX.

-P, --perf-laporan
menghasilkan laporan kinerja ke stderr. Laporan terdiri dari komentar
mengenai fitur dari melenturkan file input yang akan menyebabkan kerugian serius dari
kinerja dalam pemindai yang dihasilkan. Jika Anda memberi bendera dua kali, Anda juga akan
dapatkan komentar mengenai fitur yang menyebabkan kerugian kinerja kecil.

Perhatikan bahwa penggunaan MENOLAK, %pilihan ya, dan konteks trailing variabel (lihat
bagian Kekurangan / Bug di bawah) memerlukan penalti kinerja yang substansial;
penggunaan lagi(), itu ^ operator, dan -I bendera memerlukan kinerja kecil
hukuman.

-S, --tidak-default
menyebabkan kegagalan memerintah (input pemindai yang tak tertandingi itu digemakan ke stdout) menjadi
tertindas. Jika pemindai menemukan input yang tidak sesuai dengan aturannya,
itu dibatalkan dengan kesalahan. Opsi ini berguna untuk menemukan lubang di pemindai
aturan yang ditetapkan.

-T, --stdout
menginstruksikan melenturkan untuk menulis pemindai yang dihasilkannya ke keluaran standar alih-alih
lex.yy.c.

-di, --bertele-tele
menentukan itu melenturkan harus menulis ke stderr ringkasan statistik mengenai
pemindai yang dihasilkannya. Sebagian besar statistik tidak ada artinya bagi orang biasa melenturkan
pengguna, tetapi baris pertama mengidentifikasi versi melenturkan (sama seperti yang dilaporkan oleh -V),
dan baris berikutnya bendera yang digunakan saat membuat pemindai, termasuk yang
aktif secara default.

-w, --sekarang
menekan pesan peringatan.

-B, --kelompok
menginstruksikan melenturkan untuk menghasilkan sekumpulan pemindai, kebalikan dari interaktif scanner
dihasilkan oleh -I (Lihat di bawah). Secara umum, Anda menggunakan -B ketika kamu tertentu itu punyamu
pemindai tidak akan pernah digunakan secara interaktif, dan Anda ingin menekan a sedikit lebih
kinerja dari itu. Jika tujuan Anda adalah untuk memeras banyak lebih
kinerja, Anda harus menggunakan -Lih or -CF opsi (dibahas di bawah), yang
nyalakan -B secara otomatis pula.

-F, --cepat
menentukan bahwa cepat representasi tabel pemindai harus digunakan (dan stdio
dilewati). Representasi ini secepat representasi tabel penuh
(-F), dan untuk beberapa set pola akan jauh lebih kecil (dan untuk yang lain,
lebih besar). Secara umum, jika set pola berisi "kata kunci" dan catch-all,
aturan "pengidentifikasi", seperti di set:

"case" mengembalikan TOK_CASE;
"beralih" mengembalikan TOK_SWITCH;
...
"default" mengembalikan TOK_DEFAULT;
[az]+ kembalikan TOK_ID;

maka Anda lebih baik menggunakan representasi tabel lengkap. Andai saja
aturan "pengidentifikasi" hadir dan Anda kemudian menggunakan tabel hash atau semacamnya untuk mendeteksi
kata kunci, Anda lebih baik menggunakan -F.

Opsi ini setara dengan -CFr (Lihat di bawah). Itu tidak dapat digunakan dengan -+.

-SAYA, --interaktif
menginstruksikan melenturkan untuk menghasilkan interaktif pemindai. Pemindai interaktif adalah salah satunya
yang hanya melihat ke depan untuk memutuskan token apa yang cocok jika itu benar-benar harus.
Ternyata selalu melihat satu karakter ekstra ke depan, bahkan jika pemindai memiliki
sudah melihat teks yang cukup untuk membedakan token saat ini, sedikit lebih cepat daripada
hanya melihat ke depan bila perlu. Tapi pemindai yang selalu melihat ke depan memberi
kinerja interaktif yang mengerikan; misalnya, ketika pengguna mengetik baris baru, itu adalah
tidak dikenali sebagai token baris baru sampai mereka masuk lain token, yang sering berarti
mengetik di seluruh baris lain.

Melenturkan pemindai default ke interaktif kecuali jika Anda menggunakan -Lih or -CF meja-
opsi kompresi (lihat di bawah). Itu karena jika Anda mencari high-
kinerja Anda harus menggunakan salah satu opsi ini, jadi jika tidak, melenturkan
mengasumsikan Anda lebih suka menukar sedikit kinerja run-time untuk intuitif
perilaku interaktif. Perhatikan juga bahwa Anda tidak bisa menggunakan -I setara dengan -Lih or
-CF. Dengan demikian, opsi ini tidak terlalu dibutuhkan; ini diaktifkan secara default untuk semua itu
kasus yang diperbolehkan.

Perhatikan bahwa jika isatty () mengembalikan false untuk input pemindai, flex akan kembali ke
mode batch, bahkan jika -I telah ditentukan. Untuk memaksa mode interaktif apa pun yang terjadi,
menggunakan %pilihan selalu-interaktif (lihat Opsi di bawah).

Anda dapat memaksa pemindai untuk tidak menjadi interaktif dengan menggunakan -B (Lihat di atas).

-L, --nolin
menginstruksikan melenturkan tidak menghasilkan #garis arahan. Tanpa opsi ini, melenturkan paprika
pemindai yang dihasilkan dengan arahan #line sehingga pesan kesalahan dalam tindakan akan
ditempatkan dengan benar sehubungan dengan yang asli melenturkan file masukan (jika
kesalahan disebabkan oleh kode dalam file input), atau lex.yy.c (jika kesalahannya adalah fleksibel
kesalahan -- Anda harus melaporkan kesalahan semacam ini ke alamat email yang diberikan di bawah).

-T, --jejak
membuat melenturkan dijalankan jejak mode. Ini akan menghasilkan banyak pesan untuk stderr
mengenai bentuk input dan resultan non-deterministik dan
automata terbatas deterministik. Opsi ini sebagian besar untuk digunakan dalam pemeliharaan melenturkan.

-V, --Versi: kapan
mencetak nomor versi ke stdout dan keluar. --Versi: kapan adalah sinonim untuk -V

-7, -7bit
menginstruksikan melenturkan untuk menghasilkan pemindai 7-bit, yaitu pemindai yang hanya dapat mengenali
7-bit karakter dalam inputnya. Keuntungan menggunakan -7 apakah itu pemindai?
tabel bisa sampai setengah ukuran yang dihasilkan menggunakan -8 pilihan (lihat
di bawah). Kerugiannya adalah pemindai seperti itu sering hang atau macet jika inputnya
berisi karakter 8-bit.

Namun, perhatikan bahwa kecuali Anda membuat pemindai menggunakan -Lih or -CF tabel
opsi kompresi, penggunaan -7 hanya akan menghemat sedikit ruang meja, dan
membuat pemindai Anda jauh lebih portabel. Fleksibel perilaku default adalah untuk
menghasilkan pemindai 8-bit kecuali Anda menggunakan -Lih or -CF, dalam hal ini melenturkan
default untuk menghasilkan pemindai 7-bit kecuali situs Anda selalu dikonfigurasi untuk
menghasilkan pemindai 8-bit (seperti yang sering terjadi pada situs non-AS). Kamu bisa
beri tahu apakah flex menghasilkan pemindai 7-bit atau 8-bit dengan memeriksa flag
ringkasan di -v keluaran seperti yang dijelaskan di atas.

Perhatikan bahwa jika Anda menggunakan -Cfe or -CFe (opsi kompresi tabel itu, tetapi juga menggunakan
kelas kesetaraan seperti yang dibahas lihat di bawah), flex masih default untuk menghasilkan
Pemindai 8-bit, karena biasanya dengan opsi kompresi ini tabel 8-bit penuh adalah
tidak jauh lebih mahal dari tabel 7-bit.

-8, -8bit
menginstruksikan melenturkan untuk menghasilkan pemindai 8-bit, yaitu pemindai yang dapat mengenali 8-bit
karakter. Bendera ini hanya diperlukan untuk pemindai yang dibuat menggunakan -Lih or -CF, as
jika tidak, fleksibelkan default untuk menghasilkan pemindai 8-bit.

Lihat pembahasan -7 di atas untuk perilaku default flex dan pengorbanannya
antara pemindai 7-bit dan 8-bit.

-+, --c++
menentukan bahwa Anda ingin flex untuk menghasilkan kelas pemindai C++. Lihat bagian di
Menghasilkan Pemindai C++ di bawah ini untuk detailnya.

-C[aefFmr]
mengontrol tingkat kompresi tabel dan, lebih umum, pertukaran antara
pemindai kecil dan pemindai cepat.

-Ka, --meluruskan ("align") menginstruksikan flex untuk menukar tabel yang lebih besar di tabel yang dihasilkan
pemindai untuk kinerja yang lebih cepat karena elemen tabel lebih baik
selaras untuk akses memori dan komputasi. Pada beberapa arsitektur RISC, mengambil
dan memanipulasi kata-kata panjang lebih efisien daripada dengan unit berukuran lebih kecil seperti
kata-kata pendek. Opsi ini dapat menggandakan ukuran tabel yang digunakan oleh pemindai Anda.

-Ce, --ec mengarahkan melenturkan untuk membangun persamaan derajatnya kelas, yaitu, kumpulan karakter
yang memiliki sifat leksikal yang identik (misalnya, jika satu-satunya penampilan
angka di melenturkan input ada di kelas karakter "[0-9]" lalu digit '0',
'1', ..., '9' semuanya akan ditempatkan di kelas kesetaraan yang sama). Kelas kesetaraan
biasanya memberikan pengurangan dramatis dalam ukuran file tabel/objek akhir (biasanya a
faktor 2-5) dan dari segi kinerja cukup murah (satu pencarian array per
karakter yang dipindai).

-Lih menentukan bahwa penuh tabel pemindai harus dibuat - melenturkan jangan
kompres tabel dengan mengambil keuntungan dari fungsi transisi yang sama untuk
negara bagian yang berbeda.

-CF menentukan bahwa representasi pemindai cepat alternatif (dijelaskan di atas
bawah -F bendera) harus digunakan. Opsi ini tidak dapat digunakan dengan -+.

-cm, --meta-ecs mengarahkan melenturkan untuk membangun meta-ekuivalensi kelas, yang merupakan himpunan
kelas kesetaraan (atau karakter, jika kelas kesetaraan tidak digunakan)
yang biasa digunakan bersama. Kelas meta-ekivalensi sering kali merupakan kemenangan besar ketika
menggunakan tabel terkompresi, tetapi memiliki dampak kinerja yang moderat (satu atau dua
tes "jika" dan satu pencarian array per karakter yang dipindai).

-Kr, --Baca menyebabkan pemindai yang dihasilkan untuk memotong penggunaan perpustakaan I/O standar
(stdio) untuk masukan. Alih-alih menelepon takut() or dapatkan(), pemindai akan menggunakan
Baca() panggilan sistem, menghasilkan peningkatan kinerja yang bervariasi dari satu sistem ke sistem lainnya
sistem, tetapi secara umum mungkin dapat diabaikan kecuali Anda juga menggunakan -Lih or -CF.
Menggunakan -Kr dapat menyebabkan perilaku aneh jika, misalnya, Anda membaca dari kamu menggunakan
stdio sebelum memanggil pemindai (karena pemindai akan melewatkan teks apa pun
bacaan Anda sebelumnya tertinggal di buffer input stdio).

-Kr tidak berpengaruh jika Anda mendefinisikan YY_INPUT (lihat Pemindai yang Dihasilkan di atas).

Seorang diri -C menentukan bahwa tabel pemindai harus dikompresi tetapi tidak juga
kelas kesetaraan atau kelas meta-ekuivalensi harus digunakan.

Opsi -Lih or -CF dan -Cm tidak masuk akal bersama - tidak ada peluang
untuk kelas meta-ekivalensi jika tabel tidak dikompresi. Jika tidak,
pilihan dapat dicampur secara bebas, dan bersifat kumulatif.

Pengaturan standar adalah -Cem, yang menentukan bahwa melenturkan harus menghasilkan kesetaraan
kelas dan kelas meta-ekuivalensi. Pengaturan ini memberikan tingkat tertinggi
kompresi tabel. Anda dapat menukar pemindai yang bekerja lebih cepat dengan biaya
tabel yang lebih besar dengan yang berikut ini umumnya benar:

paling lambat & terkecil
-Cem
-Cm
-Ce
-C
-C{f,F}e
-C{f,F}
-C{f,F}a
tercepat & terbesar

Perhatikan bahwa pemindai dengan tabel terkecil biasanya dibuat dan dikompilasi
tercepat, jadi selama pengembangan Anda biasanya ingin menggunakan default, maksimal
kompresi.

-Cfe seringkali merupakan kompromi yang baik antara kecepatan dan ukuran untuk pemindai produksi.

-keluaran, --file keluaran=FILE
mengarahkan flex untuk menulis pemindai ke file keluaran alih-alih lex.yy.c. Jika kamu
menggabungkan -o pada pengatur terkenal. Pengatur ini menawarkan bantuan hukum kepada traderapabila trader berselisih dengan broker yang terdaftar dengan mereka. -t pilihan, maka pemindai ditulis ke stdout namun #garis
arahan (lihat -L opsi di atas) lihat file output.

-Awalan, --awalan=STRING
mengubah default yy awalan yang digunakan oleh melenturkan untuk semua variabel yang terlihat secara global dan
nama fungsi sebagai gantinya menjadi awalan. Sebagai contoh, -Pfoo mengubah nama yyteks
untuk teks kaki. Itu juga mengubah nama file output default dari lex.yy.c untuk
lex.foo.c. Berikut semua nama yang terpengaruh:

yy_buat_buffer
yy_hapus_buffer
yy_flex_debug
yy_init_buffer
yy_flush_buffer
yy_load_buffer_state
yy_beralih_ke_buffer
kamu
yyleng
yylex
yylineno
kamu
yrestart
yyteks
yywrap

(Jika Anda menggunakan pemindai C++, maka hanya yywrap dan yyFlexLexer terpengaruh.)
Di dalam pemindai Anda sendiri, Anda masih dapat merujuk ke variabel global dan
fungsi menggunakan salah satu versi namanya; tetapi secara eksternal, mereka memiliki
nama yang dimodifikasi.

Opsi ini memungkinkan Anda dengan mudah menautkan beberapa melenturkan program menjadi sama
dapat dieksekusi. Namun, perhatikan bahwa menggunakan opsi ini juga mengganti nama yywrap(), jadi kamu sekarang
harus berikan versi rutinitas Anda sendiri (dengan nama yang sesuai) untuk Anda
pemindai, atau gunakan %pilihan noyywrap, sebagai menghubungkan dengan -II tidak lagi menyediakan satu untuk
Anda secara default.

-kerangka_file, --skel=FILE
menimpa file kerangka default dari mana melenturkan membangun pemindainya.
Anda tidak akan pernah membutuhkan opsi ini kecuali Anda melakukannya melenturkan pemeliharaan atau pengembangan.

-X, --posix-kompatibel
kompatibilitas maksimal dengan POSIX lex.

--yylineno
melacak jumlah garis di yylineno.

--yyclass=NAMA
nama kelas C++.

--file-header=FILE
buat file header C selain pemindai.

--file-tabel[=FILE]
menulis tabel ke FILE.

-Dmakro[=defn]
#define macro defn (default defn adalah '1').

-R, --masuk kembali
menghasilkan pemindai C reentrant

--Bison-jembatan
pemindai untuk parser murni bison.

--lokasi-bison
termasuk dukungan yylloc.

--stdinit
inisialisasi yyin/yyout ke stdin/stdout.

--noansi-definisi gaya lama fungsi definisi.

--noansi-prototipe
daftar parameter kosong dalam prototipe.

--kata bendad
tidak termasuk .

--tidak ada fungsi
tidak menghasilkan FUNGSI tertentu.

melenturkan juga menyediakan mekanisme untuk mengontrol opsi dalam spesifikasi pemindai
itu sendiri, bukan dari flex command-line. Ini dilakukan dengan memasukkan %pilihan
petunjuk di bagian pertama spesifikasi pemindai. Anda dapat menentukan beberapa
pilihan dengan satu %pilihan direktif, dan beberapa arahan di bagian pertama dari
file masukan fleksibel Anda.

Sebagian besar opsi diberikan hanya sebagai nama, secara opsional didahului dengan kata "tidak" (tanpa
mengintervensi spasi putih) untuk meniadakan artinya. Angka setara dengan bendera fleksibel atau
negasi mereka:

7bit -7 pilihan
8bit -8 pilihan
menyelaraskan -Ca opsi
opsi cadangan -b
opsi batch -B
c++ -+ opsi

caseful atau
case-sensitive kebalikan dari -i (default)

peka huruf besar/kecil atau
opsi tanpa kasus -i

opsi debug -d
default kebalikan dari opsi -s
ecs -Opsi Ce
opsi -F cepat
opsi -f penuh
opsi -I interaktif
lex-compat -l opsi
opsi meta-ecs -Cm
opsi perf-laporan -p
baca -Cr opsi
opsi stdout -t
opsi verbose -v
peringatkan kebalikan dari opsi -w
(gunakan "%option nowarn" untuk -w)

array setara dengan "%array"
pointer setara dengan "%pointer" (default)

Beberapa %pilihan menyediakan fitur jika tidak tersedia:

selalu-interaktif
menginstruksikan flex untuk menghasilkan pemindai yang selalu mempertimbangkan inputnya
"interaktif". Biasanya, pada setiap file input baru yang dipanggil pemindai isatty () di
mencoba untuk menentukan apakah sumber input pemindai bersifat interaktif dan dengan demikian
harus membaca karakter pada suatu waktu. Namun, ketika opsi ini digunakan, maka tidak
panggilan seperti itu dilakukan.

utama mengarahkan flex untuk memberikan default utama() program untuk pemindai, yang hanya
panggilan yylex(). Opsi ini menyiratkan bungkus kado (Lihat di bawah).

tidak pernah-interaktif
menginstruksikan flex untuk menghasilkan pemindai yang tidak pernah menganggap inputnya "interaktif"
(sekali lagi, tidak ada panggilan untuk isatty()). Ini adalah kebalikan dari selalu-interaktif.

tumpukan memungkinkan penggunaan tumpukan kondisi awal (lihat Kondisi Awal di atas).

awal
jika diatur (yaitu, %pilihan awal) menginisialisasi kamu dan kamu untuk stdin dan stdout,
alih-alih default nol. Beberapa yang ada lex program bergantung pada perilaku ini,
meskipun tidak sesuai dengan ANSI C, yang tidak memerlukan stdin dan
stdout menjadi konstanta waktu kompilasi.

yylineno
mengarahkan melenturkan untuk menghasilkan pemindai yang mempertahankan nomor saluran saat ini
baca dari inputnya dalam variabel global yylineno. Pilihan ini tersirat oleh
%pilihan lex-compat.

yywrap jika tidak disetel (yaitu, %pilihan noyywrap), membuat pemindai tidak memanggil bungkus() pada akhirnya-
file, tetapi anggap saja tidak ada file lagi untuk dipindai (sampai pengguna
poin kamu di file dan panggilan baru yylex() lagi).

melenturkan memindai tindakan aturan Anda untuk menentukan apakah Anda menggunakan MENOLAK or lagi() fitur.
Grafik menolak dan lagi opsi tersedia untuk mengesampingkan keputusannya apakah Anda menggunakan
pilihan, baik dengan mengaturnya (misalnya, %pilihan menolak) untuk menunjukkan fitur tersebut adalah
memang digunakan, atau menghapus pengaturannya untuk menunjukkan bahwa itu sebenarnya tidak digunakan (mis. %pilihan
tidak lebih).

Tiga opsi mengambil nilai yang dibatasi string, diimbangi dengan '=':

%option outfile="ABC"

adalah setara dengan -oABC, dan

%option awalan="XYZ"

adalah setara dengan -PXYZ. Terakhir,

%option yyclass="foo"

hanya berlaku saat membuat pemindai C++ ( -+ pilihan). Ini menginformasikan melenturkan yang kamu miliki
berasal foo sebagai subkelas dari yyFlexLexer, so melenturkan akan menempatkan tindakan Anda di anggota
fungsi foo::yylex() alih-alih yyFlexLexer::yylex(). Ini juga menghasilkan
yyFlexLexer::yylex() fungsi anggota yang mengeluarkan kesalahan run-time (dengan memanggil
yyFlexLexer::LexerError()) jika dipanggil. Lihat Menghasilkan Pemindai C++, di bawah, untuk tambahan
informasi.

Sejumlah opsi tersedia untuk puritan lint yang ingin menyembunyikan tampilan
rutinitas yang tidak dibutuhkan dalam pemindai yang dihasilkan. Setiap hal berikut, jika tidak disetel (misalnya,
%pilihan kata benda ), menghasilkan rutin yang sesuai tidak muncul di yang dihasilkan
pemindai:

masukan, keluarkan
yy_push_status, yy_pop_status, yy_top_status
yy_scan_buffer, yy_scan_bytes, yy_scan_string

(meskipun yy_push_state() dan teman tetap tidak akan muncul kecuali Anda menggunakan %pilihan tumpukan).

KINERJA PERTIMBANGAN


Tujuan desain utama dari melenturkan adalah bahwa itu menghasilkan pemindai berkinerja tinggi. Telah
dioptimalkan untuk menangani dengan baik set aturan yang besar. Selain efek pada pemindai
kecepatan kompresi tabel -C pilihan yang diuraikan di atas, ada sejumlah
pilihan/tindakan yang menurunkan kinerja. Ini adalah, dari yang paling mahal hingga yang paling murah:

MENOLAK
%opsi yylineno
konteks trailing sewenang-wenang

set pola yang memerlukan pencadangan
%Himpunan
%opsi interaktif
%opsi selalu-interaktif

'^' operator awal baris
lagi()

dengan tiga yang pertama semuanya cukup mahal dan dua yang terakhir cukup murah. Catatan
itu juga hapus () diimplementasikan sebagai panggilan rutin yang berpotensi melakukan sedikit
bekerja, sedangkan tanpa kamu() adalah makro yang cukup murah; jadi jika hanya mengembalikan beberapa teks berlebih Anda
dipindai, gunakan tanpa kamu().

MENOLAK harus dihindari di semua biaya ketika kinerja penting. Ini adalah hal yang khusus
pilihan yang mahal.

Menyingkirkan pencadangan itu berantakan dan sering kali membutuhkan banyak pekerjaan untuk
pemindai yang rumit. Pada prinsipnya, seseorang mulai dengan menggunakan -b bendera untuk menghasilkan
lex.cadangan mengajukan. Misalnya, pada input

%%
untuk mengembalikan TOK_KEYWORD;
foobar mengembalikan TOK_KEYWORD;

filenya terlihat seperti:

Status #6 tidak menerima -
nomor baris aturan terkait:
2 3
transisi keluar: [ o ]
jam-transisi: EOF [ \001-n p-\177 ]

Status #8 tidak menerima -
nomor baris aturan terkait:
3
transisi keluar: [ a ]
jam-transisi: EOF [ \001-` b-\177 ]

Status #9 tidak menerima -
nomor baris aturan terkait:
3
transisi keluar: [ r ]
jam-transisi: EOF [ \001-q s-\177 ]

Tabel terkompresi selalu dicadangkan.

Beberapa baris pertama memberi tahu kami bahwa ada status pemindai yang dapat membuat transisi
pada 'o' tetapi tidak pada karakter lain, dan bahwa dalam keadaan itu saat ini dipindai
teks tidak cocok dengan aturan apa pun. Keadaan terjadi ketika mencoba mencocokkan aturan yang ditemukan di
baris 2 dan 3 dalam file input. Jika pemindai dalam kondisi itu dan kemudian membaca sesuatu
selain 'o', itu harus dicadangkan untuk menemukan aturan yang cocok. Dengan sedikit
menggaruk kepala orang dapat melihat bahwa ini pasti keadaannya ketika telah melihat "fo".
Ketika ini terjadi, jika sesuatu selain 'o' lain terlihat, pemindai akan memiliki
untuk membuat cadangan untuk hanya mencocokkan 'f' (dengan aturan default).

Komentar mengenai Status #8 menunjukkan ada masalah saat "foob" telah dipindai.
Memang, pada karakter apa pun selain 'a', pemindai harus mencadangkan untuk menerima
"foo". Demikian pula, komentar untuk Negara #9 menyangkut ketika "fooba" telah dipindai dan
'r' tidak mengikuti.

Komentar terakhir mengingatkan kita bahwa tidak ada gunanya bersusah payah menghapus
membuat cadangan dari aturan kecuali kita menggunakan -Lih or -CF, karena tidak ada peningkatan kinerja
melakukannya dengan pemindai terkompresi.

Cara menghapus cadangan adalah dengan menambahkan aturan "kesalahan":

%%
untuk mengembalikan TOK_KEYWORD;
foobar mengembalikan TOK_KEYWORD;

fooba |
foob ​​|
FO {
/* alarm palsu, sebenarnya bukan kata kunci */
kembali TOK_ID;
}

Menghilangkan pencadangan di antara daftar kata kunci juga dapat dilakukan dengan menggunakan aturan "tangkap semua":

%%
untuk mengembalikan TOK_KEYWORD;
foobar mengembalikan TOK_KEYWORD;

[az]+ kembalikan TOK_ID;

Ini biasanya merupakan solusi terbaik bila perlu.

Mencadangkan pesan cenderung mengalir. Dengan seperangkat aturan yang rumit, tidak jarang
mendapatkan ratusan pesan. Namun, jika seseorang dapat menguraikannya, seringkali hanya membutuhkan selusin
atau lebih aturan untuk menghilangkan back up (meskipun mudah untuk membuat kesalahan dan memiliki
aturan kesalahan secara tidak sengaja cocok dengan token yang valid. Masa depan yang mungkin melenturkan fitur akan menjadi
otomatis menambahkan aturan untuk menghilangkan pencadangan).

Penting untuk diingat bahwa Anda mendapatkan manfaat dari menghilangkan pencadangan saja
jika Anda menghilangkan setiap contoh back up. Meninggalkan hanya satu berarti Anda tidak mendapatkan apa-apa.

Variabel konteks trailing (di mana bagian depan dan belakang tidak memiliki tanda tetap
panjang) memerlukan kehilangan kinerja yang hampir sama dengan MENOLAK (yaitu, substansial). Jadi ketika
mungkin aturan seperti:

%%
mouse|tikus/(kucing|anjing) run();

lebih baik ditulis:

%%
mouse/kucing|lari anjing();
tikus/kucing|anjing lari();

atau sebagai

%%
mouse|tikus/kucing lari();
tikus|tikus/anjing lari();

Perhatikan bahwa di sini spesial '|' tindakan tidak tidak memberikan penghematan apa pun, dan bahkan dapat membuat
hal-hal yang lebih buruk (lihat Kekurangan / Bug di bawah).

Area lain di mana pengguna dapat meningkatkan kinerja pemindai (dan yang lebih mudah untuk
implement) muncul dari fakta bahwa semakin lama token dicocokkan, semakin cepat pemindai
akan berlari. Ini karena dengan token yang panjang, pemrosesan sebagian besar karakter input membutuhkan
tempat di loop pemindaian bagian dalam (pendek), dan tidak sering harus melalui
pekerjaan tambahan untuk menyiapkan lingkungan pemindaian (misalnya, yyteks) untuk tindakan.
Ingat pemindai untuk komentar C:

%x komentar
%%
int jumlah_baris = 1;

"/*" MULAI(komentar);

[^*\n]*
"*"+[^*/\n]*
\n ++baris_num;
"*"+"/" MULAI(AWAL);

Ini dapat dipercepat dengan menuliskannya sebagai:

%x komentar
%%
int jumlah_baris = 1;

"/*" MULAI(komentar);

[^*\n]*
[^*\n]*\n ++nomor_baris;
"*"+[^*/\n]*
"*"+[^*/\n]*\n ++nomor_baris;
"*"+"/" MULAI(AWAL);

Sekarang alih-alih setiap baris baru membutuhkan pemrosesan tindakan lain, mengenali
baris baru "didistribusikan" di atas aturan lain untuk menjaga teks yang cocok selama
mungkin. Perhatikan bahwa menambahkan aturan tidak tidak memperlambat pemindai! Kecepatan
pemindai tidak tergantung pada jumlah aturan atau (modul pertimbangan yang diberikan pada
awal bagian ini) betapa rumitnya aturan yang berkaitan dengan operator seperti
'*' dan '|'.

Contoh terakhir dalam mempercepat pemindai: misalkan Anda ingin memindai melalui file
berisi pengidentifikasi dan kata kunci, satu per baris dan tanpa karakter asing lainnya,
dan mengenali semua kata kunci. Pendekatan pertama yang alami adalah:

%%
asm |
otomatis |
istirahat |
... dll ...
mudah menguap |
sementara /* itu kata kunci */

.|\n /* itu bukan kata kunci */

Untuk menghilangkan back-tracking, perkenalkan aturan catch-all:

%%
asm |
otomatis |
istirahat |
... dll ...
mudah menguap |
sementara /* itu kata kunci */

[az]+ |
.|\n /* itu bukan kata kunci */

Sekarang, jika dijamin ada tepat satu kata per baris, maka kita dapat mengurangi
jumlah total pertandingan dengan setengah dengan menggabungkan pengakuan baris baru dengan yang dari
token lainnya:

%%
asm\n |
otomatis\n |
istirahat\n |
... dll ...
mudah berubah\n |
while\n /* itu kata kunci */

[az]+\n |
.|\n /* itu bukan kata kunci */

Kita harus berhati-hati di sini, karena kami sekarang telah memperkenalkan kembali pencadangan ke pemindai. Di
tertentu, sedangkan we ketahuilah bahwa tidak akan pernah ada karakter di aliran input
selain huruf atau baris baru, melenturkan tidak dapat mengetahui hal ini, dan itu akan direncanakan untuk mungkin
perlu mencadangkan ketika telah memindai token seperti "otomatis" dan kemudian karakter berikutnya adalah
sesuatu selain baris baru atau surat. Sebelumnya itu hanya akan cocok dengan
aturan "otomatis" dan selesai, tetapi sekarang tidak ada aturan "otomatis", hanya aturan "otomatis\n". Ke
menghilangkan kemungkinan pencadangan, kami dapat menduplikasi semua aturan tetapi tanpa
baris baru terakhir, atau, karena kami tidak pernah berharap untuk menemukan masukan seperti itu dan karena itu tidak
bagaimana itu diklasifikasikan, kami dapat memperkenalkan satu lagi aturan menangkap semua, yang ini tidak
sertakan baris baru:

%%
asm\n |
otomatis\n |
istirahat\n |
... dll ...
mudah berubah\n |
while\n /* itu kata kunci */

[az]+\n |
[az]+ |
.|\n /* itu bukan kata kunci */

Disusun dengan -Cf, ini tentang secepat yang bisa didapat melenturkan pemindai untuk melakukan ini
masalah tertentu.

Catatan terakhir: melenturkan lambat saat mencocokkan NUL, terutama ketika token berisi
beberapa NUL. Yang terbaik adalah menulis aturan yang cocok pendek jumlah teks jika itu
mengantisipasi bahwa teks akan sering menyertakan NUL.

Catatan terakhir lainnya mengenai kinerja: seperti yang disebutkan di atas di bagian Bagaimana Input
Cocok, mengubah ukuran secara dinamis yyteks untuk mengakomodasi token besar adalah proses yang lambat
karena saat ini mengharuskan token (besar) dipindai ulang dari awal. Jadi
jika kinerja sangat penting, Anda harus mencoba mencocokkan teks dalam jumlah "besar" tetapi tidak
jumlah "besar", di mana batas antara keduanya sekitar 8K karakter/token.

MENGHASILKAN C + + PEMINDAI


melenturkan menyediakan dua cara berbeda untuk menghasilkan pemindai untuk digunakan dengan C++. Cara pertama adalah
untuk hanya mengkompilasi pemindai yang dihasilkan oleh melenturkan menggunakan kompiler C++ alih-alih C
penyusun. Anda seharusnya tidak menemukan kesalahan kompilasi (harap laporkan apa pun yang Anda temukan ke
alamat email yang diberikan di bagian Penulis di bawah). Anda kemudian dapat menggunakan kode C++ di . Anda
aturan tindakan alih-alih kode C. Perhatikan bahwa sumber input default untuk pemindai Anda
sisa kamu, dan gema default masih dilakukan untuk kamu keluar. Keduanya tetap FILE *
variabel dan bukan C++ stream.

Anda juga dapat menggunakan melenturkan untuk menghasilkan kelas pemindai C++, menggunakan -+ pilihan (atau,
setara, %pilihan c++), yang secara otomatis ditentukan jika nama flex
yang dapat dieksekusi diakhiri dengan '+', seperti fleksibel++. Saat menggunakan opsi ini, flex default ke
menghasilkan pemindai ke file lex.yy.cc alih-alih lex.yy.c. Pemindai yang dihasilkan
termasuk file header FlexLexer.h, yang mendefinisikan antarmuka ke dua kelas C++.

Kelas pertama, FlexLexer, menyediakan kelas dasar abstrak yang mendefinisikan pemindai umum
antarmuka kelas. Ini menyediakan fungsi anggota berikut:

const arang* YYTeks()
mengembalikan teks dari token yang paling baru cocok, setara dengan yyteks.

int YYLeng()
mengembalikan panjang token yang paling baru cocok, setara dengan yyleng.

int baris() const
mengembalikan nomor baris input saat ini (lihat %pilihan ya), or 1 if %pilihan
yylineno tidak digunakan.

membatalkan set_debug( int bendera )
menyetel tanda debug untuk pemindai, setara dengan menetapkan ke yy_flex_debug
(lihat bagian Opsi di atas). Perhatikan bahwa Anda harus membuat pemindai menggunakan
%pilihan men-debug untuk memasukkan informasi debug di dalamnya.

int men-debug() const
mengembalikan pengaturan flag debugging saat ini.

Juga disediakan fungsi anggota yang setara dengan yy_switch_to_buffer(), yy_buat_buffer()
(meskipun argumen pertama adalah std::istream* penunjuk objek dan bukan a MENGAJUKAN*),
yy_flush_buffer(), yy_hapus_buffer(), dan kamu mulai ulang() (sekali lagi, argumen pertama adalah
std::istream* penunjuk objek).

Kelas kedua didefinisikan dalam FlexLexer.h is yyFlexLexer, yang berasal dari FlexLexer.
Ini mendefinisikan fungsi anggota tambahan berikut:

yyFlexLexer( std::istream* arg_yyin = 0, std::ostream* arg_yyou = 0 )
membangun sebuah yyFlexLexer objek menggunakan aliran yang diberikan untuk input dan output. Jika
tidak ditentukan, aliran default ke cin dan cout, masing.

maya int yylex()
melakukan peran yang sama adalah yylex() lakukan untuk pemindai fleksibel biasa: ia memindai
aliran input, menggunakan token, hingga tindakan aturan mengembalikan nilai. Jika kamu
turunkan subkelas S dari yyFlexLexer dan ingin mengakses fungsi anggota dan
variabel dari S dalam yylex(), maka Anda perlu menggunakan %pilihan yyclass="S" untuk menginformasikan
melenturkan bahwa Anda akan menggunakan subkelas itu alih-alih yyFlexLexer. Dalam hal ini,
daripada menghasilkan yyFlexLexer::yylex(), melenturkan menghasilkan S::yylex() (dan juga
menghasilkan boneka yyFlexLexer::yylex() panggilan itu yyFlexLexer::LexerError() if
ditelepon).

maya membatalkan switch_streams(std::istream* baru_in = 0,
std::ostream* baru_keluar = 0) menugaskan kembali kamu untuk baru_in (jika bukan nihil) dan kamu untuk
baru_keluar (ditto), menghapus buffer input sebelumnya jika kamu ditugaskan kembali.

int yylex( std::istream* baru_in, std::ostream* baru_keluar = 0 )
pertama-tama alihkan aliran input melalui switch_stream( baru_in, baru_keluar ) lalu
mengembalikan nilai yylex().

Selain itu, yyFlexLexer mendefinisikan fungsi virtual yang dilindungi berikut yang Anda dapat:
definisikan ulang di kelas turunan untuk menyesuaikan pemindai:

maya int Masukan Lexer( arang* penggemar, int ukuran_maks )
membaca sampai ukuran_maks karakter menjadi buf dan mengembalikan jumlah karakter yang dibaca.
Untuk menunjukkan akhir input, kembalikan 0 karakter. Perhatikan bahwa pemindai "interaktif"
(Lihat -B dan -I bendera) menentukan makro YY_INTERAKTIF. Jika Anda mendefinisikan ulang
Masukan Lexer() dan perlu mengambil tindakan yang berbeda tergantung pada apakah
pemindai mungkin memindai sumber input interaktif, Anda dapat menguji
kehadiran nama ini melalui #ifdef.

maya membatalkan Keluaran Lexer( const arang* penggemar, int ukuran )
menulis ukuran karakter dari buffer penggemar, yang, ketika NUL dihentikan, mungkin
juga berisi NUL "internal" jika aturan pemindai dapat mencocokkan teks dengan NUL di
Mereka.

maya membatalkan Kesalahan Lexer( const arang* msg )
melaporkan pesan kesalahan fatal. Versi default dari fungsi ini menulis
pesan ke aliran cerr dan keluar.

Perhatikan bahwa a yyFlexLexer objek berisi seluruh keadaan pemindaian. Dengan demikian Anda dapat menggunakan seperti itu
objek untuk membuat pemindai reentrant. Anda dapat membuat instance beberapa instance yang sama
yyFlexLexer kelas, dan Anda juga dapat menggabungkan beberapa kelas pemindai C++ bersama-sama di
program yang sama menggunakan -P opsi yang dibahas di atas.

Akhirnya, perhatikan bahwa %Himpunan fitur tidak tersedia untuk kelas pemindai C++; kamu harus
menggunakan % penunjuk (default).

Berikut adalah contoh pemindai C++ sederhana:

// Contoh penggunaan kelas pemindai C++ fleksibel.

%{
int mylineno = 0;
%}

string \"[^\n"]+\"

ws [\t]+

alfa [A-Za-z]
gali [0-9]
nama ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])*
angka1 [-+]?{dig}+\.?([eE][-+]?{dig}+)?
angka2 [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
nomor {angka1}|{angka2}

%%

{ws} /* lewati bagian yang kosong dan tab */

"/*" {
ke dalam c;

sementara((c = yyinput()) != 0)
{
jika(c == '\n')
++sayalineno;

lain jika(c == '*')
{
jika((c = yyinput()) == '/')
break;
lain
hapus (c);
}
}
}

{angka} cout << "angka " << YYText() << '\n';

\n mylineno++;

{nama} cout << "nama " << YYText() << '\n';

{string} cout << "string " << YYText() << '\n';

%%

ke dalam utama( ke dalam /* argc */, char** /* argv */ )
{
FlexLexer* lexer = yyFlexLexer baru;
while(lexer->yylex() != 0)
;
0 kembali;
}
Jika Anda ingin membuat beberapa kelas lexer (berbeda), Anda menggunakan -P bendera (atau
awalan= opsi) untuk mengganti nama masing-masing yyFlexLexer untuk beberapa lainnya xxFlexLexer. Anda kemudian bisa
memasukkan di sumber Anda yang lain sekali per kelas lexer, ganti nama terlebih dahulu
yyFlexLexer sebagai berikut:

#undef yyFlexLexer
#define yyFlexLexer xxFlexLexer
#termasuk

#undef yyFlexLexer
#define yyFlexLexer zzFlexLexer
#termasuk

jika, misalnya, Anda menggunakan %pilihan awalan = "xx" untuk salah satu pemindai Anda dan %pilihan
awalan = "zz" untuk yang lain.

PENTING: bentuk kelas pemindaian saat ini adalah eksperimental dan bisa berubah
jauh di antara rilis utama.

Ketidaksesuaian DENGAN LEX DAN POSIX


melenturkan adalah penulisan ulang dari AT&T Unix lex alat (kedua implementasi tidak berbagi
kode, meskipun), dengan beberapa ekstensi dan ketidaksesuaian, yang keduanya menjadi perhatian
mereka yang ingin menulis pemindai yang dapat diterima oleh salah satu implementasi. Fleksibel sepenuhnya
sesuai dengan POSIX lex spesifikasi, kecuali saat menggunakan % penunjuk (default),
panggilan untuk hapus () menghancurkan isi yyteks, yang berlawanan dengan POSIX
spesifikasi.

Di bagian ini kita membahas semua area ketidakcocokan yang diketahui antara flex, AT&T
lex, dan spesifikasi POSIX.

fleksibel -l opsi mengaktifkan kompatibilitas maksimum dengan AT&T asli lex penerapan,
dengan kerugian besar dalam kinerja pemindai yang dihasilkan. Kami perhatikan di bawah ini yang
ketidaksesuaian dapat diatasi dengan menggunakan -l .

melenturkan sepenuhnya kompatibel dengan lex dengan pengecualian berikut:

- Yang tidak berdokumen lex variabel internal pemindai yylineno tidak didukung kecuali -l
or %pilihan yylineno digunakan.

yylineno harus dipertahankan berdasarkan per-buffer, bukan per-scanner
(variabel global tunggal).

yylineno bukan bagian dari spesifikasi POSIX.

- The memasukkan() rutin tidak dapat didefinisikan ulang, meskipun mungkin dipanggil untuk membaca karakter
mengikuti apa saja yang telah dicocokkan dengan suatu aturan. Jika memasukkan() menemui akhir-
berkas biasa bungkus() pemrosesan dilakukan. Akhir file `` nyata '' dikembalikan oleh
memasukkan() as EOF.

Input malah dikendalikan dengan mendefinisikan YY_INPUT makro.

Grafik melenturkan pembatasan itu memasukkan() tidak dapat didefinisikan ulang sesuai dengan
Spesifikasi POSIX, yang sama sekali tidak menentukan cara apa pun untuk mengendalikan
masukan pemindai selain dengan membuat penetapan awal untuk yyin

- The hapus () rutinitas tidak dapat didefinisikan ulang. Pembatasan ini sesuai dengan
POSIX.

- melenturkan pemindai tidak masuk kembali seperti lex pemindai. Khususnya, jika Anda memiliki
pemindai interaktif dan penangan interupsi yang melompat jauh dari pemindai,
dan pemindai kemudian dipanggil lagi, Anda mungkin mendapatkan pesan berikut:

kesalahan internal pemindai fleksibel yang fatal--akhir buffer tidak terjawab

Untuk masuk kembali ke pemindai, pertama gunakan

kamu mulai ulang (yyin);

Perhatikan bahwa panggilan ini akan membuang input buffer apa pun; biasanya ini bukan
masalah dengan pemindai interaktif.

Perhatikan juga bahwa kelas pemindai C++ fleksibel adalah reentrant, jadi jika menggunakan C++ adalah pilihan
untuk Anda, Anda harus menggunakannya sebagai gantinya. Lihat "Membuat Pemindai C++" di atas untuk
rincian.

- keluaran() tidak didukung. Keluaran dari ECHO makro dilakukan ke file-pointer
kamu (bawaan stdout).

keluaran() bukan bagian dari spesifikasi POSIX.

- lex tidak mendukung kondisi awal eksklusif (%x), meskipun berada di POSIX
spesifikasi.

- Ketika definisi diperluas, melenturkan menyertakannya dalam tanda kurung. Dengan lex,
sebagai berikut:

NAMA [AZ][A-Z0-9]*
%%
untuk{NAMA}? printf("Ditemukan\n");
%%

tidak akan cocok dengan string "foo" karena ketika makro diperluas aturannya adalah
setara dengan "foo[AZ][A-Z0-9]*?" dan didahulukan sedemikian rupa sehingga '?' adalah
terkait dengan "[A-Z0-9]*". Dengan melenturkan, aturan akan diperluas menjadi "foo([AZ][A-
Z0-9]*)?" dan string "foo" akan cocok.

Perhatikan bahwa jika definisi dimulai dengan ^ atau diakhiri dengan $ maka itu tidak diperluas
dengan tanda kurung, untuk memungkinkan operator ini muncul dalam definisi tanpa kehilangan
makna khusus mereka. Tetapi , /, dan < > operator tidak dapat digunakan dalam a
melenturkan definisi.

Menggunakan -l menghasilkan lex perilaku tanpa tanda kurung di sekitar definisi.

Spesifikasi POSIX adalah bahwa definisi diapit dalam tanda kurung.

- Beberapa implementasi dari lex memungkinkan tindakan aturan untuk memulai pada baris yang terpisah, jika
pola aturan memiliki spasi kosong:

%%
foo|bar
{ foobar_aksi(); }

melenturkan tidak mendukung fitur ini.

- The lex %r (menghasilkan pemindai Ratfor) tidak didukung. Itu bukan bagian dari
spesifikasi POSIX.

- Setelah panggilan ke hapus(), yyteks tidak terdefinisi sampai token berikutnya cocok,
kecuali pemindai dibuat menggunakan %Himpunan. Ini tidak terjadi dengan lex atau itu
spesifikasi POSIX. Itu -l opsi menghilangkan ketidakcocokan ini.

- Keutamaan {} (rentang numerik) operator berbeda. lex menafsirkan
"abc{1,3}" sebagai "cocokkan satu, dua, atau tiga kemunculan 'abc'", sedangkan melenturkan
menafsirkannya sebagai "mencocokkan 'ab' diikuti oleh satu, dua, atau tiga kemunculan 'c'".
Yang terakhir ini sesuai dengan spesifikasi POSIX.

- Keutamaan ^ operatornya berbeda. lex menafsirkan "^foo|bar" sebagai "cocok
baik 'foo' di awal baris, atau 'bar' di mana saja", sedangkan melenturkan
menafsirkannya sebagai "cocok dengan 'foo' atau 'bar' jika mereka muncul di awal a
line". Yang terakhir ini sesuai dengan spesifikasi POSIX.

- Deklarasi ukuran tabel khusus seperti %a didukung oleh lex tidak diperlukan oleh
melenturkan pemindai; melenturkan mengabaikan mereka.

- Nama FLEX_SCANNER adalah #define'd sehingga pemindai dapat ditulis untuk digunakan dengan baik
melenturkan or lex. Pemindai juga termasuk: YY_FLEX_MAJOR_VERSION dan YY_FLEX_MINOR_VERSION
menunjukkan versi mana dari melenturkan menghasilkan pemindai (misalnya, untuk 2.5
rilis, definisi ini akan menjadi 2 dan 5) masing-masing).

Berikut ini melenturkan fitur tidak termasuk dalam lex atau spesifikasi POSIX:

Pemindai C++
%pilihan
mulai cakupan kondisi
mulai kondisi tumpukan
pemindai interaktif/non-interaktif
yy_scan_string() dan teman-teman
yyterminate()
yy_set_interaktif()
yy_set_bol()
YY_AT_BOL()
< >
<*>
YY_DECL
YY_START
YY_USER_ACTION
YY_USER_INIT
#arahan baris
%{} di sekitar tindakan
beberapa tindakan dalam satu baris

ditambah hampir semua flag fleksibel. Fitur terakhir dalam daftar mengacu pada fakta bahwa
dengan melenturkan Anda dapat menempatkan beberapa tindakan pada baris yang sama, dipisahkan dengan titik koma, sementara
dengan lex, pengikut

foo handle_foo(); ++num_foos_seen;

adalah (agak mengejutkan) terpotong menjadi

foo handle_foo();

melenturkan tidak memotong tindakan. Tindakan yang tidak dilampirkan dalam kurung kurawal hanyalah
diakhiri di akhir baris.

DIAGNOSTIK


peringatan, memerintah tidak bisa be cocok menunjukkan bahwa aturan yang diberikan tidak dapat dicocokkan karena
mengikuti aturan lain yang akan selalu cocok dengan teks yang sama. Misalnya, di
"foo" berikut tidak dapat dicocokkan karena muncul setelah aturan "catch-all" pengenal:

[az]+ got_identifier();
foo punya_foo();

Menggunakan MENOLAK di pemindai menekan peringatan ini.

peringatan, -s Option diberikan tapi kegagalan memerintah bisa be cocok berarti mungkin
(mungkin hanya dalam kondisi awal tertentu) bahwa aturan default (cocok dengan yang mana pun)
karakter) adalah satu-satunya yang akan cocok dengan input tertentu. Sejak -s diberikan,
mungkin ini tidak dimaksudkan.

tolak_digunakan_but_tidak_terdeteksi tidak terdefinisi or yylebih_digunakan_tetapi_tidak_terdeteksi tidak terdefinisi - Ini
kesalahan dapat terjadi pada waktu kompilasi. Mereka menunjukkan bahwa pemindai menggunakan MENOLAK or lagi()
tapi itu melenturkan gagal memperhatikan fakta, artinya melenturkan memindai dua bagian pertama
mencari kemunculan tindakan ini dan gagal menemukannya, tetapi entah bagaimana Anda menyelinap
beberapa di (melalui file #include, misalnya). Menggunakan %pilihan menolak or %pilihan lagi untuk
menunjukkan untuk melenturkan bahwa Anda benar-benar menggunakan fitur ini.

melenturkan scanner macet - pemindai yang dikompilasi dengan -s telah menemukan string input yang
tidak cocok dengan aturannya. Kesalahan ini juga dapat terjadi karena masalah internal.

token terlalu besar, melebihi YYLMAX - pemindai Anda menggunakan %Himpunan dan salah satu aturannya cocok a
string lebih panjang dari YYLMAX konstan (8K byte secara default). Anda dapat meningkatkan nilainya
oleh #mendefinisikan YYLMAX di bagian definisi Anda melenturkan memasukkan.

scanner membutuhkan -8 bendera untuk menggunakan itu karakter 'x' - Spesifikasi pemindai Anda meliputi:
mengenali karakter 8-bit 'x' dan Anda tidak menentukan bendera -8, dan pemindai Anda
default ke 7-bit karena Anda menggunakan -Lih or -CF opsi kompresi tabel. Lihat
diskusi tentang -7 bendera untuk detailnya.

melenturkan scanner mundur melimpah - Anda dulu hapus () untuk mendorong kembali begitu banyak teks sehingga
buffer pemindai tidak dapat menahan teks yang didorong mundur dan token saat ini masuk yyteks.
Idealnya pemindai harus secara dinamis mengubah ukuran buffer dalam kasus ini, tetapi saat ini
tidak.

memasukkan penyangga meluap, tidak bisa memperbesar penyangga karena scanner kegunaan MENOLAK - pemindai adalah
bekerja untuk mencocokkan token yang sangat besar dan perlu memperluas buffer input. Ini
tidak bekerja dengan pemindai yang menggunakan MENOLAK.

fatal melenturkan scanner intern kesalahan--akhir of penyangga terjawab - Ini bisa terjadi di pemindai
yang masuk kembali setelah lompatan jauh melompat keluar (atau melebihi) aktivasi pemindai
bingkai. Sebelum masuk kembali ke pemindai, gunakan:

kamu mulai ulang (yyin);

atau, seperti disebutkan di atas, beralih menggunakan kelas pemindai C++.

terlalu banyak awal Kondisi in <> membangun! - Anda mencantumkan lebih banyak kondisi awal di <>
membangun daripada yang ada (jadi Anda harus mendaftarkan setidaknya satu dari mereka dua kali).

Gunakan freebsd-lex online menggunakan layanan onworks.net


Server & Workstation Gratis

Unduh aplikasi Windows & Linux

  • 1
    fre:ac - konverter audio gratis
    fre:ac - konverter audio gratis
    fre:ac adalah konverter audio dan CD gratis
    ripper untuk berbagai format dan pembuat enkode.
    Ini fitur MP3, MP4/M4A, WMA, Ogg
    Format Vorbis, FLAC, AAC, dan Bonk
    mendukung, ...
    Unduh fre:ac - konverter audio gratis
  • 2
    Matplotlib
    Matplotlib
    Matplotlib adalah perpustakaan yang komprehensif
    untuk membuat statis, animasi, dan
    visualisasi interaktif dengan Python.
    Matplotlib membuat hal-hal mudah menjadi mudah dan
    hal yang sulit...
    Unduh Matplotlib.dll
  • 3
    Manusia Bot
    Manusia Bot
    Tulis logika chatbot Anda sekali dan
    hubungkan ke salah satu yang tersedia
    layanan perpesanan, termasuk Amazon
    Alexa, Facebook Messenger, Kendur,
    Telegram atau bahkan ...
    Unduh BotMan.dll
  • 4
    Joplin
    Joplin
    Joplin adalah sumber terbuka dan gratis
    aplikasi pencatat dan tugas yang
    dapat menangani sejumlah besar catatan di
    Format penurunan harga, atur menjadi
    buku catatan dan...
    Unduh Joplin
  • 5
    gerbv � penampil Gerber (RS-274X).
    gerbv � penampil Gerber (RS-274X).
    Gerbv adalah file Gerber sumber terbuka
    (RS-274X saja) penampil. Gerbv memungkinkan Anda
    memuat beberapa file di atas satu sama lain,
    lakukan pengukuran pada gambar yang ditampilkan,
    dll. ...
    Unduh gerbv � penampil Gerber (RS-274X).
  • 6
    meteran
    meteran
    Alat Analisis kinerja I/O.
    Pemirsa: Pengembang, Informasi
    Teknologi, Sains/Penelitian, Sistem
    Administrator. Antarmuka pengguna: Win32
    (MS.Windows). Program...
    Unduh Iometer.dll
  • Lebih banyak lagi »

Perintah Linux

Ad