Amazon Best VPN GoSearch

OnWorks favicon'u

freebsd-lex - Bulutta Çevrimiçi

Ubuntu Online, Fedora Online, Windows çevrimiçi emülatörü veya MAC OS çevrimiçi emülatörü üzerinden OnWorks ücretsiz barındırma sağlayıcısında freebsd-lex çalıştırın

Bu, Ubuntu Online, Fedora Online, Windows çevrimiçi emülatörü veya MAC OS çevrimiçi emülatörü gibi birden fazla ücretsiz çevrimiçi iş istasyonumuzdan birini kullanarak OnWorks ücretsiz barındırma sağlayıcısında çalıştırılabilen freebsd-lex komutudur.

Program:

ADI


flex, lex - hızlı sözcük çözümleyici oluşturucu

SİNOPSİS


esnek [-bcdfhilnpstvwBFILTV78+? -C[aefFmr] -çıktı -Önek -iskelet] [--Yardım --versiyon]
[dosya adı ...]

GENEL BAKIŞ


Bu kılavuzda esnek, desen eşleştirme gerçekleştiren programlar oluşturmak için bir araç
metin üzerinde. Kılavuz hem öğretici hem de referans bölümleri içerir:

Tanım
araca kısa bir genel bakış

Bazı Basit Örnekler

Giriş Dosyasının Formatı

desenler
flex tarafından kullanılan genişletilmiş düzenli ifadeler

Giriş Nasıl Eşleşir?
neyin eşleştirildiğini belirleme kuralları

İşlemler
bir model eşleştirildiğinde ne yapılacağının nasıl belirleneceği

Oluşturulan Tarayıcı
flex'in ürettiği tarayıcıyla ilgili ayrıntılar;
giriş kaynağı nasıl kontrol edilir

Başlangıç ​​Koşulları
tarayıcılarınıza bağlam ekleme ve
"mini tarayıcıları" yönetme

Çoklu Giriş Tamponları
birden çok girdi kaynağının nasıl değiştirileceği; nasıl
dosyalar yerine dizelerden tarama

Dosya Sonu Kuralları
girdinin sonunu eşleştirmek için özel kurallar

Çeşitli Makrolar
eylemler için kullanılabilen makroların bir özeti

Kullanıcının Kullanabileceği Değerler
eylemler için mevcut değerlerin bir özeti

Yacc ile Arayüz Oluşturma
yacc ayrıştırıcıları ile birlikte esnek tarayıcıları bağlama

Opsiyonlar
esnek komut satırı seçenekleri ve "% seçeneği"
Direktifler

Performans Konuları
tarayıcınızın olabildiğince hızlı çalışmasını nasıl sağlarsınız

C++ Tarayıcıları Oluşturma
C++ üretmek için (deneysel) tesis
tarayıcı sınıfları

Lex ve POSIX ile Uyumsuzluklar
flex'in AT&T lex ve POSIX lex'ten farkı nedir?
standart

Teşhis
flex (veya tarayıcılar) tarafından üretilen bu hata mesajları
üretir) anlamları açık olmayabilir

dosyalar
flex tarafından kullanılan dosyalar

Eksiklikler / Hatalar
flex ile ilgili bilinen sorunlar

Ayrıca bakınız
diğer belgeler, ilgili araçlar

Yazar
iletişim bilgilerini içerir

AÇIKLAMA


esnek üretmek için bir araçtır tarayıcılar: metindeki sözcüksel kalıpları tanıyan programlar.
esnek verilen girdi dosyalarını veya dosya adı verilmemişse standart girdisini okur.
oluşturulacak tarayıcının açıklaması. Açıklama, düzenli çiftler şeklindedir.
olarak adlandırılan ifadeler ve C kodu kuralları. esnek çıktı olarak bir C kaynak dosyası oluşturur, lex.yy.c,
hangi bir rutin tanımlar yylex(). Bu dosya derlenmiş ve -LL kütüphane
yürütülebilir bir dosya oluşturun. Yürütülebilir dosya çalıştırıldığında, girdilerini oluşumlar için analiz eder.
düzenli ifadeler. Birini bulduğunda, karşılık gelen C kodunu yürütür.

BAZI BASİT ÖRNEKLER


İlk olarak, birinin nasıl kullanıldığının tadına varmak için bazı basit örnekler esnek. Aşağıdaki esnek
input, "username" dizesiyle karşılaştığında yerini alacak bir tarayıcıyı belirtir.
kullanıcının oturum açma adıyla:

%%
kullanıcı adı printf( "%s", getlogin() );

Varsayılan olarak, eşleşmeyen herhangi bir metin esnek tarayıcı çıktıya kopyalanır, bu nedenle ağ
bu tarayıcının etkisi, giriş dosyasını her bir olayda çıktısına kopyalamaktır.
"kullanıcı adı" genişletildi. Bu girdide sadece bir kural vardır. "kullanıcı adı" model
ve "printf" eylem. "%%" kuralların başlangıcını gösterir.

İşte başka bir basit örnek:

%{
int sayı_satırları = 0, sayı_karakterleri = 0;
%}

%%
\n ++sayı_satırları; ++sayı_karakterler;
. ++sayı_karakterler;

%%
ana()
{
yylex();
printf("satır sayısı = %d, karakter sayısı = %d\n",
sayı_satırları, sayı_karakterleri);
}

Bu tarayıcı, girişindeki karakter sayısını ve satır sayısını sayar (bu
sayımlarla ilgili nihai rapordan başka çıktı üretmez). İlk satır bildiriyor
her ikisinde de erişilebilen iki global, "num_lines" ve "num_chars" yylex() ve
the ana() rutin ikinci "%%" den sonra bildirildi. Biri eşleşen iki kural vardır
bir satırsonu ("\n") ve hem satır sayısını hem de karakter sayısını artırır;
yeni satır dışındaki herhangi bir karakterle eşleşir ("." normal ifadesi ile gösterilir).

Biraz daha karmaşık bir örnek:

/* Pascal benzeri bir dil için tarayıcı */

%{
/* aşağıdaki atof() çağrısı için buna ihtiyacımız var */
#Dahil etmek
%}

Basamak [0-9]
Kimlik [az][a-z0-9]*

%%

{SAYI}+ {
printf("Bir tamsayı: %s (%d)\n", yytext,
atoi(yytext));
}

{SAYI}+"."{SAYI}* {
printf("Bir kayan nokta: %s (%g)\n", yytext,
atof(yytext));
}

if|sonra|başla|son|prosedür|fonksiyon {
printf("Bir anahtar kelime: %s\n", yytext );
}

{ID} printf( "Bir tanımlayıcı: %s\n", yytext );

"+"|"-"|"*"|"/" printf( "Bir operatör: %s\n", yytext );

"{"[^}\n]*"}" /* tek satırlık yorumları bitir */

[ \t\n]+ /* boşlukları ye */

. printf("Tanınmayan karakter: %s\n", yytext );

%%

ana (argc, argv)
int argüman;
karakter **argv;
{
++argv, --argc; /* program adını atla */
if ( argc > 0 )
yyin = fopen( argv[0], "r" );
başka
yyin = stdin;

yylex();
}

Bu, Pascal gibi bir dil için basit bir tarayıcının başlangıcıdır. tanımlar
farklı türleri token kazanabilirsiniz. ve gördüklerini rapor eder.

Bu örneğin detayları aşağıdaki bölümlerde açıklanacaktır.

FORMAT OF L' GİRİŞ DOSYA


The esnek girdi dosyası, yalnızca bir satırla ayrılmış üç bölümden oluşur. %% içinde:

tanımları
%%
kurallar
%%
Kullanıcı kodu

The tanımları bölüm basit bildirimleri içerir isim basitleştirmek için tanımlar
tarayıcı özellikleri ve beyanları başlama koşullar, hangi bir şekilde açıklanmıştır
sonraki bölüm.

Ad tanımları şu şekildedir:

isim tanımı

"Ad", bir harf veya alt çizgi ('_') ile başlayan ve ardından sıfır veya
daha fazla harf, rakam, '_' veya '-' (tire). Tanım ilk başta başlamak üzere alınır
adı takip eden ve satırın sonuna kadar devam eden beyaz boşluk olmayan karakter. bu
tanım daha sonra genişleyecek olan "{name}" kullanılarak ifade edilebilir.
"(tanım)". Örneğin,

Basamak [0-9]
Kimlik [az][a-z0-9]*

"SAYI", tek bir basamakla eşleşen normal bir ifade ve "ID"yi bir
Bir harfin ardından sıfır veya daha fazla harf veya rakamla eşleşen normal ifade. A
sonraki referans

{SAYI}+"."{DIGIT}*

ile aynı

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

ve arkasından bir '.' gelen bir veya daha fazla rakamla eşleşir. ardından sıfır veya daha fazla rakam gelir.

The kurallar bölümünde esnek input, formun bir dizi kuralını içerir:

desen eylemi

desenin girintisiz olması ve eylemin aynı satırda başlaması gerekir.

Kalıpların ve eylemlerin daha fazla açıklaması için aşağıya bakın.

Son olarak, kullanıcı kodu bölümü basitçe şuraya kopyalanır: lex.yy.c kelimesi kelimesine. İçin kullanılır
tarayıcı tarafından çağrılan veya çağrılan eşlik eden rutinler. Bu bölümün varlığı
İsteğe bağlı; yoksa ikinci %% girdi dosyasında da atlanabilir.

Tanımlar ve kurallar bölümlerinde, herhangi bir girintili içindeki metin veya metin %{ ve %} is
çıktıya kelimesi kelimesine kopyalandı (%{} kaldırılmış olarak). %{}'ler girintisiz görünmelidir
satırlarda kendi başlarına.

Kurallar bölümünde, ilk kuraldan önce görünen girintili veya %{} metin kullanılabilir
tarama rutininde yerel olan değişkenleri bildirmek ve (bildirimlerden sonra)
tarama rutini girildiğinde yürütülecek kod. Diğer girintili veya
%{} kural bölümündeki metin çıktıya hala kopyalanıyor, ancak anlamı iyi değil-
tanımlıdır ve derleme zamanı hatalarına neden olabilir (bu özellik, POSIX
uyma; bu tür diğer özellikler için aşağıya bakın).

Tanımlar bölümünde (ancak kurallar bölümünde değil), girintisiz bir yorum (ör.
"/*") ile başlayan satır da bir sonraki "*/" harfine kadar çıktıya aynen kopyalanır.

DESENLER


Girdideki desenler, genişletilmiş bir düzenli ifadeler kümesi kullanılarak yazılır. Bunlar
şunlardır:

x, 'x' karakteriyle eşleşir
. yeni satır hariç herhangi bir karakter (bayt)
[xyz] bir "karakter sınıfı"; bu durumda desen
'x', 'y' veya 'z' ile eşleşir
[abj-oZ] içinde bir aralık bulunan bir "karakter sınıfı"; maçlar
bir 'a', bir 'b', 'j' ile 'o' arasındaki herhangi bir harf,
veya bir 'Z'
[^AZ] bir "olumsuz karakter sınıfı", yani herhangi bir karakter
ama sınıftakiler Bu durumda, herhangi bir
karakter büyük harf HARİÇ.
[^AZ\n] büyük harf HARİÇ herhangi bir karakter veya
yeni satır
r* sıfır veya daha fazla r, burada r herhangi bir normal ifadedir
r+ bir veya daha fazla r
r? sıfır veya bir r (yani, "isteğe bağlı bir r")
r{2,5} iki ila beş r arasında herhangi bir yerde
r{2,} iki veya daha fazla r
r{4} tam olarak 4 r
{name} "ad" tanımının genişletilmesi
(yukarıyı görmek)
"[xyz]\"foo"
değişmez dize: [xyz]"foo
\X X bir 'a', 'b', 'f', 'n', 'r', 't' veya 'v' ise,
sonra \x'in ANSI-C yorumu.
Aksi takdirde, değişmez bir 'X' (kaçmak için kullanılır
'*' gibi operatörler)
\0 bir NUL karakteri (ASCII kodu 0)
\123 sekizlik değeri 123 olan karakter
\x2a onaltılık değeri 2a olan karakter
(r) bir r ile eşleşir; parantezler geçersiz kılmak için kullanılır
öncelik (aşağıya bakınız)

rs normal ifadesi r ve ardından
düzenli ifadeler; "birleştirme" denir

r|s ya bir r ya da bir s

r/s ve r ancak yalnızca arkasından bir s geliyorsa. bu
s ile eşleşen metin belirlenirken dahil edilir
bu kuralın "en uzun eşleşme" olup olmadığı,
ancak daha sonra girişe geri döndürülür
eylem yürütülür. Yani sadece eylem
r ile eşleşen metni görür. Bu tip
desenin izleyen bağlamı" olarak adlandırılır.
(Esneyen bazı r/s kombinasyonları vardır.
doğru eşleşemez; içindeki notlara bakın
Aşağıdaki Eksiklikler / Hatalar bölümü
"tehlikeli takip eden bağlam".)
^r an r, ancak yalnızca satırın başında (yani,
taramaya yeni başladığınızda veya bir
yeni satır tarandı).
r$ an r, ancak yalnızca bir satırın sonunda (yani, sadece
yeni satırdan önce). "r/\n" ile eşdeğerdir.

Flex'in "yeni satır" kavramının tam olarak
flex'i derlemek için kullanılan C derleyicisi ne olursa olsun
'\n' olarak yorumlar; özellikle, bazı DOS'larda
sistemlerindeki \r'leri filtrelemeniz gerekir.
kendiniz girin veya "r$" için açıkça r/\r\n kullanın.

r an r, ancak yalnızca başlangıç ​​koşulunda s (bkz.
başlangıç ​​koşullarının tartışılması için aşağıda)
r
aynı, ancak başlangıç ​​koşullarının herhangi birinde s1
s2 veya s3
<*>r bir r herhangi bir başlangıç ​​koşulunda, hatta özel bir koşulda.

< > dosya sonu
< >
s1 veya s2 başlangıç ​​koşulundayken dosya sonu

Bir karakter sınıfının içinde, tüm normal ifade operatörlerinin özel özelliklerini kaybettiğini unutmayın.
kaçış ('\') ve karakter sınıfı operatörleri, '-', ']' ve
sınıfın başlangıcı, '^'.

Yukarıda listelenen normal ifadeler, önceliğe göre en yüksekten başlayarak gruplandırılmıştır.
öncelik en üstte en altta en alta doğru. Birlikte gruplananlar eşit
öncelik. Örneğin,

foo|bar*

aynıdır

(foo)|(ba(r*))

'*' operatörü birleştirme işleminden daha yüksek önceliğe sahip olduğundan ve birleştirme daha yüksek olduğundan
alternatiften ('|'). Bu model bu nedenle eşleşir ya "foo" dizisi or the
"ba" dizesi, ardından sıfır veya daha fazla r. "Foo" veya sıfır veya daha fazla "bar" ile eşleştirmek için şunu kullanın:

foo|(çubuk)*

ve sıfır veya daha fazla "foo" veya "bar" ile eşleştirmek için:

(foo|bar)*

