Ito ang command na freebsd-lex na maaaring patakbuhin sa OnWorks na libreng hosting provider gamit ang isa sa aming maramihang libreng online na workstation gaya ng Ubuntu Online, Fedora Online, Windows online emulator o MAC OS online emulator
PROGRAMA:
NAME
flex, lex - mabilis na lexical analyzer generator
SINOPSIS
pagbaluktot [-bcdfhilnpstvwBFILTV78+? -C[aefFmr] -ooutput -Pprefix -Skeleton] [--tulong --bersyon]
[filename ...]
PANGKALAHATANG-IDEYA
Inilalarawan ng manwal na ito baluktot, isang tool para sa pagbuo ng mga program na gumaganap ng pattern-matching
sa text. Kasama sa manual ang parehong mga seksyon ng tutorial at sanggunian:
paglalarawan
isang maikling pangkalahatang-ideya ng tool
Ilang Simpleng Halimbawa
Format Ng Input File
Pattern
ang pinalawig na mga regular na expression na ginagamit ng flex
Paano Tinutugma ang Input
ang mga patakaran para sa pagtukoy kung ano ang naitugma
Aksyon
kung paano tukuyin kung ano ang gagawin kapag ang isang pattern ay tumugma
Ang Binuo na Scanner
mga detalye tungkol sa scanner na ginagawa ng flex;
paano kontrolin ang input source
Mga Kundisyon ng Simula
pagpapasok ng konteksto sa iyong mga scanner, at
pamamahala ng "mini-scanners"
Maramihang Input Buffer
kung paano manipulahin ang maramihang mga mapagkukunan ng input; Paano
i-scan mula sa mga string sa halip na mga file
Mga Panuntunan sa End-of-file
mga espesyal na panuntunan para sa pagtutugma sa dulo ng input
Sari-saring Macros
isang buod ng mga macro na magagamit sa mga aksyon
Mga Halaga na Magagamit Sa Gumagamit
isang buod ng mga halaga na magagamit sa mga aksyon
Interfacing Sa Yacc
pagkonekta ng mga flex scanner kasama ng mga yacc parser
Options
flex command-line na mga opsyon, at ang "%option"
direktiba
Mga Pagsasaalang-alang sa Pagganap
kung paano gawin ang iyong scanner na pumunta nang mas mabilis hangga't maaari
Pagbuo ng mga C++ Scanner
ang (pang-eksperimentong) pasilidad para sa pagbuo ng C++
mga klase ng scanner
Mga Incompatibilities Sa Lex At POSIX
kung paano naiiba ang flex sa AT&T lex at sa POSIX lex
pamantayan
Diagnostics
ang mga mensahe ng error na iyon na ginawa ng flex (o mga scanner
ito ay bumubuo) na ang mga kahulugan ay maaaring hindi maliwanag
File
mga file na ginamit ng flex
Mga Kakulangan / Mga Bug
mga kilalang problema sa flex
Tingnan din
iba pang dokumentasyon, mga kaugnay na tool
may-akda
may kasamang impormasyon sa pakikipag-ugnayan
DESCRIPTION
pagbaluktot ay isang kasangkapan para sa pagbuo mga scanner: mga programang kumikilala ng mga leksikal na pattern sa teksto.
pagbaluktot binabasa ang ibinigay na mga file ng input, o ang karaniwang input nito kung walang ibinigay na mga pangalan ng file, para sa a
paglalarawan ng isang scanner na bubuo. Ang paglalarawan ay nasa anyo ng mga pares ng regular
expression at C code, na tinatawag panuntunan. pagbaluktot bumubuo bilang output ng isang C source file, lex.yy.c,
na tumutukoy sa isang gawain yylex(). Ang file na ito ay pinagsama-sama at naka-link sa -ll library sa
gumawa ng executable. Kapag pinapatakbo ang executable, sinusuri nito ang input nito para sa mga pangyayari
ng mga regular na expression. Sa tuwing makakahanap ito ng isa, ipapatupad nito ang kaukulang C code.
ILANG SIMPLE HALIMBAWA
Una ang ilang mga simpleng halimbawa upang makuha ang lasa ng kung paano ginagamit ng isa baluktot Ang mga sumusunod na pagbaluktot
Tinutukoy ng input ang isang scanner na sa tuwing makakatagpo ito ng string na "username" ay papalitan
ito kasama ang pangalan ng pag-log in ng user:
%%
username printf("%s", getlogin() );
Bilang default, anumang text na hindi tumugma sa a pagbaluktot scanner ay kinopya sa output, kaya ang net
epekto ng scanner na ito ay upang kopyahin ang input file nito sa output nito sa bawat paglitaw ng
pinalawak ang "username." Sa input na ito, mayroon lamang isang panuntunan. "username" ay ang huwaran
at ang "printf" ay ang pagkilos. Ang "%%" ay nagmamarka sa simula ng mga panuntunan.
Narito ang isa pang simpleng halimbawa:
%{
int num_lines = 0, num_chars = 0;
%}
%%
\n ++num_lines; ++num_chars;
. ++num_chars;
%%
main ()
{
yylex();
printf("# ng mga linya = %d, # ng mga character = %d\n",
num_lines, num_chars );
}
Binibilang ng scanner na ito ang bilang ng mga character at ang bilang ng mga linya sa input nito (ito
hindi gumagawa ng output maliban sa huling ulat sa mga bilang). Ang unang linya ay nagpapahayag
dalawang global, "num_lines" at "num_chars", na parehong mapupuntahan sa loob yylex() at sa
ang main () nakagawiang idineklara pagkatapos ng pangalawang "%%". Mayroong dalawang mga patakaran, isa na tumutugma
isang bagong linya ("\n") at dinadagdagan ang bilang ng linya at bilang ng character, at isa na
tumutugma sa anumang karakter maliban sa isang bagong linya (ipinahiwatig ng "." regular na expression).
Isang medyo mas kumplikadong halimbawa:
/* scanner para sa laruang mala-Pascal na wika */
%{
/* kailangan ito para sa tawag sa atof() sa ibaba */
# isama
%}
DIGIT [0-9]
ID [az][a-z0-9]*
%%
{DIGIT}+ {
printf("Isang integer: %s (%d)\n", yytext,
atoi( yytext ) );
}
{DIGIT}+"."{DIGIT}* {
printf("Isang float: %s (%g)\n", yytext,
atof( yytext ) );
}
kung|pagkatapos|simulan|tapos|pamamaraan|function {
printf("Isang keyword: %s\n", yytext );
}
{ID} printf( "Isang identifier: %s\n", yytext );
"+"|"-"|"*"|"/" printf( "Isang operator: %s\n", yytext );
"{"[^}\n]*"}" /* kumain ng isang linyang komento */
[ \t\n]+ /* kumain ng whitespace */
. printf("Hindi nakikilalang karakter: %s\n", yytext );
%%
pangunahing( argc, argv )
int argc;
char **argv;
{
++argv, --argc; /* laktawan ang pangalan ng program */
kung ( argc > 0 )
yyin = fopen( argv[0], "r" );
iba
yyin = stdin;
yylex();
}
Ito ang simula ng isang simpleng scanner para sa isang wika tulad ng Pascal. Kinikilala nito
iba't ibang uri ng token at mga ulat sa kung ano ang nakita nito.
Ang mga detalye ng halimbawang ito ay ipapaliwanag sa mga sumusunod na seksyon.
FORMAT OF ANG INPUT FILE
Ang pagbaluktot input file ay binubuo ng tatlong mga seksyon, na pinaghihiwalay ng isang linya na may lamang %% sa loob:
mga kahulugan
%%
patakaran
%%
code ng gumagamit
Ang mga kahulugan seksyon ay naglalaman ng mga deklarasyon ng simple pangalan mga kahulugan upang gawing simple ang
detalye ng scanner, at mga deklarasyon ng simula kondisyon, na ipinaliwanag sa a
susunod na seksyon.
Ang mga kahulugan ng pangalan ay may anyo:
kahulugan ng pangalan
Ang "pangalan" ay isang salita na nagsisimula sa isang titik o isang underscore ('_') na sinusundan ng zero o
higit pang mga titik, digit, '_', o '-' (gitling). Ang kahulugan ay kinuha upang magsimula sa una
non-white-space na character na sumusunod sa pangalan at nagpapatuloy hanggang sa dulo ng linya. Ang
ang kahulugan ay maaaring i-refer pagkatapos gamit ang "{name}", na lalawak sa
"(kahulugan)". Halimbawa,
DIGIT [0-9]
ID [az][a-z0-9]*
Tinutukoy ang "DIGIT" bilang isang regular na expression na tumutugma sa isang digit, at ang "ID" ay isang
regular na expression na tumutugma sa isang titik na sinusundan ng zero-o-higit pang mga titik-o-digit. A
kasunod na pagtukoy sa
{DIGIT}+"."{DIGIT}*
ay magkapareho sa
([0-9])+"."([0-9])*
at tumutugma sa isa-o-higit pang mga digit na sinusundan ng isang '.' na sinusundan ng zero-o-higit pang mga digit.
Ang patakaran na seksyon ng pagbaluktot Ang input ay naglalaman ng isang serye ng mga patakaran ng form:
pagkilos ng pattern
kung saan ang pattern ay dapat na hindi naka-indent at ang aksyon ay dapat magsimula sa parehong linya.
Tingnan sa ibaba para sa karagdagang paglalarawan ng mga pattern at pagkilos.
Panghuli, ang seksyon ng user code ay kinopya lamang sa lex.yy.c verbatim. Ito ay ginagamit para sa
kasamang gawain na tumatawag o tinatawag ng scanner. Ang pagkakaroon ng seksyong ito
ay opsyonal; kung ito ay nawawala, ang pangalawa %% sa input file ay maaaring laktawan din.
Sa mga seksyon ng mga kahulugan at panuntunan, anuman naka-indent text o text na nakapaloob %{ at %} is
kinopya ang verbatim sa output (na inalis ang %{}). Ang %{}'s ay dapat lumabas na hindi naka-indent
sa mga linya sa kanilang sarili.
Sa seksyon ng mga panuntunan, maaaring gamitin ang anumang naka-indent o %{} na text na lumalabas bago ang unang panuntunan
para magdeklara ng mga variable na lokal sa routine ng pag-scan at (pagkatapos ng mga deklarasyon)
code na dapat isakatuparan sa tuwing ipinasok ang routine ng pag-scan. Iba pang naka-indent o
Ang %{} na teksto sa seksyon ng panuntunan ay kinopya pa rin sa output, ngunit hindi maganda ang kahulugan nito-
tinukoy at maaari itong maging sanhi ng mga error sa oras ng pag-compile (naroroon ang tampok na ito para sa POSIX
pagsunod; tingnan sa ibaba para sa iba pang mga tampok).
Sa seksyon ng mga kahulugan (ngunit hindi sa seksyon ng mga panuntunan), isang hindi naka-indent na komento (ibig sabihin, a
Ang linya na nagsisimula sa "/*") ay kinopya din ng verbatim sa output hanggang sa susunod na "*/".
MGA pattern
Ang mga pattern sa input ay isinusulat gamit ang pinahabang hanay ng mga regular na expression. Ang mga ito
ay:
x tumutugma sa character na 'x'
. anumang character (byte) maliban sa newline
[xyz] isang "klase ng character"; sa kasong ito, ang pattern
tumutugma sa alinman sa isang 'x', isang 'y', o isang 'z'
[abj-oZ] isang "klase ng character" na may saklaw dito; mga posporo
isang 'a', isang 'b', anumang titik mula sa 'j' hanggang sa 'o',
o isang 'Z'
[^AZ] isang "negated character class", ibig sabihin, anumang character
pero yung nasa klase. Sa kasong ito, anuman
character MALIBAN sa malaking titik.
[^AZ\n] anumang character MALIBAN sa malaking titik o
isang bagong linya
r* zero o higit pang mga r, kung saan ang r ay anumang regular na expression
r+ isa o higit pang mga r
r? zero o isang r (iyon ay, "isang opsyonal na r")
r{2,5} kahit saan mula dalawa hanggang limang r
r{2,} dalawa o higit pang mga r
r{4} eksaktong 4 r's
{name} ang pagpapalawak ng kahulugan ng "pangalan."
(tingnan sa itaas)
"[xyz]\"foo"
ang literal na string: [xyz]"foo
\X kung ang X ay isang 'a', 'b', 'f', 'n', 'r', 't', o 'v',
pagkatapos ay ang ANSI-C interpretasyon ng \x.
Kung hindi, isang literal na 'X' (ginamit upang makatakas
mga operator tulad ng '*')
\0 isang NUL na character (ASCII code 0)
\123 ang character na may octal value na 123
\x2a ang character na may hexadecimal value na 2a
(r) tumugma sa isang r; ang mga panaklong ay ginagamit upang i-override
nangunguna (tingnan sa ibaba)
rs ang regular na expression r sinusundan ng
regular na expression s; tinatawag na "concatenation"
r|s alinman sa isang r o isang s
r/s an r ngunit lamang kung ito ay sinusundan ng isang s. Ang
ang tekstong tumugma sa s ay kasama kapag tinutukoy
kung ang panuntunang ito ay ang "pinakamahabang tugma",
ngunit pagkatapos ay ibinalik sa input bago
ang aksyon ay naisakatuparan. Kaya ang aksyon lamang
nakikita ang tekstong itinugma ni r. Ganitong klase
ng pattern ay tinatawag na trailing context".
(May ilang kumbinasyon ng r/s na nabaluktot
hindi maaaring tumugma nang tama; tingnan ang mga tala sa
Mga Deficiencies / Bugs na seksyon sa ibaba tungkol sa
"mapanganib na konteksto ng trailing".)
^r an r, ngunit sa simula lamang ng isang linya (ibig sabihin,
kapag nagsisimula pa lang mag-scan, o pagkatapos ng a
na-scan ang bagong linya).
r$ an r, ngunit sa dulo lamang ng isang linya (ibig sabihin, just
bago ang isang bagong linya). Katumbas ng "r/\n".
Tandaan na ang paniwala ni flex ng "newline" ay eksakto
anuman ang ginamit ng C compiler para mag-compile ng flex
binibigyang kahulugan ang '\n' bilang; sa partikular, sa ilang DOS
mga system dapat mong i-filter ang mga \r sa
ipasok ang iyong sarili, o tahasang gumamit ng r/\r\n para sa "r$".
r an r, ngunit sa panimulang kondisyon s (tingnan
sa ibaba para sa talakayan ng mga kondisyon ng pagsisimula)
r
pareho, ngunit sa alinman sa mga kondisyon ng pagsisimula s1,
s2, o s3
<*>r an r sa anumang panimulang kundisyon, kahit na isang eksklusibo.
< > isang end-of-file
< >
isang end-of-file kapag nasa panimulang kondisyon s1 o s2
Tandaan na sa loob ng klase ng character, lahat ng regular na expression operator ay nawawala ang kanilang espesyal
ibig sabihin maliban sa pagtakas ('\') at ang mga operator ng klase ng character, '-', ']', at, sa
simula ng klase, '^'.
Ang mga regular na expression na nakalista sa itaas ay pinagsama-sama ayon sa precedence, mula sa pinakamataas
nangunguna sa itaas hanggang sa pinakamababa sa ibaba. Ang mga pinagsama-sama ay may pantay
karapatan sa pangunguna. Halimbawa,
foo|bar*
ay pareho
(foo)|(ba(r*))
dahil ang '*' operator ay may mas mataas na precedence kaysa concatenation, at concatenation mas mataas
kaysa sa paghalili ('|'). Ang pattern na ito samakatuwid ay tumutugma alinman sa ang string na "foo" or ang
string na "ba" na sinusundan ng zero-or-more r's. Upang tumugma sa "foo" o zero-o-more "bar", gamitin ang:
foo|(bar)*
at upang tumugma sa zero-o-more "foo"'s-or-"bar"'s:
(foo|bar)*
Bilang karagdagan sa mga character at hanay ng mga character, maaari ding maglaman ang mga klase ng character
klase ng karakter mga ekspresyon. Ito ay mga ekspresyong nakapaloob sa loob [: at :] mga delimiter
(na dapat lumitaw sa pagitan ng '[' at ']' ng klase ng character; iba pa
Ang mga elemento ay maaaring mangyari din sa loob ng klase ng character). Ang mga wastong expression ay:
[:alnum:] [:alpha:] [:blangko:]
[:cntrl:] [:digit:] [:graph:]
[:lower:] [:print:] [:punct:]
[:space:] [:upper:] [:xdigit:]
Lahat ng mga expression na ito ay nagtatalaga ng isang set ng mga character na katumbas ng katumbas
pamantayan C ayXXX function. Halimbawa, [:alnum:] itinalaga ang mga karakter kung saan
isalnum() nagbabalik ng true - ibig sabihin, anumang alpabeto o numeric. Ang ilang mga sistema ay hindi nagbibigay
isblank(), so flex define [:blangko:] bilang isang blangko o isang tab.
Halimbawa, ang mga sumusunod na klase ng character ay katumbas ng lahat:
[[:alnum:]]
[[:alpha:][:digit:]]
[[:alpha:]0-9]
[a-zA-Z0-9]
Kung ang iyong scanner ay case-insensitive (ang -i bandila), pagkatapos [:itaas:] at [:baba:] ay
katumbas ng [:alpha:].
Ang ilang mga tala sa mga pattern:
- Isang tinanggihang klase ng character gaya ng halimbawang "[^AZ]" sa itaas habilin tumugma a bagong linya
maliban kung ang "\n" (o isang katumbas na pagkakasunud-sunod ng pagtakas) ay isa sa mga character na tahasang
naroroon sa negated na klase ng character (hal., "[^AZ\n]"). Ito ay hindi katulad ng kung gaano karami
ang ibang mga regular na tool sa pagpapahayag ay tinatrato ang mga negadong klase ng character, ngunit sa kasamaang-palad
ang hindi pagkakapare-pareho ay nakabaon sa kasaysayan. Ang pagtutugma ng mga bagong linya ay nangangahulugan na a
pattern tulad ng [^"]* ay maaaring tumugma sa buong input maliban kung may isa pang quote sa
input.
- Ang isang panuntunan ay maaaring magkaroon ng hindi hihigit sa isang pagkakataon ng sumusunod na konteksto (ang '/' operator o ang
operator na '$'). Ang panimulang kondisyon, '^', at "< >" ang mga pattern ay maaari lamang mangyari sa
ang simula ng isang pattern, at, pati na rin sa '/' at '$', ay hindi maaaring ipangkat
loob ng panaklong. Isang '^' na hindi nangyayari sa simula ng isang panuntunan o isang '$'
na hindi nangyayari sa dulo ng isang panuntunan ay nawawala ang mga espesyal na katangian nito at ay
itinuturing bilang isang normal na karakter.
Ang mga sumusunod ay ilegal:
foo/bar$
foo bar
Tandaan na ang una sa mga ito, ay maaaring isulat na "foo/bar\n".
Ang sumusunod ay magreresulta sa '$' o '^' na itinuturing bilang isang normal na karakter:
foo|(bar$)
foo|^bar
Kung ang gusto ay isang "foo" o isang bar-sinusundan-by-a-newline, ang sumusunod ay maaaring
ginamit (ang espesyal na aksyong '|' ay ipinaliwanag sa ibaba):
foo |
bar$ /* napupunta dito ang aksyon */
Ang isang katulad na trick ay gagana para sa pagtutugma ng isang foo o isang bar-sa-simula-ng-isang-linya.
PAANO ANG INPUT IS MATCHED
Kapag pinapatakbo ang nabuong scanner, sinusuri nito ang input nito na naghahanap ng mga string na tumutugma
alinman sa mga pattern nito. Kung makakahanap ito ng higit sa isang tugma, aabutin ang pinakakatugma
text (para sa sumusunod na mga panuntunan sa konteksto, kabilang dito ang haba ng trailing na bahagi, kahit na
kahit na ito ay ibabalik sa input). Kung nakahanap ito ng dalawa o higit pang mga tugma ng
parehong haba, ang panuntunang unang nakalista sa pagbaluktot pinili ang input file.
Kapag natukoy na ang tugma, ang text na tumutugma sa tugma (tinatawag na token) is
ginawang available sa pandaigdigang character pointer yytext, at ang haba nito sa global
kabuuan yyleng. Ang aksyon naaayon sa katugmang pattern ay ipapatupad (isang higit pa
ang detalyadong paglalarawan ng mga aksyon ay sumusunod), at pagkatapos ay ang natitirang input ay ini-scan para sa
isa pang laban.
Kung walang nakitang tugma, ang default mamuno ay naisakatuparan: ang susunod na character sa input
ay itinuturing na tumugma at kinopya sa karaniwang output. Kaya, ang pinakasimpleng legal pagbaluktot
ang input ay:
%%
na bumubuo ng scanner na kinokopya lang ang input nito (isang character sa isang pagkakataon) sa nito
output.
Tandaan na ang yytext maaaring tukuyin sa dalawang magkaibang paraan: alinman bilang isang karakter puntero o bilang
isang karakter pag-ayos. Maaari mong kontrolin kung aling kahulugan pagbaluktot ginagamit sa pamamagitan ng pagsasama ng isa sa
mga espesyal na direktiba %pointer or %array sa unang (mga kahulugan) na seksyon ng iyong pagbaluktot
input. Ang default ay %pointer, maliban kung gagamitin mo ang -l lex compatibility option, kung saan
kaso yytext ay magiging isang array. Ang bentahe ng paggamit %pointer ay lubos na mas mabilis
pag-scan at walang buffer overflow kapag tumutugma sa napakalaking token (maliban kung maubusan ka ng
dynamic na memorya). Ang kawalan ay na ikaw ay pinaghihigpitan sa kung paano magagawa ng iyong mga aksyon
baguhin yytext (tingnan ang susunod na seksyon), at tumawag sa unput() ang pag-andar ay sumisira sa
kasalukuyang nilalaman ng yytext, na maaaring maging isang malaking porting sakit ng ulo kapag gumagalaw
sa pagitan ng magkakaiba lex mga bersyon.
Ang bentahe ng %array ay na maaari mong baguhin yytext sa nilalaman ng iyong puso, at
mga tawag sa unput() huwag sirain yytext (tingnan sa ibaba). Higit pa rito, umiiral lex mga programa
minsan access yytext panlabas gamit ang mga deklarasyon ng form:
extern char yytext[];
Ang kahulugan na ito ay mali kapag ginamit kasama ng %pointer, ngunit tama para sa %array.
%array tumutukoy yytext upang maging isang array ng YYLMAX character, na nagde-default sa isang patas
malaking halaga. Maaari mong baguhin ang laki sa pamamagitan lamang ng #define'ing YYLMAX sa ibang halaga sa
ang unang seksyon ng iyong pagbaluktot input. Gaya ng nabanggit sa itaas, kasama %pointer lumalaki ang yytext
dynamic na paraan upang mapaunlakan ang malalaking token. Habang ito ay nangangahulugan ng iyong %pointer lata ng scanner
tumanggap ng napakalaking mga token (tulad ng pagtutugma sa buong bloke ng mga komento), tandaan
na sa bawat oras na dapat baguhin ang laki ng scanner yytext dapat din itong muling i-scan ang buong token mula sa
sa simula, kaya maaaring mabagal ang pagtutugma ng mga naturang token. yytext kasalukuyang ginagawa hindi
dynamic na lumalaki kung isang tawag sa unput() nagreresulta sa masyadong maraming teksto na itinulak pabalik; sa halip,
isang run-time na error ang mga resulta.
Tandaan din na hindi mo magagamit %array na may mga klase ng C++ scanner (ang c ++ opsyon; tingnan sa ibaba).
MGA PAGKILOS
Ang bawat pattern sa isang panuntunan ay may kaukulang aksyon, na maaaring maging anumang arbitrary na C statement.
Nagtatapos ang pattern sa unang hindi nakatakas na whitespace na character; ang natitira sa linya
ang aksyon nito. Kung ang aksyon ay walang laman, pagkatapos ay kapag ang pattern ay tumugma sa input token
basta na lang itinatapon. Halimbawa, narito ang detalye para sa isang program na nagtatanggal
lahat ng paglitaw ng "zap me" mula sa input nito:
%%
"sagutin mo ako"
(Kokopyahin nito ang lahat ng iba pang mga character sa input sa output dahil sila ay maitugma
sa pamamagitan ng default na panuntunan.)
Narito ang isang programa na nagpi-compress ng maramihang mga blangko at mga tab pababa sa isang blangko, at
itinatapon ang whitespace na matatagpuan sa dulo ng isang linya:
%%
[ \t]+ putchar( ' ' );
[ \t]+$ /* huwag pansinin ang token na ito */
Kung ang aksyon ay naglalaman ng isang '{', ang aksyon ay sumasaklaw hanggang sa ang pagbabalanse '}' ay matagpuan, at
ang aksyon ay maaaring tumawid sa maraming linya. pagbaluktot alam ang tungkol sa mga C string at komento at hindi magiging
niloloko ng mga braces na matatagpuan sa loob ng mga ito, ngunit pinapayagan din ang mga aksyon na magsimula sa %{ at kalooban
isaalang-alang ang aksyon na ang lahat ng teksto hanggang sa susunod %} (hindi alintana ang ordinaryong braces
sa loob ng aksyon).
Ang isang aksyon na binubuo lamang ng isang patayong bar ('|') ay nangangahulugang "kapareho ng aksyon para sa susunod
panuntunan." Tingnan sa ibaba para sa isang paglalarawan.
Maaaring kabilang sa mga aksyon ang arbitrary C code, kasama ang pagbabalik mga pahayag upang ibalik ang isang halaga
kahit anong tawag sa routine yylex(). Sa bawat oras yylex() ay tinatawag na ito ay patuloy na pagproseso
mga token mula sa kung saan ito huling huminto hanggang sa maabot nito ang dulo ng file o i-execute
ang pagbalik.
Ang mga aksyon ay libre upang baguhin yytext maliban sa pagpapahaba nito (pagdaragdag ng mga character sa
end--ito ay mag-o-overwrite sa mga susunod na character sa input stream). Ito gayunpaman ay hindi
ilapat kapag ginagamit %array (tingnan sa itaas); sa kasong iyon, yytext maaaring malayang mabago sa alinman
paraan.
Ang mga aksyon ay libre upang baguhin yyleng maliban kung hindi nila dapat gawin ito kung kasama rin ang aksyon
gumamit ng yymore() (tingnan sa ibaba).
Mayroong ilang mga espesyal na direktiba na maaaring isama sa loob ng isang aksyon:
- Echo kinokopya ang yytext sa output ng scanner.
- BEGIN na sinusundan ng pangalan ng isang panimulang kondisyon ay naglalagay ng scanner sa
kaukulang kondisyon ng pagsisimula (tingnan sa ibaba).
- TANGGIHAN nagdidirekta sa scanner na magpatuloy sa "pangalawang pinakamahusay" na panuntunan na tumugma
ang input (o isang prefix ng input). Ang panuntunan ay pinili tulad ng inilarawan sa itaas sa
"Paano Tinutugma ang Input", at yytext at yyleng i-set up nang naaangkop. Maaaring
alinman sa isa na tumugma sa kasing dami ng text gaya ng orihinal na napiling panuntunan ngunit dumating
mamaya sa pagbaluktot input file, o isa na tumugma sa mas kaunting text. Halimbawa, ang
ang sumusunod ay parehong bibilangin ang mga salita sa input at tatawagin ang regular na special()
sa tuwing makikita ang "frob":
int word_count = 0;
%%
espesyal na frob(); TANGGIHAN;
[^ \t\n]+ ++word_count;
Wala ang TANGGIHAN, anumang "frob" sa input ay hindi mabibilang bilang mga salita, dahil
ang scanner ay karaniwang nagsasagawa lamang ng isang aksyon sa bawat token. Maramihan REJECT's ay
pinapayagan, bawat isa ay naghahanap ng susunod na pinakamahusay na pagpipilian sa kasalukuyang aktibong panuntunan. Para sa
halimbawa, kapag ini-scan ng sumusunod na scanner ang token na "abcd", ito ay magsusulat
"abcdabbaba" sa output:
%%
a |
ab |
abc |
abcd ECHO; TANGGIHAN;
.|\n /* kainin ang anumang walang kapantay na karakter */
(Ang unang tatlong panuntunan ay nagbabahagi ng pagkilos ng ikaapat dahil ginagamit nila ang espesyal na '|'
aksyon.) TANGGIHAN ay isang partikular na mahal na tampok sa mga tuntunin ng scanner
pagganap; kung ito ay ginagamit sa anumang ng mga aksyon ng scanner ito ay magpapabagal lahat of
ang tugma ng scanner. At saka, TANGGIHAN hindi maaaring gamitin sa -Cf or -CF
mga pagpipilian (tingnan sa ibaba).
Tandaan din na hindi tulad ng iba pang mga espesyal na aksyon, TANGGIHAN ay isang sangay; code
kaagad na sinusundan ito sa aksyon ay hindi papatayin.
- yymore() nagsasabi sa scanner na sa susunod na tumugma ito sa isang panuntunan, ang katumbas na
token dapat nakadugtong papunta sa kasalukuyang halaga ng yytext sa halip na palitan ito.
Halimbawa, ibinigay ang input na "mega-kludge" ang sumusunod ay magsusulat ng "mega-mega-
kludge" sa output:
%%
mega- ECHO; yymore();
kludge ECHO;
Ang unang "mega-" ay itinugma at ini-echo sa output. Pagkatapos "kludge" ay tumugma, ngunit
ang dating "mega-" ay tumatambay pa rin sa simula ng yytext kaya ang Echo
para sa panuntunang "kludge" ay talagang magsusulat ng "mega-kludge".
Dalawang tala tungkol sa paggamit ng yymore(). Una, yymore() depende sa halaga ng yyleng
wastong sumasalamin sa laki ng kasalukuyang token, kaya hindi mo dapat baguhin yyleng kung
ay gumagamit yymore(). Pangalawa, ang presensya ng yymore() sa pagkilos ng scanner ay nangangailangan ng a
maliit na parusa sa pagganap sa bilis ng pagtutugma ng scanner.
- yyless(n) ibinabalik ang lahat maliban sa una n mga character ng kasalukuyang token pabalik sa
input stream, kung saan ire-scan ang mga ito kapag hinahanap ng scanner ang susunod
tumutugma. yytext at yyleng ay nababagay nang naaangkop (hal., yyleng magiging ngayon
katumbas ng n ). Halimbawa, sa input na "foobar" ang mga sumusunod ay isusulat
"foobarbar":
%%
foobar ECHO; yyless(3);
[az]+ ECHO;
Isang argumento ng 0 hanggang yyless ay magiging sanhi ng pag-scan sa buong kasalukuyang input string
muli. Maliban kung binago mo kung paano ipoproseso ng scanner ang input nito
(gamit MAGSIMULA, halimbawa), magreresulta ito sa walang katapusang loop.
Tandaan na ang yyless ay isang macro at magagamit lamang sa flex input file, hindi mula sa iba
source file.
- unput(c) naglalagay ng karakter c bumalik sa input stream. Ito ang susunod
na-scan ng character. Ang sumusunod na aksyon ay kukuha ng kasalukuyang token at magiging sanhi nito
na muling i-scan na nakapaloob sa mga panaklong.
{
int i;
/* Kopyahin ang yytext dahil ang unput() ay nagtatapon ng yytext */
char *yycopy = strdup( yytext );
unput( ')' );
para sa ( i = yyleng - 1; i >= 0; --i )
unput( yycopy[i] );
unput( '(' );
libre(yycopy);
}
Tandaan na dahil sa bawat isa unput() ibinabalik ang ibinigay na karakter sa simula ng
input stream, ang pagtulak pabalik na mga string ay dapat gawin pabalik-sa-harap.
Isang mahalagang potensyal na problema kapag gumagamit unput() ay iyon kung ikaw ay gumagamit %pointer (Ang
default), isang tawag sa unput() sumisira ang nilalaman ng yytext, simula sa pinaka kanan nito
karakter at nilalamon ang isang karakter sa kaliwa sa bawat tawag. Kung kailangan mo ng halaga
ng yytext na napanatili pagkatapos ng isang tawag sa unput() (tulad ng sa halimbawa sa itaas), dapat mo rin
kopyahin muna ito sa ibang lugar, o buuin ang iyong scanner gamit %array sa halip (tingnan ang How The Input Is
Katugma).
Sa wakas, tandaan na hindi mo maibabalik EOF upang subukang markahan ang input stream ng isang
end-of-file.
- input() binabasa ang susunod na character mula sa input stream. Halimbawa, ang mga sumusunod
ay isang paraan upang kainin ang mga komento ng C:
%%
"/*" {
int c;
para kay ( ; ; )
{
habang ( (c = input()) != '*' &&
c != EOF )
; /* kumain ng teksto ng komento */
kung ( c == '*' )
{
habang ( (c = input()) == '*' )
;
kung ( c == '/' )
pahinga; /* natagpuan ang dulo */
}
kung ( c == EOF )
{
error ("EOF sa komento");
masira;
}
}
}
(Tandaan na kung ang scanner ay pinagsama-sama gamit ang C++, pagkatapos input() sa halip ay tinutukoy
sa bilang yyinput(), upang maiwasan ang isang pagkakasalungatan ng pangalan sa C + + stream sa pamamagitan ng pangalan ng
input.)
- YY_FLUSH_BUFFER pinapa-flush ang internal buffer ng scanner upang sa susunod na pagkakataon ay ang
Sinusubukan ng scanner na tumugma sa isang token, ito ay unang magre-refill ng buffer gamit YY_INPUT
(tingnan ang The Generated Scanner, sa ibaba). Ang aksyon na ito ay isang espesyal na kaso ng higit pa
pangkalahatan yy_flush_buffer() function, na inilarawan sa ibaba sa seksyong Maramihang Input
Mga buffer
- yterminate() ay maaaring gamitin bilang kapalit ng return statement sa isang aksyon. Ito
tinatapos ang scanner at nagbabalik ng 0 sa tumatawag ng scanner, na nagpapahiwatig ng "all
tapos na". Bilang default, yterminate() ay tinatawag din kapag ang isang end-of-file ay
nakatagpo. Ito ay isang macro at maaaring muling tukuyin.
ANG NABUO PARA MAG-SCAN
Ang output ng pagbaluktot ay ang file lex.yy.c, na naglalaman ng routine sa pag-scan yylex(), a
bilang ng mga talahanayan na ginagamit nito para sa pagtutugma ng mga token, at isang bilang ng mga auxiliary na gawain at
mga macro. Bilang default, yylex() ay ipinahayag tulad ng sumusunod:
int yylex()
{
... iba't ibang mga kahulugan at ang mga aksyon dito ...
}
(Kung sinusuportahan ng iyong kapaligiran ang mga function prototype, ito ay magiging "int yylex( void )".)
Maaaring baguhin ang kahulugang ito sa pamamagitan ng pagtukoy sa macro na "YY_DECL". Halimbawa, maaari mong
gamitin ang:
#define YY_DECL float lexscan( a, b ) float a, b;
para bigyan ng pangalan ang routine ng pag-scan lexscan, pagbabalik ng float, at pagkuha ng dalawang float bilang
mga argumento. Tandaan na kung magbibigay ka ng mga argumento sa routine ng pag-scan gamit ang K&R-style/non-
prototyped function na deklarasyon, dapat mong wakasan ang kahulugan gamit ang isang semi-colon (;).
Tuwing yylex() ay tinatawag na, ito ay nag-scan ng mga token mula sa global input file yyin (na
default sa stdin). Nagpapatuloy ito hanggang sa maabot nito ang isang end-of-file (sa puntong iyon
ibinabalik nito ang halagang 0) o isa sa mga aksyon nito ang nagpapatupad ng a pagbabalik pahayag.
Kung ang scanner ay umabot sa isang end-of-file, ang mga kasunod na tawag ay hindi matukoy maliban kung alinman yyin
ay nakaturo sa isang bagong input file (kung saan ang pag-scan ay magpapatuloy mula sa file na iyon), o
yyrestart() ay tinatawag na. yyrestart() tumatagal ng isang argumento, a FILE * pointer (na maaaring
wala, kung na-set up mo na YY_INPUT upang mag-scan mula sa isang pinagmulan maliban sa yyin), at nagpapasimula
yyin para sa pag-scan mula sa file na iyon. Sa esensya walang pagkakaiba sa pagitan ng makatarungan
nagtatalaga yyin sa isang bagong input file o gamit yyrestart() upang gawin ito; ang huli ay magagamit
para sa pagiging tugma sa mga nakaraang bersyon ng baluktot, at dahil ito ay magagamit upang lumipat
mag-input ng mga file sa gitna ng pag-scan. Maaari rin itong gamitin upang itapon ang agos
input buffer, sa pamamagitan ng pagtawag dito na may argumento ng yyin; pero mas magandang gamitin YY_FLUSH_BUFFER
(tingnan sa itaas). Tandaan na yyrestart() ang hindi i-reset ang panimulang kondisyon sa Inisyal (Tingnan ang
Mga Kundisyon ng Simula, sa ibaba).
If yylex() huminto sa pag-scan dahil sa pagsasagawa ng a pagbabalik pahayag sa isa sa mga aksyon, ang
maaaring muling tawagan ang scanner at magpapatuloy ito sa pag-scan kung saan ito tumigil.
Bilang default (at para sa mga layunin ng kahusayan), ang scanner ay gumagamit ng mga block-read kaysa sa
simple getc() mga tawag para basahin ang mga character mula sa yyin. Ang likas na katangian ng kung paano ito nakukuha ang input nito
makontrol sa pamamagitan ng pagtukoy sa YY_INPUT macro. Ang sequence ng pagtawag ni YY_INPUT ay
"YY_INPUT(buf, resulta, max_size)". Ang aksyon nito ay upang ilagay hanggang sa max_size mga tauhan sa
hanay ng character buf at bumalik sa integer variable resulta alinman sa bilang ng
mga character na nabasa o ang pare-parehong YY_NULL (0 sa mga sistema ng Unix) upang ipahiwatig ang EOF. Ang default
Nagbabasa ang YY_INPUT mula sa pandaigdigang file-pointer na "yyin".
Isang sample na kahulugan ng YY_INPUT (sa seksyon ng mga kahulugan ng input file):
%{
#define YY_INPUT(buf,result,max_size) \
{ \
int c = getchar(); \
resulta = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \
}
%}
Papalitan ng kahulugang ito ang pagpoproseso ng input upang mangyari ang isang character sa bawat pagkakataon.
Kapag nakatanggap ang scanner ng end-of-file indication mula sa YY_INPUT, susuriin nito ang
ywrap() function. Kung ywrap() nagbabalik ng false (zero), pagkatapos ay ipinapalagay na ang function
ay nauna na at nag-set up yyin upang tumuro sa isa pang input file, at magpapatuloy ang pag-scan. Kung
ito ay nagbabalik ng true (non-zero), pagkatapos ay ang scanner ay magwawakas, na nagbabalik ng 0 sa kanyang tumatawag. Tandaan
na sa alinmang kaso, ang kondisyon ng pagsisimula ay nananatiling hindi nagbabago; ginagawa nito hindi bumalik sa INITIAL.
Kung hindi ka nagbibigay ng sarili mong bersyon ng ywrap(), pagkatapos ay dapat mong gamitin ang alinman %opsyon
noyywrap (kung saan ang scanner ay kumikilos na parang ywrap() ibinalik ang 1), o dapat
Link na may -ll upang makuha ang default na bersyon ng routine, na palaging nagbabalik ng 1.
Tatlong gawain ang magagamit para sa pag-scan mula sa mga in-memory na buffer kaysa sa mga file:
yy_scan_string(), yy_scan_bytes(), at yy_scan_buffer(). Tingnan ang talakayan ng mga ito sa ibaba
sa seksyong Maramihang Mga Input Buffer.
Ang scanner ay nagsusulat nito Echo output sa yyout global (default, stdout), na maaaring
muling tinukoy ng gumagamit sa pamamagitan lamang ng pagtatalaga nito sa iba FILE pointer
START MGA KONDISYON
pagbaluktot ay nagbibigay ng mekanismo para sa kondisyong pag-activate ng mga panuntunan. Anumang tuntunin na ang pattern ay
may prefix na " " magiging aktibo lamang kapag ang scanner ay nasa panimulang kundisyon na pinangalanan
"sc". Halimbawa,
[^"]* { /* kainin ang string body ... */
...
}
magiging aktibo lamang kapag ang scanner ay nasa "STRING" na kondisyon ng pagsisimula, at
\. { /* humawak ng pagtakas ... */
...
}
magiging aktibo lamang kapag ang kasalukuyang kundisyon ng pagsisimula ay alinman sa "INITIAL", "STRING", o
"QUOTE".
Ang mga kundisyon ng pagsisimula ay ipinahayag sa mga kahulugan (unang) seksyon ng paggamit ng input
mga linyang walang indent na nagsisimula sa alinman %s or %x sinusundan ng isang listahan ng mga pangalan. Ang dating
Ipinahayag napapabilang simulan ang mga kondisyon, ang huli eksklusibo simulan ang mga kondisyon. Isang panimula
ang kundisyon ay isinaaktibo gamit ang BEGIN aksyon. Hanggang sa susunod BEGIN naisasagawa ang aksyon,
Ang mga panuntunang may ibinigay na kundisyon ng pagsisimula ay magiging aktibo at ang mga panuntunan sa iba pang kundisyon ng pagsisimula
magiging hindi aktibo. Kung ang panimulang kondisyon ay kasama, pagkatapos ay mga panuntunan na walang simula
magiging aktibo din ang mga kundisyon. Kung ito ay eksklusibo, pagkatapos lamang mga tuntuning kwalipikado sa
magiging aktibo ang panimulang kondisyon. Isang hanay ng mga panuntunan na nakasalalay sa parehong eksklusibong simula
inilalarawan ng kundisyon ang isang scanner na independiyente sa alinman sa iba pang mga panuntunan sa pagbaluktot
input. Dahil dito, pinapadali ng eksklusibong mga kundisyon sa pagsisimula ang pagtukoy ng "mini-
scanner" na nag-scan ng mga bahagi ng input na syntactically naiiba mula sa iba
(hal., mga komento).
Kung ang pagkakaiba sa pagitan ng inklusibo at eksklusibong mga kondisyon ng pagsisimula ay kaunti pa rin
malabo, narito ang isang simpleng halimbawa na naglalarawan ng koneksyon sa pagitan ng dalawa. Ang set ng
panuntunan:
%s halimbawa
%%
foo do_something();
bar something_else();
ay katumbas ng
%x halimbawa
%%
foo do_something();
bar something_else();
Wala ang qualifier, ang bar pattern sa pangalawang halimbawa ay hindi magiging
aktibo (ibig sabihin, hindi tumugma) kapag nasa panimulang kondisyon Halimbawa. Kung ginamit lang natin
upang maging kwalipikado bar, bagaman, pagkatapos ay magiging aktibo lamang ito sa halimbawa at hindi sa UNA, habang
sa unang halimbawa ito ay aktibo sa pareho, dahil sa unang halimbawa ang halimbawa simula
kondisyon ay isang napapabilang (%s) kondisyon ng pagsisimula.
Tandaan din na ang espesyal na start-condition specifier <*> tumutugma sa bawat kondisyon ng pagsisimula.
Kaya, ang halimbawa sa itaas ay maaari ding naisulat;
%x halimbawa
%%
foo do_something();
<*>bar something_else();
Ang default na panuntunan (sa Echo anumang walang kaparis na karakter) ay nananatiling aktibo sa mga kondisyon ng pagsisimula. Ito
ay katumbas ng:
<*>.|\n ECHO;
BEGIN(0) babalik sa orihinal na estado kung saan ang mga panuntunan lamang na walang mga kundisyon sa pagsisimula
aktibo. Ang estadong ito ay maaari ding tukuyin bilang panimulang kondisyon na "INITIAL", kaya
SIMULA(INISIYA) ay katumbas ng BEGINNa (0). (Ang mga panaklong sa paligid ng panimulang kondisyon
hindi kailangan ang pangalan ngunit itinuturing na magandang istilo.)
BEGIN ang mga aksyon ay maaari ding ibigay bilang naka-indent na code sa simula ng seksyon ng mga panuntunan.
Halimbawa, ang mga sumusunod ay magiging sanhi ng pagpasok ng scanner sa "ESPESYAL" na kondisyon ng pagsisimula
kailanman yylex() ay tinatawag na at ang global variable enter_special ay totoo:
int enter_special;
%x ESPESYAL
%%
kung ( enter_special )
MAGSIMULA(ESPESYAL);
blahblahblah
...susunod ang higit pang mga patakaran...
Upang ilarawan ang paggamit ng mga kondisyon ng pagsisimula, narito ang isang scanner na nagbibigay ng dalawang magkaibang
mga interpretasyon ng isang string tulad ng "123.456". Bilang default, ituturing ito bilang tatlong token,
ang integer na "123", isang tuldok ('.'), at ang integer na "456". Ngunit kung ang string ay nauna
mas maaga sa linya ng string na "expect-floats" ay ituturing ito bilang isang solong token, ang
floating-point na numero 123.456:
%{
# isama
%}
%s inaasahan
%%
expect-floats BEGIN(expect);
[0-9]+"."[0-9]+ {
printf("nakahanap ng float, = %f\n",
atof( yytext ) );
}
\n {
/* iyon ang dulo ng linya, kaya
* kailangan namin ng isa pang "expect-number"
* bago pa natin makilala
* numero
*/
MAGSIMULA(INITIAL);
}
[0-9]+ {
printf("nakahanap ng integer, = %d\n",
atoi( yytext ) );
}
"." printf("nakahanap ng tuldok\n");
Narito ang isang scanner na kumikilala (at nagtatapon) ng mga komento sa C habang pinapanatili ang isang bilang ng
ang kasalukuyang linya ng input.
%x komento
%%
int line_num = 1;
"/*" BEGIN(comment);
[^*\n]* /* kumain ng kahit ano na hindi '*' */
"*"+[^*/\n]* /* kumain '*'s hindi sinundan ng '/'s */
\n ++line_num;
"*"+"/" BEGIN(INITIAL);
Ang scanner na ito ay napupunta sa isang maliit na problema upang tumugma sa mas maraming teksto hangga't maaari sa bawat panuntunan.
Sa pangkalahatan, kapag sinusubukang magsulat ng isang high-speed scanner subukang tumugma hangga't maaari
bawat panuntunan, dahil isa itong malaking panalo.
Tandaan na ang mga pangalan ng start-condition ay talagang mga integer na halaga at maaaring iimbak nang ganoon.
Kaya, ang nasa itaas ay maaaring pahabain sa sumusunod na paraan:
%x komento foo
%%
int line_num = 1;
int comment_caller;
"/*" {
comment_caller = INITIAL;
BEGIN(komento);
}
...
"/*" {
comment_caller = foo;
BEGIN(komento);
}
[^*\n]* /* kumain ng kahit ano na hindi '*' */
"*"+[^*/\n]* /* kumain '*'s hindi sinundan ng '/'s */
\n ++line_num;
"*"+"/" BEGIN(comment_caller);
Higit pa rito, maaari mong ma-access ang kasalukuyang kondisyon ng pagsisimula gamit ang integer-valued YY_START
macro. Halimbawa, ang mga takdang-aralin sa itaas sa comment_caller maaaring isulat sa halip
comment_caller = YY_START;
Nagbibigay ang Flex YYSTATE bilang alyas para sa YY_START (dahil iyon ang ginagamit ng AT&T lex).
Tandaan na ang mga kondisyon ng pagsisimula ay walang sariling name-space; Nagdeklara ng mga pangalan ang %s at %x
sa parehong paraan bilang #define's.
Panghuli, narito ang isang halimbawa ng kung paano itugma ang C-style quoted strings gamit ang eksklusibong simula
kundisyon, kabilang ang pinalawak na mga pagkakasunud-sunod ng pagtakas (ngunit hindi kasama ang pagsuri para sa isang string
masyadong mahaba):
%x str
%%
char string_buf[MAX_STR_CONST];
char *string_buf_ptr;
\" string_buf_ptr = string_buf; BEGIN(str);
\" { /* nakita ang pagsasara ng quote - tapos na lahat */
MAGSIMULA(INITIAL);
*string_buf_ptr = '\0';
/* return string pare-pareho ang uri ng token at
* halaga sa parser
*/
}
\n {
/* error - unterminated string constant */
/* bumuo ng mensahe ng error */
}
\\[0-7]{1,3} {
/* octal escape sequence */
int resulta;
(walang bisa) sscanf( yytext + 1, "%o", &result );
kung ( resulta > 0xff )
/* error, ang constant ay out-of-bounds */
*string_buf_ptr++ = resulta;
}
\\[0-9]+ {
/* bumuo ng error - masamang escape sequence; isang bagay
* tulad ng '\48' o '\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 = yytext;
habang ( *yptr )
*string_buf_ptr++ = *yptr++;
}
Kadalasan, tulad ng sa ilan sa mga halimbawa sa itaas, natatapos mo ang pagsulat ng isang buong grupo ng mga panuntunan
lahat ay naunahan ng parehong (mga) kondisyon ng pagsisimula. Ginagawang mas madali at mas malinis ito ng Flex
sa pamamagitan ng pagpapasok ng ideya ng kondisyon ng pagsisimula saklaw. Ang saklaw ng panimulang kondisyon ay sinisimulan sa:
{
saan Mga SC ay isang listahan ng isa o higit pang mga kondisyon sa pagsisimula. Sa loob ng saklaw ng panimulang kondisyon,
bawat panuntunan ay awtomatikong may prefix inilapat dito, hanggang sa a '}' na tumutugma sa
pauna '{'. Kaya, halimbawa,
{
"\\n" ibalik ang '\n';
"\\r" ibalik ang '\r';
"\\f" ibalik ang '\f';
"\\0" ibalik ang '\0';
}
ay katumbas ng:
"\\n" ibalik ang '\n';
"\\r" ibalik ang '\r';
"\\f" ibalik ang '\f';
"\\0" ibalik ang '\0';
Maaaring naka-nest ang mga saklaw ng kundisyon ng pagsisimula.
Tatlong gawain ang magagamit para sa pagmamanipula ng mga stack ng mga kondisyon ng pagsisimula:
walang bisa yy_push_state(int new_state)
itinutulak ang kasalukuyang kundisyon ng pagsisimula sa tuktok ng stack ng kondisyon ng pagsisimula at
lumipat sa bagong_estado parang ginamit mo BEGIN bagong_estado (tandaan ang simula
Ang mga pangalan ng kundisyon ay mga integer din).
walang bisa yy_pop_state()
nagpa-pop sa tuktok ng stack at lumipat dito sa pamamagitan ng MAGSIMULA.
int yy_top_state()
ibinabalik ang tuktok ng stack nang hindi binabago ang mga nilalaman ng stack.
Ang stack ng panimulang kondisyon ay dynamic na lumalaki at sa gayon ay walang built-in na limitasyon sa laki. Kung
ang memorya ay naubos, ang pagpapatupad ng programa ay naabort.
Upang gumamit ng mga panimulang stack ng kondisyon, ang iyong scanner ay dapat na may kasamang a %opsyon magtalaksan direktiba (tingnan
Mga opsyon sa ibaba).
MADAMI INPUT MGA BUFFER
Ang ilang mga scanner (gaya ng mga sumusuporta sa "isama" na mga file) ay nangangailangan ng pagbabasa mula sa ilan
input stream. Bilang pagbaluktot ang mga scanner ay gumagawa ng isang malaking halaga ng buffering, hindi makokontrol ng isa kung saan
ang susunod na input ay babasahin mula sa pamamagitan lamang ng pagsulat ng a YY_INPUT na sensitibo sa
konteksto ng pag-scan. YY_INPUT ay tinatawag lamang kapag ang scanner ay umabot sa dulo ng buffer nito,
na maaaring matagal pagkatapos ng pag-scan sa isang pahayag tulad ng isang "isama" na nangangailangan
pagpapalit ng input source.
Upang makipag-ayos sa mga ganitong uri ng problema, pagbaluktot nagbibigay ng mekanismo para sa paglikha at paglipat
sa pagitan ng maraming input buffer. Ang isang input buffer ay nilikha sa pamamagitan ng paggamit ng:
YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
na tumatagal ng a FILE pointer at laki at lumilikha ng buffer na nauugnay sa ibinigay na file
at sapat na malaki upang hawakan laki mga character (kapag may pagdududa, gamitin YY_BUF_SIZE para sa laki).
Nagbabalik ito a YY_BUFFER_STATE hawakan, na maaaring maipasa sa iba pang mga gawain (tingnan
sa ibaba). Ang YY_BUFFER_STATE uri ay isang pointer sa isang malabo istruktura yy_buffer_state
istraktura, upang ligtas mong masimulan ang mga variable ng YY_BUFFER_STATE sa ((YY_BUFFER_STATE) 0)
kung nais mo, at sumangguni din sa opaque na istraktura upang maipahayag nang tama ang input
buffer sa mga source file maliban sa iyong scanner. Tandaan na ang FILE nakaturo sa
ang tawag sa yy_create_buffer ay ginagamit lamang bilang halaga ng yyin nakita ni YY_INPUT; kung
muling tukuyin YY_INPUT kaya hindi na ito gumagamit yyin, pagkatapos ay maaari mong ligtas na makapasa ng nil FILE puntero
sa yy_create_buffer. Pumili ka ng isang partikular na buffer upang i-scan mula sa paggamit ng:
void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
inililipat ang input buffer ng scanner upang magmumula ang mga kasunod na token new_buffer. nota
na yy_switch_to_buffer() maaaring gamitin ng yywrap() upang i-set up ang mga bagay para sa pagpapatuloy
pag-scan, sa halip na magbukas ng bagong file at magturo yyin sa ito. Tandaan din ang paglipat
mga mapagkukunan ng input sa pamamagitan ng alinman yy_switch_to_buffer() or ywrap() ang hindi baguhin ang simula
kondisyon.
void yy_delete_buffer( YY_BUFFER_STATE buffer )
ay ginagamit upang mabawi ang storage na nauugnay sa isang buffer. ( nagpapahina ng lakas maaaring wala, kung saan
kaso walang ginagawa ang routine.) Maaari mo ring i-clear ang kasalukuyang nilalaman ng isang buffer
gamit ang:
walang bisa yy_flush_buffer( YY_BUFFER_STATE buffer )
Itinatapon ng function na ito ang mga nilalaman ng buffer, kaya sa susunod na pagtatangka ng scanner
tumugma sa isang token mula sa buffer, pupunuin muna nito ang buffer gamit ang YY_INPUT.
yy_new_buffer() ay isang alyas para sa yy_create_buffer(), ibinigay para sa pagiging tugma sa
C++ paggamit ng bago at alisin para sa paglikha at pagsira ng mga dynamic na bagay.
Panghuli, ang mga YY_CURRENT_BUFFER macro returns a YY_BUFFER_STATE hawakan sa kasalukuyang
buffer.
Narito ang isang halimbawa ng paggamit ng mga tampok na ito para sa pagsulat ng isang scanner na lumalawak kasama
mga file (ang < > tampok ay tinalakay sa ibaba):
/* ang "incl" na estado ay ginagamit para sa pagkuha ng pangalan
* ng isang kasamang file
*/
%x kasama
%{
#define MAX_INNCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr = 0;
%}
%%
isama ang BEGIN(incl);
[az]+ ECHO;
[^az\n]*\n? ECHO;
[ \t]* /* kainin ang whitespace */
[^ \t\n]+ { /* nakuha ang include file name */
kung ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
fprintf( stderr, "May kasamang nested masyadong malalim" );
labasan(1);
}
include_stack[include_stack_ptr++] =
YY_CURRENT_BUFFER;
yyin = fopen( yytext, "r" );
kung ( ! yyin )
pagkakamali(...);
yy_switch_to_buffer(
yy_create_buffer( yyin, YY_BUF_SIZE ) );
MAGSIMULA(INITIAL);
}
< > {
kung ( --include_stack_ptr < 0 )
{
yyterminate();
}
iba
{
yy_delete_buffer( YY_CURRENT_BUFFER );
yy_switch_to_buffer(
include_stack[include_stack_ptr] );
}
}
Tatlong gawain ang magagamit para sa pag-set up ng mga input buffer para sa pag-scan ng mga in-memory string
sa halip na mga file. Lahat sila ay lumikha ng bagong input buffer para sa pag-scan ng string, at
ibalik ang isang katumbas YY_BUFFER_STATE hawakan (na dapat mong tanggalin gamit ang
yy_delete_buffer() kapag tapos na ito). Lumipat din sila sa bagong buffer gamit
yy_switch_to_buffer(), kaya ang susunod na tawag sa yylex() magsisimulang i-scan ang string.
yy_scan_string(const tangke *str)
sinusuri ang isang string na tinapos ng NUL.
yy_scan_bytes(const tangke *bytes, int len)
scan Len bytes (kabilang ang posibleng NUL's) na nagsisimula sa lokasyon byte.
Tandaan na ang parehong mga function na ito ay gumagawa at nag-scan ng a kopyahin ng string o byte. (Ito
maaaring kanais-nais, dahil yylex() binabago ang mga nilalaman ng buffer na ini-scan nito.) Ikaw
maiiwasan ang kopya sa pamamagitan ng paggamit ng:
yy_scan_buffer(char *base, yy_size_t laki)
na nag-scan sa lugar ng buffer simula sa base, na binubuo ng mga laki bytes, ang
huling dalawang byte nito dapat be YY_END_OF_BUFFER_CHAR (ASCII NUL). Ang huling dalawang ito
ang mga byte ay hindi na-scan; kaya, ang pag-scan ay binubuo ng base[0] sa pamamagitan ng base[size-2],
kasama.
Kung nabigo kang mag-set up base sa ganitong paraan (ibig sabihin, kalimutan ang huling dalawa
YY_END_OF_BUFFER_CHAR bytes), pagkatapos yy_scan_buffer() nagbabalik ng nil pointer sa halip
ng paglikha ng bagong input buffer.
Ang uri yy_size_t ay isang mahalagang uri kung saan maaari kang maglagay ng integer na expression
sumasalamin sa laki ng buffer.
END-OF-FILE MGA ALITUNTUNIN
Ang espesyal na panuntunan "< >" ay nagpapahiwatig ng mga aksyon na dapat gawin kapag ang isang end-of-file ay
encountered at ang yywrap() ay nagbabalik ng non-zero (ibig sabihin, wala nang karagdagang file na ipoproseso).
Dapat tapusin ang aksyon sa pamamagitan ng paggawa ng isa sa apat na bagay:
- pagtatalaga yyin sa isang bagong input file (sa mga nakaraang bersyon ng flex, pagkatapos gawin ang
takdang-aralin na kailangan mong tawagan ang espesyal na pagkilos YY_NEW_FILE; ito ay hindi na
kinakailangan);
- pagsasagawa ng a pagbabalik pahayag;
- pagsasagawa ng espesyal yterminate() aksyon;
- o, lumipat sa isang bagong buffer gamit yy_switch_to_buffer() tulad ng ipinapakita sa halimbawa
sa itaas.
< > ang mga panuntunan ay hindi maaaring gamitin kasama ng iba pang mga pattern; maaari lamang silang maging kwalipikado sa isang listahan
ng mga kondisyon ng pagsisimula. Kung ang isang hindi kwalipikadong < > ibinigay ang panuntunan, nalalapat ito sa lahat simula
kundisyon na wala pang < > mga aksyon. Upang tukuyin ang isang < > tuntunin para lamang
ang paunang kondisyon ng pagsisimula, gamitin
< >
Ang mga panuntunang ito ay kapaki-pakinabang para sa paghuli ng mga bagay tulad ng hindi saradong mga komento. Isang halimbawa:
%x quote
%%
...iba pang mga panuntunan para sa pagharap sa mga quote...
< > {
error ("hindi natapos na quote");
yyterminate();
}
< > {
kung ( *++ filelist )
yyin = fopen( *filelist, "r" );
iba
yyterminate();
}
IBA PA MACROS
Ang macro YY_USER_ACTION maaaring tukuyin upang magbigay ng isang aksyon na palaging isinasagawa
bago ang pagkilos ng katugmang panuntunan. Halimbawa, maaaring #define'd ang pagtawag sa isang routine
para i-convert ang yytext sa lower-case. Kailan YY_USER_ACTION ay tinatawag, ang variable yy_act
nagbibigay ng numero ng katugmang panuntunan (ang mga panuntunan ay binibilang na nagsisimula sa 1). Kumbaga ikaw
gustong i-profile kung gaano kadalas itinutugma ang bawat isa sa iyong mga panuntunan. Ang mga sumusunod ay gagawin ang
panlilinlang:
#define YY_USER_ACTION ++ctr[yy_act]
saan ctr ay isang array upang i-hold ang mga bilang para sa iba't ibang mga panuntunan. Tandaan na ang macro
YY_NUM_RULES nagbibigay ng kabuuang bilang ng mga panuntunan (kabilang ang default na panuntunan, kahit na ginagamit mo
-s), kaya isang tamang deklarasyon para sa ctr ay:
int ctr[YY_NUM_RULES];
Ang macro YY_USER_INIT ay maaaring tukuyin upang magbigay ng isang aksyon na palaging isinasagawa bago
ang unang pag-scan (at bago magawa ang mga panloob na pagsisimula ng scanner). Halimbawa,
maaari itong magamit upang tumawag sa isang nakagawiang magbasa sa isang talahanayan ng data o magbukas ng isang logging file.
Ang macro yy_set_interactive(is_interactive) ay maaaring gamitin upang makontrol kung ang kasalukuyang
isinasaalang-alang ang buffer interactive. Ang isang interactive na buffer ay pinoproseso nang mas mabagal, ngunit
dapat gamitin kapag interactive talaga ang input source ng scanner para maiwasan ang mga problemang dapat mangyari
sa paghihintay na punan ang mga buffer (tingnan ang talakayan ng -I bandila sa ibaba). Isang hindi zero na halaga sa
minarkahan ng macro invocation ang buffer bilang interactive, isang zero na value bilang non-interactive.
Tandaan na ang paggamit ng macro na ito ay na-override %opsyon interactive , %opsyon laging-interactive or
%opsyon hindi kailanman-interactive (tingnan ang Opsyon sa ibaba). yy_set_interactive() dapat i-invoke bago
sa simulang i-scan ang buffer na (o hindi) maituturing na interactive.
Ang macro yy_set_bol(at_bol) ay maaaring gamitin upang kontrolin kung ang kasalukuyang buffer's scanning
Ang konteksto para sa susunod na tugma ng token ay ginagawa na parang nasa simula ng isang linya. Isang hindi zero
Ang macro argument ay gumagawa ng mga panuntunang nakaangkla sa
Ang macro YY_AT_BOL() babalik ng true kung ang susunod na token na na-scan mula sa kasalukuyang buffer ay
may mga panuntunang '^' na aktibo, false kung hindi.
Sa nabuong scanner, ang lahat ng mga aksyon ay natipon sa isang malaking switch statement at
pinaghihiwalay gamit YY_BREAK, na maaaring muling tukuyin. Bilang default, ito ay simpleng "break", sa
paghiwalayin ang pagkilos ng bawat panuntunan mula sa sumusunod na panuntunan. Muling pagtukoy YY_BREAK nagpapahintulot, para sa
halimbawa, ang mga user ng C++ na #define YY_BREAK na walang gagawin (habang napakaingat na ang bawat
Ang panuntunan ay nagtatapos sa isang "break" o isang "return"!) upang maiwasan ang paghihirap mula sa hindi maabot na pahayag
mga babala kung saan dahil ang pagkilos ng isang panuntunan ay nagtatapos sa "pagbabalik", ang YY_BREAK ay hindi naa-access.
Mga halaga MAGAGAMIT SA ANG USER
Binubuod ng seksyong ito ang iba't ibang value na available sa user sa mga pagkilos ng panuntunan.
- tangke *yytext hawak ang teksto ng kasalukuyang token. Maaari itong baguhin ngunit hindi
pinahaba (hindi ka maaaring magdagdag ng mga character sa dulo).
Kung ang espesyal na direktiba %array lalabas sa unang seksyon ng scanner
paglalarawan, pagkatapos yytext sa halip ay ipinahayag tangke yytext[YYLMAX], saan YYLMAX ay isang
macro definition na maaari mong tukuyin muli sa unang seksyon kung hindi mo gusto ang
default na halaga (karaniwan ay 8KB). Gamit %array nagreresulta sa medyo mabagal na mga scanner,
ngunit ang halaga ng yytext nagiging immune sa mga tawag sa input() at unput(), alin
posibleng sirain ang halaga nito kapag yytext ay isang character pointer. Ang kabaligtaran ng
%array is %pointer, na kung saan ay ang default.
Hindi mo magagamit %array kapag bumubuo ng mga klase ng C++ scanner (ang -+ bandila).
- int yyleng hawak ang haba ng kasalukuyang token.
- FILE *yyin ay ang file na bilang default pagbaluktot nagbabasa mula sa. Ito ay maaaring muling tukuyin ngunit
ang paggawa nito ay makatuwiran lamang bago magsimula ang pag-scan o pagkatapos ng isang EOF
nakatagpo. Ang pagpapalit nito sa gitna ng pag-scan ay magkakaroon ng mga hindi inaasahang resulta
mula noon pagbaluktot buffer ang input nito; gamitin yyrestart() sa halip. Kapag natapos na ang pag-scan
dahil may nakitang end-of-file, maaari kang magtalaga yyin sa bagong input file at
pagkatapos ay tawagan muli ang scanner upang ipagpatuloy ang pag-scan.
- walang bisa yyrestart( FILE *bagong file ) maaaring tawagin upang ituro yyin sa bagong input file.
Ang paglipat-over sa bagong file ay agaran (anumang dating na-buffer-up na input ay
nawala). Tandaan na ang pagtawag yyrestart() sa yyin bilang argumento kaya itinatapon ang
kasalukuyang input buffer at patuloy na ini-scan ang parehong input file.
- FILE *kayo ay ang file kung saan Echo ginagawa ang mga aksyon. Maaari itong muling italaga ng
ang gumagamit.
- YY_CURRENT_BUFFER nagbabalik a YY_BUFFER_STATE hawakan sa kasalukuyang buffer.
- YY_START nagbabalik ng integer value na tumutugma sa kasalukuyang kondisyon ng pagsisimula.
Maari mong gamitin ang value na ito pagkatapos BEGIN upang bumalik sa panimulang kondisyon.
INTERFACING SA YACC
Isa sa mga pangunahing gamit ng pagbaluktot ay bilang isang kasama sa yacc parser-generator. yacc mga parser
asahan na tumawag sa isang nakagawiang pinangalanan yylex() para mahanap ang susunod na input token. Ang routine ay
dapat ibalik ang uri ng susunod na token pati na rin ang paglalagay ng anumang nauugnay na halaga
ang global yylval. Upang gamitin ang pagbaluktot sa yacc, ang isa ay tumutukoy sa -d pagpipilian sa yacc tuturuan
ito upang makabuo ng file y.tab.h naglalaman ng mga kahulugan ng lahat ng %token lumilitaw sa
yacc input. Ang file na ito ay kasama sa pagbaluktot scanner. Halimbawa, kung ang isa sa
ang mga token ay "TOK_NUMBER", bahagi ng scanner ay maaaring magmukhang:
%{
#include "y.tab.h"
%}
%%
[0-9]+ yylval = atoi( yytext ); ibalik ang TOK_NUMBER;
Opsyon
pagbaluktot ay may mga sumusunod na opsyon:
-b, --backup
Bumuo ng impormasyon sa pag-back up sa lex.backup. Ito ay isang listahan ng mga estado ng scanner
na nangangailangan ng pag-back up at ang mga input na character kung saan nila ito ginagawa. Sa pamamagitan ng pagdaragdag
mga panuntunang maaaring alisin ng isa ang mga estado ng pag-back up. Kung lahat inalis ang mga back-up na estado
at -Cf or -CF ay ginagamit, ang nabuong scanner ay tatakbo nang mas mabilis (tingnan ang -p bandila).
Ang mga user lang na gustong i-squeeze ang bawat huling cycle sa labas ng kanilang mga scanner ang kailangang mag-alala
tungkol sa opsyong ito. (Tingnan ang seksyon sa Pagsasaalang-alang sa Pagganap sa ibaba.)
-c ay isang do-nothing, hindi na ginagamit na opsyon na kasama para sa pagsunod sa POSIX.
-d, --debug
pinapatakbo ang nabuong scanner mag-alis ng mga insekto mode. Sa tuwing nakikilala ang isang pattern
at ang pandaigdig yy_flex_debug ay non-zero (na ang default), gagawin ng scanner
sumulat sa stderr isang linya ng form:
--pagtanggap ng panuntunan sa linya 53 ("ang katugmang teksto")
Ang numero ng linya ay tumutukoy sa lokasyon ng panuntunan sa file na tumutukoy sa scanner
(ibig sabihin, ang file na ipinakain sa pagbaluktot). Ang mga mensahe ay nabuo din kapag ang
nagba-back up ang scanner, tinatanggap ang default na panuntunan, naabot ang dulo ng input buffer nito (o
nakatagpo ng isang NUL; sa puntong ito, pareho ang hitsura ng dalawa gaya ng sa scanner
nababahala), o umabot sa isang end-of-file.
-f, --puno
tumutukoy mabilis scanner Walang table compression ang tapos at ang stdio ay na-bypass. Ang
malaki ang resulta ngunit mabilis. Ang pagpipiliang ito ay katumbas ng -Cfr (tingnan sa ibaba).
-h, - Tumulong
bumubuo ng buod ng "tulong" ng flex's mga pagpipilian sa stdout at pagkatapos ay lumabas. -? at
- Tumulong ay kasingkahulugan ng -h.
-ako, --case-insensitive
nagtuturo pagbaluktot upang bumuo ng isang case-insensitive scanner. Ang kaso ng mga sulat na ibinigay
nasa pagbaluktot ang mga pattern ng pag-input ay hindi papansinin, at ang mga token sa input ay tutugma
anuman ang kaso. Ang katugmang teksto na ibinigay sa yytext magkakaroon ng iniingatang kaso
(ibig sabihin, hindi ito matitiklop).
-l, --lex-compat
Ino-on ang maximum compatibility sa orihinal na AT&T lex pagpapatupad. Tandaan
na hindi ibig sabihin nito ganap pagkakatugma. Ang paggamit ng opsyong ito ay nagkakahalaga ng a
malaking halaga ng pagganap, at hindi ito magagamit sa -+, -f, -F, -Cf,
or -CF mga pagpipilian. Para sa mga detalye sa mga compatibility na ibinibigay nito, tingnan ang seksyon
"Incompatibilities With Lex And POSIX" sa ibaba. Ang pagpipiliang ito ay nagreresulta din sa pangalan
YY_FLEX_LEX_COMPAT pagiging #define'd sa nabuong scanner.
-n ay isa pang do-nothing, hindi na ginagamit na opsyon na kasama lang para sa pagsunod sa POSIX.
-p, --perf-ulat
bumubuo ng isang ulat ng pagganap sa stderr. Ang ulat ay binubuo ng mga komento
patungkol sa mga katangian ng pagbaluktot input file na magdudulot ng malubhang pagkawala ng
pagganap sa resultang scanner. Kung ibibigay mo ang bandila ng dalawang beses, gagawin mo rin
makakuha ng mga komento tungkol sa mga feature na humahantong sa maliit na pagkawala ng performance.
Tandaan na ang paggamit ng TANGGIHAN, %opsyon yylineno, at variable na sumusunod na konteksto (tingnan
ang seksyong Mga Kakulangan / Mga Bug sa ibaba) ay nangangailangan ng malaking parusa sa pagganap;
gumamit ng yymore(), ang ^ operator, at ang -I ang bandila ay nangangailangan ng menor de edad na pagganap
mga parusa.
-oo, --no-default
nagiging sanhi ng default mamuno (na ang walang kaparis na input ng scanner ay ini-echoed sa stdout) upang maging
pinigilan. Kung nakatagpo ang scanner ng input na hindi tumutugma sa alinman sa mga panuntunan nito,
ito ay nag-abort na may error. Ang pagpipiliang ito ay kapaki-pakinabang para sa paghahanap ng mga butas sa isang scanner
itinakda ng panuntunan.
-t, --stdout
nagtuturo pagbaluktot upang isulat ang scanner na nabuo nito sa karaniwang output sa halip na
lex.yy.c.
-sa, --verbose
tinutukoy iyon pagbaluktot dapat sumulat sa stderr isang buod ng mga istatistika tungkol sa
scanner na nabuo nito. Karamihan sa mga istatistika ay walang kahulugan sa kaswal pagbaluktot
user, ngunit kinikilala ng unang linya ang bersyon ng pagbaluktot (katulad ng iniulat ni -V),
at sa susunod na linya ang mga flag na ginamit kapag bumubuo ng scanner, kasama ang mga iyon
ay naka-on bilang default.
-w, --nowarn
pinipigilan ang mga mensahe ng babala.
-B, --batch
nagtuturo pagbaluktot upang bumuo ng isang pulutong scanner, ang kabaligtaran ng interactive Scanner
nabuo ng -I (tingnan sa ibaba). Sa pangkalahatan, ginagamit mo -B kapag ikaw ay tiyak sayo yan
Ang scanner ay hindi kailanman gagamitin nang interactive, at gusto mong i-squeeze a kaunti mas marami pang
pagganap sa labas nito. Kung ang iyong layunin ay sa halip ay pisilin a marami mas marami pang
pagganap, dapat mong gamitin ang -Cf or -CF mga opsyon (tinalakay sa ibaba), na
buksan -B awtomatiko pa rin.
-F, --mabilis
tumutukoy na ang mabilis Dapat gamitin ang representasyon ng talahanayan ng scanner (at stdio
nalampasan). Ang representasyong ito ay halos kasing bilis ng buong representasyon ng talahanayan
(-f), at para sa ilang hanay ng mga pattern ay magiging mas maliit (at para sa iba,
mas malaki). Sa pangkalahatan, kung ang pattern set ay naglalaman ng parehong "mga keyword" at isang catch-all,
"identifier" na panuntunan, tulad ng sa set:
"case" ibalik ang TOK_CASE;
"switch" ibalik ang TOK_SWITCH;
...
"default" ibalik ang TOK_DEFAULT;
[az]+ ibalik ang TOK_ID;
pagkatapos ay mas mahusay na gamitin mo ang buong representasyon ng talahanayan. Kung ang
Ang "identifier" na panuntunan ay naroroon at pagkatapos ay gagamit ka ng hash table o ilang tulad nito upang matukoy
ang mga keyword, mas mahusay mong gamitin -F.
Ang pagpipiliang ito ay katumbas ng -CFr (tingnan sa ibaba). Hindi ito maaaring gamitin kasama ng -+.
-ako, --interactive
nagtuturo pagbaluktot upang makabuo ng isang interactive scanner. Ang isang interactive na scanner ay isa
na tumitingin lamang sa unahan upang magpasya kung anong token ang naitugma kung talagang dapat.
Lumalabas na palaging naghahanap ng isang dagdag na karakter sa unahan, kahit na mayroon ang scanner
nakakita na ng sapat na teksto upang i-disambiguate ang kasalukuyang token, ay medyo mas mabilis kaysa
nakatingin lang sa unahan kung kinakailangan. Ngunit nagbibigay ang mga scanner na laging nasa unahan
kakila-kilabot na interactive na pagganap; halimbawa, kapag ang isang user ay nag-type ng isang bagong linya, ito ay
hindi kinikilala bilang token ng bagong linya hanggang sa pumasok sila isa pa token, na kadalasang nangangahulugang
nagta-type sa isa pang buong linya.
Pagbaluktot ang mga scanner ay default sa interactive maliban kung gagamitin mo ang -Cf or -CF mesa-
mga opsyon sa compression (tingnan sa ibaba). Iyon ay dahil kung naghahanap ka ng mataas na-
pagganap dapat mong ginagamit ang isa sa mga opsyong ito, kaya kung hindi mo ginawa, pagbaluktot
Ipinapalagay na mas gusto mong ipagpalit ang kaunting pagganap ng run-time para sa intuitive
interactive na pag-uugali. Tandaan din na ikaw hindi maaari gamitin -I kasabay ng -Cf or
-CF. Kaya, ang pagpipiliang ito ay hindi talaga kailangan; ito ay naka-on bilang default para sa lahat ng iyon
mga kaso kung saan ito ay pinahihintulutan.
Tandaan na kung isatty () nagbabalik ng false para sa input ng scanner, babalik ang flex sa
batch mode, kahit na -I ay tinukoy. Upang pilitin ang interactive na mode kahit na ano,
gamitin %opsyon laging-interactive (tingnan ang Opsyon sa ibaba).
Maaari mong pilitin ang isang scanner hindi maging interactive sa pamamagitan ng paggamit -B (tingnan sa itaas).
-L, --noline
nagtuturo pagbaluktot hindi para makabuo #linya mga direktiba. Kung wala ang pagpipiliang ito, pagbaluktot peppers
ang nabuong scanner na may mga #line na direktiba kaya ang mga mensahe ng error sa mga aksyon ay
wastong matatagpuan na may kinalaman sa alinman sa orihinal pagbaluktot input file (kung ang
ang mga error ay dahil sa code sa input file), o lex.yy.c (kung ang mga pagkakamali ay flex's
kasalanan -- dapat mong iulat ang mga ganitong uri ng mga error sa email address na ibinigay sa ibaba).
-T, --bakas
Ginagawang pagbaluktot tumakbo sa kopyahin o sipiin sa pamamagitan ng pag-aninag mode. Ito ay bubuo ng maraming mensahe sa stderr
tungkol sa anyo ng input at ang resultang non-deterministic at
deterministikong may hangganang automata. Ang pagpipiliang ito ay kadalasang ginagamit sa pagpapanatili baluktot
-V, --bersyon
ini-print ang numero ng bersyon sa stdout at paglabas. --bersyon ay isang kasingkahulugan para sa -V.
-7, --7bit
nagtuturo pagbaluktot upang makabuo ng 7-bit na scanner, ibig sabihin, isa na makikilala lamang
7-bit na mga character sa input nito. Ang bentahe ng paggamit -7 sa scanner ba yan
ang mga talahanayan ay maaaring hanggang sa kalahati ng laki ng mga nabuo gamit ang -8 pagpipilian (tingnan
sa ibaba). Ang kawalan ay ang mga naturang scanner ay madalas na nakabitin o nag-crash kung ang kanilang input
naglalaman ng 8-bit na character.
Tandaan, gayunpaman, na maliban kung bubuo ka ng iyong scanner gamit ang -Cf or -CF mesa
mga pagpipilian sa compression, paggamit ng -7 ay magse-save lamang ng isang maliit na halaga ng table space, at
gawing hindi gaanong portable ang iyong scanner. kay Flex ang default na pag-uugali ay ang
bumuo ng 8-bit scanner maliban kung gagamitin mo ang -Cf or -CF, kung saan pagbaluktot
default sa pagbuo ng 7-bit scanner maliban kung ang iyong site ay palaging naka-configure
makabuo ng 8-bit na mga scanner (tulad ng kadalasang nangyayari sa mga hindi-USA na site). Kaya mo
sabihin kung nakabuo ang flex ng 7-bit o 8-bit na scanner sa pamamagitan ng pag-inspeksyon sa flag
buod sa -v output tulad ng inilarawan sa itaas.
Tandaan na kung gagamitin mo -Cfe or -CFe (mga opsyon sa compression ng talahanayan, ngunit ginagamit din
equivalence classes gaya ng tinalakay tingnan sa ibaba), flex pa rin ang default sa pagbuo ng isang
8-bit scanner, dahil kadalasan kasama ng mga opsyon sa compression na ito ang buong 8-bit na mga talahanayan ay
hindi gaanong mas mahal kaysa sa 7-bit na mga talahanayan.
-8, --8bit
nagtuturo pagbaluktot upang makabuo ng isang 8-bit scanner, ibig sabihin, isa na maaaring makilala ang 8-bit
mga karakter. Ang flag na ito ay kailangan lamang para sa mga scanner na nabuo gamit -Cf or -CF, as
kung hindi, mag-flex default sa pagbuo ng isang 8-bit scanner pa rin.
Tingnan ang talakayan ng -7 sa itaas para sa default na pag-uugali ni flex at ang mga tradeoff
sa pagitan ng 7-bit at 8-bit scanner.
-+, --c++
tumutukoy na gusto mong flex upang makabuo ng isang klase ng C++ scanner. Tingnan ang seksyon sa
Pagbuo ng mga C++ Scanner sa ibaba para sa mga detalye.
-C[aefFmr]
kinokontrol ang antas ng table compression at, sa pangkalahatan, ang mga trade-off sa pagitan
maliliit na scanner at mabilis na scanner.
-Ca, --align ("align") ay nagtuturo sa flex na ipagpalit ang mas malalaking talahanayan sa nabuo
scanner para sa mas mabilis na pagganap dahil ang mga elemento ng mga talahanayan ay mas mahusay
nakahanay para sa pag-access sa memorya at pag-compute. Sa ilang RISC architecture, kinukuha
at ang pagmamanipula ng mga mahabang salita ay mas mahusay kaysa sa mas maliit na laki ng mga yunit tulad ng
mga maikling salita. Maaaring doblehin ng opsyong ito ang laki ng mga talahanayang ginagamit ng iyong scanner.
-Ce, --ecs namamahala pagbaluktot magtayo pagkakapantay-pantay mga klase, ie, set ng mga character
na may magkaparehong mga katangian ng leksikal (halimbawa, kung ang tanging anyo ng
mga numero sa pagbaluktot Ang input ay nasa klase ng character na "[0-9]" pagkatapos ay ang mga digit na '0',
'1', ..., '9' lahat ay ilalagay sa parehong equivalence class). Mga klase ng equivalence
kadalasang nagbibigay ng mga dramatikong pagbawas sa panghuling laki ng file ng talahanayan/bagay (karaniwang a
factor ng 2-5) at medyo mura ang performance-wise (isang array look-up bawat
na-scan ng character).
-Cf tumutukoy na ang ganap Dapat na mabuo ang mga talahanayan ng scanner - pagbaluktot hindi dapat
i-compress ang mga talahanayan sa pamamagitan ng pagsasamantala ng mga katulad na function ng transition para sa
iba't ibang estado.
-CF tumutukoy na ang alternatibong mabilis na representasyon ng scanner (inilarawan sa itaas
sa ilalim ng -F bandila) ay dapat gamitin. Ang opsyon na ito ay hindi magagamit sa -+.
-Cm, --meta-ecs namamahala pagbaluktot magtayo meta-katumbas mga klase, na mga set
ng mga equivalence classes (o mga character, kung hindi ginagamit ang equivalence classes)
na karaniwang ginagamit nang magkasama. Ang mga klase sa meta-equivalence ay madalas na isang malaking panalo kapag
gamit ang mga naka-compress na talahanayan, ngunit mayroon silang katamtamang epekto sa pagganap (isa o dalawa
"if" na mga pagsubok at isang array look-up sa bawat character na na-scan).
-Cr, --basahin nagiging sanhi ng nabuong scanner sa pasikut-sikot paggamit ng karaniwang I/O library
(stdio) para sa input. Sa halip na tumawag fread() or getc(), gagamitin ng scanner ang
basahin () system call, na nagreresulta sa isang performance gain na nag-iiba mula sa system hanggang
system, ngunit sa pangkalahatan ay malamang na bale-wala maliban kung gumagamit ka rin -Cf or -CF.
paggamit -Cr maaaring magdulot ng kakaibang pag-uugali kung, halimbawa, magbasa ka mula sa yyin paggamit
stdio bago tumawag sa scanner (dahil ang scanner ay makaligtaan ang anumang teksto
naiwan ang iyong mga naunang nabasa sa buffer ng input ng stdio).
-Cr walang epekto kung tutukuyin mo YY_INPUT (tingnan ang The Generated Scanner sa itaas).
Isang nag-iisa -C tumutukoy na ang mga talahanayan ng scanner ay dapat i-compress ngunit hindi
dapat gamitin ang mga equivalence class o meta-equivalence classes.
Ang mga pagpipilian -Cf or -CF at -Cm huwag magkaroon ng kahulugan magkasama - walang pagkakataon
para sa mga klase ng meta-equivalence kung ang talahanayan ay hindi na-compress. Kung hindi man ang
ang mga opsyon ay maaaring malayang pinaghalo, at pinagsama-sama.
Ang default na setting ay -Cem, na tumutukoy na pagbaluktot dapat makabuo ng equivalence
mga klase at mga klase ng meta-equivalence. Ang setting na ito ay nagbibigay ng pinakamataas na antas ng
compression ng talahanayan. Maaari mong ipagpalit ang mas mabilis na gumaganang mga scanner sa halaga ng
mas malalaking talahanayan na ang mga sumusunod ay karaniwang totoo:
pinakamabagal at pinakamaliit
-Cem
-Cm
-Ce
-C
-C{f,F}e
-C{f,F}
-C{f,F}a
pinakamabilis at pinakamalaki
Tandaan na ang mga scanner na may pinakamaliit na mga talahanayan ay karaniwang binubuo at pinagsama-sama ang
pinakamabilis, kaya sa panahon ng pag-unlad ay karaniwang nais mong gamitin ang default, pinakamalaki
compression.
-Cfe ay madalas na isang magandang kompromiso sa pagitan ng bilis at laki para sa mga scanner ng produksyon.
-ooutput, --outputfile=FILE
nagdidirekta sa pagbaluktot upang isulat ang scanner sa file output sa halip ng lex.yy.c. Kung ikaw
pagsamahin -o sa -t opsyon, pagkatapos ay nakasulat ang scanner sa stdout ngunit nito #linya
mga direktiba (tingnan ang -L opsyon sa itaas) sumangguni sa file output.
-Pprefix, --prefix=STRING
binabago ang default yy prefix na ginamit ng pagbaluktot para sa lahat ng variable na nakikita sa buong mundo at
mga pangalan ng function na sa halip ay unlapi Halimbawa, -Pfoo binabago ang pangalan ng yytext
sa foottext. Binabago din nito ang pangalan ng default na output file mula sa lex.yy.c sa
lex.foo.c. Narito ang lahat ng mga pangalan na apektado:
yy_create_buffer
yy_delete_buffer
yy_flex_debug
yy_init_buffer
yy_flush_buffer
yy_load_buffer_state
yy_switch_to_buffer
yyin
yyleng
yylex
yylineno
yyout
yyrestart
yytext
ywrap
(Kung gumagamit ka ng C++ scanner, pagkatapos lamang ywrap at yyFlexLexer ay apektado.)
Sa loob mismo ng iyong scanner, maaari ka pa ring sumangguni sa mga global variable at
mga function gamit ang alinmang bersyon ng kanilang pangalan; ngunit sa panlabas, mayroon silang
binagong pangalan.
Hinahayaan ka ng opsyong ito na madaling mag-link ng maramihang pagbaluktot mga programa sa pareho
maipapatupad. Tandaan, gayunpaman, na ang paggamit ng opsyong ito ay nagpapalit din ng pangalan ywrap(), kaya ikaw ngayon
dapat alinman ay magbigay ng iyong sariling (naaangkop na pinangalanan) na bersyon ng routine para sa iyong
scanner, o gamitin %opsyon noyywrap, bilang pag-uugnay sa -ll hindi na nagbibigay ng isa para sa
ikaw bilang default.
-Skeleton_file, --skel=FILE
overrides ang default na skeleton file kung saan pagbaluktot gumagawa ng mga scanner nito.
Hindi mo kailanman kakailanganin ang opsyong ito maliban kung ginagawa mo ito pagbaluktot pagpapanatili o pag-unlad.
-X, --posix-compat
pinakamataas na compatibility sa POSIX lex.
--yylineno
bilang ng linya ng track sa yylineno.
--yyclass=NAME
pangalan ng klase ng C++.
--header-file=FILE
lumikha ng isang C header file bilang karagdagan sa scanner.
--tables-file[=FILE]
sumulat ng mga talahanayan sa FILE.
-Dmacro[=defn]
#define macro defn (default defn ay '1').
-R, --reentrant
bumuo ng isang reentrant C scanner
--bison-tulay
scanner para sa bison pure parser.
--bison-lokasyon
isama ang yylloc support.
--stdinit
simulan ang yyin/yyout sa stdin/stdout.
--noansi-mga kahulugan lumang istilo tungkulin mga kahulugan.
--noansi-prototypes
walang laman na listahan ng parameter sa mga prototype.
--nounistd
huwag isama .
--hindi gumana
huwag bumuo ng isang partikular na FUNCTION.
pagbaluktot nagbibigay din ng mekanismo para sa pagkontrol ng mga opsyon sa loob ng detalye ng scanner
mismo, sa halip na mula sa flex command-line. Ginagawa ito sa pamamagitan ng pagsasama %opsyon
mga direktiba sa unang seksyon ng detalye ng scanner. Maaari mong tukuyin ang maramihang
mga pagpipilian na may isang solong %opsyon direktiba, at maraming direktiba sa unang seksyon ng
iyong flex input file.
Karamihan sa mga opsyon ay ibinibigay lamang bilang mga pangalan, opsyonal na pinangungunahan ng salitang "hindi" (na may no
intervening whitespace) upang pabayaan ang kanilang kahulugan. Ang isang numero ay katumbas ng mga flex flag o
kanilang negasyon:
7bit -7 na opsyon
8bit -8 na opsyon
align -Ca opsyon
backup -b opsyon
batch -B opsyon
c++ -+ na opsyon
caseful o
case-sensitive na kabaligtaran ng -i (default)
case-insensitive o
caseless -i na opsyon
debug -d na opsyon
default na kabaligtaran ng -s na opsyon
ecs -Ce na opsyon
mabilis -F na opsyon
buong -f na opsyon
interactive -I na opsyon
lex-compat -l na opsyon
meta-ecs -Cm na opsyon
perf-ulat -p opsyon
basahin -Cr opsyon
stdout -t opsyon
verbose -v opsyon
babala kabaligtaran ng -w na opsyon
(gamitin ang "%option nowarn" para sa -w)
array na katumbas ng "%array"
pointer na katumbas ng "%pointer" (default)
ilan %opsyon's magbigay ng mga tampok kung hindi man ay hindi magagamit:
laging-interactive
nagtuturo sa flex upang bumuo ng isang scanner na palaging isinasaalang-alang ang input nito
"interactive". Karaniwan, sa bawat bagong input file tumatawag ang scanner isatty () sa isang
subukang tukuyin kung interactive ang input source ng scanner at sa gayon
dapat basahin ang isang karakter sa isang pagkakataon. Kapag ginamit ang opsyong ito, gayunpaman, hindi
ginawa ang naturang tawag.
pangunahin nagdidirekta ng flex upang magbigay ng default main () programa para sa scanner, na simpleng
tawag yylex(). Ang pagpipiliang ito ay nagpapahiwatig noyywrap (tingnan sa ibaba).
hindi kailanman-interactive
nagtuturo sa flex na bumuo ng isang scanner na hindi kailanman isinasaalang-alang ang input nito na "interactive"
(muli, walang tawag na ginawa sa isatty()). Ito ang kabaligtaran ng laging-interactive.
magtalaksan nagbibigay-daan sa paggamit ng mga stack ng panimulang kondisyon (tingnan ang Mga Kundisyon sa Pagsisimula sa itaas).
stinit
kung itinakda (ibig sabihin, %opsyon stdinit) nagpapasimula yyin at yyout sa si stdin at matapang,
sa halip na ang default ng wala. Ilang umiiral lex ang mga programa ay nakasalalay sa pag-uugaling ito,
kahit na hindi ito sumusunod sa ANSI C, na hindi nangangailangan si stdin at
stdout upang maging compile-time constant.
yylineno
namamahala pagbaluktot upang makabuo ng scanner na nagpapanatili ng bilang ng kasalukuyang linya
basahin mula sa input nito sa global variable yylineno. Ang pagpipiliang ito ay ipinahiwatig ng
%opsyon lex-compat.
ywrap kung hindi nakatakda (ibig sabihin, %opsyon noyywrap), ginagawang hindi tumatawag ang scanner ywrap() sa isang dulo-
of-file, ngunit ipagpalagay lamang na wala nang mga file na i-scan (hanggang ang user
puntos yyin sa isang bagong file at mga tawag yylex() muli).
pagbaluktot sinusuri ang iyong mga aksyon sa panuntunan upang matukoy kung ginagamit mo ang TANGGIHAN or yymore() mga tampok.
Ang tanggihan at yymore available ang mga opsyon para ma-override ang desisyon nito kung gagamit ka
ang mga opsyon, alinman sa pamamagitan ng pagtatakda ng mga ito (hal, %opsyon tanggihan) upang ipahiwatig ang tampok ay
talagang ginamit, o i-unset ang mga ito upang ipahiwatig na hindi talaga ito ginagamit (hal, %opsyon
noyymore).
Tatlong opsyon ang kumukuha ng mga string-delimited na value, offset ng '=':
%option outfile="ABC"
ay katumbas ng -oABC, at
%option prefix="XYZ"
ay katumbas ng -PXYZ. Sa wakas,
%option yyclass="foo"
nalalapat lamang kapag bumubuo ng isang C++ scanner ( -+ opsyon). Nagpapaalam ito pagbaluktot na mayroon ka
nanggaling foo bilang isang subclass ng yyFlexLexer, so pagbaluktot ilalagay ang iyong mga aksyon sa miyembro
tungkulin foo::yylex() sa halip ng yyFlexLexer::yylex(). Ito rin ay bumubuo ng a
yyFlexLexer::yylex() function ng miyembro na naglalabas ng error sa run-time (sa pamamagitan ng pag-invoke
yyFlexLexer::LexerError()) kung tawagin. Tingnan ang Pagbuo ng Mga C++ Scanner, sa ibaba, para sa karagdagang
impormasyon.
Ang isang bilang ng mga pagpipilian ay magagamit para sa lint purists na gustong sugpuin ang hitsura ng
mga hindi kinakailangang gawain sa nabuong scanner. Ang bawat isa sa mga sumusunod, kung hindi nakatakda (hal,
%opsyon nounput ), nagreresulta sa kaukulang gawain na hindi lumilitaw sa nabuo
scanner:
input, unput
yy_push_state, yy_pop_state, yy_top_state
yy_scan_buffer, yy_scan_bytes, yy_scan_string
(bagaman yy_push_state() at hindi lalabas ang mga kaibigan maliban kung gagamitin mo %opsyon salansan).
PAGGANAP KONSIDERASYON
Ang pangunahing layunin ng disenyo ng pagbaluktot na ito ay bumubuo ng mga scanner na may mataas na pagganap. Ito ay naging
na-optimize para sa mahusay na pakikitungo sa malalaking hanay ng mga panuntunan. Bukod sa mga epekto sa scanner
bilis ng compression ng talahanayan -C mga opsyon na nakabalangkas sa itaas, mayroong ilang
mga opsyon/aksyon na nagpapababa sa pagganap. Ito ay, mula sa pinakamahal hanggang sa pinakamababa:
TANGGIHAN
%opsyon yylineno
arbitrary trailing context
mga pattern set na nangangailangan ng pag-back up
%array
%opsyon interactive
%option palaging-interactive
'^' simula-ng-linya na operator
yymore()
na ang unang tatlo ay lahat ay medyo mahal at ang huling dalawa ay medyo mura. Tandaan
ganun din unput() ay ipinapatupad bilang isang nakagawiang tawag na posibleng nagagawa ng kaunti
trabaho, habang yyless() ay isang medyo murang macro; kaya kung ibinabalik lamang ang ilang labis na text sa iyo
na-scan, gumamit yyless().
TANGGIHAN dapat na iwasan sa lahat ng mga gastos kapag ang pagganap ay mahalaga. Ito ay isang partikular na
mahal na opsyon.
Ang pag-alis ng pag-back up ay magulo at kadalasan ay maaaring isang napakalaking dami ng trabaho para sa isang
kumplikadong scanner. Sa punong-guro, nagsisimula ang isa sa paggamit ng -b watawat upang makabuo ng a
lex.backup file. Halimbawa, sa input
%%
foo ibalik ang TOK_KEYWORD;
foobar ibalik ang TOK_KEYWORD;
ang hitsura ng file ay:
Ang estado #6 ay hindi tumatanggap -
nauugnay na mga numero ng linya ng panuntunan:
2 3
mga out-transition: [ o ]
jam-transitions: EOF [ \001-n p-\177 ]
Ang estado #8 ay hindi tumatanggap -
nauugnay na mga numero ng linya ng panuntunan:
3
mga out-transition: [ a ]
jam-transitions: EOF [ \001-` b-\177 ]
Ang estado #9 ay hindi tumatanggap -
nauugnay na mga numero ng linya ng panuntunan:
3
mga out-transition: [ r ]
jam-transitions: EOF [ \001-q s-\177 ]
Palaging naka-back up ang mga naka-compress na talahanayan.
Sinasabi sa amin ng unang ilang linya na mayroong estado ng scanner kung saan maaari itong gumawa ng paglipat
sa isang 'o' ngunit hindi sa anumang iba pang karakter, at sa estadong iyon ang kasalukuyang na-scan
hindi tumutugma ang text sa anumang panuntunan. Ang estado ay nangyayari kapag sinusubukang itugma ang mga panuntunang makikita sa
linya 2 at 3 sa input file. Kung ang scanner ay nasa ganoong estado at pagkatapos ay nagbabasa ng isang bagay
maliban sa isang 'o', kakailanganin nitong i-back up upang makahanap ng isang panuntunan na tumutugma. Na may kaunting
Kapag nagkamot ng ulo, makikita na ito dapat ang estado kung kailan ito nakakita ng "fo".
Kapag nangyari na ito, kung may makikitang iba maliban sa isa pang 'o', magkakaroon ang scanner
upang i-back up upang itugma lamang ang 'f' (sa pamamagitan ng default na panuntunan).
Ang komento tungkol sa Estado #8 ay nagpapahiwatig na mayroong problema kapag na-scan ang "foob".
Sa katunayan, sa anumang karakter maliban sa isang 'a', ang scanner ay kailangang i-back up upang tanggapin
"foo". Katulad nito, ang komento para sa Estado #9 ay nag-aalala kapag ang "fooba" ay na-scan at isang
'r' ay hindi sumusunod.
Ang huling komento ay nagpapaalala sa amin na walang saysay ang lahat ng problema sa pag-alis
pag-back up mula sa mga panuntunan maliban kung ginagamit namin -Cf or -CF, dahil walang performance gain
ginagawa ito gamit ang mga naka-compress na scanner.
Ang paraan upang alisin ang pag-back up ay ang pagdaragdag ng mga panuntunang "error":
%%
foo ibalik ang TOK_KEYWORD;
foobar ibalik ang TOK_KEYWORD;
fooba |
tanga |
para {
/* false alarm, hindi talaga isang keyword */
ibalik ang TOK_ID;
}
Ang pag-aalis ng pag-back up sa isang listahan ng mga keyword ay maaari ding gawin gamit ang panuntunang "catch-all":
%%
foo ibalik ang TOK_KEYWORD;
foobar ibalik ang TOK_KEYWORD;
[az]+ ibalik ang TOK_ID;
Kadalasan ito ang pinakamahusay na solusyon kung naaangkop.
Ang pag-back up ng mga mensahe ay may posibilidad na mag-cascade. Sa isang kumplikadong hanay ng mga panuntunan ay hindi karaniwan
makakuha ng daan-daang mga mensahe. Kung ang isa ay maaaring maintindihan ang mga ito, bagaman, ito ay madalas na tumatagal lamang ng isang dosena
o higit pang mga panuntunan upang alisin ang pag-back up (bagaman madaling magkamali at magkaroon ng
hindi sinasadyang tumugma ang panuntunan ng error sa isang wastong token. Isang posibleng kinabukasan pagbaluktot magiging tampok ang
awtomatikong magdagdag ng mga panuntunan upang maalis ang pag-back up).
Mahalagang tandaan na makukuha mo ang mga benepisyo ng pag-aalis ng pag-back up lamang
kung aalisin mo bawat halimbawa ng pag-back up. Ang pag-iwan ng isa lang ay nangangahulugang wala kang mapapala.
Paiba-iba konteksto ng trailing (kung saan ang mga nangunguna at trailing na bahagi ay walang nakapirming
haba) ay nangangailangan ng halos kaparehong pagkawala ng pagganap bilang TANGGIHAN (ibig sabihin, malaki). Kaya kapag
posibleng isang panuntunan tulad ng:
%%
daga|daga/(pusa|aso) tumakbo();
ay mas mahusay na nakasulat:
%%
mouse/cat|dog run();
daga/pusa|takbuhan ng aso();
o bilang
%%
daga|daga/pusa tumakbo();
daga|daga/aso tumakbo();
Tandaan na dito ang espesyal na '|' ginagawa ng aksyon hindi magbigay ng anumang pagtitipid, at maaari pang kumita
mas malala ang mga bagay (tingnan ang Mga Kakulangan / Mga Bug sa ibaba).
Ang isa pang lugar kung saan maaaring pataasin ng user ang pagganap ng isang scanner (at isa na mas madaling
implement) ay nagmumula sa katotohanan na kung mas mahaba ang mga token ay tumugma, mas mabilis ang scanner
tatakbo. Ito ay dahil sa mahabang mga token ang pagpoproseso ng karamihan sa mga input na character ay tumatagal
ilagay sa (maikling) inner scanning loop, at hindi madalas na dumaan sa
karagdagang gawain ng pag-set up ng kapaligiran sa pag-scan (hal., yytext) para sa aksyon.
Alalahanin ang scanner para sa mga komento sa C:
%x komento
%%
int line_num = 1;
"/*" BEGIN(comment);
[^*\n]*
"*"+[^*/\n]*
\n ++line_num;
"*"+"/" BEGIN(INITIAL);
Ito ay maaaring mapabilis sa pamamagitan ng pagsulat nito bilang:
%x komento
%%
int line_num = 1;
"/*" BEGIN(comment);
[^*\n]*
[^*\n]*\n ++line_num;
"*"+[^*/\n]*
"*"+[^*/\n]*\n ++line_num;
"*"+"/" BEGIN(INITIAL);
Ngayon sa halip na ang bawat bagong linya ay nangangailangan ng pagproseso ng isa pang aksyon, ang pagkilala sa
Ang mga bagong linya ay "ibinahagi" sa iba pang mga panuntunan upang mapanatili ang katugmang teksto hangga't
maaari. Tandaan na pagdaragdag ginagawa ng mga panuntunan hindi pabagalin ang scanner! Ang bilis ng
Ang scanner ay independiyente sa bilang ng mga panuntunan o (modulo ang mga pagsasaalang-alang na ibinigay sa
simula ng seksyong ito) kung gaano kakomplikado ang mga patakaran patungkol sa mga operator tulad ng
'*' at '|'.
Isang huling halimbawa sa pagpapabilis ng isang scanner: ipagpalagay na gusto mong mag-scan sa isang file
naglalaman ng mga identifier at keyword, isa sa bawat linya at walang ibang mga extraneous na character,
at kilalanin ang lahat ng mga keyword. Ang isang natural na unang diskarte ay:
%%
asm |
sasakyan |
break |
... atbp ...
pabagu-bago ng isip |
habang /* ito ay isang keyword */
.|\n /* ito ay hindi isang keyword */
Para alisin ang back-tracking, magpakilala ng catch-all na panuntunan:
%%
asm |
sasakyan |
break |
... atbp ...
pabagu-bago ng isip |
habang /* ito ay isang keyword */
[az]+ |
.|\n /* ito ay hindi isang keyword */
Ngayon, kung ginagarantiyahan na mayroong eksaktong isang salita sa bawat linya, maaari nating bawasan ang
kabuuang bilang ng mga tugma sa pamamagitan ng kalahati sa pamamagitan ng pagsasama sa pagkilala ng mga bagong linya sa na ng
ang iba pang mga token:
%%
asm\n |
auto\n |
break\n |
... atbp ...
pabagu-bago\n |
habang\n /* ito ay isang keyword */
[az]+\n |
.|\n /* ito ay hindi isang keyword */
Ang isa ay kailangang mag-ingat dito, dahil muli na nating ipinakilala ang pag-back up sa scanner. Sa
partikular, habang we alam na hindi kailanman magkakaroon ng anumang mga character sa input stream
maliban sa mga titik o bagong linya, pagbaluktot hindi ko maisip ito, at ito ay magplano para sa posibleng
kailangang i-back up kapag na-scan nito ang isang token tulad ng "auto" at pagkatapos ay ang susunod na karakter ay
isang bagay maliban sa isang bagong linya o isang liham. Dati ay tumutugma lamang ito sa
"auto" na panuntunan at tapos na, ngunit ngayon ay wala na itong "auto" na panuntunan, isang "auto\n" na panuntunan lang. Upang
alisin ang posibilidad ng pag-back up, maaari naming i-duplicate ang lahat ng mga panuntunan ngunit wala
huling mga bagong linya, o, dahil hindi namin inaasahan na makatagpo ng ganoong input at samakatuwid ay hindi
kung paano ito inuri, maaari tayong magpakilala ng isa pang catch-all na panuntunan, ito ay hindi
isama ang isang bagong linya:
%%
asm\n |
auto\n |
break\n |
... atbp ...
pabagu-bago\n |
habang\n /* ito ay isang keyword */
[az]+\n |
[az]+ |
.|\n /* ito ay hindi isang keyword */
Pinagsama-sama sa -Cf, ito ay halos kasing bilis ng makukuha ng isa pagbaluktot scanner upang pumunta para dito
partikular na problema.
Ang pangwakas na tala: pagbaluktot ay mabagal kapag tumutugma sa NUL, lalo na kapag naglalaman ang isang token
maramihang NUL's. Pinakamainam na magsulat ng mga panuntunan na tumutugma maikli dami ng text kung ito ay
inaasahan na ang teksto ay madalas na kasama ang NUL's.
Isa pang huling tala tungkol sa pagganap: tulad ng nabanggit sa itaas sa seksyong Paano ang Input
ay Katugma, dynamic na nagbabago ng laki yytext ang pag-accommodate ng malalaking token ay isang mabagal na proseso
dahil ito ay kasalukuyang nangangailangan na ang (malaking) token ay muling i-scan mula sa simula. Sa gayon
kung mahalaga ang pagganap, dapat mong subukang itugma ang "malalaking" dami ng teksto ngunit hindi
"malaking" dami, kung saan ang cutoff sa pagitan ng dalawa ay nasa humigit-kumulang 8K character/token.
PAGBUBUO C + + MGA KARAPATAN
pagbaluktot nagbibigay ng dalawang magkaibang paraan upang makabuo ng mga scanner para magamit sa C++. Ang unang paraan ay
para lang mag-compile ng scanner na ginawa ni pagbaluktot gamit ang isang C++ compiler sa halip na isang C
compiler. Hindi ka dapat makatagpo ng anumang mga error sa compilation (mangyaring iulat ang anumang nahanap mo sa
ang email address na ibinigay sa seksyon ng May-akda sa ibaba). Maaari mong gamitin ang C++ code sa iyong
mga pagkilos ng panuntunan sa halip na C code. Tandaan na ang default na input source para sa iyong scanner
labi yyin, at ang default echoing ay ginagawa pa rin sa yyout. Parehong nananatili ang mga ito FILE *
mga variable at hindi C++ batis.
Vous pouvez aussi paggamit pagbaluktot upang makabuo ng klase ng C++ scanner, gamit ang -+ opsyon (o,
katumbas, %opsyon c++), na awtomatikong tinukoy kung ang pangalan ng flex
executable ay nagtatapos sa isang '+', tulad ng flex++. Kapag ginagamit ang opsyong ito, i-flex ang default sa
pagbuo ng scanner sa file lex.yy.cc sa halip ng lex.yy.c. Ang nabuong scanner
kasama ang header file FlexLexer.h, na tumutukoy sa interface sa dalawang C++ na klase.
Ang unang klase, FlexLexer, nagbibigay ng abstract base class na tumutukoy sa pangkalahatang scanner
interface ng klase. Nagbibigay ito ng mga sumusunod na function ng miyembro:
const char* YYText()
ibinabalik ang teksto ng pinakakamakailang naitugmang token, ang katumbas ng yytext.
int YYLeng()
ibinabalik ang haba ng pinakakamakailang naitugmang token, ang katumbas ng yyleng.
int lineno() const
ibinabalik ang kasalukuyang numero ng linya ng input (tingnan ang %opsyon yylineno), or 1 if %opsyon
yylineno ay hindi ginamit.
walang bisa set_debug( int bandila )
itinatakda ang debugging flag para sa scanner, katumbas ng pagtatalaga sa yy_flex_debug
(tingnan ang seksyong Mga Pagpipilian sa itaas). Tandaan na dapat mong buuin ang scanner gamit ang
%opsyon mag-alis ng mga insekto upang isama ang impormasyon sa pag-debug dito.
int debug() const
ibinabalik ang kasalukuyang setting ng debugging flag.
Ibinigay din ang mga function ng miyembro na katumbas ng yy_switch_to_buffer(), yy_create_buffer()
(bagaman ang unang argumento ay isang std::istream* object pointer at hindi a FILE*),
yy_flush_buffer(), yy_delete_buffer(), at yyrestart() (muli, ang unang argumento ay a
std::istream* pointer ng bagay).
Ang pangalawang klase ay tinukoy sa FlexLexer.h is yyFlexLexer, na nagmula sa FlexLexer.
Tinutukoy nito ang mga sumusunod na karagdagang function ng miyembro:
yyFlexLexer( std::istream* arg_yyin = 0, std::ostream* arg_yyyout = 0 )
constructs a yyFlexLexer object gamit ang ibinigay na stream para sa input at output. Kung
hindi tinukoy, ang mga stream ay default sa cin at cout, ayon sa pagkakabanggit.
sa katunayan int yylex()
gumaganap ng parehong papel ay yylex() para sa mga ordinaryong flex scanner: ini-scan nito ang
input stream, pagkonsumo ng mga token, hanggang sa magbalik ng halaga ang pagkilos ng isang panuntunan. kung ikaw
kumuha ng subclass S mula yyFlexLexer at gustong ma-access ang mga function ng miyembro at
mga variable ng S loob yylex(), pagkatapos ay kailangan mong gamitin %opsyon yyclass="S" ipaalam
pagbaluktot na gagamitin mo ang subclass na iyon sa halip na yyFlexLexer. Sa kasong ito,
kaysa sa pagbuo yyFlexLexer::yylex(), pagbaluktot bumubuo S::yylex() (at saka
bumubuo ng isang dummy yyFlexLexer::yylex() na tumatawag yyFlexLexer::LexerError() if
tinawag).
sa katunayan walang bisa switch_streams(std::istream* bago sa = 0,
std::ostream* bagong_labas = 0) muling pagtatalaga yyin sa bago sa (kung non-nil) at yyout sa
bagong_labas (ganito), tinatanggal ang nakaraang input buffer kung yyin ay muling itinalaga.
int yylex( std::istream* bago sa, std::ostream* bagong_labas = 0 )
unang inililipat ang input stream sa pamamagitan ng switch_streams( bago sa, bagong_labas ) at pagkatapos ay
ibinabalik ang halaga ng yylex().
Sa karagdagan, yyFlexLexer tumutukoy sa mga sumusunod na protektadong virtual function na magagawa mo
muling tukuyin sa mga nagmula na klase upang maiangkop ang scanner:
sa katunayan int LexerInput( char* buf, int max_size )
nagbabasa hanggang sa max_size mga character sa buf at ibinabalik ang bilang ng mga character na binasa.
Para isaad ang end-of-input, magbalik ng 0 character. Tandaan na ang mga "interactive" na scanner
(Tingnan ang -B at -I flags) tukuyin ang macro YY_INTERACTIVE. Kung muling tukuyin mo
LexerInput() at kailangang gumawa ng iba't ibang aksyon depende sa kung ang
Maaaring nag-scan ang scanner ng isang interactive na mapagkukunan ng input, maaari mong subukan ang
pagkakaroon ng pangalang ito sa pamamagitan ng #ifdef.
sa katunayan walang bisa LexerOutput( const char* buf, int laki )
nagsusulat laki mga character mula sa buffer buf, na, habang tinapos ang NUL, ay maaaring
naglalaman din ng "internal" na NUL kung ang mga panuntunan ng scanner ay maaaring tumugma sa text sa NUL's in
Kanila.
sa katunayan walang bisa LexerError( const char* msg )
nag-uulat ng nakamamatay na mensahe ng error. Ang default na bersyon ng function na ito ay nagsusulat ng
mensahe sa stream cerr at paglabas.
Tandaan na a yyFlexLexer bagay ay naglalaman nito buo estado ng pag-scan. Kaya maaari mong gamitin ang ganoon
mga bagay upang lumikha ng mga reentrant scanner. Maaari kang mag-instantiate ng maraming pagkakataon ng pareho
yyFlexLexer class, at maaari mo ring pagsamahin ang maramihang mga klase ng C++ scanner nang magkasama sa
parehong programa gamit ang -P opsyon na tinalakay sa itaas.
Panghuli, tandaan na ang %array hindi available ang feature sa mga klase ng C++ scanner; kailangan mo
gamitin %pointer (ang default).
Narito ang isang halimbawa ng isang simpleng C++ scanner:
// Isang halimbawa ng paggamit ng flex C++ scanner class.
%{
int mylineno = 0;
%}
string \"[^\n"]+\"
ws [ \t]+
alpha [A-Za-z]
humukay [0-9]
pangalan ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])*
num1 [-+]?{dig}+\.?([eE][-+]?{dig}+)?
num2 [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
numero {num1}|{num2}
%%
{ws} /* laktawan ang mga blangko at tab */
"/*" {
int c;
habang((c = yyinput()) != 0)
{
kung(c == '\n')
++mylineno;
else if(c == '*')
{
if((c = yyinput()) == '/')
masira;
iba
unput(c);
}
}
}
{number} cout << "numero " << YYText() << '\n';
\n mylineno++;
{pangalan} cout << "pangalan " << YYText() << '\n';
{string} cout << "string" << YYText() << '\n';
%%
int main( int /* argc */, char** /* argv */ )
{
FlexLexer* lexer = bago yyFlexLexer;
while(lexer->yylex() != 0)
;
0 bumalik;
}
Kung gusto mong lumikha ng maramihang (iba't ibang) klase ng lexer, gagamitin mo ang -P bandila (o ang
prefix= opsyon) upang palitan ang pangalan ng bawat isa yyFlexLexer sa ilang iba pa xxFlexLexer. Kaya mo na
isama sa iyong iba pang mga mapagkukunan nang isang beses bawat klase ng lexer, unang palitan ang pangalan
yyFlexLexer tulad ng sumusunod:
#undef yyFlexLexer
#define yyFlexLexer xxFlexLexer
#isama
#undef yyFlexLexer
#define yyFlexLexer zzFlexLexer
#isama
kung, halimbawa, ginamit mo %opsyon prefix="xx" para sa isa sa iyong mga scanner at %opsyon
prefix="zz" para sa iba.
MAHALAGA: ang kasalukuyang anyo ng klase ng pag-scan ay pagsubok at maaaring magbago
malaki sa pagitan ng mga pangunahing paglabas.
HINDI PAGKAKASUNDO SA LEX AT POSIX
pagbaluktot ay isang muling pagsulat ng AT&T Unix lex tool (ang dalawang pagpapatupad ay hindi nagbabahagi ng anuman
code, gayunpaman), na may ilang mga extension at hindi pagkakatugma, na parehong nababahala sa
ang mga nais magsulat ng mga scanner na katanggap-tanggap sa alinmang pagpapatupad. Ganap na ang Flex
sumusunod sa POSIX lex detalye, maliban na kapag ginagamit %pointer (ang default),
isang tawag sa unput() sinisira ang nilalaman ng yytext, na kontra sa POSIX
pagtutukoy.
Sa seksyong ito, tinatalakay namin ang lahat ng kilalang bahagi ng hindi pagkakatugma sa pagitan ng flex, AT&T
lex, at ang detalye ng POSIX.
flex's -l Ino-on ng opsyon ang maximum na compatibility sa orihinal na AT&T lex pagpapatupad,
sa halaga ng isang malaking pagkawala sa pagganap ng nabuong scanner. Tandaan namin sa ibaba kung alin
ang mga hindi pagkakatugma ay maaaring pagtagumpayan gamit ang -l pagpipilian.
pagbaluktot ay ganap na magkatugma lex kasama ang mga sumusunod na mga pagbubukod:
- Ang undocumented lex panloob na variable ng scanner yylineno ay hindi suportado maliban kung -l
or %opsyon yylineno Ginagamit.
yylineno dapat panatilihin sa isang per-buffer na batayan, sa halip na isang per-scanner
(iisang pandaigdigang variable) na batayan.
yylineno ay hindi bahagi ng detalye ng POSIX.
- Ang input() Ang routine ay hindi muling tukuyin, bagaman maaari itong tawaging magbasa ng mga character
pagsunod sa anumang naitugma ng isang panuntunan. Kung input() nakatagpo ng pagtatapos ng-
mag-file ng normal ywrap() tapos na ang pagproseso. Isang ``real'' end-of-file ang ibinalik ni
input() as EOF.
Ang input ay sa halip ay kinokontrol sa pamamagitan ng pagtukoy sa YY_INPUT macro.
Ang pagbaluktot paghihigpit na input() hindi maaaring muling tukuyin ay alinsunod sa
POSIX na pagtutukoy, na hindi nagsasaad ng anumang paraan ng pagkontrol sa
input ng scanner maliban sa paggawa ng paunang pagtatalaga sa yyin.
- Ang unput() ang gawain ay hindi muling tukuyin. Ang paghihigpit na ito ay alinsunod sa
POSIX.
- pagbaluktot ang mga scanner ay hindi kasing reentrant lex mga scanner. Sa partikular, kung mayroon kang isang
interactive na scanner at isang interrupt handler na matagal na tumatalon palabas ng scanner,
at ang scanner ay tatawagin muli, maaari mong makuha ang sumusunod na mensahe:
fatal flex scanner internal error--nalampasan ang dulo ng buffer
Upang muling ipasok ang scanner, gamitin muna
yyrestart( yyin );
Tandaan na itatapon ng tawag na ito ang anumang naka-buffer na input; kadalasan hindi ito a
problema sa isang interactive na scanner.
Tandaan din na ibaluktot ang mga klase ng C++ scanner ay reentrant, kaya kung ang paggamit ng C++ ay isang opsyon
para sa iyo, dapat mong gamitin ang mga ito sa halip. Tingnan ang "Pagbuo ng mga C++ Scanner" sa itaas para sa
mga detalye.
- output() ay hindi suportado. Output mula sa Echo macro ay tapos na sa file-pointer
yyout (default stdout).
output() ay hindi bahagi ng detalye ng POSIX.
- lex ay hindi sumusuporta sa mga eksklusibong kundisyon ng pagsisimula (%x), kahit na ang mga ito ay nasa POSIX
pagtutukoy.
- Kapag pinalawak ang mga kahulugan, pagbaluktot nilalagay ang mga ito sa panaklong. Kasama si lex, ang
sumusunod:
PANGALAN [AZ][A-Z0-9]*
%%
foo{NAME}? printf("Nahanap na\n");
%%
ay hindi tutugma sa string na "foo" dahil kapag ang macro ay pinalawak ang panuntunan ay
katumbas ng "foo[AZ][A-Z0-9]*?" at ang pangunguna ay tulad na ang '?' ay
nauugnay sa "[A-Z0-9]*". Sa baluktot, ang panuntunan ay palalawakin sa "foo([AZ][A-
Z0-9]*)?" at kaya ang string na "foo" ay magtutugma.
Tandaan na kung ang kahulugan ay nagsisimula sa ^ o nagtatapos sa $ kung gayon ito ay hindi pinalaki
na may mga panaklong, upang payagan ang mga operator na ito na lumitaw sa mga kahulugan nang hindi nawawala
kanilang mga espesyal na kahulugan. Ngunit ang , /, at < > hindi maaaring gamitin ang mga operator sa a
pagbaluktot kahulugan.
paggamit -l nagreresulta sa lex pag-uugali ng walang panaklong sa paligid ng kahulugan.
Ang pagtutukoy ng POSIX ay ang kahulugan ay nakapaloob sa mga panaklong.
- Ilang mga pagpapatupad ng lex payagan ang pagkilos ng isang panuntunan na magsimula sa isang hiwalay na linya, kung
ang pattern ng panuntunan ay may sumusunod na whitespace:
%%
foo|bar
{ foobar_action(); }
pagbaluktot ay hindi sumusuporta sa tampok na ito.
- Ang lex %r (bumuo ng Ratfor scanner) na opsyon ay hindi suportado. Hindi ito bahagi ng
ang detalye ng POSIX.
- Pagkatapos ng isang tawag sa unput(), yytext ay hindi natukoy hanggang sa ang susunod na token ay tumugma,
maliban kung ang scanner ay binuo gamit %array. Hindi ito ang kaso sa lex o ang
Detalye ng POSIX. Ang -l Tinatanggal ng pagpipilian ang hindi pagkakatugma na ito.
- Ang nangunguna sa {} (numeric range) operator ay iba. lex nagpapakahulugan
"abc{1,3}" bilang "tugma sa isa, dalawa, o tatlong paglitaw ng 'abc'", samantalang pagbaluktot
binibigyang-kahulugan ito bilang "tugmang 'ab' na sinusundan ng isa, dalawa, o tatlong paglitaw ng 'c'".
Ang huli ay sumasang-ayon sa detalye ng POSIX.
- Ang nangunguna sa ^ iba ang operator. lex binibigyang-kahulugan ang "^foo|bar" bilang "tugma
alinman sa 'foo' sa simula ng isang linya, o 'bar' kahit saan", samantalang pagbaluktot
binibigyang kahulugan ito bilang "itugma ang alinman sa 'foo' o 'bar' kung dumating sila sa simula ng a
linya". Ang huli ay sumasang-ayon sa detalye ng POSIX.
- Ang mga espesyal na deklarasyon sa laki ng talahanayan tulad ng %a suportado ng lex ay hindi hinihingi ng
pagbaluktot mga scanner; pagbaluktot hindi sila pinapansin.
- Ang pangalan FLEX_SCANNER ay #define'd upang ang mga scanner ay maaaring isulat para magamit sa alinman
pagbaluktot or lex Kasama rin sa mga scanner YY_FLEX_MAJOR_VERSION at YY_FLEX_MINOR_VERSION
na nagpapahiwatig kung aling bersyon ng pagbaluktot nabuo ang scanner (halimbawa, para sa 2.5
release, ang mga pagtukoy na ito ay magiging 2 at 5 ayon sa pagkakabanggit).
Ang mga sumusunod na pagbaluktot ang mga tampok ay hindi kasama sa lex o ang detalye ng POSIX:
C++ scanner
%opsyon
simulan ang mga saklaw ng kondisyon
simulan ang mga stack ng kondisyon
interactive/non-interactive na mga scanner
yy_scan_string() at mga kaibigan
yterminate()
yy_set_interactive()
yy_set_bol()
YY_AT_BOL()
< >
<*>
YY_DECL
YY_START
YY_USER_ACTION
YY_USER_INIT
#line na mga direktiba
%{}'s sa paligid ng mga aksyon
maraming aksyon sa isang linya
plus halos lahat ng flex flag. Ang huling tampok sa listahan ay tumutukoy sa katotohanang iyon
sa pagbaluktot maaari kang maglagay ng maraming aksyon sa parehong linya, na pinaghihiwalay ng mga semi-colon, habang
sa lex, ang mga sumusunod na
foo handle_foo(); ++num_foos_seen;
ay (sa halip nakakagulat) pinutol sa
foo handle_foo();
pagbaluktot hindi pinuputol ang aksyon. Ang mga aksyon na hindi nakapaloob sa mga braces ay simple lang
winakasan sa dulo ng linya.
DIAGNOSTICS
babala, mamuno hindi maaari be naitugma ay nagpapahiwatig na ang ibinigay na panuntunan ay hindi maaaring tumugma dahil ito
sumusunod sa iba pang mga panuntunan na palaging tutugma sa parehong teksto tulad nito. Halimbawa, sa
Ang pagsunod sa "foo" ay hindi maaaring itugma dahil ito ay pagkatapos ng isang identifier na "catch-all" na panuntunan:
[az]+ got_identifier();
foo got_foo();
paggamit TANGGIHAN sa isang scanner ay pinipigilan ang babalang ito.
babala, -s opsyon naibigay na pero default mamuno maaari be naitugma nangangahulugan na ito ay posible
(marahil lamang sa isang partikular na kondisyon ng pagsisimula) na ang default na panuntunan (tumutugma sa anumang solong
character) ay ang isa lamang na tutugma sa isang partikular na input. Since -s ay ibinigay,
siguro hindi ito sinadya.
tanggihan_ginamit_ngunit_hindi_natukoy hindi naipalilawanag or yymore_used_but_not_detected hindi naipalilawanag - mga ito
maaaring mangyari ang mga error sa oras ng pag-compile. Ipinapahiwatig nila na ang scanner ay gumagamit TANGGIHAN or yymore()
ngunit iyon pagbaluktot nabigong mapansin ang katotohanan, ibig sabihin iyon pagbaluktot na-scan ang unang dalawang seksyon
naghahanap ng mga paglitaw ng mga pagkilos na ito at nabigong makahanap ng anuman, ngunit kahit papaano ay sumuko ka
ilang sa (sa pamamagitan ng isang #include file, halimbawa). Gamitin %opsyon tanggihan or %opsyon yymore sa
ipahiwatig upang ibaluktot na talagang ginagamit mo ang mga tampok na ito.
pagbaluktot scanner naka-jam - isang scanner na pinagsama-sama -s ay nakatagpo ng isang input string na
ay hindi tumugma sa alinman sa mga panuntunan nito. Ang error na ito ay maaari ding mangyari dahil sa mga panloob na problema.
token masyado malaki, Lumagpas ang YYLMAX - ginagamit ng iyong scanner %array at isa sa mga tuntunin nito ay tumugma sa a
string na mas mahaba kaysa sa YYLMAX pare-pareho (8K bytes bilang default). Maaari mong taasan ang halaga
sa pamamagitan ng #define'ing YYLMAX sa seksyon ng mga kahulugan ng iyong pagbaluktot input.
scanner nangangailangan -8 bandila sa gamitin ang katangian 'x' - Kasama sa detalye ng iyong scanner
pagkilala sa 8-bit na character 'x' at hindi mo tinukoy ang -8 flag, at ang iyong scanner
na-default sa 7-bit dahil ginamit mo ang -Cf or -CF mga pagpipilian sa compression ng talahanayan. Tingnan ang
talakayan ng -7 bandila para sa mga detalye.
pagbaluktot scanner push-back apaw - ginamit mo unput() to push back so much text that the
Hindi mahawakan ng buffer ng scanner ang parehong push-back na text at ang kasalukuyang token in yytext.
Sa isip, ang scanner ay dapat na dynamic na baguhin ang laki ng buffer sa kasong ito, ngunit sa kasalukuyan ito
ay hindi.
input nagpapahina ng lakas pag-apaw, hindi pwede palakihin nagpapahina ng lakas dahil sa scanner Gumagamit TANGGIHAN - ang scanner noon
nagtatrabaho sa pagtutugma ng napakalaking token at kailangan upang palawakin ang input buffer. Ito
ay hindi gumagana sa mga scanner na gumagamit TANGGIHAN.
nakamamatay pagbaluktot scanner panloob pagkakamali--tapos of nagpapahina ng lakas napalampas - Ito ay maaaring mangyari sa isang scanner
na muling ipinasok pagkatapos ng mahabang pagtalon ay tumalon palabas (o lampas) sa pag-activate ng scanner
kuwadro. Bago ipasok muli ang scanner, gamitin ang:
yyrestart( yyin );
o, gaya ng nabanggit sa itaas, lumipat sa paggamit ng C++ scanner class.
masyado marami simula kundisyon in <> bumuo! - naglista ka ng higit pang mga kundisyon ng pagsisimula sa isang <>
construct kaysa sa umiiral (kaya dapat ay nakalista ka ng kahit isa sa mga ito nang dalawang beses).
Gumamit ng freebsd-lex online gamit ang mga serbisyo ng onworks.net