Karakterlere ve karakter aralıklarına ek olarak, karakter sınıfları ayrıca şunları içerebilir:
karakter sınıfı ifade. Bunlar içine alınmış ifadelerdir. [: ve :] sınırlayıcı
(karakter sınıfının '[' ve ']' arasında görünmesi gerekir; diğer
öğeler karakter sınıfı içinde de oluşabilir). Geçerli ifadeler şunlardır:

[:alnum:] [:alpha:] [:boş:]
[:cntrl:] [:rakam:] [:grafik:]
[:alt:] [:baskı:] [:punkt:]
[:boşluk:] [:üst:] [:xdigit:]

Bu ifadelerin tümü, karşılık gelen karakter kümesine eşdeğer bir karakter kümesini belirtir.
standart C isXXX işlev. Örneğin, [:alnum:] hangi karakterleri belirtir
isalnum() true döndürür - yani, herhangi bir alfabetik veya sayısal. Bazı sistemler sağlamaz
boş(), yani esnek tanımlar [:boşluk:] boş veya sekme olarak.

Örneğin, aşağıdaki karakter sınıflarının tümü eşdeğerdir:

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

Tarayıcınız büyük/küçük harfe duyarlı değilse ( -i bayrak), ardından [:üst:] ve [:daha düşük:] vardır
eşdeğerdir [:alfa:].

Kalıplarla ilgili bazı notlar:

- Yukarıdaki "[^AZ]" örneği gibi olumsuzlanmış bir karakter sınıfı irade maç a Yeni hat
"\n" (veya eşdeğer bir kaçış dizisi) açıkça karakterlerden biri değilse
olumsuzlanan karakter sınıfında bulunur (örneğin, "[^AZ\n]"). Bu kaç farklı
diğer normal ifade araçları, reddedilen karakter sınıflarını ele alır, ancak ne yazık ki
tutarsızlık tarihsel olarak yerleşiktir. Yeni satırları eşleştirmek şu anlama gelir:
[^"]* gibi bir kalıp, başka bir alıntı olmadığı sürece girdinin tamamıyla eşleşebilir.
giriş.

- Bir kuralın sonunda en fazla bir bağlam örneği olabilir ('/' operatörü veya
'$' operatörü). Başlangıç ​​koşulu, '^' ve "< >" desenler yalnızca
bir kalıbın başlangıcı ve '/' ve '$' ile olduğu gibi gruplandırılamaz
parantez içinde. Bir kuralın başında geçmeyen bir '^' veya bir '$'
Bir kuralın sonunda oluşmayan, özel özelliklerini kaybeder ve
normal bir karakter olarak kabul edilir.

Aşağıdakiler yasa dışıdır:

foo/bar$
ahmak Çubuk

Bunlardan ilkinin "foo/bar\n" olarak yazılabileceğine dikkat edin.

Aşağıdakiler, '$' veya '^' karakterlerinin normal bir karakter olarak ele alınmasına neden olur:

foo|(çubuk$)
foo|^bar

İstenen şey bir "foo" veya bir çubuk-sonra-a-yeni satır ise, aşağıdakiler olabilir:
kullanılır (özel '|' eylemi aşağıda açıklanmıştır):

foo |
bar$ /* işlem buraya gelir */

Benzer bir numara, bir satırın başındaki bir çizgiyi veya bir çubuğu eşleştirmek için işe yarayacaktır.

NASIL L' GİRİŞ IS EŞLEŞTİRİLDİ


Oluşturulan tarayıcı çalıştırıldığında, eşleşen dizeleri arayan girdisini analiz eder.
desenlerinden herhangi biri. Birden fazla eşleşme bulursa, en çok eşleşeni alır.
metin (sondaki bağlam kuralları için bu, sondaki bölümün uzunluğunu içerir, hatta
ancak daha sonra girişe döndürülecektir). İki veya daha fazla eşleşme bulursa
aynı uzunlukta, ilk sırada listelenen kural esnek girdi dosyası seçilir.

Eşleşme belirlendikten sonra, eşleşmeye karşılık gelen metin ( jeton) is
genel karakter işaretçisinde kullanıma sunuldu ymetin, ve dünyadaki uzunluğu
tamsayı Yyleng. The aksiyon eşleşen desene karşılık gelen daha sonra yürütülür (bir daha
eylemlerin ayrıntılı açıklaması aşağıdadır) ve ardından kalan girdi taranır.
başka bir maç.

Eşleşme bulunamazsa, o zaman varsayılan kural yürütülür: girişteki bir sonraki karakter
eşleştiği kabul edilir ve standart çıktıya kopyalanır. Böylece en basit yasal esnek
giriş:

%%

girişini (her seferinde bir karakter) basitçe kopyalayan bir tarayıcı üreten
çıktı.

Bunu not et ymetin iki farklı şekilde tanımlanabilir: ya bir karakter olarak işaretçi ya da
bir karakter dizisi. Hangi tanımı kontrol edebilirsiniz esnek birini dahil ederek kullanır
özel direktifler %Işaretçi or %dizi esnekliğinizin ilk (tanımlar) bölümünde
giriş. Varsayılan %Işaretçi, kullanmadığınız sürece -l lex uyumluluk seçeneği,
dava ymetin dizi olacak. kullanmanın avantajı %Işaretçi önemli ölçüde daha hızlı
tarama ve çok büyük belirteçleri eşleştirirken arabellek taşması yok (eğer tükenmezseniz)
dinamik bellek). Dezavantajı, eylemlerinizin nasıl olabileceği konusunda kısıtlı olmanızdır.
değiştirmek ymetin (sonraki bölüme bakın) ve çıktı() işlevi yok eder
mevcut içeriği ymetin, hareket ederken önemli bir taşıma baş ağrısı olabilir
farklı arasında Lex sürümleri.

avantajı %dizi daha sonra değiştirebileceğiniz ymetin gönlünüze göre ve
çağrıları çıktı() yok etme, mahvetme ymetin (aşağıya bakınız). Ayrıca, mevcut Lex programlar
bazen erişim ymetin harici olarak formun bildirimlerini kullanarak:
harici karakter yytext[];
ile kullanıldığında bu tanım hatalıdır. %Işaretçi, ama için doğru %sıralamak.

%dizi tanımlar ymetin dizisi olmak YYLMAX oldukça varsayılan olan karakterler
büyük değer. Boyutu basitçe #define'ing ile değiştirebilirsiniz. YYLMAX içinde farklı bir değere
senin ilk bölümü esnek giriş. ile yukarıda belirtildiği gibi %Işaretçi yytext büyür
büyük belirteçleri barındırmak için dinamik olarak. Bu senin anlamına gelirken %Işaretçi tarayıcı olabilir
çok büyük belirteçleri barındırın (tüm yorum bloklarını eşleştirmek gibi), aklınızda bulundurun
tarayıcının her yeniden boyutlandırılması gerektiğinde ymetin ayrıca tüm belirteci yeniden taramalıdır.
başlangıç, bu nedenle bu tür belirteçleri eşleştirmek yavaş olabilir. ymetin şu anda yapıyor değil
bir çağrı varsa dinamik olarak büyümek çıktı() çok fazla metnin geri itilmesine neden olur; Bunun yerine,
bir çalışma zamanı hatası sonuçları.

Ayrıca kullanamayacağınızı da unutmayın. %dizi C++ tarayıcı sınıflarıyla ( c ++ seçenek; aşağıya bakınız).

EYLEMLER


Bir kuraldaki her kalıp, herhangi bir isteğe bağlı C ifadesi olabilen karşılık gelen bir eyleme sahiptir.
Desen, çıkış yapılmayan ilk boşluk karakterinde biter; satırın geri kalanı
onun eylemidir. Eylem boşsa, desen eşleştiğinde giriş belirteci
basitçe atılır. Örneğin, silen bir programın belirtimi buradadır.
girdisinden tüm "zap me" oluşumları:

%%
"zapt beni"

(Girişteki diğer tüm karakterleri eşleşecekleri için çıkışa kopyalayacaktır.
varsayılan kurala göre.)

İşte birden fazla boşluğu ve sekmeyi tek bir boşluğa sıkıştıran bir program ve
bir satırın sonunda bulunan boşlukları atar:

%%
[ \t]+ putchar(' ');
[ \t]+$ /* bu belirteci yoksay */

Eylem bir '{' içeriyorsa, eylem '}' dengelemesi bulunana kadar sürer ve
eylem birden fazla satırı geçebilir. esnek C dizelerini ve yorumlarını bilir ve olmayacak
içlerinde bulunan parantezler tarafından kandırılır, ancak eylemlerin başlamasına da izin verir %{ ve olacak
eylemi bir sonrakine kadar tüm metin olarak düşünün %} (sıradan diş tellerinden bağımsız olarak
eylemin içinde).

Yalnızca dikey çubuktan ('|') oluşan bir eylem, "bir sonraki
kural." Bir örnek için aşağıya bakın.

Eylemler, aşağıdakiler dahil olmak üzere isteğe bağlı C kodunu içerebilir: dönüş bir değer döndürmek için ifadeler
hangi rutin denirse yylex(). Her zaman yylex() denir, işlemeye devam eder
en son kaldığı yerden dosyanın sonuna ulaşana veya yürütülene kadar belirteçler
geridönüş.

Eylemleri değiştirmek ücretsizdir ymetin uzatmak dışında (karakter eklemek
end--bunlar giriş akışındaki sonraki karakterlerin üzerine yazar). Ancak bu olmaz
kullanırken uygula %dizi (yukarıyı görmek); bu durumda, ymetin herhangi bir şekilde serbestçe değiştirilebilir
yol.

Eylemleri değiştirmek ücretsizdir Yyleng eylem ayrıca şunları içeriyorsa, bunu yapmamaları dışında
kullanımı daha fazla() (aşağıya bakınız).

Bir eyleme dahil edilebilecek bir dizi özel direktif vardır:

- EKO yytext'i tarayıcının çıktısına kopyalar.

- BAŞLA ardından bir başlangıç ​​koşulunun adı, tarayıcıyı
ilgili başlatma koşulu (aşağıya bakın).

- REDDET tarayıcıyı eşleşen "ikinci en iyi" kurala geçmeye yönlendirir
girdi (veya girdinin öneki). Kural, yukarıda açıklandığı gibi seçilir.
"Giriş Nasıl Eşleştirilir" ve ymetin ve Yyleng uygun şekilde kurun. Olabilir
ya orijinal olarak seçilen kural kadar metinle eşleşen ancak gelen
daha sonra esnek girdi dosyası veya daha az metinle eşleşen bir dosya. Örneğin,
takip etmek hem girdideki kelimeleri sayar hem de özel rutini çağırır ()
"frob" görüldüğünde:

int kelime_sayısı = 0;
%%

frob özel(); REDDETMEK;
[^ \t\n]+ ++kelime_sayısı;

Olmadan REDDETMEK, girdideki herhangi bir "frob" kelime olarak sayılmaz, çünkü
tarayıcı normalde belirteç başına yalnızca bir eylem gerçekleştirir. çoklu REDDET vardır
izin verilir, her biri o anda etkin olan kurala göre bir sonraki en iyi seçeneği bulur. İçin
örneğin, aşağıdaki tarayıcı "abcd" belirtecini taradığında, şunu yazacaktır:
çıktıya "abcdabcaba":

%%
bir |
AB |
ABC |
abcd ECHO; REDDETMEK;
.|\n /* eşleşmeyen tüm karakterleri ye */

(İlk üç kural, özel '|' kullandığından dördüncünün eylemini paylaşır.
eylem.) REDDET tarayıcı açısından özellikle pahalı bir özelliktir
verim; içinde kullanılıyorsa herhangi tarayıcının eylemleri yavaşlayacak herşey of
tarayıcının eşleşmesi. Üstelik, REDDET ile kullanılamaz -Çf or CF
seçenekler (aşağıya bakın).

Ayrıca, diğer özel eylemlerden farklı olarak, REDDET bir şube; kod
eylemde hemen ardından değil idam edilecek.

- daha fazla() tarayıcıya, bir sonraki kural eşleşmesinde ilgili
belirteç olmalıdır ekli şu anki değeri üzerine ymetin yerine koymak yerine.
Örneğin, "mega-kludge" girişi verildiğinde, aşağıdakiler "mega-mega-
kludge" çıktısına:

%%
mega- ECHO; ymore();
çamur ECHO;

İlk "mega-" eşleştirilir ve çıktıya yansıtılır. Sonra "kludge" eşleştirilir, ancak
önceki "mega-" hala başında takılıyor ymetin böylece EKO
"kludge" kuralı için aslında "mega-kludge" yazacaktır.

kullanımına ilişkin iki not yymore(). İlk olarak, daha fazla() değerine bağlıdır Yyleng
geçerli jetonun boyutunu doğru bir şekilde yansıtıyor, bu nedenle değiştirmemelisiniz Yyleng eğer
kullanıyorlar yymore(). İkincisi, varlığı daha fazla() tarayıcının eyleminde bir
tarayıcının eşleştirme hızında küçük performans cezası.

- yılsız(n) ilk hariç hepsini döndürür n geçerli jetonun karakterleri geri
tarayıcı bir sonrakini aradığında yeniden taranacakları giriş akışı
maç. ymetin ve Yyleng uygun şekilde ayarlanır (örn. Yyleng şimdi olacak
eşittir n ). Örneğin, "foobar" girişinde aşağıdakiler yazacaktır
"foobarbar":

%%
foobar ECHO; yılsız(3);
[az]+ EKO;

0 ile arasında bir argüman yılsız geçerli giriş dizisinin tamamının taranmasına neden olur
yine. Tarayıcının daha sonra girdisini nasıl işleyeceğini değiştirmediyseniz
(kullanarak BAŞLAMAK, örneğin), bu sonsuz bir döngü ile sonuçlanacaktır.

Bunu not et yılsız bir makrodur ve diğer dosyalardan değil, yalnızca esnek girdi dosyasında kullanılabilir.
kaynak dosyaları.

- çıkarılmamış(c) karakteri koyar c giriş akışına geri dönün. Bir sonraki olacak
karakter tarandı. Aşağıdaki eylem mevcut jetonu alacak ve buna neden olacaktır.
parantez içinde yeniden taranacaktır.

{
int ben;
/* yytext'i kopyalayın çünkü unput() yytext'i çöpe atar */
char *yycopy = strdup(yytext);
unput(')');
için ( i = yyleng - 1; i >= 0; --i )
unput(yycopy[i]);
unput('(');
ücretsiz (yycopy);
}

Unutmayın ki, her biri çıktı() verilen karakteri geri koyar başlangıç arasında
giriş akışı, dizeleri geriye iterek önden arkaya yapılmalıdır.

kullanırken önemli bir potansiyel sorun çıktı() eğer kullanıyorsan %Işaretçi (
varsayılan), bir çağrı çıktı() bunları tahrip içeriği ymetin, en sağından başlayarak
karakter ve her aramada sola doğru bir karakter yutma. değere ihtiyacınız varsa
bir çağrıdan sonra korunan yytext çıktı() (yukarıdaki örnekte olduğu gibi),
önce başka bir yere kopyalayın veya tarayıcınızı kullanarak oluşturun %dizi bunun yerine (bkz. Giriş Nasıldır?
Eşleşti).

Son olarak, geri koyamayacağınızı unutmayın. EOF giriş akışını bir işaretle işaretlemeye çalışmak için
dosyanın sonu.

- giriş() giriş akışından sonraki karakteri okur. Örneğin, aşağıdakiler
C yorumlarını yemenin bir yolu:

%%
"/*" {
int c;

için ( ; ; )
{
while ( (c = input()) != '*' &&
c != EOF)
; /* yorum metnini ye */

if (c == '*' )
{
while ( (c = input()) == '*' )
;
if (c == '/' )
kırmak; /* sonunu bulduk */
}

eğer ( c == EOF )
{
error("EOF yorumda");
break;
}
}
}

(Tarayıcı kullanılarak derlenmişse, C++, sonra giriş() bunun yerine başvurulur
olarak yyingiriş(), ile bir isim çakışmasını önlemek için C + + adına göre akış
giriş.)

- YY_FLUSH_BUFFER tarayıcının dahili arabelleğini temizler, böylece bir dahaki sefere
tarayıcı bir belirteci eşleştirmeye çalışırsa, önce arabelleği kullanarak yeniden doldurur. YY_GİRİŞ
(aşağıdaki Oluşturulan Tarayıcıya bakın). Bu eylem, daha özel bir durum
genel yy_flush_buffer() aşağıda Çoklu Giriş bölümünde açıklanan işlev
Tamponlar.

- yysonlandırma() bir eylemde return ifadesi yerine kullanılabilir. o
tarayıcıyı sonlandırır ve tarayıcıyı arayan kişiye "tümü" şeklinde bir 0 döndürür.
bitti". Varsayılan olarak, yysonlandırma() bir dosya sonu olduğunda da çağrılır
karşılaşıldı. Bu bir makrodur ve yeniden tanımlanabilir.

L' OLUŞTURULDU TARAYICI


Çıktısı esnek dosya mı lex.yy.c, tarama rutinini içeren yylex(), a
belirteçleri eşleştirmek için kullandığı tablo sayısı ve bir dizi yardımcı rutin ve
makrolar. Varsayılan olarak, yylex() aşağıdaki gibi ilan edilir:

int yylex()
{
...çeşitli tanımlar ve buradaki eylemler...
}

(Ortamınız işlev prototiplerini destekliyorsa, "int yylex( void )" olacaktır.)
Bu tanım "YY_DECL" makrosu tanımlanarak değiştirilebilir. Örneğin,
kullanımı:

#define YY_DECL kayan nokta lexscan( a, b ) kayan nokta a, b;

tarama rutinine isim vermek için sözlük taraması, bir şamandıra döndürme ve iki şamandıra olarak almak
argümanlar. K&R-tarzı/olmayan kullanarak tarama rutinine argümanlar verirseniz unutmayın.
prototiplenmiş işlev bildirimi, tanımı noktalı virgül (;) ile sonlandırmalısınız.

Her ne zaman yylex() çağrılır, global girdi dosyasındaki belirteçleri tarar yin (hangi
varsayılan olarak stdin'dir). Dosya sonuna ulaşana kadar devam eder (bu noktada
0 değerini döndürür veya eylemlerinden biri bir dönüş ifadesi.

Tarayıcı bir dosyanın sonuna ulaşırsa, sonraki çağrılar aşağıdakilerden biri olmadıkça tanımsızdır. yin
yeni bir girdi dosyasına yönlendirilirse (bu durumda tarama o dosyadan devam eder) veya
yeniden başlat() denir. yeniden başlat() bir argüman alır, bir DOSYA * işaretçi (olabilir
sıfır, eğer kurduysan YY_GİRİŞ dışındaki bir kaynaktan taramak için yyin), ve başlatır
yin bu dosyadan taramak için. Esasen, sadece arasında hiçbir fark yoktur.
atama yin yeni bir girdi dosyasına veya kullanarak yeniden başlat() böyle yaparak; ikincisi mevcut
önceki sürümleriyle uyumluluk için esnek, ve geçiş yapmak için kullanılabildiğinden
dosyaları taramanın ortasında girin. Akımı atmak için de kullanılabilir
giriş arabelleği, bir argümanla çağırarak yyin; ama kullanmak daha iyi YY_FLUSH_BUFFER
(yukarıyı görmek). Bunu not et yeniden başlat() yok değil başlangıç ​​koşulunu sıfırla BAŞLANGIÇ (görmek
Başlangıç ​​Koşulları, aşağıda).

If yylex() yürütülmesi nedeniyle taramayı durdurur dönüş eylemlerden birindeki ifade,
tarayıcı daha sonra tekrar çağrılabilir ve taramaya kaldığı yerden devam eder.

Varsayılan olarak (ve verimlilik amacıyla), tarayıcı yerine blok okumaları kullanır.
basit getc() karakter okumak için çağrılar eyyin. Girdisini nasıl elde ettiğinin doğası,
tanımlanarak kontrol edilebilir. YY_GİRİŞ makro. YY_INPUT'ın arama sırası:
"YY_INPUT(tampon,sonuç,maks_boyut)". Onun eylemi maksimum_boyut içindeki karakterler
karakter dizisi buf ve tamsayı değişkeninde dönüş sonuç ya sayısı
EOF'yi belirtmek için okunan karakterler veya YY_NULL (Unix sistemlerinde 0) sabiti. Varsayılan
YY_INPUT, "yyin" global dosya işaretçisinden okur.

YY_INPUT için örnek bir tanım (giriş dosyasının tanımlar bölümünde):

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

Bu tanım, girdi işlemeyi her seferinde bir karakter oluşacak şekilde değiştirecektir.

Tarayıcı, YY_INPUT'tan bir dosya sonu bildirimi aldığında, daha sonra aşağıdakileri kontrol eder:
yywrap() işlev. Eğer yywrap() false (sıfır) döndürür, ardından işlevin
devam etti ve kurdu yin başka bir girdi dosyasına işaret eder ve tarama devam eder. Eğer
true (sıfır olmayan) döndürür, ardından tarayıcı sona erer ve arayana 0 döndürür. Not
her iki durumda da başlangıç ​​koşulu değişmeden kalır; yapar değil geri dönmek İLK.

Kendi sürümünüzü sağlamazsanız yywrap(), o zaman ya kullanmalısın %seçenek
noyywrap (bu durumda tarayıcı sanki yywrap() döndürüldü 1) veya yapmanız gerekir
ile bağlantı kur -LL her zaman 1 döndüren rutinin varsayılan sürümünü elde etmek için.

Dosyalar yerine bellek içi arabelleklerden tarama yapmak için üç rutin mevcuttur:
yy_scan_string(), yy_scan_bytes(), ve yy_scan_buffer(). Aşağıdaki tartışmaya bakın
Çoklu Giriş Tamponları bölümünde.

Tarayıcı yazıyor EKO çıkış sen global (varsayılan, stdout), olabilecek
kullanıcı tarafından basitçe başka birine atayarak yeniden tanımlanır. DOSYA Işaretçi.

BAŞLANGIÇ KOŞULLAR


esnek kuralları koşullu olarak etkinleştirmek için bir mekanizma sağlar. Deseni olan herhangi bir kural
ön eki " " yalnızca tarayıcı belirtilen başlangıç ​​koşulunda olduğunda etkin olacaktır.
"sk". Örneğin,

[^"]* { /* string gövdesini ye... */
Kendi ID’n ile mağazalarını oluştur
}

yalnızca tarayıcı "STRING" başlangıç ​​koşulundayken etkin olacaktır ve

\. { /* bir kaçışı ele al ... */
Kendi ID’n ile mağazalarını oluştur
}

yalnızca mevcut başlatma koşulu "INITIAL", "STRING" veya "STRING" olduğunda etkin olacaktır.
"ALINTI YAPMAK".

Başlangıç ​​koşulları, girişin tanımlar (ilk) bölümünde şu şekilde belirtilir:
ya ile başlayan girintisiz satırlar %s or %x ardından bir isim listesi gelir. Eski
beyan dahil başlangıç ​​koşulları, ikincisi özel başlangıç ​​koşulları. Bir başlangıç
koşulu kullanılarak etkinleştirilir. BAŞLA eylem. Sıradakine kadar BAŞLA eylem yürütülür,
verilen başlangıç ​​koşuluna sahip kurallar aktif olacak ve diğer başlangıç ​​koşullarına sahip kurallar
inaktif olacaktır. Başlangıç ​​koşulu ise dahil, o zaman başlangıçsız kurallar
koşullar da aktif olacaktır. Eğer öyleyse özel, sonra bir tek nitelikli kurallar
başlangıç ​​koşulu aktif olacaktır. Aynı özel başlangıca bağlı bir dizi kural
koşul, diğer kurallardan herhangi birinden bağımsız olan bir tarayıcıyı tanımlar. esnek
giriş. Bu nedenle, özel başlatma koşulları "mini-
girişin sözdizimsel olarak diğerlerinden farklı olan kısımlarını tarayan tarayıcılar"
(örneğin, yorumlar).

Kapsayıcı ve özel başlangıç ​​koşulları arasındaki fark hala biraz
belirsiz, işte ikisi arasındaki bağlantıyı gösteren basit bir örnek. set
kurallar:

%s örneği
%%

foo do_something();

bar bir şey_else();

eşdeğerdir

%x örnek
%%

foo do_something();

bar bir şey_else();

Olmadan niteleyici, bar ikinci örnekteki desen olmazdı
başlangıç ​​durumundayken aktif (yani eşleşemedi) örnek. Eğer sadece kullandıysak
Hak kazanmak için bar, yine de, o zaman sadece aktif olurdu örnek ve içinde değil İLK, süre
ilk örnekte her ikisinde de etkindir, çünkü ilk örnekte örnek başlama
koşul bir dahil (%S) başlangıç ​​koşulu.

Ayrıca, özel başlangıç ​​koşulu belirtecinin <*> her başlangıç ​​koşuluyla eşleşir.
Böylece yukarıdaki örnek de yazılabilirdi;

%x örnek
%%

foo do_something();

<*>bir şey çubuğu_else();

Varsayılan kural ( EKO eşleşmeyen herhangi bir karakter) başlangıç ​​koşullarında etkin kalır. o
şuna eşittir:

<*>.|\n EKO;

BAŞLA(0) yalnızca başlangıç ​​koşulu olmayan kuralların olduğu orijinal duruma döner
aktif. Bu durum aynı zamanda "BAŞLANGIÇ" başlangıç ​​koşulu olarak da adlandırılabilir, bu nedenle
BAŞLA(BAŞLANGIÇ) eşdeğerdir BAŞLA(0). (Başlangıç ​​koşulunun etrafındaki parantezler
ad gerekli değildir, ancak iyi stil olarak kabul edilir.)

BAŞLA eylemler, kurallar bölümünün başında girintili kod olarak da verilebilir.
Örneğin, aşağıdakiler tarayıcının "ÖZEL" başlatma koşuluna girmesine neden olur.
her ne zaman yylex() çağrılır ve global değişken enter_özel doğru:

int enter_özel;

%x ÖZEL
%%
if ( enter_özel )
BAŞLA(ÖZEL);

fahişe
...daha fazla kural takip eder...

Başlatma koşullarının kullanımlarını göstermek için, burada iki farklı özellik sağlayan bir tarayıcı verilmiştir.
"123.456" gibi bir dizenin yorumları. Varsayılan olarak, onu üç jeton olarak değerlendirecektir,
"123" tamsayı, bir nokta ('.') ve "456" tamsayı. Ama dize önceyse
satırında daha önce "expect-floats" dizesiyle tek bir belirteç olarak ele alacaktır,
kayan nokta sayısı 123.456:

%{
#Dahil etmek
%}
%s bekleniyor

%%
BAŞLA(bekle);

[0-9]+"."[0-9]+ {
printf( "bir kayan nokta bulundu, = %f\n",
atof(yytext));
}
\n {
/* bu satırın sonu, yani
* başka bir "beklenen numaraya" ihtiyacımız var
* daha fazlasını tanımadan önce
* sayılar
*/
BAŞLA(BAŞLANGIÇ);
}

[0-9]+ {
printf( "bir tamsayı bulundu, = %d\n",
atoi(yytext));
}

"." printf("bir nokta bulundu\n");

Burada, C yorumlarını tanıyan (ve atan) ve bir yandan da
geçerli giriş satırı

%x yorum
%%
int satır_sayısı = 1;

"/*" BEGIN(yorum);

[^*\n]* /* '*' olmayan her şeyi ye */
"*"+[^*/\n]* /* '*'leri '/'ler */ takip etmez
\n ++satır_sayısı;
"*"+"/" BEGIN(BAŞLANGIÇ);

Bu tarayıcı, her bir kuralla mümkün olduğu kadar çok metni eşleştirmek için biraz zahmete giriyor.
Genel olarak, yüksek hızlı bir tarayıcı yazmaya çalışırken mümkün olduğunca
Her kural, büyük bir kazanç olduğu için.

Başlangıç ​​koşulları adlarının gerçekten tamsayı değerler olduğunu ve bu şekilde saklanabileceğini unutmayın.
Böylece, yukarıdakiler aşağıdaki şekilde genişletilebilir:

%x yorum foo
%%
int satır_sayısı = 1;
int yorum_çağrıcısı;

"/*" {
comment_caller = BAŞLANGIÇ;
BAŞLA(yorum);
}

Kendi ID’n ile mağazalarını oluştur

"/*" {
yorum_çağrı = foo;
BAŞLA(yorum);
}

[^*\n]* /* '*' olmayan her şeyi ye */
"*"+[^*/\n]* /* '*'leri '/'ler */ takip etmez
\n ++satır_sayısı;
"*"+"/" BEGIN(comment_caller);

Ayrıca, tamsayı değerli kullanarak mevcut başlatma koşuluna erişebilirsiniz. YY_START
makro. Örneğin, yukarıdaki atamalar yorum_çağrıcısı bunun yerine yazılabilir

yorum_arayan = YY_START;

Flex sağlar YİSTAT takma ad olarak YY_START (AT&T tarafından kullanılan bu olduğundan lex).

Başlangıç ​​koşullarının kendi ad-alanına sahip olmadığına dikkat edin; %s ve %x adları bildiriyor
#define ile aynı şekilde.

Son olarak, burada özel başlangıç ​​kullanılarak C-tarzı alıntılanmış dizelerin nasıl eşleştirileceğine dair bir örnek verilmiştir.
genişletilmiş kaçış dizileri de dahil olmak üzere koşullar (ancak bir dize denetimi dahil değil)
bu çok uzun):

%x dize

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

\" string_buf_ptr = string_buf; BEGIN(str);

\" { /* kapanış teklifini gördüm - hepsi bitti */
BAŞLA(BAŞLANGIÇ);
*string_buf_ptr = '\0';
/* string sabit belirteç tipini döndür ve
* ayrıştırıcı için değer
*/
}

\n {
/* hata - sonlandırılmamış dize sabiti */
/* hata mesajı oluştur */
}

\\[0-7]{1,3} {
/* sekizli kaçış dizisi */
int sonuç;

(geçersiz) sscanf( yytext + 1, "%o", &sonuç );

if ( sonuç > 0xff )
/* hata, sabit sınır dışı */

*string_buf_ptr++ = sonuç;
}

\\[0-9]+ {
/* hata üret - hatalı kaçış sırası; bir şey
* '\48' veya '\0777777' gibi
*/
}

\\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 = ymetin;

süre ( *yptr )
*string_buf_ptr++ = *yptr++;
}

Çoğu zaman, örneğin yukarıdaki bazı örneklerde olduğu gibi, bir sürü kural yazarsınız.
hepsinden önce aynı başlangıç ​​koşulu/koşulları gelir. Flex bunu biraz daha kolay ve temiz hale getirir
başlangıç ​​koşulu kavramını tanıtarak dürbün. Bir başlangıç ​​koşulu kapsamı şu şekilde başlatılır:

{

nerede SC'lerin bir veya daha fazla başlangıç ​​koşulunun listesidir. Başlangıç ​​koşulu kapsamı içinde,
her kuralın otomatik olarak öneki vardır uygulanana kadar, '}' hangisiyle eşleşir
ilk '{'. Yani, örneğin,

{
"\\n" dönüş '\n';
"\\r" dönüş '\r';
"\\f" dönüş '\f';
"\\0" '\0' döndürür;
}

şuna eşittir:

"\\n" dönüş '\n';
"\\r" dönüş '\r';
"\\f" dönüş '\f';
"\\0" '\0' döndürür;

Başlangıç ​​koşulu kapsamları iç içe olabilir.

Başlangıç ​​koşulları yığınlarını değiştirmek için üç rutin mevcuttur:

geçersiz yy_Push_state(int) yeni_durum)
mevcut başlangıç ​​koşulunu başlangıç ​​koşulu yığınının en üstüne iter ve
geçiş yapar yeni_durum sanki sen kullanmışsın BAŞLA yeni_durum (bu başlangıcı hatırla
koşul adları da tam sayılardır).

geçersiz yy_pop_state()
yığının üstünü açar ve üzerinden geçer BAŞLAMAK.

int yy_top_state()
yığının içeriğini değiştirmeden yığının üstünü döndürür.

Başlangıç ​​koşulu yığını dinamik olarak büyür ve bu nedenle yerleşik boyut sınırlaması yoktur. Eğer
bellek tükendi, program yürütme iptal edildi.

Başlangıç ​​koşulu yığınlarını kullanmak için tarayıcınızın bir %seçenek yığın direktif (bkz.
Aşağıdaki seçenekler).

BİRDEN GİRİŞ TAMPONLAR


Bazı tarayıcılar ("include" dosyalarını destekleyenler gibi) birkaç tarayıcıdan okuma gerektirir.
giriş akışları Olarak esnek tarayıcılar büyük miktarda arabelleğe alma yapar, nerede olduğu kontrol edilemez
sonraki giriş sadece bir yazı yazarak okunacaktır. YY_GİRİŞ duyarlı olan
tarama bağlamı. YY_GİRİŞ yalnızca tarayıcı arabelleğinin sonuna ulaştığında çağrılır,
gerektiren bir "include" gibi bir ifadeyi taradıktan sonra uzun bir süre olabilir.
giriş kaynağının değiştirilmesi.

Bu tür sorunları müzakere etmek için, esnek oluşturmak ve değiştirmek için bir mekanizma sağlar
çoklu giriş arabellekleri arasında. Aşağıdakiler kullanılarak bir giriş arabelleği oluşturulur:

YY_BUFFER_STATE yy_create_buffer( DOSYA *dosya, int boyutu)

ki bir DOSYA işaretçi ve bir boyut ve verilen dosyayla ilişkili bir arabellek oluşturur
ve tutacak kadar büyük boyut karakterler (şüpheniz olduğunda, YY_BUF_SIZE boyut için).
bir döndürür YY_BUFFER_STATE tanıtıcı, daha sonra diğer rutinlere geçirilebilir (bkz.
altında). YY_BUFFER_STATE type opak bir işaretçidir yapı yy_buffer_durumu
yapı, böylece YY_BUFFER_STATE değişkenlerini güvenle başlatabilirsiniz. ((YY_BUFFER_STATE) 0)
İsterseniz, girişi doğru bir şekilde bildirmek için opak yapıya da bakın.
tarayıcınızınki dışındaki kaynak dosyalarda arabellekler. Şuna dikkat edin: DOSYA işaretçi
çağrı yy_create_buffer sadece değeri olarak kullanılır yin tarafından görülebilir YY_GİRİŞ; eğer
yeniden tanımlamak YY_GİRİŞ yani artık kullanmıyor eyyin, o zaman güvenle bir sıfırı geçebilirsin DOSYA işaretçi
için yy_create_buffer. Aşağıdakileri kullanarak taramak için belirli bir arabellek seçersiniz:

geçersiz yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )

tarayıcının giriş arabelleğini değiştirir, böylece sonraki belirteçler yeni_tampon. not
o yy_switch_to_buffer() işleri devam ettirmek için yywrap() tarafından kullanılabilir
yeni bir dosya açıp işaret etmek yerine tarama yin ona. Ayrıca, anahtarlamanın
aracılığıyla giriş kaynakları yy_switch_to_buffer() or yywrap() yok değil başlangıcı değiştir
koşul.

void yy_delete_buffer(YY_BUFFER_STATE arabelleği)

bir arabellekle ilişkili depolamayı geri almak için kullanılır. ( tampon sıfır olabilir, ki
yordamın hiçbir şey yapmaması durumunda.) Ayrıca bir arabelleğin mevcut içeriğini de temizleyebilirsiniz.
kullanarak:

void yy_flush_buffer(YY_BUFFER_STATE arabelleği)

Bu işlev, arabelleğin içeriğini atar, böylece tarayıcı bir dahaki sefere
arabellekteki bir belirteci eşleştirin, önce arabelleği kullanarak yeniden dolduracaktır. YY_GİRİŞ.

yy_new_buffer() takma addır yy_create_buffer(), ile uyumluluk için sağlanan
C++ kullanımı yeni ve silmek dinamik nesneler oluşturmak ve yok etmek için.

Son olarak, YY_CURRENT_BUFFER makro bir döndürür YY_BUFFER_STATE akımla başa çıkmak
tampon eklendi.

Genişleyen bir tarayıcı yazmak için bu özellikleri kullanmanın bir örneği, şunları içerir:
dosyalar ( < > özellik aşağıda tartışılmaktadır):

/* "incl" durumu adı almak için kullanılır
* bir içerme dosyasının
*/
%x dahil

%{
#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr = 0;
%}

%%
BEGIN(dahil);

[az]+ EKO;
[^az\n]*\n? EKO;

[ \t]* /* boşlukları ye */
[^ \t\n]+ { /* dahil edilen dosya adını aldı */
if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
fprintf( stderr, "İç içe çok derin içerir");
çıkış( 1 );
}

include_stack[include_stack_ptr++] =
YY_CURRENT_BUFFER;

yyin = fopen(yytext, "r");

eğer ( ! yyin )
hata( ... );

yy_switch_to_buffer(
yy_create_buffer(yyin, YY_BUF_SIZE ) );

BAŞLA(BAŞLANGIÇ);
}

< > {
if ( --include_stack_ptr < 0 )
{
yterminate();
}

başka
{
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(
include_stack[include_stack_ptr] );
}
}

Bellek içi dizeleri taramak için giriş arabelleklerini ayarlamak için üç rutin mevcuttur
dosyalar yerine. Hepsi, dizeyi taramak için yeni bir giriş arabelleği oluşturur ve
karşılık gelen bir dönüş YY_BUFFER_STATE tutamaç (ki ile silmeniz gerekir)
yy_delete_buffer() onunla bittiğinde). Ayrıca kullanarak yeni arabelleğe geçerler.
yy_switch_to_buffer(), bu yüzden bir sonraki çağrı yylex() dizeyi taramaya başlayacaktır.

yy_scan_string(sabit tank *str)
NUL ile sonlandırılmış bir diziyi tarar.

yy_scan_bytes(sabit tank *bayt, int uzun)
tarar len baytlar (muhtemelen NUL'ler dahil) konumdan başlar bayt.

Bu işlevlerin her ikisinin de bir kopya dize veya bayt sayısı. (Bu
istenebilir, çünkü yylex() taradığı arabelleğin içeriğini değiştirir.)
aşağıdakileri kullanarak kopyadan kaçınabilirsiniz:

yy_scan_buffer(karakter *temel, yy_size_t boyut)
hangi tamponu yerinde tarar baz, oluşan boyut bayt,
son iki baytı , eğer mülteci statüleri sona erdirilmemişse Amerika'ya geldikten bir yıl sonra be YY_END_OF_BUFFER_CHAR (ASCII NUL). Bu son ikisi
baytlar taranmaz; bu nedenle, tarama şunlardan oluşur: temel[0] içinden taban[boyut-2],
kapsayıcı.

kurmayı başaramazsanız baz bu şekilde (yani, son ikisini unutun)
YY_END_OF_BUFFER_CHAR bayt), ardından yy_scan_buffer() bunun yerine bir nil işaretçisi döndürür
yeni bir giriş arabelleği oluşturma.

tip yy_size_t bir tamsayı ifadesi oluşturabileceğiniz bir integral türüdür
tamponun boyutunu yansıtır.

DOSYANIN SONU KURALLAR


Özel kural "< >", bir dosya sonu olduğunda gerçekleştirilecek eylemleri belirtir.
karşılaşıldı ve yywrap() sıfırdan farklı bir değer döndürür (yani, işlenecek başka dosya olmadığını gösterir).
Eylem, dört şeyden birini yaparak bitmelidir:

- atama yin yeni bir girdi dosyasına (eski flex sürümlerinde,
özel eylemi çağırmanız gereken ödev YY_NEW_FILE; bu artık değil
gerekli);

- yürütme dönüş deyimi;

- özel yürütme yysonlandırma() aksiyon;

- veya kullanarak yeni bir arabelleğe geçmek yy_switch_to_buffer() örnekte gösterildiği gibi
yukarıdaki.

< > kurallar diğer kalıplarla birlikte kullanılamaz; sadece bir liste ile kalifiye olabilirler
başlangıç ​​koşulları. Eğer niteliksiz bir < > kural verilir, için geçerlidir herşey başlama
zaten olmayan koşullar < > eylemler. < belirtmek için > kural sadece
ilk başlatma koşulu, kullanın

< >

Bu kurallar, kapatılmamış yorumlar gibi şeyleri yakalamak için kullanışlıdır. Bir örnek:

%x alıntı
%%

...alıntılarla ilgili diğer kurallar...

< > {
error("sonlandırılmamış alıntı");
yterminate();
}
< > {
if ( *++ dosya listesi )
yyin = fopen( *dosya listesi, "r");
başka
yterminate();
}

ÇEŞİTLİ MAKROS


Makro YY_USER_ACTION her zaman yürütülen bir eylem sağlamak için tanımlanabilir
eşleşen kuralın eyleminden önce. Örneğin, bir rutini çağırmak #tanımlı olabilir
yytext'i küçük harfe dönüştürmek için. Ne zaman YY_USER_ACTION çağrılır, değişken yy_act
eşleşen kuralın numarasını verir (kurallar 1'den başlayarak numaralandırılır). varsayalım
Kurallarınızın her birinin ne sıklıkla eşleştiğinin profilini çıkarmak istiyorsunuz. Aşağıdakiler yapacak
hile:

#define YY_USER_ACTION ++ctr[yy_act]

nerede ctr farklı kurallar için sayıları tutan bir dizidir. makro olduğunu unutmayın
YY_NUM_RULES toplam kural sayısını verir (kullansanız bile varsayılan kural dahil)
-S), bu yüzden doğru bir beyan ctr olduğu:

int ktr[YY_NUM_RULES];

Makro YY_USER_INIT her zaman önce yürütülen bir eylem sağlamak için tanımlanabilir
ilk tarama (ve tarayıcının dahili başlatma işlemleri yapılmadan önce). Örneğin,
bir veri tablosunda okumak veya bir günlük dosyasını açmak için bir rutin çağırmak için kullanılabilir.

Makro yy_set_interactive(is_interactive) akımın olup olmadığını kontrol etmek için kullanılabilir.
tampon kabul edilir İnteraktif. Etkileşimli bir arabellek daha yavaş işlenir, ancak
nedeniyle sorunlardan kaçınmak için tarayıcının giriş kaynağı gerçekten etkileşimli olduğunda kullanılmalıdır.
tamponları doldurmayı beklemek için (bkz. -I Aşağıdaki bayrak). içinde sıfır olmayan bir değer
makro çağırma, arabelleği etkileşimli olarak, sıfır değerini ise etkileşimli olmayan olarak işaretler.
Bu makronun kullanımının geçersiz kılındığını unutmayın %seçenek interaktif , %seçenek her zaman etkileşimli or
%seçenek asla etkileşimli (aşağıdaki Seçeneklere bakın). yy_set_interactive() önceden çağrılmalıdır
etkileşimli olarak kabul edilecek (veya olmayacak) arabelleği taramaya başlamak.

Makro yy_set_bol(at_bol) geçerli arabelleğin taranıp taranmadığını kontrol etmek için kullanılabilir
sonraki simge eşleşmesinin bağlamı, sanki bir satırın başındaymış gibi yapılır. sıfır olmayan
makro argümanı, kuralları birbirine bağlı hale getirir

Makro YY_AT_BOL() geçerli arabellekten taranan bir sonraki belirteç
'^' kuralları aktif, aksi halde false.

Oluşturulan tarayıcıda, eylemlerin tümü tek bir büyük anahtar ifadesinde toplanır ve
kullanılarak ayrılmış YY_BREAK, hangi yeniden tanımlanabilir. Varsayılan olarak, bu sadece bir "mola"dır.
her kuralın eylemini aşağıdaki kuralın eyleminden ayırın. yeniden tanımlama YY_BREAK izin verir, için
örneğin, C++ kullanıcılarının hiçbir şey yapmamak için #define YY_BREAK yapması (her
kural bir "ara" veya "dönüş" ile sona erer!)
uyarılar, bir kuralın eylemi "dönüş" ile bittiği için, YY_BREAK erişilemez.

DEĞERLER MEVCUT TO L' KULLANICI


Bu bölüm, kural eylemlerinde kullanıcının kullanabileceği çeşitli değerleri özetler.

- tank *ymetni geçerli belirtecin metnini tutar. Değiştirilebilir ama değil
uzatılmış (sonuna karakter ekleyemezsiniz).

özel yönerge ise %dizi tarayıcının ilk bölümünde görünür
açıklama, o zaman ymetin bunun yerine ilan edildi tank ymetin[YYLMAX], nerede YYLMAX bir
beğenmediyseniz ilk bölümde yeniden tanımlayabileceğiniz makro tanımı
varsayılan değer (genellikle 8KB). kullanma %dizi biraz daha yavaş tarayıcılarla sonuçlanır,
ama değeri ymetin aramalara karşı bağışıklık kazanır giriş() ve çıktı(), hangi
potansiyel olarak değerini yok ettiğinde ymetin bir karakter işaretçisidir. Karşıtı
%dizi is %Işaretçi, hangisi varsayılandır.

kullanamazsın %dizi C++ tarayıcı sınıfları oluştururken ( -+ bayrak).

- int Yyleng geçerli jetonun uzunluğunu tutar.

- DOSYA *yyin varsayılan olarak dosyadır esnek itibaren okur. Yeniden tanımlanabilir, ancak
bunu yapmak yalnızca tarama başlamadan önce veya bir EOF yapıldıktan sonra mantıklıdır.
karşılaşıldı. Taramanın ortasında değiştirmek, beklenmedik sonuçlara yol açacaktır.
beri esnek girdisini tamponlar; kullanmak yeniden başlat() Bunun yerine. Tarama sona erdiğinde
bir dosya sonu görüldüğünden, atayabilirsiniz yin yeni girdi dosyasında ve
ardından taramaya devam etmek için tarayıcıyı tekrar arayın.

- geçersiz yeniden başlat( DOSYA *yeni dosya ) noktaya çağrılabilir yin yeni giriş dosyasında.
Yeni dosyaya geçiş anında gerçekleşir (önceden arabelleğe alınmış herhangi bir giriş
kayıp). çağırdığını unutmayın yeniden başlat() ile yin bir argüman olarak, böylece
geçerli giriş arabelleği ve aynı giriş dosyasını taramaya devam eder.

- DOSYA *yout hangi dosya EKO eylemler yapılır. tarafından yeniden atanabilir.
Kullanıcı.

- YY_CURRENT_BUFFER bir verir YY_BUFFER_STATE geçerli arabelleğe işle.

- YY_START geçerli başlangıç ​​koşuluna karşılık gelen bir tamsayı değeri döndürür.
Daha sonra bu değeri ile kullanabilirsiniz. BAŞLA bu başlangıç ​​koşuluna geri dönmek için

ARAYÜZ İLE YACC


Ana kullanımlarından biri esnek yoldaş gibidir yacc ayrıştırıcı-jeneratör. yacc ayrıştırıcıları
adlı bir rutin çağırmayı bekliyoruz yylex() Bir sonraki giriş belirtecini bulmak için. rutin
sonraki belirtecin türünü döndürmesi ve ilişkili herhangi bir değeri içine koyması gerekiyordu.
Küresel yıl. Kullanmak için esnek ile yacc, biri belirtir -d için seçenek yacc talimat vermek
dosyayı oluşturmak için y.tab.h tüm tanımları içeren % jeton görünen
yacc giriş. Bu dosya daha sonra esnek tarayıcı. Örneğin, eğer biri
belirteçler "TOK_NUMBER", tarayıcının bir kısmı şöyle görünebilir:

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

%%

[0-9]+ yylval = atoi(yytext); TOK_NUMBER döndür;

SEÇENEKLER


esnek aşağıdaki seçeneklere sahiptir:

-B, --destek olmak
için yedekleme bilgileri oluşturun lex.yedekleme Bu, tarayıcı durumlarının bir listesidir
yedekleme gerektiren ve bunu yaptıkları giriş karakterleri. Toplayarak
yedekleme durumlarını kaldırabileceğiniz kurallar. Eğer herşey yedekleme durumları ortadan kalkar
ve -Çf or CF kullanılırsa, oluşturulan tarayıcı daha hızlı çalışacaktır (bkz. -p bayrak).
Yalnızca tarayıcılarından her son döngüyü çıkarmak isteyen kullanıcıların endişelenmesi gerekir
Bu seçenek hakkında. (Aşağıdaki Performans Değerlendirmeleri bölümüne bakın.)

-c POSIX uyumluluğu için hiçbir şey yapmama, kullanımdan kaldırılmış bir seçenektir.

-NS, - hata ayıklama
oluşturulan tarayıcının çalışmasını sağlar ayıklamak modu. Bir desen tanındığında
ve küresel yy_flex_debug sıfır değilse (varsayılandır), tarayıcı
yazmak Stderr formun bir satırı:

-- 53. satırdaki kuralı kabul ediyor ("eşleşen metin")

Satır numarası, tarayıcıyı tanımlayan dosyadaki kuralın konumunu belirtir.
(yani, flex için beslenen dosya). Mesajlar aynı zamanda oluşturulduğunda da oluşturulur.
tarayıcı yedekler, varsayılan kuralı kabul eder, giriş arabelleğinin sonuna ulaşır (veya
bir NUL ile karşılaşır; bu noktada, ikisi tarayıcınınkiyle aynı görünüyor.
ilgili) veya dosyanın sonuna ulaşır.

-F, --tam dolu
belirtir hızlı tarayıcı. Tablo sıkıştırması yapılmaz ve stdio atlanır. bu
sonuç büyük ama hızlı. Bu seçenek eşdeğerdir -Cfr (aşağıya bakınız).

-H, --yardım et
için bir "yardım" özeti oluşturur. esnek seçenekler stdout'u ve sonra çıkar. -? ve
--yardım et için eşanlamlıdır -H.

-ben, --büyük/küçük harfe duyarsız
talimatını esnek üretmek için büyük küçük harf duyarsız tarayıcı. Verilen mektupların durumu
içinde esnek giriş kalıpları yok sayılacak ve girişteki belirteçler eşleştirilecek
durumda ne olursa olsun. Verilen eşleşen metin ymetin korunmuş durumda olacak
(yani, katlanmayacaktır).

-ben, --lex-uyumluluğu
orijinal AT&T ile maksimum uyumluluğu açar Lex uygulama. Not
bunun şu anlama gelmediğini tam uyumluluk. Bu seçeneğin kullanımı bir
önemli miktarda performans ve ile kullanılamaz -+, -F, -F, -Bkz.
or CF seçenekler. Sağladığı uyumluluklarla ilgili ayrıntılar için bkz.
Aşağıdaki "Lex ve POSIX ile Uyumsuzluklar". Bu seçenek aynı zamanda isimle sonuçlanır.
YY_FLEX_LEX_COMPAT oluşturulan tarayıcıda #tanımlı olmak.

-n yalnızca POSIX uyumluluğu için dahil edilen, hiçbir şey yapmama, kullanımdan kaldırılmış başka bir seçenektir.

-P, --perf-raporu
stderr için bir performans raporu oluşturur. Rapor yorumlardan oluşuyor
özellikleri ile ilgili olarak esnek ciddi bir kayba neden olacak girdi dosyası
ortaya çıkan tarayıcıdaki performans. Bayrağı iki kez verirseniz, siz de
küçük performans kayıplarına yol açan özelliklerle ilgili yorumlar alın.

Not REDDETMEK, %seçenek yylineno, ve değişken izleyen bağlam (bkz.
Aşağıdaki Eksiklikler / Hatalar bölümü) önemli bir performans cezası gerektirir;
kullanımı daha fazla(), the ^ operatör ve -I bayrak küçük performans gerektirir
cezalar.

-Evet, --standart değil
neden olur varsayılan kural (eşleşmeyen tarayıcı girişi, standart) olduğu
bastırılmış. Tarayıcı, kurallarından herhangi biriyle eşleşmeyen bir girdiyle karşılaşırsa,
bir hata ile iptal edilir. Bu seçenek, tarayıcının deliklerini bulmak için kullanışlıdır.
kural seti.

-T, --stdout
talimatını esnek oluşturduğu tarayıcıyı yerine standart çıktıya yazmak için
lex.yy.c.

-içinde, --ayrıntılı
belirtir esnek yazmalı Stderr ile ilgili istatistiklerin bir özeti
oluşturduğu tarayıcı. İstatistiklerin çoğu sıradan insanlar için anlamsızdır. esnek
kullanıcı, ancak ilk satır sürümünü tanımlar esnek (tarafından bildirilenle aynı -V),
ve bir sonraki satır, tarayıcıyı oluştururken kullanılan bayraklar da dahil olmak üzere,
varsayılan olarak açıktır.

-w, --bilmek
uyarı mesajlarını bastırır.

-B, --grup
talimatını esnek üretmek için yığın tarayıcı, tersi interaktif tarayıcılar
tarafından oluşturuldu -I (aşağıya bakınız). Genel olarak kullandığınız -B ne zaman sen belli bu senin
tarayıcı asla etkileşimli olarak kullanılmayacaktır ve küçük Daha
performans ondan. Amacınız bunun yerine bir çok Daha
performans, kullanmanız gerekir -Çf or CF seçenekler (aşağıda tartışılmıştır), hangi
-B nasılsa otomatik olarak.

-F, --hızlı
belirtir hızlı tarayıcı tablosu gösterimi kullanılmalıdır (ve stdio
atlandı). Bu gösterim, tam tablo gösterimi kadar hızlıdır.
(-F), ve bazı model grupları için önemli ölçüde daha küçük olacaktır (ve diğerleri için,
daha büyük). Genel olarak, kalıp seti hem "anahtar kelimeleri" hem de tümünü yakalamayı içeriyorsa,
sette olduğu gibi "tanımlayıcı" kuralı:

"vaka" dönüş TOK_CASE;
"geçiş" TOK_SWITCH döndürür;
Kendi ID’n ile mağazalarını oluştur
"varsayılan" dönüş TOK_DEFAULT;
[az]+ TOK_ID döndür;

o zaman tam tablo gösterimini kullanmaktan daha iyisin. eğer sadece
"tanımlayıcı" kuralı mevcut ve daha sonra algılamak için bir karma tablo veya benzeri bir şey kullanırsınız
anahtar kelimeleri kullanmanız daha iyi -F.

Bu seçenek eşdeğerdir -CFr (aşağıya bakınız). ile kullanılamaz -+.

-BEN, --interaktif
talimatını esnek oluşturmak için interaktif tarayıcı. Etkileşimli tarayıcı bir
bu, yalnızca kesinlikle gerekliyse hangi jetonun eşleştirildiğine karar vermek için ileriye bakar.
Tarayıcı, tarayıcıya sahip olsa bile, her zaman fazladan bir karakter ileriye baktığı ortaya çıktı.
mevcut jetonun belirsizliğini gidermek için zaten yeterli metin görüldü, şundan biraz daha hızlı
sadece gerektiğinde ileriye bakmak. Ancak her zaman ileriye bakan tarayıcılar
korkunç etkileşimli performans; örneğin, bir kullanıcı yeni bir satır yazdığında,
girene kadar yeni satır belirteci olarak tanınmaz bir diğeri genellikle anlamına gelen belirteç
başka bir tam satırda yazarak.

Esnek tarayıcılar varsayılan olarak interaktif kullanmadığınız sürece -Çf or CF tablo-
sıkıştırma seçenekleri (aşağıya bakın). Çünkü eğer yüksek-
performans için bu seçeneklerden birini kullanıyor olmalısınız, yani kullanmadıysanız, esnek
sezgisel performans için biraz çalışma zamanı performansından ödün vermeyi tercih edeceğinizi varsayar
etkileşimli davranış. Şunu da unutmayın ki Amerika’ya vize ile ya da Meksika üzerinden geldikten sonra ilticaya başvuran kişileri, herhangi bir suça karışmadıkları sürece mahkeme kararı olmadan sınır dışı (deport) ettiremez. kullanım -I ile birlikte -Çf or
-CF. Bu nedenle, bu seçeneğe gerçekten ihtiyaç yoktur; tüm bunlar için varsayılan olarak açıktır
izin verildiği durumlar.

Unutmayın ki isatty () tarayıcı girişi için false döndürür, flex geri döner
toplu mod, olsa bile -I belirtilmişti. Ne olursa olsun etkileşimli modu zorlamak için,
kullanım %seçenek her zaman etkileşimli (aşağıdaki Seçeneklere bakın).

Bir tarayıcıyı değil kullanarak etkileşimli olun -B (yukarıyı görmek).

-L, --noline
talimatını esnek üretmemek #hat direktifler. Bu seçenek olmadan, esnek biber
#line yönergeleri ile oluşturulan tarayıcı, bu nedenle eylemlerdeki hata mesajları
orijinaline göre doğru bir şekilde yerleştirilmelidir esnek girdi dosyası (eğer
hatalar giriş dosyasındaki koddan kaynaklanır) veya lex.yy.c (eğer hatalar esnek
hata -- bu tür hataları aşağıda verilen e-posta adresine bildirmelisiniz).

-T, --iz
yapar esnek çalıştırmak iz modu. için çok sayıda mesaj üretecektir. Stderr
girdinin biçimi ve sonuçta ortaya çıkan deterministik olmayan ve
deterministik sonlu otomatlar. Bu seçenek çoğunlukla bakımda kullanım içindir. esnek.

-V, --versiyon
sürüm numarasını yazdırır stdout'u ve çıkışlar. --versiyon ile eşanlamlıdır -V.

-7, --7 bit
talimatını esnek 7 bitlik bir tarayıcı, yani yalnızca tanıyabilen bir tarayıcı oluşturmak için
Girişinde 7 bitlik karakterler. kullanmanın avantajı -7 bu tarayıcının mı
tablolar, kullanılarak oluşturulanların boyutunun yarısına kadar olabilir. -8 seçeneği (bkz.
altında). Dezavantajı, bu tür tarayıcıların, girişleri durumunda genellikle askıda kalması veya çökmesidir.
8 bitlik bir karakter içerir.

Ancak, tarayıcınızı aşağıdakileri kullanarak oluşturmadığınız sürece unutmayın. -Çf or CF tablo
sıkıştırma seçenekleri, kullanımı -7 sadece az miktarda masa alanından tasarruf edecek ve
tarayıcınızı önemli ölçüde daha az taşınabilir hale getirin. Flex'in varsayılan davranış
kullanmadığınız sürece 8 bitlik bir tarayıcı oluşturun. -Çf or -CF, bu durumda esnek
siteniz her zaman şu şekilde yapılandırılmamışsa, varsayılan olarak 7 bit tarayıcılar oluşturur.
8 bit tarayıcılar oluşturun (genellikle ABD dışı sitelerde olduğu gibi). Yapabilirsiniz
bayrağı inceleyerek flex'in 7 bit mi yoksa 8 bit tarayıcı mı oluşturduğunu söyleyin
özet -v yukarıda açıklandığı gibi çıktı.

Dikkat edin, eğer kullanırsanız -Cfe or -CFe (bu tablo sıkıştırma seçenekleri, aynı zamanda
aşağıda tartışıldığı gibi denklik sınıfları), flex hala varsayılan olarak bir
8 bit tarayıcı, genellikle bu sıkıştırma seçenekleriyle tam 8 bit tablolar
7-bit tablolardan çok daha pahalı değil.

-8, --8 bit
talimatını esnek 8-bit tarayıcı, yani 8-bit tanıyabilen bir tarayıcı oluşturmak için
karakterler. Bu bayrak yalnızca kullanılarak oluşturulan tarayıcılar için gereklidir. -Çf or -CF, as
aksi halde, yine de 8 bitlik bir tarayıcı oluşturmak için varsayılanları esnetin.

tartışmasına bakın -7 flex'in varsayılan davranışı ve ödünleşimler için yukarıda
7-bit ve 8-bit tarayıcılar arasında.

-+, --c++
flex'in bir C++ tarayıcı sınıfı oluşturmasını istediğinizi belirtir. bölümüne bakın
Ayrıntılar için aşağıdaki C++ Tarayıcıları Oluşturuluyor.

-C[aefFmr]
tablo sıkıştırma derecesini ve daha genel olarak aralarındaki dengeleri kontrol eder.
küçük tarayıcılar ve hızlı tarayıcılar.

-CA, --hizalamak ("align") flex'e, oluşturulan tablodaki daha büyük tabloları takas etmesi talimatını verir.
tabloların öğeleri daha iyi olduğu için daha hızlı performans için tarayıcı
bellek erişimi ve hesaplama için hizalanmış. Bazı RISC mimarilerinde, getiriliyor
ve uzun sözcükleri manipüle etmek, aşağıdakiler gibi daha küçük boyutlu birimlerden daha verimlidir:
kısa kelimeler. Bu seçenek, tarayıcınız tarafından kullanılan tabloların boyutunu iki katına çıkarabilir.

-Ce, --ecs yönlendirir esnek inşa etmek denklik sınıflar yani, karakter kümeleri
özdeş sözcüksel özelliklere sahip olan (örneğin,
içindeki rakamlar esnek giriş "[0-9]" karakter sınıfında, ardından '0' rakamları,
'1', ..., '9' hepsi aynı denklik sınıfına konulacaktır). denklik sınıfları
genellikle nihai tablo/nesne dosya boyutlarında (tipik olarak
2-5 faktöründedir ve performans açısından oldukça ucuzdur (her bir dizi için bir dizi arama
karakter tarandı).

-Çf belirtir tam tarayıcı tabloları oluşturulmalıdır - esnek olmamalı
için benzer geçiş fonksiyonlarının avantajlarından yararlanarak tabloları sıkıştırın.
farklı devletler.

CF alternatif hızlı tarayıcı gösteriminin (yukarıda açıklanmıştır)
altında -F bayrağı) kullanılmalıdır. Bu seçenek ile kullanılamaz -+.

-Santimetre, --meta-ecs yönlendirir esnek inşa etmek meta-denklik sınıflar kümeler hangileri
denklik sınıfları (veya denklik sınıfları kullanılmıyorsa karakterler)
birlikte yaygın olarak kullanılanlardır. Meta-eşdeğerlik sınıfları genellikle büyük bir kazançtır.
sıkıştırılmış tablolar kullanır, ancak orta düzeyde bir performans etkisine sahiptirler (bir veya iki
"if" testleri ve taranan karakter başına bir dizi arama).

-Kr, --okuman oluşturulan tarayıcının baypas standart I/O kitaplığının kullanımı
(stdio) giriş için. aramak yerine korku() or getc(), tarayıcı kullanacak
oku () sistem çağrısı, sistemden sisteme değişen bir performans kazancıyla sonuçlanır.
sistem, ancak genel olarak, aynı zamanda kullanmıyorsanız muhtemelen ihmal edilebilir. -Çf or -CF.
kullanma -Kr örneğin şuradan okursanız garip davranışlara neden olabilir. yin kullanma
stdio tarayıcıyı çağırmadan önce (çünkü tarayıcı herhangi bir metni kaçıracaktır)
önceki okumalarınız stdio giriş arabelleğinde kaldı).

-Kr tanımlarsan hiçbir etkisi olmaz YY_GİRİŞ (yukarıdaki Oluşturulan Tarayıcıya bakın).

Tek başına -C tarayıcı tablolarının sıkıştırılması gerektiğini ancak ikisinin de sıkıştırılmaması gerektiğini belirtir.
eşdeğerlik sınıfları veya meta-denklik sınıfları kullanılmalıdır.

Seçenekler -Çf or CF ve -Santimetre birlikte anlam ifade etmeyin - fırsat yok
tablo sıkıştırılmıyorsa meta-eşdeğerlik sınıfları için. Aksi takdirde
seçenekler serbestçe karıştırılabilir ve birikimlidir.

Varsayılan ayar şudur -Cem, hangi bunu belirtir esnek denklik oluşturmalı
sınıflar ve meta-denklik sınıfları. Bu ayar, en yüksek dereceyi sağlar.
tablo sıkıştırma Daha hızlı çalışan tarayıcıları aşağıdaki maliyetler karşılığında takas edebilirsiniz:
aşağıdakiler genel olarak doğru olan daha büyük tablolar:

en yavaş ve en küçük
-Cem
-Santimetre
-Bu
-C
-C{f,F}e
-C{f,F}
-C{f,F}a
en hızlı ve en büyük

En küçük tablolara sahip tarayıcıların genellikle oluşturulduğunu ve derlendiğini unutmayın.
en hızlıdır, bu nedenle geliştirme sırasında genellikle varsayılanı, maksimumu kullanmak isteyeceksiniz.
sıkıştırma.

-Cfe genellikle üretim tarayıcıları için hız ve boyut arasında iyi bir uzlaşmadır.

-çıktı, --outputfile=DOSYA
tarayıcıyı dosyaya yazmak için flex'i yönlendirir çıktı yerine lex.yy.c. Eğer sen
birleştirmek -o ile -t seçeneği, ardından tarayıcıya yazılır stdout'u ama #hat
direktifler (bkz. -L yukarıdaki seçenek) dosyaya bakın çıktı.

-Önek, --prefix=STRING
varsayılanı değiştirir yy tarafından kullanılan önek esnek küresel olarak görülebilen tüm değişkenler için ve
bunun yerine işlev adları önek. Örneğin, -Pfoo adını değiştirir ymetin
için ayak yazısı. Ayrıca varsayılan çıktı dosyasının adını da değiştirir. lex.yy.c için
lex.foo.c. İşte etkilenen tüm isimler:

yy_create_buffer
yy_delete_buffer
yy_flex_debug
yy_init_buffer
yy_flush_buffer
yy_load_buffer_state
yy_switch_to_buffer
yin
Yyleng
Yylex
Yylineno
sen
yeniden başlat
ymetin
yywrap

(Bir C++ tarayıcı kullanıyorsanız, yalnızca yywrap ve yyFlexLexer etkilenir.)
Tarayıcınızın içinde, yine de global değişkenlere başvurabilirsiniz ve
adlarının herhangi bir sürümünü kullanan işlevler; ama harici olarak, onlar var
değiştirilmiş isim.

Bu seçenek, birden çok esnek programları aynı şekilde
yürütülebilir. Yine de, bu seçeneği kullanmanın aynı zamanda yywrap(), yani şimdi sen
, eğer mülteci statüleri sona erdirilmemişse Amerika'ya geldikten bir yıl sonra ya sizin için rutinin kendi (uygun şekilde adlandırılmış) versiyonunu sağlayın
tarayıcı veya kullanım %seçenek hayır, ile bağlantı olarak -LL artık bir tane sağlamıyor
varsayılan olarak sen.

-İskelet_dosyası, --skel=DOSYA
olduğu varsayılan iskelet dosyasını geçersiz kılar. esnek tarayıcılarını oluşturur.
yapmadığınız sürece bu seçeneğe asla ihtiyacınız olmayacak. esnek bakım veya geliştirme.

-X, --posix-uyumluluk
POSIX lex ile maksimum uyumluluk.

--yylineno
yylineno'da parça satırı sayısı.

--yyclass=AD
C++ sınıfının adı.

--header-file=DOSYA
tarayıcıya ek olarak bir C başlık dosyası oluşturun.

--tables-dosyası[=DOSYA]
tabloları DOSYA'ya yazın.

-Dmakro[=defn]
#define makro tanımı (varsayılan tanım '1'dir).

-R, --yeni giren
yeniden girişli bir C tarayıcı oluştur

--bizon-köprü
bizon saf ayrıştırıcı için tarayıcı.

--bizon-konumlar
yylloc desteğini içerir.

--stdinit
yyin/yyout'u stdin/stdout'a başlatın.

--noansi-tanımları eski tarz işlev tanımlar.

--noansi-prototipler
prototiplerde boş parametre listesi.

--isimci
dahil etme .

--fonksiyonsuz
belirli bir FONKSİYON üretmeyin.

esnek ayrıca tarayıcı spesifikasyonu içindeki seçenekleri kontrol etmek için bir mekanizma sağlar
esnek komut satırından değil, kendisi. Bu dahil edilerek yapılır %seçenek
tarayıcı belirtiminin ilk bölümündeki yönergeler. birden fazla belirtebilirsiniz
seçenekleri ile tek %seçenek direktif ve ilk bölümdeki çoklu direktifler
esnek giriş dosyanız.

Çoğu seçenek, isteğe bağlı olarak "hayır" kelimesiyle (hiçbir
araya giren boşluk) anlamlarını reddetmek için. Bir sayı, esnek bayraklara eşdeğerdir veya
onların inkarı:

7bit -7 seçeneği
8bit -8 seçeneği
hizala -Ca seçeneği
yedek -b seçeneği
toplu -B seçeneği
c++ -+ seçeneği

davalı veya
-i'nin büyük/küçük harf duyarlı tersi (varsayılan)

büyük/küçük harfe duyarsız veya
kılıfsız -i seçeneği

hata ayıklama -d seçeneği
-s seçeneğinin varsayılan tersi
ecs -Ce seçeneği
hızlı -F seçeneği
tam -f seçeneği
etkileşimli -I seçeneği
lex-compat -l seçeneği
meta-ecs -Cm seçeneği
mükemmel rapor -p seçeneği
-Cr seçeneğini oku
stdout -t seçeneği
ayrıntılı -v seçeneği
-w seçeneğinin tersini uyar
(-w için "%option nowarn" kullanın)

"%array" ile eşdeğer dizi
"%pointer" ile eşdeğer işaretçi (varsayılan)

Bizi %seçenekler aksi halde mevcut olmayan özellikleri sağlayın:

her zaman etkileşimli
flex'e her zaman girdisini dikkate alan bir tarayıcı oluşturma talimatı verir
"etkileşimli". Normalde, tarayıcı her yeni girdi dosyasında isatty () bir bölgesindeki
tarayıcının giriş kaynağının etkileşimli olup olmadığını belirlemeye çalışın ve böylece
bir seferde bir karakter okunmalıdır. Ancak bu seçenek kullanıldığında, hayır
böyle bir arama yapılır.

ana bir varsayılan sağlamak için flex'i yönlendirir ana() tarayıcı için program, sadece
aramalar yylex(). Bu seçenek şu anlama gelir: noyywrap (aşağıya bakınız).

asla etkileşimli
flex'e girdisini asla "etkileşimli" olarak kabul etmeyen bir tarayıcı oluşturması talimatını verir
(yine arama yapılmadı isatty()). Bu tam tersi her zaman etkileşimli.

yığın başlangıç ​​koşulu yığınlarının kullanılmasını sağlar (yukarıdaki Başlangıç ​​Koşullarına bakın).

standart
ayarlanmışsa (yani, %seçenek standart) başlatır yin ve sen için stdin ve standart,
varsayılan yerine sıfır. Bazı mevcut Lex programlar bu davranışa bağlıdır,
gerektirmeyen ANSI C ile uyumlu olmasa da stdin ve
stdout'u derleme zamanı sabiti olmak.

Yylineno
yönlendirir esnek geçerli satırın numarasını koruyan bir tarayıcı oluşturmak için
global değişkendeki girdisinden oku yilineno. Bu seçenek şu şekilde ima edilir:
%seçenek lex uyumlu.

yywrap ayarlanmazsa (yani, %seçenek hayıryywrap), tarayıcının aramamasını sağlar yywrap() sonunda-
dosyaya ait değil, ancak taranacak başka dosya olmadığını varsayın (kullanıcı
noktaları yin yeni bir dosyada ve aramalarda yylex() tekrar).

esnek kullanıp kullanmadığınızı belirlemek için kural eylemlerinizi tarar. REDDET or daha fazla() özellikleri.
The reddetmek ve daha fazla kullanıp kullanmadığınıza ilişkin kararını geçersiz kılmak için seçenekler mevcuttur.
seçenekleri ayarlayarak (örn. %seçenek reddetmek) özelliği belirtmek için
gerçekten kullanılmış veya gerçekte kullanılmadığını belirtmek için ayarını kaldırarak (örn. %seçenek
noymore).

Üç seçenek dizeyle ayrılmış değerler alır, '=' ile dengelenir:

%option outfile="ABC"

eşdeğerdir -oABC, ve

%option öneki="XYZ"

eşdeğerdir -PXYZ. En sonunda,

%option yyclass="foo"

yalnızca bir C++ tarayıcı oluştururken geçerlidir ( -+ seçenek). bilgi verir esnek sahip olduğun
türetilmiş foo alt sınıfı olarak yyFlexLexer, so esnek eylemlerinizi üyeye yerleştirecek
işlev foo::yylex() yerine yyFlexLexer::yylex(). Aynı zamanda bir
yyFlexLexer::yylex() çalışma zamanı hatası veren üye işlevi (çağırarak
yyFlexLexer::LexerError()) denirse. Ek bilgi için aşağıdaki C++ Tarayıcıları Oluşturma bölümüne bakın.
bilgiler.

görünümünü bastırmak isteyen tiftik temizleyiciler için bir dizi seçenek mevcuttur.
oluşturulan tarayıcıda gereksiz rutinler. Ayarlanmadıysa, aşağıdakilerden her biri (örn.
%seçenek isim ), ilgili rutinin oluşturulan programda görünmemesine neden olur.
tarayıcı:

girdi, çıktı
yy_Push_state, yy_pop_state, yy_top_state
yy_scan_buffer, yy_scan_bytes, yy_scan_string

(gerçi yy_Push_state() ve siz kullanmadığınız sürece arkadaşlar zaten görünmeyecek %seçenek yığın).

PERFORMANS İLGİLİ HUSUSLAR


ana tasarım hedefi esnek yüksek performanslı tarayıcılar üretmesidir. Olmuştur
büyük kurallar kümesiyle iyi başa çıkmak için optimize edilmiştir. Tarayıcı üzerindeki etkilerin yanı sıra
tablo sıkıştırma hızı -C Yukarıda özetlenen seçenekler, bir dizi
performansı düşüren seçenekler/eylemler. Bunlar, en pahalıdan en aza doğru:

REDDET
%seçenek yylineno
keyfi takip eden bağlam

yedekleme gerektiren desen setleri
%dizi
%seçenek etkileşimli
%seçenek her zaman etkileşimli

'^' satır başı operatörü
daha fazla()

ilk üçü oldukça pahalı ve son ikisi oldukça ucuz. Not
ayrıca bu çıktı() potansiyel olarak oldukça fazla şey yapan rutin bir çağrı olarak uygulanır.
çalışmak, süre yılsız() oldukça ucuz bir makrodur; bu yüzden sadece biraz fazla metni geri koyarsanız
taranmış, kullan yyless().

REDDET performans önemli olduğunda ne pahasına olursa olsun kaçınılmalıdır. Bu özellikle bir
pahalı seçenek.

Yedeklemeden kurtulmak dağınıktır ve çoğu zaman bir kişi için çok büyük miktarda iş olabilir.
karmaşık tarayıcı Prensipte, kişi aşağıdakileri kullanarak başlar: -b oluşturmak için bayrak
lex.yedekleme dosya. Örneğin, girişte

%%
foo dönüş TOK_KEYWORD;
foobar dönüşü TOK_KEYWORD;

dosya şöyle görünür:

Devlet #6 kabul etmiyor -
ilişkili kural satır numaraları:
2 3
geçişler: [ o ]
sıkışma geçişleri: EOF [ \001-n p-\177 ]

Devlet #8 kabul etmiyor -
ilişkili kural satır numaraları:
3
geçişler: [ a ]
sıkışma geçişleri: EOF [ \001-` b-\177 ]

Devlet #9 kabul etmiyor -
ilişkili kural satır numaraları:
3
geçişler: [ r ]
sıkışma geçişleri: EOF [ \001-q s-\177 ]

Sıkıştırılmış tablolar her zaman yedeklenir.

İlk birkaç satır bize, geçiş yapabileceği bir tarayıcı durumu olduğunu söylüyor.
bir 'o' üzerinde ancak başka bir karakterde değil ve bu durumda şu anda taranan
metin herhangi bir kuralla eşleşmiyor. Durum, şu adreste bulunan kurallarla eşleşmeye çalışıldığında ortaya çıkar.
girdi dosyasındaki 2. ve 3. satırlar. Tarayıcı bu durumdaysa ve ardından bir şey okursa
'o' dışında, eşleşen bir kuralı bulmak için yedekleme yapması gerekir. biraz ile
kafa kaşıyarak, bunun "fo"yu gördüğü andaki hali olması gerektiğini görebiliriz.
Bu olduğunda, başka bir 'o' dışında bir şey görülürse, tarayıcı
'f' ile eşleşmek üzere yedeklemek için (varsayılan kurala göre).

Durum #8 ile ilgili yorum, "aptal" tarandığında bir sorun olduğunu gösterir.
Gerçekten de, 'a' dışındaki herhangi bir karakterde, tarayıcının kabul etmek için yedekleme yapması gerekir.
"foo". Benzer şekilde, Devlet #9 için yapılan yorum, "fooba"nın ne zaman tarandığı ve bir
'r' takip etmez.

Son yorum bize, kaldırma zahmetine girmenin bir anlamı olmadığını hatırlatıyor.
kullanmadığımız sürece kurallardan yedekliyoruz -Çf or -CF, performans kazancı olmadığı için
sıkıştırılmış tarayıcılarla yapıyor.

Yedeklemeyi kaldırmanın yolu "hata" kuralları eklemektir:

%%
foo dönüş TOK_KEYWORD;
foobar dönüşü TOK_KEYWORD;

aptal |
aptal |
için {
/* yanlış alarm, gerçekten bir anahtar kelime değil */
TOK_ID'yi iade et;
}

Bir anahtar kelime listesi arasında yedeklemeyi ortadan kaldırmak, bir "hepsini yakala" kuralı kullanılarak da yapılabilir:

%%
foo dönüş TOK_KEYWORD;
foobar dönüşü TOK_KEYWORD;

[az]+ TOK_ID döndür;

Bu genellikle uygun olduğunda en iyi çözümdür.

Mesajları yedeklemek kademeli olma eğilimindedir. Karmaşık bir kurallar dizisiyle,
yüzlerce mesaj alın. Yine de biri onları deşifre edebilirse, genellikle sadece bir düzine alır.
ya da yedeklemeyi ortadan kaldırmak için kurallar (hata yapmak ve bir hata yapmak kolay olsa da)
hata kuralı yanlışlıkla geçerli bir jetonla eşleşir. olası bir gelecek esnek özellik olacak
yedeklemeyi ortadan kaldırmak için otomatik olarak kurallar ekleyin).

Yalnızca yedeklemeyi ortadan kaldırmanın avantajlarından yararlanabileceğinizi unutmamak önemlidir.
eğer ortadan kaldırırsan her yedekleme örneği. Sadece bir tane bırakmak, hiçbir şey kazanmadığınız anlamına gelir.

Değişken sondaki bağlam (hem önde gelen hem de sondaki parçaların sabit bir
uzunluk) neredeyse aynı performans kaybını gerektirir REDDET (yani, önemli). Öyleyse ne zaman
olası bir kural gibi:

%%
fare|fare/(kedi|köpek) run();

daha iyi yazılır:

%%
fare/kedi|köpek koşusu();
sıçan/kedi|köpek koşusu();

ya da

%%
fare|sıçan/kedi koşusu();
fare|sıçan/köpek koşusu();

Burada özel '|' eylem yapar değil herhangi bir tasarruf sağlar ve hatta yapabilir
işler daha da kötüleşir (aşağıdaki Eksiklikler / Hatalar bölümüne bakın).

Kullanıcının bir tarayıcının performansını artırabileceği başka bir alan (ve
uygulama), belirteçler ne kadar uzun süre eşleşirse, tarayıcının o kadar hızlı olması gerçeğinden kaynaklanır.
koşacak. Bunun nedeni, uzun belirteçlerle çoğu giriş karakterinin işlenmesinin uzun zaman almasıdır.
(kısa) iç tarama döngüsüne yerleştirin ve genellikle
tarama ortamını kurmak için ek çalışma (örn. ymetin) eylem için.
C yorumları için tarayıcıyı geri çağırın:

%x yorum
%%
int satır_sayısı = 1;

"/*" BEGIN(yorum);

[^*\n]*
"*"+[^*/\n]*
\n ++satır_sayısı;
"*"+"/" BEGIN(BAŞLANGIÇ);

Bu, şu şekilde yazılarak hızlandırılabilir:

%x yorum
%%
int satır_sayısı = 1;

"/*" BEGIN(yorum);

[^*\n]*
[^*\n]*\n ++satır_num;
"*"+[^*/\n]*
"*"+[^*/\n]*\n ++satır_num;
"*"+"/" BEGIN(BAŞLANGIÇ);

Şimdi, başka bir eylemin işlenmesini gerektiren her yeni satır yerine,
yeni satırlar, eşleşen metni olduğu sürece tutmak için diğer kuralların üzerine "dağıtılır".
mümkün. Bunu not et ekleme kurallar yapar değil tarayıcıyı yavaşlatın! hızı
tarayıcı, kural sayısından bağımsızdır veya (modulo'da verilen hususlar
Bu bölümün başında) gibi operatörler açısından kuralların ne kadar karmaşık olduğu
'*' ve '|'.

Tarayıcıyı hızlandırmak için son bir örnek: bir dosya üzerinden tarama yapmak istediğinizi varsayalım.
her satıra bir tane olmak üzere tanımlayıcılar ve anahtar kelimeler içeren ve başka yabancı karakterler içermeyen,
ve tüm anahtar kelimeleri tanır. Doğal bir ilk yaklaşım:

%%
asm |
oto |
mola |
... vb ...
uçucu |
while /* bu bir anahtar kelime */

.|\n /* bu bir anahtar kelime değil */

Geri izlemeyi ortadan kaldırmak için bir tümünü yakalama kuralı uygulayın:

%%
asm |
oto |
mola |
... vb ...
uçucu |
while /* bu bir anahtar kelime */

[az]+ |
.|\n /* bu bir anahtar kelime değil */

Şimdi, eğer satır başına tam olarak bir kelime olduğu garanti ediliyorsa, o zaman
yeni satırların tanınmasıyla birleştirilerek toplam eşleşme sayısı yarı yarıya
diğer jetonlar:

%%
asm\n |
otomatik\n |
ara\n |
... vb ...
değişken\n |
while\n /* bu bir anahtar kelime */

[az]+\n |
.|\n /* bu bir anahtar kelime değil */

Tarayıcıya yedeklemeyi yeniden başlattığımız için burada dikkatli olunmalıdır. İçinde
özellikle, iken we giriş akışında hiçbir zaman karakter olmayacağını bilin
harfler veya yeni satırlar dışında, esnek bunu çözemiyorum ve muhtemelen planlayacak
"auto" gibi bir belirteci taradığında yedekleme ihtiyacı ve ardından bir sonraki karakter
yeni satır veya harf dışında bir şey. Önceden o zaman sadece eşleşirdi
"auto" kuralı ve yapılması gerekir, ancak artık "auto" kuralı yoktur, yalnızca "auto\n" kuralı vardır. İle
yedekleme olasılığını ortadan kaldırırsanız, tüm kuralları çoğaltabiliriz, ancak
son satırsonu satırları veya böyle bir girdiyle karşılaşmayı asla beklemediğimizden ve bu nedenle
nasıl sınıflandırıldığına göre, bir tane daha hepsini yakalama kuralı ekleyebiliriz, bu
yeni satır ekle:

%%
asm\n |
otomatik\n |
ara\n |
... vb ...
değişken\n |
while\n /* bu bir anahtar kelime */

[az]+\n |
[az]+ |
.|\n /* bu bir anahtar kelime değil */

ile derlenmiştir -Bkz. bu, birinin alabileceği kadar hızlı esnek Bunun için gitmek için tarayıcı
özel sorun.

Son bir not: esnek NUL'leri eşleştirirken yavaştır, özellikle bir belirteç içerdiğinde
çoklu NUL'lar. Eşleşen kurallar yazmak en iyisidir kısa eğer varsa metin miktarları
metnin genellikle NUL'ları içereceği tahmin ediliyor.

Performansla ilgili başka bir son not: Yukarıda Girdi Nasıl Yapılır bölümünde belirtildiği gibi
Eşleştirildi, dinamik olarak yeniden boyutlandırıldı ymetin büyük jetonları barındırmak yavaş bir süreçtir
çünkü şu anda (dev) belirtecin baştan yeniden taranmasını gerektiriyor. Böylece
performans hayati önem taşıyorsa, "büyük" metin miktarlarını eşleştirmeye çalışmalısınız, ancak
ikisi arasındaki sınırın yaklaşık 8K karakter/belirteç olduğu "dev" miktarlar.

ÜRETİCİ C + + TARAYICILAR


esnek C++ ile kullanım için tarayıcılar oluşturmak için iki farklı yol sağlar. İlk yol
tarafından oluşturulan bir tarayıcıyı basitçe derlemek için esnek C yerine C++ derleyicisi kullanma
derleyici. Herhangi bir derleme hatasıyla karşılaşmamalısınız (lütfen bulduklarınızı
Aşağıdaki Yazar bölümünde verilen e-posta adresi). Daha sonra C++ kodunu kullanabilirsiniz.
C kodu yerine kural eylemleri. Tarayıcınız için varsayılan giriş kaynağının
kalıntılar eyyin, ve varsayılan yankı hala yapılır sen. Bu ikisi kalır DOSYA *
değişkenler ve C++ değil akışları.

Ayrıca kullanabilirsiniz esnek kullanarak bir C++ tarayıcı sınıfı oluşturmak için -+ seçeneği (veya,
eşit olarak, %seçenek c++), esnek adı varsa otomatik olarak belirtilir
yürütülebilir dosya bir '+' ile biter, örneğin esnek++. Bu seçeneği kullanırken, flex varsayılanları
tarayıcıyı dosyaya oluşturma lex.yy.cc yerine lex.yy.c. oluşturulan tarayıcı
başlık dosyasını içerir FlexLexer.h, bu, arayüzü iki C++ sınıfına tanımlar.

İlk sınıf, FlexLexer, genel tarayıcıyı tanımlayan soyut bir temel sınıf sağlar
sınıf arayüzü. Aşağıdaki üye işlevlerini sağlar:

const karakter* YYMetin()
en son eşleşen belirtecin metnini döndürür, eşdeğeri ymetin.

int YYLeng()
en son eşleşen belirtecin uzunluğunu döndürür, eşdeğeri Yyleng.

int çizgi() const
geçerli giriş satır numarasını döndürür (bkz. %seçenek yllineno), or 1 if %seçenek
Yylineno kullanılmadı.

geçersiz set_debug( int bayrak )
atamaya eşdeğer, tarayıcı için hata ayıklama bayrağını ayarlar. yy_flex_debug
(yukarıdaki Seçenekler bölümüne bakın). Tarayıcıyı kullanarak oluşturmanız gerektiğini unutmayın.
%seçenek ayıklamak hata ayıklama bilgilerini dahil etmek için.

int hata ayıklama() const
hata ayıklama bayrağının geçerli ayarını döndürür.

Ayrıca aşağıdakilere eşdeğer üye işlevleri de sağlanmıştır: yy_switch_to_buffer(), yy_create_buffer()
(ilk argüman bir standart::istream* nesne işaretçisi ve değil DOSYA*),
yy_flush_buffer(), yy_delete_buffer(), ve yeniden başlat() (yine, ilk argüman bir
standart::istream* nesne işaretçisi).

Tanımlanan ikinci sınıf FlexLexer.h is yyFlexLexer, hangi türetilmiştir FlexLexer.
Aşağıdaki ek üye işlevlerini tanımlar:

yyFlexLexer( standart::istream* arg_yyin = 0, standart::ostream* arg_yyout = 0 )
inşa eder yyFlexLexer giriş ve çıkış için verilen akışları kullanan nesne. Eğer
belirtilmemiş, akışlar varsayılan olarak cin ve ama, respectivamente.

sanal int yylex()
aynı rolü oynar yylex() sıradan esnek tarayıcılar için yapar:
giriş akışı, bir kuralın eylemi bir değer döndürene kadar belirteçleri tüketir. Eğer sen
bir alt sınıf türet S itibaren yyFlexLexer ve üye işlevlerine erişmek istiyorum ve
değişkenleri S içeride yylex(), o zaman kullanman gerek %seçenek y sınıfı = "S" bilgi vermek
esnek yerine bu alt sınıfı kullanacağınızı yyFlexLexer. Bu durumda,
üretmekten ziyade yyFlexLexer::yylex(), esnek üretir S::yylex() (ve ayrıca
bir kukla oluşturur yyFlexLexer::yylex() bu arar yyFlexLexer::LexerError() if
aranan).

sanal geçersiz switch_streams(std::istream* yeni_in = 0,
standart::ostream* yeni_çıktı = 0) yeniden atar yin için yeni_in (sıfır değilse) ve sen için
yeni_çıktı (aynen), önceki giriş arabelleğini silmek, eğer yin yeniden atanır.

int yylex( standart::istream* yeni_in, standart::ostream* yeni_çıktı = 0 )
önce giriş akışlarını şu şekilde değiştirir: akışları değiştir( yeni_in, yeni_çıktı ) ve sonra
değerini döndürür yylex().

Ek olarak, yyFlexLexer yapabileceğiniz aşağıdaki korumalı sanal işlevleri tanımlar.
tarayıcıyı uyarlamak için türetilmiş sınıflarda yeniden tanımlayın:

sanal int LexerGirdi( karakter* meraklı int maksimum_boyut )
kadar okur maksimum_boyut karakterler buf ve okunan karakter sayısını döndürür.
Girişin sonunu belirtmek için 0 karakter döndürün. "Etkileşimli" tarayıcıların
(bkz -B ve -I bayraklar) makroyu tanımlayın YY_İNTERAKTİF. yeniden tanımlarsanız
LexerGirişi() olup olmamasına göre farklı aksiyonlar alması gerekmektedir.
tarayıcı etkileşimli bir giriş kaynağını tarıyor olabilir,
aracılığıyla bu ismin varlığı #ifdef.

sanal geçersiz LexerÇıkış( const karakter* meraklı int boyut )
yazar boyut arabellekteki karakterler meraklı bu, NUL sonlandırılırken,
tarayıcının kuralları metin içindeki NUL'larla eşleşebiliyorsa, "dahili" NUL'leri de içerir.
Onları.

sanal geçersiz LexerHatası( const karakter* msg )
önemli bir hata mesajı bildirir. Bu işlevin varsayılan sürümü,
akışa mesaj CERR ve çıkışlar.

Bir not yyFlexLexer nesne içerir tüm tarama durumu. Böylece böyle kullanabilirsiniz
yeniden giriş yapan tarayıcılar oluşturmak için nesneler. Aynı şeyin birden çok örneğini başlatabilirsiniz
yyFlexLexer sınıfında birden çok C++ tarayıcı sınıfını bir araya getirebilirsiniz.
aynı programı kullanarak -P Yukarıda tartışılan seçenek.

Son olarak, şunu unutmayın: %dizi özellik, C++ tarayıcı sınıflarında mevcut değildir; Mecbursun
kullanım %Işaretçi (varsayılan).

İşte basit bir C++ tarayıcı örneği:

// flex C++ tarayıcı sınıfını kullanma örneği.

%{
int hattım = 0;
%}

dize \"[^\n"]+\"

[ \t]+

alfa [A-Za-z]
kazmak [0-9]
ad ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])*
num1 [+]?{dig}+\.?([eE][-+]?{dig}+)?
num2 [+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
sayı {num1}|{num2}

%%

{ws} /* boşlukları ve sekmeleri atla */

"/*" {
int c;

while((c = yyinput()) != 0)
{
if(c == '\n')
++milineno;

başka if(c == '*')
{
if((c = yyinput()) == '/')
break;
başka
girdi(c);
}
}
}

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

\n mylineno++;

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

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

%%

int ana( int /* argc */, karakter** /* argv */ )
{
FlexLexer* lexer = yeni yyFlexLexer;
while(lexer->yylex() != 0)
;
0 dönmek;
}
Birden fazla (farklı) lexer sınıfı oluşturmak istiyorsanız, -P bayrak (veya
önek= seçeneği) her birini yeniden adlandırmak için yyFlexLexer bir başkasına xxFlexLexer. o zaman yapabilirsin
dahil diğer kaynaklarınızda lexer sınıfı başına bir kez, önce yeniden adlandırma
yyFlexLexer aşağıdaki gibidir:

#undef yyFlexLexer
#define yyFlexLexer xxFlexLexer
#Dahil etmek

#undef yyFlexLexer
#define yyFlexLexer zzFlexLexer
#Dahil etmek

örneğin, kullandıysanız %seçenek önek = "xx" tarayıcılarınızdan biri için ve %seçenek
önek = "zz" Diğeri için.

ÖNEMLİ: tarama sınıfının mevcut biçimi deneysel ve değişebilir
önemli sürümler arasında önemli ölçüde.

UYUMSUZLUKLAR İLE LEX VE POSIX


esnek AT&T Unix'in yeniden yazılmış halidir Lex aracı (iki uygulama hiçbirini paylaşmaz)
kod olsa da), her ikisi de endişe verici olan bazı uzantılar ve uyumsuzluklarla
her iki uygulama için de kabul edilebilir tarayıcılar yazmak isteyenler. Flex tamamen
POSIX ile uyumlu Lex spesifikasyon, kullanım dışında %Işaretçi (varsayılan),
bir çağrı çıktı() içeriğini yok eder ymetin, POSIX'e karşı olan
Şartname.

Bu bölümde, flex, AT&T arasındaki bilinen tüm uyumsuzluk alanlarını tartışacağız.
lex ve POSIX belirtimi.

esnek -l seçeneği, orijinal AT&T ile maksimum uyumluluğu açar Lex uygulanması,
üretilen tarayıcının performansında büyük bir kayıp pahasına. Aşağıda not ediyoruz
kullanılarak uyumsuzlukların üstesinden gelinebilir. -l seçeneği.

esnek Ile tamamen uyumludur Lex aşağıdaki istisnalar dışında:

- Belgesiz Lex tarayıcı dahili değişkeni Yylineno sürece desteklenmez -l
or %seçenek Yylineno kullanıldı.

Yylineno tarayıcı başına değil, arabellek bazında korunmalıdır
(tek global değişken) bazında.

Yylineno POSIX spesifikasyonunun bir parçası değildir.

- giriş() rutin yeniden tanımlanamaz, ancak karakterleri okumak için çağrılabilir
bir kuralla eşleştirilen her şeyi takip etmek. Eğer giriş() bir sonla karşılaşır-
normali dosyala yywrap() işleme yapılır. "Gerçek" bir dosya sonu şu şekilde döndürülür:
giriş() as EOF.

Giriş, bunun yerine tanımlanarak kontrol edilir. YY_GİRİŞ makro.

The esnek kısıtlama giriş() yeniden tanımlanamaz
kontrol etmenin herhangi bir yolunu belirtmeyen POSIX spesifikasyonu.
için bir başlangıç ​​ataması yapmak dışında tarayıcının girdisi eyyin.

- çıktı() rutin yeniden tanımlanamaz. Bu kısıtlamaya göre
POSIX.

- esnek tarayıcılar kadar reentrant değildir Lex tarayıcılar. Özellikle, eğer bir
etkileşimli tarayıcı ve tarayıcıdan uzun süre atlayan bir kesme işleyicisi,
ve ardından tarayıcı tekrar aranırsa, aşağıdaki mesajı alabilirsiniz:

önemli esnek tarayıcı dahili hatası--arabellek sonu kaçırıldı

Tarayıcıya yeniden girmek için önce

yyrestart(yyin);

Bu çağrının arabelleğe alınmış tüm girdileri atacağını unutmayın; genellikle bu bir değil
etkileşimli tarayıcı ile ilgili sorun.

Ayrıca, flex C++ tarayıcı sınıflarının vardır reentrant, yani C++ kullanmak bir seçenekse
sizin için, onları kullanmalısınız. için yukarıdaki "C++ Tarayıcıları Oluşturma" bölümüne bakın.
detaylar.

- çıktı() desteklenmiyor. çıkış EKO dosya işaretçisine makro yapılır
sen (varsayılan standart).

çıktı() POSIX spesifikasyonunun bir parçası değildir.

- Lex POSIX'te olmalarına rağmen özel başlatma koşullarını (%x) desteklemez
Şartname.

- Tanımlar genişletildiğinde, esnek bunları parantez içine alır. lex ile,
Aşağıdaki:

ADI [AZ][A-Z0-9]*
%%
foo{NAME}? printf("Buldum\n");
%%

"foo" dizesiyle eşleşmeyecek çünkü makro genişletildiğinde kural
"foo[AZ][A-Z0-9]*?" ve öncelik öyle ki '?' dır-dir
"[A-Z0-9]*" ile ilişkili. İle esnek, kural "foo([AZ][A-)" şeklinde genişletilecektir.
Z0-9]*)?" ve böylece "foo" dizesi eşleşecektir.

Tanım ile başlarsa unutmayın ^ veya ile biter $ o zaman öyle değil genişletilmiş
bu operatörlerin tanımlarda kaybolmadan görünmesini sağlamak için parantez içinde
onların özel anlamları. Ama , /, ve < > operatörler bir yerde kullanılamaz
esnek tanım.

kullanma -l sonuçları Lex tanım etrafında parantez olmayan davranış.

POSIX belirtimi, tanımın parantez içine alınmasıdır.

- Bazı uygulamalar Lex varsa, bir kuralın eyleminin ayrı bir satırda başlamasına izin verin
kuralın deseninin sonunda boşluk var:

%%
foo|bar
{ foobar_action(); }

esnek bu özelliği desteklemiyor.

- Lex %r (Ratfor tarayıcı oluştur) seçeneği desteklenmez. parçası değil
POSIX spesifikasyonu.

- Bir aramadan sonra çıktı(), ymetin sonraki belirteç eşleşene kadar tanımsızdır,
tarayıcı kullanılarak oluşturulmadıysa %sıralamak. Bu durum böyle değil Lex ya da
POSIX spesifikasyonu. bu -l seçeneği bu uyumsuzluğu ortadan kaldırır.

- Önceliği {} (sayısal aralık) operatörü farklıdır. Lex yorumlayıp
"abc{1,3}", "'abc'nin bir, iki veya üç örneğini eşleştir" olarak, oysa esnek
bunu "' ab 'eşleştirmesi ve ardından bir, iki veya üç 'c' oluşumu" olarak yorumlar.
İkincisi, POSIX spesifikasyonu ile uyumludur.

- Önceliği ^ operatör farklıdır. Lex "^foo|bar" ifadesini "eşleşme" olarak yorumlar
ya bir satırın başında 'foo' ya da herhangi bir yerde 'bar'", oysa esnek
başında gelirlerse "'foo' veya 'bar' ile eşleşecek şekilde yorumlar.
satırı". İkincisi, POSIX spesifikasyonu ile uyumludur.

- gibi özel tablo boyutu bildirimleri %a Tarafından desteklenen Lex tarafından gerekli değildir
esnek tarayıcılar; esnek onları görmezden gelir.

- İsim FLEX_TARAYICI #tanımlı olduğundan tarayıcılar her ikisiyle de kullanılmak üzere yazılabilir
esnek or sözlük Tarayıcılar ayrıca şunları içerir: YY_FLEX_MAJOR_VERSION ve YY_FLEX_MINOR_VERSION
hangi versiyonunun olduğunu gösteren esnek tarayıcıyı oluşturdu (örneğin, 2.5 için
sürüm, bu tanımlar sırasıyla 2 ve 5 olacaktır).

Aşağıdaki esnek özellikler dahil değildir Lex veya POSIX spesifikasyonu:

C++ tarayıcıları
%seçenek
başlangıç ​​koşulu kapsamları
koşul yığınlarını başlat
etkileşimli/etkileşimli olmayan tarayıcılar
yy_scan_string() ve arkadaşları
yysonlandırma()
yy_set_interactive()
yy_set_bol()
YY_AT_BOL()
< >
<*>
YY_DECL
YY_START
YY_USER_ACTION
YY_USER_INIT
#line yönergeleri
%{} eylemlerin etrafında
bir satırda birden fazla eylem

artı neredeyse tüm esnek bayraklar. Listedeki son özellik şu gerçeği ifade eder:
ile esnek noktalı virgülle ayırarak aynı satıra birden fazla eylem koyabilirsiniz.
ile sözlük, aşağıdaki

foo tanıtıcı_foo(); ++num_foos_seen;

(oldukça şaşırtıcı bir şekilde) kısaltılır

foo tanıtıcı_foo();

esnek eylemi kesmez. Parantez içine alınmayan eylemler basitçe
satırın sonunda sonlandırılır.

TANI


uyarı, kural Amerika’ya vize ile ya da Meksika üzerinden geldikten sonra ilticaya başvuran kişileri, herhangi bir suça karışmadıkları sürece mahkeme kararı olmadan sınır dışı (deport) ettiremez. be eşleşti verilen kuralın eşleştirilemeyeceğini gösterir çünkü
her zaman onunla aynı metinle eşleşecek diğer kuralları takip eder. Örneğin,
Aşağıdaki "foo", tanımlayıcı "hepsini yakala" kuralından sonra geldiği için eşleştirilemez:

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

kullanma REDDET tarayıcıda bu uyarıyı bastırır.

uyarı, -s seçenek verilmiş fakat varsayılan kural yapabilmek be eşleşti mümkün olduğu anlamına gelir
(belki yalnızca belirli bir başlangıç ​​koşulunda) varsayılan kuralın (herhangi bir
karakter) belirli bir girdiyle eşleşen tek karakterdir. Dan beri -s verilmişti,
muhtemelen bu amaçlanmamıştır.

reddet_used_but_not_tespit edildi tanımlanmamış or yymore_used_but_not_algılandı tanımlanmamış - Bunlar
derleme zamanında hatalar oluşabilir. Tarayıcının kullandığını belirtirler. REDDET or daha fazla()
ancak esnek gerçeği fark edemedi, yani esnek ilk iki bölümü taradım
bu eylemlerin oluşumlarını arıyor ve hiçbirini bulamadınız, ancak bir şekilde gizlice girdiniz
bazıları içeri (örneğin bir #include dosyası aracılığıyla). Kullanmak %seçenek reddetmek or %seçenek daha fazla için
bu özellikleri gerçekten kullanıp kullanmadığınızı göstermek için belirtin.

esnek tarayıcı sıkışmış - ile derlenmiş bir tarayıcı -s bir giriş dizesiyle karşılaştı
hiçbir kuralına uymuyordu. Bu hata, dahili sorunlar nedeniyle de oluşabilir.

simge çok büyük, aşıyor YYLMAX - tarayıcınız kullanır %dizi ve kurallarından biri bir
dizeden daha uzun YYLMAX sabit (varsayılan olarak 8K bayt). Değeri artırabilirsiniz
#tanımlayarak YYLMAX tanımları bölümünde esnek giriş.

tarayıcı gerektirir -8 bayrak için kullanım the karakter 'x' - Tarayıcınızın teknik özellikleri şunları içerir:
8 bitlik karakteri tanıma 'x' ve -8 bayrağını belirtmediniz ve tarayıcınız
kullandığınız için varsayılan olarak 7 bit -Çf or CF tablo sıkıştırma seçenekleri. Bkz.
tartışması -7 Ayrıntılar için bayrak.

esnek tarayıcı Geri itmek taşma - kullandınız çıktı() o kadar çok metni geri itmek için
tarayıcının arabelleği, hem geri gönderilen metni hem de geçerli belirteci içeride tutamadı ymetin.
İdeal olarak, tarayıcı bu durumda arabelleği dinamik olarak yeniden boyutlandırmalıdır, ancak şu anda
değil.

giriş tampon taşma, olamaz büyütmek tampon Çünkü tarayıcı kullanım REDDET - tarayıcı
son derece büyük bir belirteç eşleştirme üzerinde çalışıyor ve giriş arabelleğini genişletmek için gerekli. Bu
kullanan tarayıcılarla çalışmaz. REDDETMEK.

ölümcül esnek tarayıcı hata--son of tampon cevapsız - Bu bir tarayıcıda meydana gelebilir
uzun bir atlamadan sonra (veya tarayıcının aktivasyonunun üzerinden) tekrar girilen
çerçeve. Tarayıcıya yeniden girmeden önce şunları kullanın:

yyrestart(yyin);

veya yukarıda belirtildiği gibi, C++ tarayıcı sınıfını kullanmaya geçin.

çok çok başlama koşullar in <> inşa et! - <> içinde daha fazla başlangıç ​​koşulu listelediniz
oluştur (yani en az birini iki kez listelemiş olmalısınız).

onworks.net hizmetlerini kullanarak freebsd-lex'i çevrimiçi kullanın


Ücretsiz Sunucular ve İş İstasyonları

Windows ve Linux uygulamalarını indirin

Linux komutları

Ad




×
reklâm
❤️Buradan alışveriş yapın, rezervasyon yapın veya satın alın; ücretsizdir, hizmetlerin ücretsiz kalmasına yardımcı olur.