EngelsFransSpaans

Ad


OnWorks-favicon

freebsd-lex - Online in de cloud

Voer freebsd-lex uit in de gratis hostingprovider van OnWorks via Ubuntu Online, Fedora Online, Windows online emulator of MAC OS online emulator

Dit is de opdracht freebsd-lex die kan worden uitgevoerd in de gratis hostingprovider van OnWorks met behulp van een van onze meerdere gratis online werkstations zoals Ubuntu Online, Fedora Online, Windows online emulator of MAC OS online emulator

PROGRAMMA:

NAAM


flex, lex - snelle lexicale analysatorgenerator

KORTE INHOUD


buigen [-bcdfhilnpstvwBFILTV78+? -C[aefFmr] -uitvoer -Pvoorvoegsel -Skelet] [--hulp --versie]
[bestandsnaam

Overzicht


Deze handleiding beschrijft buigen, een hulpmiddel voor het genereren van programma's die patroonmatching uitvoeren
op tekst. De handleiding bevat zowel zelfstudie- als referentiesecties:

Omschrijving
een kort overzicht van het hulpmiddel

Enkele eenvoudige voorbeelden

Formaat van het invoerbestand

Patronen
de uitgebreide reguliere expressies die door flex worden gebruikt

Hoe de invoer op elkaar wordt afgestemd
de regels om te bepalen wat er is gematcht

Acties
hoe u kunt opgeven wat er moet gebeuren als een patroon overeenkomt

De gegenereerde scanner
details over de scanner die flex produceert;
hoe u de ingangsbron kunt bedienen

Startvoorwaarden
context introduceren in uw scanners, en
beheren van "miniscanners"

Meerdere invoerbuffers
hoe je meerdere invoerbronnen kunt manipuleren; hoe
scannen vanaf tekenreeksen in plaats van bestanden

Regels voor het einde van het bestand
speciale regels voor het matchen van het einde van de invoer

Diverse macro's
een samenvatting van de macro's die beschikbaar zijn voor de acties

Waarden beschikbaar voor de gebruiker
een samenvatting van de waarden die beschikbaar zijn voor de acties

Interface met Yacc
flexscanners verbinden met yacc-parsers

Opties
flex opdrachtregelopties en de "%option"
Richtlijnen

Prestatieoverwegingen
hoe u uw scanner zo snel mogelijk kunt laten werken

C++-scanners genereren
de (experimentele) faciliteit voor het genereren van C++
scannerklassen

Onverenigbaarheden met Lex en POSIX
hoe flex verschilt van AT&T lex en de POSIX lex
standaard

Diagnostiek
die foutmeldingen geproduceerd door flex (of scanners
het genereert) waarvan de betekenis misschien niet duidelijk is

Bestanden
bestanden gebruikt door flex

Tekortkomingen / bugs
bekende problemen met flex

Zie ook
andere documentatie, gerelateerde tools

Auteur
bevat contactgegevens

PRODUCTBESCHRIJVING


buigen is een hulpmiddel voor het genereren scanners: programma's die lexicale patronen in tekst herkennen.
buigen leest de gegeven invoerbestanden, of de standaardinvoer ervan als er geen bestandsnamen zijn opgegeven, voor a
beschrijving van een scanner die moet worden gegenereerd. De beschrijving is in de vorm van paren regelmatig
expressies en C-code, genaamd regels. buigen genereert als uitvoer een C-bronbestand, lex.jj.c,
die een routine definieert yylex(). Dit bestand wordt samengesteld en gekoppeld aan de -NS bibliotheek naar
een uitvoerbaar bestand produceren. Wanneer het uitvoerbare bestand wordt uitgevoerd, analyseert het de invoer op gebeurtenissen
van de reguliere expressies. Wanneer het er een vindt, voert het de bijbehorende C-code uit.

SOMMIGE EENVOUDIG Voorbeelden


Eerst enkele eenvoudige voorbeelden om de smaak te krijgen van hoe men gebruikt buigen. De volgende buigen
input specificeert een scanner die telkens wanneer deze de string "gebruikersnaam" tegenkomt, zal vervangen
met de inlognaam van de gebruiker:

%%
gebruikersnaam printf( "%s", getlogin() );

Standaard wordt elke tekst die niet overeenkomt met a buigen scanner wordt gekopieerd naar de uitvoer, dus het net
Het effect van deze scanner is dat het invoerbestand naar de uitvoer wordt gekopieerd telkens wanneer
"gebruikersnaam" uitgebreid. Bij deze invoer geldt slechts één regel. "gebruikersnaam" is de patroon
en de "printf" is de actie. De "%%" markeert het begin van de regels.

Hier is nog een eenvoudig voorbeeld:

%{
int aantal_lijnen = 0, aantal_chars = 0;
%}

%%
\n ++aantal_regels; ++aantal_tekens;
. ++aantal_tekens;

%%
hoofd()
{
yylex();
printf( "# regels = %d, # tekens = %d\n",
num_lines, num_chars );
}

Deze scanner telt het aantal tekens en het aantal regels in zijn invoer (it
produceert geen andere output dan het eindrapport over de tellingen). De eerste regel verklaart
twee globalen, "num_lines" en "num_chars", die beide binnenin toegankelijk zijn yylex() en in
de hoofd() routine gedeclareerd na de tweede "%%". Er zijn twee regels, waarvan er één overeenkomt
een nieuwe regel ("\n") en verhoogt zowel het aantal regels als het aantal tekens, en één die
komt overeen met elk ander teken dan een nieuwe regel (aangegeven door de reguliere expressie ".").

Een wat ingewikkelder voorbeeld:

/* scanner voor een speelgoed-Pascal-achtige taal */

%{
/* heb dit nodig voor de aanroep van atof() hieronder */
# omvatten
%}

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

%%

{CIJFER}+ {
printf( "Een geheel getal: %s (%d)\n", yytext,
atoi( yytekst ) );
}

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

als | dan | begin | eind | procedure | functie {
printf("Een trefwoord: %s\n", yytext );
}

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

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

"{"[^}\n]*"}" /* eet commentaar van één regel op */

[ \t\n]+ /* spatie opeten */

. printf( "Onbekend teken: %s\n", yytext );

%%

hoofd(argc, argv )
int argc;
char **argv;
{
++argv, --argc; /* programmanaam overslaan */
als (argc > 0)
yyin = fopen( argv[0], "r" );
anders
yyin = standaard;

yylex();
}

Dit is het begin van een eenvoudige scanner voor een taal als Pascal. Het identificeert
verschillende types van penningen en rapporteert over wat het heeft gezien.

De details van dit voorbeeld worden in de volgende secties uitgelegd.

FORMAT OF HET INVOER FILE


De buigen invoerbestand bestaat uit drie secties, gescheiden door een regel met just %% in het:

definities
%%
reglement
%%
gebruikerscode

De definities sectie bevat verklaringen van simple naam definities om het te vereenvoudigen
scannerspecificatie en verklaringen van begin voorwaarden, die worden uitgelegd in a
later gedeelte.

Naamdefinities hebben de vorm:

naam definitie

De "naam" is een woord dat begint met een letter of een onderstrepingsteken ('_'), gevolgd door nul of
meer letters, cijfers, '_' of '-' (streepje). Er wordt aangenomen dat de definitie bij de eerste begint
teken zonder witruimte dat de naam volgt en doorgaat tot het einde van de regel. De
Er kan vervolgens naar de definitie worden verwezen met behulp van "{naam}", dat zal worden uitgebreid naar
"(definitie)". Bijvoorbeeld,

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

definieert "DIGIT" als een reguliere expressie die overeenkomt met een enkel cijfer, en "ID" als een
reguliere expressie die overeenkomt met een letter gevolgd door nul of meer letters of cijfers. A
daaropvolgende verwijzing naar

{DIGIT}+"."{DIGIT}*

is identiek aan

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

en komt overeen met een of meer cijfers gevolgd door een '.' gevolgd door nul of meer cijfers.

De reglement gedeelte van de buigen invoer bevat een reeks regels van de vorm:

patroon actie

waarbij het patroon niet ingesprongen mag zijn en de actie op dezelfde lijn moet beginnen.

Zie hieronder voor een verdere beschrijving van patronen en acties.

Ten slotte wordt eenvoudigweg het gebruikerscodegedeelte gekopieerd lex.jj.c woordelijk. Je gebruikt het voor
begeleidende routines die bellen of worden gebeld door de scanner. De aanwezigheid van deze sectie
is optioneel; als het ontbreekt, de tweede %% in het invoerbestand kan ook worden overgeslagen.

In de secties met definities en regels zijn alle ingesprongen tekst of tekst ingesloten %{ en %} is
woordelijk gekopieerd naar de uitvoer (met de %{} verwijderd). De %{}'s moeten niet ingesprongen zijn
op lijnen zelf.

In het regelsgedeelte kan elke ingesprongen of %{} tekst die vóór de eerste regel verschijnt, worden gebruikt
om variabelen te declareren die lokaal zijn voor de scanroutine en (na de declaraties)
code die moet worden uitgevoerd wanneer de scanroutine wordt ingevoerd. Andere ingesprongen of
%{} tekst in de regelsectie wordt nog steeds naar de uitvoer gekopieerd, maar de betekenis ervan is niet goed
gedefinieerd en het kan heel goed compileerfouten veroorzaken (deze functie is aanwezig voor POSIX
naleving; zie hieronder voor andere soortgelijke functies).

In het definitiegedeelte (maar niet in het regelsgedeelte) kan een niet-ingesprongen commentaar (dat wil zeggen een
regel die begint met "/*") wordt ook woordelijk gekopieerd naar de uitvoer tot aan de volgende "*/".

PATRONEN


De patronen in de invoer worden geschreven met behulp van een uitgebreide set reguliere expressies. Deze
zijn:

x komt overeen met het teken 'x'
. elk teken (byte) behalve nieuwe regel
[xyz] een "karakterklasse"; in dit geval het patroon
komt overeen met een 'x', een 'y' of een 'z'
[abj-oZ] een "karakterklasse" met een bereik erin; wedstrijden
een 'a', een 'b', elke letter van 'j' tot en met 'o',
of een 'Z'
[^AZ] een "ontkende tekenklasse", dwz elk teken
maar die in de klas. In dit geval: elke
karakter BEHALVE een hoofdletter.
[^AZ\n] elk teken BEHALVE een hoofdletter of
een nieuwe regel
r* nul of meer r's, waarbij r een reguliere expressie is
r+ een of meer r's
R? nul of één r's (dat wil zeggen: "een optionele r")
r{2,5} ergens tussen twee en vijf r's
r{2,} twee of meer r's
r{4} precies 4 r's
{name} de uitbreiding van de definitie van "naam".
(zie hierboven)
"[xyz]\"foo"
de letterlijke tekenreeks: [xyz]"foo
\X als X een 'a', 'b', 'f', 'n', 'r', 't' of 'v' is,
dan de ANSI-C-interpretatie van \x.
Anders een letterlijke 'X' (gebruikt om te ontsnappen
operatoren zoals '*')
\0 een NUL-teken (ASCII-code 0)
\123 het teken met octale waarde 123
\x2a het teken met hexadecimale waarde 2a
(r) overeenkomen met een r; Er worden haakjes gebruikt om te overschrijven
voorrang (zie hieronder)

rs de reguliere expressie r gevolgd door de
normale uitdrukkingen; zogenaamde "aaneenschakeling"

r|s is een r of een s

r/s een r, maar alleen als deze wordt gevolgd door een s. De
tekst die overeenkomt met s wordt meegenomen bij het bepalen
of deze regel de "langste match" is,
maar wordt dan teruggestuurd naar de voorgaande invoer
de actie wordt uitgevoerd. Dus alleen de actie
ziet de tekst overeenkomen met r. Dit type
van het patroon wordt achterliggende context genoemd".
(Er zijn enkele combinaties van r/s die buigen
kan niet correct overeenkomen; zie opmerkingen in de
Tekortkomingen / Bugs hieronder met betrekking tot
"gevaarlijke achterliggende context".)
^r en r, maar alleen aan het begin van een regel (dwz
wanneer u net begint met scannen, of direct na een
nieuwe regel is gescand).
r$ en r, maar alleen aan het einde van een regel (dwz net
vóór een nieuwe regel). Gelijk aan "r/\n".

Merk op dat Flex's notie van "nieuwe regel" precies is
wat de C-compiler ook gebruikte om flex te compileren
interpreteert '\n' als; in het bijzonder op sommige DOS
systemen moet u \r's in het
voer het zelf in, of gebruik expliciet r/\r\n voor "r$".

r en r, maar alleen in startconditie s (zie
hieronder voor bespreking van startvoorwaarden)
R
hetzelfde, maar in een van de startomstandigheden s1,
s2 of s3
<*>r en r in elke startconditie, zelfs een exclusieve.

< > een einde-bestand
< >
een einde-van-bestand in startconditie s1 of s2

Merk op dat binnen een karakterklasse alle reguliere expressieoperatoren hun special verliezen
wat betekent behalve escape ('\') en de karakterklasse-operatoren, '-', ']', en, bij de
begin van de les, '^'.

De hierboven genoemde reguliere expressies zijn gegroepeerd op basis van prioriteit, vanaf de hoogste
prioriteit bovenaan en de laagste onderaan. Degenen die bij elkaar zijn gegroepeerd, zijn gelijk
voorrang. Bijvoorbeeld,

foe|bar*

is hetzelfde als

(foe)|(ba(r*))

aangezien de operator '*' een hogere prioriteit heeft dan aaneenschakeling, en aaneenschakeling hoger
dan afwisseling ('|'). Dit patroon komt dus overeen beide de tekenreeks "foo" or de
string "ba" gevolgd door nul of meer r's. Om "foo" of nul-of-meer "bar"'s te matchen, gebruik je:

foo|(maat)*

en om nul of meer "foo"'s-of-"bar"'s te matchen:

(foe|bar)*

Naast karakters en reeksen karakters kunnen karakterklassen ook
tekenklasse uitdrukkingen. Dit zijn uitdrukkingen die erin zijn ingesloten [: en :] begrenzers
(die zelf moeten verschijnen tussen de '[' en ']' van de karakterklasse; other
elementen kunnen ook binnen de karakterklasse voorkomen). De geldige expressies zijn:

[:alnum:] [:alpha:] [:blank:]
[:cntrl:] [:digit:] [:grafiek:]
[:lager:] [:print:] [:punct:]
[:spatie:] [:boven:] [:xdigit:]

Deze uitdrukkingen duiden allemaal een reeks tekens aan die gelijkwaardig zijn aan de overeenkomstige
standaard C isXXX functie. Bijvoorbeeld, [:alum:] geeft de tekens aan waarvoor
isalnummer() retourneert waar - dat wil zeggen, alfabetisch of numeriek. Sommige systemen bieden dit niet
is leeg(), dus flex definieert [:blanco:] als blanco of als tabblad.

De volgende tekenklassen zijn bijvoorbeeld allemaal gelijkwaardig:

[[:alum:]]
[[:alfa:][:cijfer:]]
[[:alfa:]0-9]
[a-zA-Z0-9]

Als uw scanner niet hoofdlettergevoelig is (de -i vlag), dan [:bovenste:] en [:lager:] zijn
gelijkwaardig [:alfa:].

Enkele opmerkingen over patronen:

- Een genegeerde tekenklasse, zoals het voorbeeld "[^AZ]" hierboven wil match a nieuwe lijn
tenzij "\n" (of een gelijkwaardige escape-reeks) expliciet een van de tekens is
aanwezig in de genegeerde tekenklasse (bijvoorbeeld "[^AZ\n]"). Dit is anders dan hoeveel
andere reguliere expressietools behandelen genegeerde karakterklassen, maar helaas
de inconsistentie is historisch verankerd. Overeenkomende nieuwe regels betekent dat a
Een patroon zoals [^"]* kan overeenkomen met de gehele invoer, tenzij er nog een aanhalingsteken in de
invoer.

- Een regel kan maximaal één exemplaar van de afsluitende context bevatten (de operator '/' of de
'$'-operator). De startvoorwaarde, '^' en "< >" patronen kunnen alleen voorkomen bij
het begin van een patroon, en kunnen, net als bij '/' en '$', niet worden gegroepeerd
tussen haakjes. Een '^' die niet aan het begin van een regel voorkomt of een '$'
wat aan het einde van een regel niet voorkomt, verliest zijn bijzondere eigenschappen en is dat wel
behandeld als een normaal karakter.

Het volgende is illegaal:

foo/bar$
foe bar

Merk op dat de eerste hiervan kan worden geschreven als "foo/bar\n".

Het volgende zal ertoe leiden dat '$' of '^' als een normaal teken wordt behandeld:

foe|(bar$)
foo|^balk

Als wat nodig is een "foo" is, of een balk gevolgd door een nieuwe regel, zou het volgende kunnen zijn
gebruikt (de speciale actie '|' wordt hieronder uitgelegd):

foe |
bar$ /* actie komt hier */

Een soortgelijke truc werkt voor het matchen van een foo of een maatstreep aan het begin van een regel.

HOE HET INVOER IS OP ELKAAR AFGESTEMD


Wanneer de gegenereerde scanner wordt uitgevoerd, analyseert deze de invoer op zoek naar strings die overeenkomen
elk van zijn patronen. Als er meer dan één overeenkomst wordt gevonden, wordt degene genomen die het meest overeenkomt
tekst (voor afsluitende contextregels omvat dit zelfs de lengte van het afsluitende gedeelte
hoewel het dan wordt teruggestuurd naar de invoer). Als er twee of meer overeenkomsten van de
dezelfde lengte, de regel die als eerste wordt vermeld in de buigen invoerbestand is gekozen.

Zodra de match is bepaald, wordt de tekst die overeenkomt met de match (de zogenaamde teken) is
beschikbaar gemaakt in de globale karakteraanwijzer yytekst, en de lengte ervan in de wereld
geheel getal yeleng. De actie die overeenkomt met het overeenkomende patroon wordt vervolgens uitgevoerd (een meer
gedetailleerde beschrijving van acties volgt), en vervolgens wordt naar de resterende invoer gescand
nog een wedstrijd.

Als er geen overeenkomst wordt gevonden, wordt de verzuim regeren wordt uitgevoerd: het volgende teken in de invoer
wordt beschouwd als gekoppeld en gekopieerd naar de standaarduitvoer. Dus de eenvoudigste juridische buigen
invoer is:

%%

die een scanner genereert die eenvoudigweg de invoer (één teken tegelijk) naar zijn
uitgang.

Merk op dat yytekst kan op twee verschillende manieren worden gedefinieerd: hetzij als een personage wijzer of als
een karakter matrix. U kunt bepalen welke definitie buigen gebruikt door een van de
speciale richtlijnen %wijzer or %matrix in het eerste (definitie)gedeelte van uw flex
invoer. De standaardwaarde is %wijzer, tenzij je gebruik maakt van de -l lex-compatibiliteitsoptie, waarin
geval yytekst zal een array zijn. Het voordeel van gebruiken %wijzer is aanzienlijk sneller
scannen en geen bufferoverloop bij het matchen van zeer grote tokens (tenzij je geen voorraad meer hebt
dynamisch geheugen). Het nadeel is dat je beperkt wordt in hoe je kunt handelen
wijzigen yytekst (zie het volgende gedeelte), en oproepen naar de ongedaan maken() functie vernietigt de
huidige inhoud van yytekst, wat bij het verplaatsen aanzienlijke hoofdpijn kan veroorzaken
tussen lex versies.

Het voordeel van %matrix is dat u het vervolgens kunt wijzigen yytekst naar hartenlust, en
oproepen naar ongedaan maken() niet vernietigen yytekst (zie hieronder). Verder bestaand lex programma's
soms toegang yytekst extern met behulp van verklaringen van het formulier:
externe char yytext[];
Deze definitie is onjuist wanneer deze wordt gebruikt met %wijzer, maar juist voor %matrix.

%matrix definieert yytekst een array zijn van YYLMAX karakters, die standaard op een fair
grote waarde. Je kunt de grootte wijzigen door simpelweg te #define'en YYLMAX naar een andere waarde in
het eerste deel van je buigen invoer. Zoals hierboven vermeld, met %wijzer yytext groeit
dynamisch om grote tokens te huisvesten. Terwijl dit jouw %wijzer scanner kan
Houd er rekening mee dat er zeer grote tokens kunnen worden geplaatst (zoals het matchen van hele blokken met opmerkingen).
dat elke keer dat de scanner het formaat moet wijzigen yytekst het moet ook het hele token opnieuw scannen
het begin, dus het matchen van dergelijke tokens kan traag blijken. yytekst momenteel wel niet
dynamisch groeien als een oproep daartoe ongedaan maken() resulteert in het terugdringen van te veel tekst; in plaats van,
er ontstaat een runtimefout.

Houd er ook rekening mee dat u er geen gebruik van kunt maken %matrix met C++ scannerklassen (de C ++ keuze; zie hieronder).

ACTIES


Elk patroon in een regel heeft een overeenkomstige actie, die elke willekeurige C-instructie kan zijn.
Het patroon eindigt bij het eerste witruimteteken zonder escapecodes; de rest van de lijn
is zijn actie. Als de actie leeg is, wordt het invoertoken weergegeven als het patroon overeenkomt
wordt gewoonweg weggegooid. Hier vindt u bijvoorbeeld de specificatie voor een programma dat verwijdert
alle exemplaren van "zap me" uit de invoer:

%%
"Zap mij"

(Het kopieert alle andere tekens in de invoer naar de uitvoer, omdat ze overeenkomen
volgens de standaardregel.)

Hier is een programma dat meerdere lege velden en tabbladen comprimeert tot één enkele blanco, en
gooit witruimte aan het einde van een regel weg:

%%
[ \t]+ putchar( ' ' );
[ \t]+$ /* negeer dit token */

Als de actie een '{' bevat, duurt de actie totdat de balancerende '}' is gevonden, en
de actie kan meerdere lijnen overschrijden. buigen kent C-snaren en opmerkingen en zal dat niet zijn
voor de gek gehouden door beugels die erin zitten, maar staat ook acties toe om mee te beginnen %{ en wil
beschouw de actie als de hele tekst tot aan de volgende %} (ongeacht gewone beugels
binnen de actie).

Een actie die uitsluitend uit een verticale balk bestaat ('|') betekent 'hetzelfde als de actie voor de volgende'
regel." Zie hieronder voor een illustratie.

Acties kunnen willekeurige C-code omvatten, inclusief terugkeer uitspraken om een ​​waarde aan terug te geven
welke routine ook riep yylex(). Elke keer weer yylex() wordt het voortgezette verwerking genoemd
tokens vanaf het punt waar het voor het laatst was gebleven totdat het het einde van het bestand bereikt of wordt uitgevoerd
een terugkeer.

Acties kunnen vrij worden gewijzigd yytekst behalve het verlengen ervan (het toevoegen van tekens aan de
end - deze zullen latere tekens in de invoerstroom overschrijven). Dit gebeurt echter niet
toepassen bij gebruik %matrix (zie hierboven); in dat geval, yytekst kan in elk geval vrijelijk worden gewijzigd
manier.

Acties kunnen vrij worden gewijzigd yeleng behalve dat ze dit niet zouden moeten doen als de actie ook omvat
gebruik van meer() (zie hieronder).

Er zijn een aantal bijzondere richtlijnen die binnen een actie kunnen worden opgenomen:

- ECHO kopieert yytext naar de uitvoer van de scanner.

- BEGINNEN gevolgd door de naam van een startvoorwaarde plaatst de scanner in de
overeenkomstige startvoorwaarde (zie hieronder).

- WEIGEREN geeft de scanner opdracht om verder te gaan met de "tweede beste" regel die overeenkomt
de invoer (of een voorvoegsel van de invoer). De regel wordt gekozen zoals hierboven beschreven in
"Hoe de invoer wordt gematcht", en yytekst en yeleng op de juiste manier opzetten. Het kan
ofwel een regel die evenveel tekst bevat als de oorspronkelijk gekozen regel, maar toch komt
later in de buigen invoerbestand, of een bestand dat minder tekst bevat. Bijvoorbeeld de
het volgende zal zowel de woorden in de invoer tellen als de routine special() aanroepen
telkens wanneer "frob" wordt gezien:

int woord_telling = 0;
%%

frob speciaal(); AFWIJZEN;
[^ \t\n]+ ++word_count;

Zonder de AFWIJZEN, eventuele "frob"'s in de invoer worden sindsdien niet als woorden geteld
de scanner voert normaal gesproken slechts één actie per token uit. Meerdere WEIGEREN zijn
toegestaan, waarbij iedereen de beste keuze vindt naast de momenteel actieve regel. Voor
Wanneer de volgende scanner bijvoorbeeld het token "abcd" scant, zal deze schrijven
"abcdabcaba" naar de uitvoer:

%%
een |
ab |
abc |
abcd-ECHO; AFWIJZEN;
.|\n /* eet elk ongeëvenaard karakter op */

(De eerste drie regels delen de actie van de vierde omdat ze de speciale '|' gebruiken
actie.) WEIGEREN is een bijzonder dure functie in termen van scanner
prestatie; als het erin wordt gebruikt elke van de acties van de scanner zal het vertragen allen of
de scanner komt overeen. Verder, WEIGEREN kan niet worden gebruikt met de -Vgl or CF
opties (zie hieronder).

Merk ook op dat, in tegenstelling tot de andere speciale acties, WEIGEREN is een Afdeling; code
onmiddellijk volgen in het actietestament niet worden uitgevoerd.

- meer() vertelt de scanner dat de volgende keer dat hij aan een regel voldoet, de overeenkomstige
teken zou moeten zijn toegevoegd op de huidige waarde van yytekst in plaats van het te vervangen.
Gegeven de invoer "mega-kludge" zal het volgende bijvoorbeeld "mega-mega-
kludge" naar de uitvoer:

%%
mega-ECHO; yymore();
klungelen ECHO;

De eerste "mega-" wordt gematcht en herhaald met de uitvoer. Dan wordt "kludge" geëvenaard, maar
de vorige "mega-" hangt nog steeds rond aan het begin van yytekst dus de ECHO
want de "kludge"-regel zal feitelijk "mega-kludge" schrijven.

Twee opmerkingen over het gebruik van meer(). Eerste, meer() hangt af van de waarde van yeleng
correct de grootte van het huidige token weergeeft, dus u mag deze niet wijzigen yeleng als je
gebruiken meer(). Ten tweede, de aanwezigheid van meer() in de actie van de scanner omvat a
kleine prestatievermindering in de matchingsnelheid van de scanner.

- yloos(n) geeft alles terug, behalve de eerste n tekens van het huidige token terug naar de
invoerstroom, waar ze opnieuw worden gescand wanneer de scanner naar de volgende zoekt
overeenkomen. yytekst en yeleng op de juiste manier zijn aangepast (bijv. yeleng zal nu zijn
gelijk aan n ). Op de invoer "foobar" wordt bijvoorbeeld het volgende geschreven
"foobarbar":

%%
foobar ECHO; zonder(3);
[az]+ECHO;

Een argument van 0 tot zonder zorgt ervoor dat de gehele huidige invoerreeks wordt gescand
opnieuw. Tenzij u hebt gewijzigd hoe de scanner vervolgens de invoer verwerkt
(met behulp van BEGINNEN, bijvoorbeeld), zal dit resulteren in een eindeloze lus.

Merk op dat zonder is een macro en kan alleen worden gebruikt in het flex-invoerbestand, niet vanuit andere bestanden
bronbestanden.

- ongedaan maken(c) zet het karakter c terug naar de invoerstroom. Het zal de volgende zijn
teken gescand. De volgende actie zal het huidige token nemen en dit veroorzaken
om opnieuw te scannen, tussen haakjes.

{
int i;
/* Kopieer yytext omdat unput() yytext weggooit */
char *yycopy = strdup( yytekst);
ongedaan maken( ')');
voor ( i = yyleng - 1; ik >= 0; --i )
unput( yykopie[i] );
unput( '(');
gratis( yykopie );
}

Merk op dat sinds elk ongedaan maken() plaatst het gegeven karakter terug op de begin van de
inputstroom, het terugduwen van strings moet van achteren naar voren worden gedaan.

Een belangrijk potentieel probleem bij het gebruik ongedaan maken() is dat als je gebruikt %wijzer (De
standaard), een oproep naar ongedaan maken() vernietigt de inhoud van yytekst, te beginnen met de meest rechtse
personage en verslindt bij elke oproep één personage naar links. Als je de waarde nodig hebt
van yytext bewaard na een oproep naar ongedaan maken() (zoals in het bovenstaande voorbeeld), moet u een van beide doen
kopieer het eerst ergens anders, of bouw uw scanner met behulp van %matrix in plaats daarvan (zie Hoe de invoer is
Op elkaar afgestemd).

Houd er ten slotte rekening mee dat u het niet terug kunt plaatsen EOF om te proberen de invoerstroom te markeren met een
einde van het bestand.

- invoer() leest het volgende teken uit de invoerstroom. Bijvoorbeeld het volgende
is een manier om C-opmerkingen op te eten:

%%
"/*" {
intc;

voor ( ; ; )
{
terwijl ( (c = invoer()) != '*' &&
c != EOF )
; /* eet tekst van commentaar op */

als ( c == '*' )
{
terwijl ( (c = invoer()) == '*' )
;
als ( c == '/' )
pauze; /* het einde gevonden */
}

als ( c == EOF )
{
error("EOF in commentaar");
te breken;
}
}
}

(Merk op dat als de scanner is gecompileerd met behulp van C ++, harte invoer() wordt in plaats daarvan verwezen
als yyinvoer(), om een ​​naamconflict met de C + + streamen met de naam
invoer.)

- YY_FLUSH_BUFFER leegt de interne buffer van de scanner, zodat de volgende keer dat het
scanner probeert een token te matchen, zal eerst de buffer worden bijgevuld met behulp van JJ_INPUT
(zie De gegenereerde scanner hieronder). Deze actie is een speciaal geval van meer
algemeen yy_flush_buffer() functie, hieronder beschreven in de sectie Meerdere invoer
buffers.

- yyterminate() kan worden gebruikt in plaats van een return-instructie in een actie. Het
beëindigt de scanner en retourneert een 0 naar de beller van de scanner, wat aangeeft "all
klaar". Standaard is yyterminate() wordt ook aangeroepen als er sprake is van end-of-file
tegengekomen. Het is een macro en kan opnieuw worden gedefinieerd.

HET GEGENEREERD SCANNER


De uitvoer van buigen is het bestand? lex.jj.c, die de scanroutine bevat yylex(), a
aantal tabellen die het gebruikt voor het matchen van tokens, en een aantal hulproutines en
macro's. Standaard, yylex() wordt als volgt verklaard:

int yylex()
{
... verschillende definities en de acties hier ...
}

(Als uw omgeving functieprototypes ondersteunt, is dit "int yylex( void )".)
Deze definitie kan worden gewijzigd door de macro "YY_DECL" te definiëren. Dat zou je bijvoorbeeld kunnen doen
gebruiken:

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

om de scanroutine een naam te geven Lexscan, een vlotter retourneren, en twee vlotters nemen als
argumenten. Merk op dat als u argumenten aan de scanroutine geeft met behulp van een K&R-stijl/niet-
geprototypeerde functiedeclaratie, moet u de definitie afsluiten met een puntkomma (;).

Telkens als yylex() wordt aangeroepen, scant het tokens uit het globale invoerbestand yyin (welke
standaard ingesteld op stdin). Het gaat door totdat het een einde van het bestand bereikt (op welk punt
het retourneert de waarde 0) of een van zijn acties voert a uit terugkeer verklaring.

Als de scanner het einde van het bestand bereikt, zijn daaropvolgende aanroepen ongedefinieerd, tenzij een van beide yyin
wordt verwezen naar een nieuw invoerbestand (in welk geval het scannen verdergaat vanaf dat bestand), of
yyherstart() wordt genoemd. yyherstart() neemt één argument, a FILE * aanwijzer (wat kan zijn
nul, als je het hebt ingesteld JJ_INPUT scannen vanaf een andere bron dan yyin), en initialiseert
yyin voor het scannen van dat bestand. In wezen is er geen verschil tussen gewoon
toewijzen yyin naar een nieuw invoerbestand of met behulp van yyherstart() om dit te doen; deze laatste is beschikbaar
voor compatibiliteit met eerdere versies van buigen, en omdat je er mee kunt schakelen
invoerbestanden tijdens het scannen. Het kan ook worden gebruikt om de stroom weg te gooien
invoerbuffer, door deze aan te roepen met een argument van yyin; maar beter is om te gebruiken YY_FLUSH_BUFFER
(zie hierboven). Let daar op yyherstart() doet niet reset de startvoorwaarde naar EERSTE (Zie
Startvoorwaarden, hieronder).

If yylex() stopt met scannen vanwege het uitvoeren van een terugkeer verklaring in een van de acties, de
De scanner kan dan opnieuw worden opgeroepen en hervat het scannen waar hij was gebleven.

Standaard (en uit oogpunt van efficiëntie) gebruikt de scanner bloklezen in plaats van
simpel haal() oproepen om tekens uit te lezen yyin. De aard van de manier waarop het zijn input krijgt, kan dat wel zijn
gecontroleerd worden door het definiëren van de JJ_INPUT macro. De aanroepreeks van YY_INPUT is
"JJ_INPUT(buf,resultaat,max_grootte)". Zijn actie is om tot max_grootte karakters in de
tekenreeks buf en retourneer de integer-variabele resultaat ofwel het aantal
gelezen tekens of de constante YY_NULL (0 op Unix-systemen) om EOF aan te geven. De standaard
YY_INPUT leest van de globale bestandsaanwijzer "yyin".

Een voorbeelddefinitie van YY_INPUT (in het definitiegedeelte van het invoerbestand):

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

Deze definitie verandert de invoerverwerking zodat deze karakter voor teken plaatsvindt.

Wanneer de scanner een indicatie voor het einde van het bestand ontvangt van YY_INPUT, controleert deze vervolgens de
yywrap() functie. Als yywrap() retourneert false (nul), dan wordt aangenomen dat de functie
is doorgegaan en opgezet yyin om naar een ander invoerbestand te verwijzen, en het scannen gaat door. Als
het retourneert waar (niet-nul), waarna de scanner wordt beëindigd en 0 terugkeert naar de beller. Opmerking
dat in beide gevallen de startvoorwaarde ongewijzigd blijft; het doet niet terugkeren naar VOORLETTER.

Als u niet uw eigen versie van jjwrap(), dan moet je een van beide gebruiken %keuze
noyywrap (In dat geval gedraagt ​​de scanner zich alsof yywrap() geretourneerd 1), of je moet
link met -NS om de standaardversie van de routine te verkrijgen, die altijd 1 retourneert.

Er zijn drie routines beschikbaar voor het scannen vanuit buffers in het geheugen in plaats van vanuit bestanden:
yy_scan_string(), yy_scan_bytes(), en yy_scan_buffer(). Zie de bespreking ervan hieronder
in de sectie Meerdere invoerbuffers.

De scanner schrijft zijn ECHO uitvoer naar de ja jij global (standaard, stdout), wat mogelijk is
opnieuw gedefinieerd door de gebruiker, simpelweg door het aan iemand anders toe te wijzen FILE wijzer.

Start het spel ZIEKTEBEELDEN


buigen biedt een mechanisme voor het voorwaardelijk activeren van regels. Elke regel waarvan het patroon is
voorafgegaan door " " zal alleen actief zijn als de scanner zich in de genoemde startvoorwaarde bevindt
"sc". Bijvoorbeeld,

[^"]* { /* eet het snaarlichaam op ... */
...
}

zal alleen actief zijn als de scanner zich in de startvoorwaarde "STRING" bevindt, en

\. { /* zorg voor een ontsnapping ... */
...
}

zal alleen actief zijn als de huidige startvoorwaarde "INITIAL", "STRING" of
"CITAAT".

Startvoorwaarden worden gedeclareerd in de definities (eerste) sectie van de invoer met behulp van
niet-ingesprongen regels die met een van beide beginnen %s or %x gevolgd door een lijst met namen. De voormalige
verklaart inclusief startvoorwaarden, de laatste exclusief startvoorwaarden. Een start
voorwaarde wordt geactiveerd met behulp van de BEGINNEN actie. Tot de volgende BEGINNEN actie wordt uitgevoerd,
regels met de gegeven startvoorwaarde zullen actief zijn en regels met andere startvoorwaarden
zal inactief zijn. Als de startvoorwaarde is inclusief, dan regeert zonder begin
omstandigheden zullen ook actief zijn. Als het is exclusief, harte Slechts regels waar mee gekwalificeerd is
de startvoorwaarde is actief. Een reeks regels die afhankelijk zijn van dezelfde exclusieve start
voorwaarde beschrijft een scanner die onafhankelijk is van een van de andere regels in de buigen
invoer. Hierdoor maken exclusieve startvoorwaarden het eenvoudig om ‘mini-
scanners" die delen van de invoer scannen die syntactisch verschillen van de rest
(bijvoorbeeld opmerkingen).

Als het onderscheid tussen inclusieve en exclusieve startvoorwaarden nog steeds klein is
vaag, hier is een eenvoudig voorbeeld dat het verband tussen de twee illustreert. Het stel van
reglement:

%s voorbeeld
%%

foo doe_iets();

bar iets_else();

is gelijk aan

%x voorbeeld
%%

foo doe_iets();

bar iets_else();

Zonder de kwalificatie, de bars het patroon in het tweede voorbeeld zou dat niet zijn
actief (dat wil zeggen, kon niet overeenkomen) in de startconditie voorbeeld. Als we het maar gebruikten
kwalificeren bar, maar dan zou het alleen actief zijn in voorbeeld en niet in VOORLETTER, en
in het eerste voorbeeld is het in beide actief, omdat in het eerste voorbeeld de voorbeeld begin
voorwaarde is een inclusief (%S) start conditie.

Houd er ook rekening mee dat de speciale startconditiespecificatie <*> voldoet aan elke startvoorwaarde.
Het bovenstaande voorbeeld had dus ook geschreven kunnen worden;

%x voorbeeld
%%

foo doe_iets();

<*>bar iets_else();

De standaardregel (to ECHO elk ongeëvenaard karakter) blijft actief in startomstandigheden. Het
is gelijk aan:

<*>.|\n ECHO;

BEGINNEN(0) keert terug naar de oorspronkelijke staat waar alleen de regels zonder startvoorwaarden zijn
actief. Deze toestand kan ook wel de startvoorwaarde "INITIAL" worden genoemd
BEGIN(INITIEEL) is gelijk aan BEGINNEN(0). (De haakjes rond de startvoorwaarde
naam zijn niet verplicht, maar worden als een goede stijl beschouwd.)

BEGINNEN acties kunnen ook als ingesprongen code aan het begin van het regelgedeelte worden gegeven.
Het volgende zorgt er bijvoorbeeld voor dat de scanner in de startvoorwaarde "SPECIAL" terechtkomt
telkens als yylex() wordt aangeroepen en de globale variabele enter_speciaal is waar:

int enter_special;

%x SPECIAAL
%%
als ( enter_special )
BEGIN(SPECIAAL);

blablabla
...er volgen meer regels...

Om het gebruik van startvoorwaarden te illustreren, is hier een scanner die twee verschillende biedt
interpretaties van een string als "123.456". Standaard behandelt het het als drie tokens,
het gehele getal "123", een punt ('.') en het gehele getal "456". Maar als de string voorafgegaan wordt
eerder in de regel bij de string "expect-floats" zal het het als een enkel token behandelen, de
drijvende-kommagetal 123.456:

%{
# omvatten
%}
%s verwachten

%%
verwachten-zweeft BEGIN(verwachten);

[0-9]+"."[0-9]+ {
printf( "een vlotter gevonden, = %f\n",
atof(yytekst));
}
\N {
/* dat is het einde van de regel, dus
* we hebben nog een "verwacht-nummer" nodig
* voordat we er nog meer herkennen
* cijfers
*/
BEGIN(INITIEEL);
}

[0-9]+ {
printf( "een geheel getal gevonden, = %d\n",
atoi( yytekst ) );
}

"." printf("een punt gevonden\n" );

Hier is een scanner die C-opmerkingen herkent (en weggooit) terwijl het aantal wordt bijgehouden
de huidige invoerregel.

%x reactie
%%
int regel_getal = 1;

"/*" BEGIN(opmerking);

[^*\n]* /* eet alles dat geen '*' is */
"*"+[^*/\n]* /* opeten '*'s niet gevolgd door '/'s */
\n ++regelnummer;
"*"+"/" BEGIN(INITIEEL);

Deze scanner doet een beetje moeite om zoveel mogelijk tekst aan elke regel te koppelen.
Over het algemeen moet u bij het schrijven van een hogesnelheidsscanner zoveel mogelijk proberen te matchen
elke regel, want het is een grote overwinning.

Merk op dat de namen van startvoorwaarden in werkelijkheid gehele waarden zijn en als zodanig kunnen worden opgeslagen.
Het bovenstaande zou dus op de volgende manier kunnen worden uitgebreid:

%x reactie foo
%%
int regel_getal = 1;
int comment_beller;

"/*" {
comment_caller = EERSTE;
BEGIN(opmerking);
}

...

"/*" {
comment_beller = foo;
BEGIN(opmerking);
}

[^*\n]* /* eet alles dat geen '*' is */
"*"+[^*/\n]* /* opeten '*'s niet gevolgd door '/'s */
\n ++regelnummer;
"*"+"/" BEGIN(commentaar_aanroeper);

Bovendien kunt u toegang krijgen tot de huidige startvoorwaarde met behulp van de waarde geheel getal JJ_START
macro. Bovenstaande opdrachten zijn bijvoorbeeld aan commentaar_beller in plaats daarvan geschreven zou kunnen worden

comment_beller = YY_START;

Flex biedt YYSTAAT als een alias voor JJ_START (aangezien dat is wat AT&T gebruikt les).

Merk op dat startvoorwaarden geen eigen naamruimte hebben; %s's en %x's declareren namen
op dezelfde manier als die van #define.

Ten slotte is hier een voorbeeld van hoe u C-stijl tekenreeksen tussen aanhalingstekens kunt matchen met behulp van exclusieve start
voorwaarden, inclusief uitgebreide escape-reeksen (maar exclusief het controleren op een string
dat is te lang):

%x str

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

\" string_buf_ptr = string_buf; BEGIN(str);

\" { /* zag slotcitaat - alles klaar */
BEGIN(INITIEEL);
*string_buf_ptr = '\0';
/* return tekenreeks constant tokentype en
* waarde voor parser
*/
}

\N {
/* fout - niet-afgesloten tekenreeksconstante */
/* foutmelding genereren */
}

\\[0-7]{1,3} {
/* octale ontsnappingsreeks */
int-resultaat;

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

als ( resultaat > 0xff )
/* fout, constante is buiten bereik */

*string_buf_ptr++ = resultaat;
}

\\[0-9]+ {
/* fout genereren - slechte ontsnappingsreeks; iets
* zoals '\48' of '\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++ = yytekst[1];

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

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

Vaak, zoals in sommige van de bovenstaande voorbeelden, eindig je met het schrijven van een hele reeks regels
allemaal voorafgegaan door dezelfde startvoorwaarde(n). Flex maakt dit een beetje eenvoudiger en schoner
door een notie van startvoorwaarde te introduceren reikwijdte. Een startvoorwaardebereik begint met:

{

WAAR SC's is een lijst met een of meer startvoorwaarden. Binnen het bereik van de startvoorwaarden,
elke regel heeft automatisch het voorvoegsel erop toegepast, totdat a '}' die past bij de
eerste '{'. Dus bijvoorbeeld

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

is gelijk aan:

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

Startvoorwaardebereiken kunnen genest zijn.

Er zijn drie routines beschikbaar voor het manipuleren van stapels startvoorwaarden:

komen te vervallen yy_push_state(int nieuwe_staat)
duwt de huidige startvoorwaarde naar de bovenkant van de startvoorwaardestapel en
schakelt naar nieuwe_staat alsof je het had gebruikt BEGINNEN nieuwe_staat (denk aan dat begin
voorwaardenamen zijn ook gehele getallen).

komen te vervallen jj_pop_state()
springt bovenaan de stapel en schakelt ernaar toe via BEGINNEN.

int yy_top_state()
geeft de bovenkant van de stapel terug zonder de inhoud van de stapel te wijzigen.

De startconditiestapel groeit dynamisch en heeft dus geen ingebouwde groottebeperking. Als
het geheugen is uitgeput en de uitvoering van het programma wordt afgebroken.

Om startvoorwaardestapels te gebruiken, moet uw scanner een %keuze stack richtlijn (zie
Opties hieronder).

MEERDERE INVOER BUFFERS


Sommige scanners (zoals die welke "include"-bestanden ondersteunen) vereisen het lezen van meerdere
invoerstromen. Als buigen scanners doen een grote hoeveelheid buffering, je kunt niet bepalen waar
de volgende invoer wordt gelezen door simpelweg a te schrijven JJ_INPUT die gevoelig is voor de
context scannen. JJ_INPUT wordt alleen aangeroepen als de scanner het einde van zijn buffer bereikt,
wat lang kan duren na het scannen van een verklaring, zoals een "include", waarvoor dit vereist is
omschakelen van de ingangsbron.

Om over dit soort problemen te onderhandelen, buigen biedt een mechanisme voor het maken en schakelen
tussen meerdere invoerbuffers. Een invoerbuffer wordt gemaakt met behulp van:

YY_BUFFER_STATE yy_create_buffer( BESTAND *bestand, int-grootte )

waarvoor een FILE pointer en een grootte en creëert een buffer die bij het gegeven bestand hoort
en groot genoeg om vast te houden grootte tekens (gebruik bij twijfel JJ_BUF_SIZE voor de maat).
Het retourneert een JJ_BUFFER_STATE handle, die vervolgens kan worden doorgegeven aan andere routines (zie
onderstaand). De JJ_BUFFER_STATE type is een verwijzing naar een ondoorzichtige struct yy_buffer_status
structuur, zodat u YY_BUFFER_STATE variabelen veilig kunt initialiseren ((YY_BUFFER_STATE) 0)
als u dat wenst, en raadpleeg ook de ondoorzichtige structuur om de invoer correct te declareren
buffers in andere bronbestanden dan die van uw scanner. Merk op dat de FILE wijzer naar binnen
de oproep naar yy_create_buffer wordt alleen gebruikt als de waarde van yyin zichtbaar JJ_INPUT; als je
herdefiniëren JJ_INPUT dus hij wordt niet meer gebruikt yyin, dan kun je gerust een nul passeren FILE wijzer
naar yy_create_buffer. U selecteert een bepaalde buffer waaruit u wilt scannen met behulp van:

void yy_switch_to_buffer( YY_BUFFER_STATE nieuwe_buffer )

schakelt de invoerbuffer van de scanner zodat volgende tokens vandaan komen nieuwe_buffer. Note
dat yy_switch_to_buffer() kan door yywrap() worden gebruikt om dingen in te stellen voor vervolg
scannen, in plaats van een nieuw bestand te openen en aan te wijzen yyin erbij. Let ook op dat schakelen
invoerbronnen via beide yy_switch_to_buffer() or yywrap() doet niet verander het begin
staat.

void yy_delete_buffer( YY_BUFFER_STATE buffer )

wordt gebruikt om de opslag terug te winnen die aan een buffer is gekoppeld. ( buffer kan nul zijn, waarbij
als de routine niets doet.) U kunt ook de huidige inhoud van een buffer wissen
met:

void yy_flush_buffer( YY_BUFFER_STATE buffer )

Deze functie negeert de inhoud van de buffer, dus de volgende keer dat de scanner dit probeert
overeenkomen met een token uit de buffer, zal deze eerst de buffer opnieuw vullen met behulp van JJ_INPUT.

yy_new_buffer() is een alias voor yy_create_buffer(), voorzien voor compatibiliteit met de
C++ gebruik van nieuwe en verwijderen voor het maken en vernietigen van dynamische objecten.

Ten slotte JJ_CURRENT_BUFFER macro retourneert een JJ_BUFFER_STATE omgaan met de stroom
buffer.

Hier is een voorbeeld van het gebruik van deze functies voor het schrijven van een scanner die zich uitbreidt
bestanden (de < > functie wordt hieronder besproken):

/* de status "incl" wordt gebruikt voor het ophalen van de naam
* van een include-bestand
*/
%x inbegrepen

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

%%
omvatten BEGIN(incl);

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

[ \t]* /* eet de witruimte */
[^ \t\n]+ { /* heeft de include-bestandsnaam */
if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
fprintf( stderr, "Inclusief te diep genest" );
uitgang( 1 );
}

include_stack[include_stack_ptr++] =
JJ_CURRENT_BUFFER;

yyin = fopen( yytekst, "r" );

als (! yyin)
fout( ... );

yy_switch_to_buffer(
yy_create_buffer(yyin, YY_BUF_SIZE ) );

BEGIN(INITIEEL);
}

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

anders
{
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(
include_stack[include_stack_ptr]);
}
}

Er zijn drie routines beschikbaar voor het instellen van invoerbuffers voor het scannen van tekenreeksen in het geheugen
in plaats van bestanden. Ze creëren allemaal een nieuwe invoerbuffer voor het scannen van de string, en
een overeenkomstig terugsturen JJ_BUFFER_STATE handle (die je moet verwijderen met
yy_delete_buffer() als je er klaar mee bent). Ze schakelen ook over naar de nieuwe buffer met behulp van
yy_switch_to_buffer(), dus het volgende telefoontje naar yylex() zal beginnen met het scannen van de string.

yy_scan_string(const verkolen *str)
scant een NUL-afgesloten tekenreeks.

yy_scan_bytes(const verkolen *bytes, int len)
scant len bytes (inclusief mogelijk NUL's) beginnend op locatie bytes.

Merk op dat beide functies een kopiëren van de string of bytes. (Dit
kan wenselijk zijn, aangezien yylex() wijzigt de inhoud van de buffer die wordt gescand.) You
kunt de kopie vermijden door gebruik te maken van:

yy_scan_buffer(char *baseren, jj_maat_t grootte)
die de buffer op zijn plaats scant, beginnend bij baseren, bestaande uit grootte bytes, de
waarvan de laatste twee bytes Dan moet je be YY_END_OF_BUFFER_CHAR (ASCII NUL). Deze laatste twee
bytes worden niet gescand; scannen bestaat dus uit basis[0] door basis [maat-2],
inclusive.

Als het niet lukt om in te stellen baseren op deze manier (dat wil zeggen, vergeet de laatste twee
YY_END_OF_BUFFER_CHAR bytes), dan yy_scan_buffer() retourneert in plaats daarvan een nulaanwijzer
van het creëren van een nieuwe invoerbuffer.

Het type jj_maat_t is een integraaltype waarnaar u een geheeltallige expressie kunt casten
weerspiegelt de grootte van de buffer.

EINDE VAN BESTAND REGLEMENT


De speciale regel "< >" geeft acties aan die moeten worden ondernomen wanneer een bestand einde is
aangetroffen en yywrap() retourneert niet-nul (dat wil zeggen, geeft aan dat er geen verdere bestanden zijn om te verwerken).
De actie moet eindigen door een van de volgende vier dingen te doen:

- toewijzen yyin naar een nieuw invoerbestand (in eerdere versies van flex, na het uitvoeren van de
opdracht die je de speciale actie moest noemen JJ_NEW_FILE; dit is niet langer
nodig);

- het uitvoeren van een terugkeer uitspraak;

- het uitvoeren van de special yyterminate() actie;

- of, overschakelen naar een nieuwe buffer met behulp van yy_switch_to_buffer() zoals weergegeven in het voorbeeld
bovenstaand.

< > regels mogen niet worden gebruikt bij andere patronen; ze kunnen alleen worden gekwalificeerd met een lijst
van startvoorwaarden. Als een niet-gekwalificeerde < >regel gegeven is, waarop deze van toepassing is allen begin
voorwaarden die nog geen < > acties. Om een ​​< > regel voor alleen
de initiële startvoorwaarde, gebruik

< >

Deze regels zijn handig voor het onderscheppen van zaken als niet-gesloten opmerkingen. Een voorbeeld:

%x citaat
%%

...andere regels voor het omgaan met offertes...

< > {
error("niet-beëindigde quote");
yyterminate();
}
< > {
if ( *++bestandslijst )
yyin = fopen( *bestandslijst, "r" );
anders
yyterminate();
}

DIVERSE MACRO'S


de macro JJ_USER_ACTION kan worden gedefinieerd om een ​​actie te bieden die altijd wordt uitgevoerd
voorafgaand aan de actie van de overeenkomende regel. Het kan bijvoorbeeld #define'd zijn om een ​​routine aan te roepen
om yytext naar kleine letters te converteren. Wanneer JJ_USER_ACTION wordt aangeroepen, de variabele jj_act
geeft het nummer van de overeenkomende regel (regels zijn genummerd vanaf 1). Stel je voor
wilt profileren hoe vaak elk van uw regels overeenkomt. Het volgende zou het doen
truc:

#define YY_USER_ACTION ++ctr[yy_act]

WAAR ctr is een array waarin de tellingen voor de verschillende regels worden bewaard. Merk op dat de macro
JJ_NUM_RULES geeft het totale aantal regels (inclusief de standaardregel, zelfs als u gebruik maakt van
-S), dus een correcte aangifte voor ctr is:

int ctr[YY_NUM_RULES];

de macro JJ_USER_INIT kan worden gedefinieerd om een ​​actie te bieden die altijd eerder wordt uitgevoerd
de eerste scan (en voordat de interne initialisaties van de scanner zijn voltooid). Bijvoorbeeld,
het kan worden gebruikt om een ​​routine aan te roepen om een ​​gegevenstabel in te lezen of een logbestand te openen.

de macro yy_set_interactive(is_interactief) kan worden gebruikt om te controleren of de stroom
buffer wordt beschouwd interactief. Een interactieve buffer wordt langzamer verwerkt, maar
moet worden gebruikt als de invoerbron van de scanner inderdaad interactief is om problemen te voorkomen
tot het wachten om buffers te vullen (zie de bespreking van de -I vlag hieronder). Een waarde die niet nul is in
de macro-aanroep markeert de buffer als interactief, een nulwaarde als niet-interactief.
Houd er rekening mee dat het gebruik van deze macro voorrang heeft %keuze interactieve , %keuze altijd interactief or
%keuze nooit interactief (zie Opties hieronder). yy_set_interactive() moet vooraf worden ingeroepen
om te beginnen met het scannen van de buffer die (of niet) als interactief moet worden beschouwd.

de macro jj_set_bol(op_bol) kan worden gebruikt om te controleren of de huidige buffer wordt gescand
context voor de volgende tokenmatch wordt gedaan alsof aan het begin van een regel. Een niet-nul
macro-argument maakt regels verankerd met

de macro JJ_AT_BOL() retourneert waar als het volgende token dat vanuit de huidige buffer wordt gescand, dat ook doet
hebben '^'-regels actief, anders false.

In de gegenereerde scanner worden de acties allemaal verzameld in één grote switch-instructie en
gescheiden gebruik JJ_BREAK, die opnieuw gedefinieerd kan worden. Standaard is het gewoon een "pauze", om
scheid de actie van elke regel van die van de volgende regel. Herdefiniëren JJ_BREAK toestaan ​​voor
C++-gebruikers moeten bijvoorbeeld #define YY_BREAK gebruiken om niets te doen (terwijl ze heel voorzichtig zijn dat every
regel eindigt met een "break" of een "return") om te voorkomen dat u last krijgt van een onbereikbare verklaring
waarschuwingen waarbij, omdat de actie van een regel eindigt met "return", de JJ_BREAK ontoegankelijk is.

WAARDEN BESCHIKBAAR TO HET GEBRUIKER


In deze sectie worden de verschillende waarden samengevat die beschikbaar zijn voor de gebruiker in de regelacties.

- verkolen *yytekst bevat de tekst van het huidige token. Het kan gewijzigd worden, maar niet
verlengd (u kunt geen tekens aan het einde toevoegen).

Als de bijzondere richtlijn %matrix verschijnt in het eerste gedeelte van de scanner
omschrijving dan yytekst wordt in plaats daarvan verklaard verkolen yytekst[YYLMAX], WAAR YYLMAX is een
macrodefinitie die u in de eerste sectie opnieuw kunt definiëren als u de
standaardwaarde (doorgaans 8 KB). Gebruik makend van %matrix resulteert in iets langzamere scanners,
maar de waarde van yytekst wordt immuun voor oproepen naar invoer() en ongedaan maken(), welke
mogelijk de waarde ervan vernietigen wanneer yytekst is een karakteraanwijzer. Het tegenovergestelde van
%matrix is %wijzer, wat de standaard is.

U kunt niet gebruiken %matrix bij het genereren van C++-scannerklassen (de -+ vlag).

- int yeleng bevat de lengte van het huidige token.

- FILE *yyin is het bestand dat standaard buigen leest van. Het kan opnieuw worden gedefinieerd, maar
dit heeft alleen zin voordat het scannen begint of nadat er een EOF is geweest
tegengekomen. Als u dit tijdens het scannen wijzigt, heeft dit onverwachte resultaten
sinds buigen buffert zijn invoer; gebruik yyherstart() in plaats van. Zodra het scannen is beëindigd
omdat er een end-of-file is gezien, kunt u deze toewijzen yyin bij het nieuwe invoerbestand en
bel vervolgens opnieuw de scanner om door te gaan met scannen.

- komen te vervallen jjherstart( FILE *nieuw bestand ) kan ter sprake worden gebracht yyin bij het nieuwe invoerbestand.
De omschakeling naar het nieuwe bestand vindt onmiddellijk plaats (elke eerder gebufferde invoer is
kwijt). Let op dat bellen yyherstart() Met yyin als argument gooit dus de
huidige invoerbuffer en gaat door met het scannen van hetzelfde invoerbestand.

- FILE *jij is het bestand waarnaar ECHO acties worden gedaan. Het kan opnieuw worden toegewezen door
de gebruiker.

- JJ_CURRENT_BUFFER geeft een terug JJ_BUFFER_STATE handle naar de huidige buffer.

- JJ_START retourneert een geheel getal dat overeenkomt met de huidige startvoorwaarde.
Deze waarde kunt u vervolgens gebruiken met BEGINNEN om terug te keren naar die starttoestand.

INTERFACE MET YACC


Een van de belangrijkste toepassingen van buigen is als metgezel van de jacc parser-generator. jacc parser
verwacht een routine met de naam aan te roepen yylex() om het volgende invoertoken te vinden. De routine is
Het is de bedoeling dat het het type van het volgende token retourneert en dat de bijbehorende waarde wordt ingevoerd
de globale yylval. Te gebruiken buigen Met Jacc, men specificeert de -d optie om jacc instrueren
om het bestand te genereren y.tab.h met definities van alle %Munten verschijnen in de
jacc invoer. Dit bestand wordt vervolgens opgenomen in het buigen scanner. Als bijvoorbeeld een van de
tokens is "TOK_NUMBER", een deel van de scanner kan er als volgt uitzien:

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

%%

[0-9]+ yylval = atoi( yytekst ); retour TOK_NUMBER;

OPTIES


buigen heeft de volgende opties:

-B, --back-up
Genereer back-upinformatie voor lex.back-up. Dit is een lijst met scannerstatussen
waarvoor een back-up nodig is en de invoertekens waarop ze dit doen. Door toe te voegen
regels kan men back-upstatussen verwijderen. Als allen back-upstaten worden geëlimineerd
en -Vgl or CF wordt gebruikt, zal de gegenereerde scanner sneller werken (zie de -p vlag).
Alleen gebruikers die elke laatste cyclus uit hun scanners willen halen, hoeven zich zorgen te maken
over deze optie. (Zie het gedeelte over prestatieoverwegingen hieronder.)

-c is een verouderde, nietsdoende optie die is opgenomen voor POSIX-compliance.

-NS, --debuggen
laat de gegenereerde scanner inlopen debug modus. Wanneer een patroon wordt herkend
en het globale yy_flex_debug niet nul is (wat de standaardinstelling is), zal de scanner dat doen
Schrijven aan stderr een regel van de vorm:

--acceptatieregel op regel 53 ("de overeenkomende tekst")

Het regelnummer verwijst naar de locatie van de regel in het bestand dat de scanner definieert
(dat wil zeggen, het bestand dat naar flex is ingevoerd). Er worden ook berichten gegenereerd wanneer de
scanner maakt een back-up, accepteert de standaardregel, bereikt het einde van zijn invoerbuffer (of
stuit op een NUL; op dit punt zien de twee er hetzelfde uit als die van de scanner
betrokken), of bereikt een einde van het bestand.

-F, --vol
specificeert snel scanner. Er wordt geen tabelcompressie uitgevoerd en stdio wordt omzeild. De
resultaat is groot maar snel. Deze optie is gelijk aan -Cfr (zie hieronder).

-H, --help
genereert een "help"-samenvatting van flex's opties om stdout en gaat dan uit. -? en
--help zijn synoniemen voor -H.

-l, --hoofdlettergevoelig
instrueert buigen om een ​​te genereren hoofdlettergevoelig scanner. Het geval van gegeven brieven
in de buigen invoerpatronen worden genegeerd en tokens in de invoer worden gematcht
ongeacht het geval. De overeenkomende tekst die is opgegeven yytekst zal de bewaarde koffer hebben
(dat wil zeggen, het wordt niet gevouwen).

-ik, --lex-compatibel
zorgt voor maximale compatibiliteit met de originele AT&T lex implementatie. Opmerking
dat dit niet betekent vol compatibiliteit. Het gebruik van deze optie kost a
aanzienlijke hoeveelheid prestaties, en het kan niet worden gebruikt met de -+, -F, -F, -Cf,
or CF opties. Zie de sectie voor meer informatie over de compatibiliteit die het biedt
"Incompatibiliteiten met Lex en POSIX" hieronder. Deze optie resulteert ook in de naam
YY_FLEX_LEX_COMPAT wordt #define'd in de gegenereerde scanner.

-n is een andere nietsdoende, verouderde optie die alleen is opgenomen voor POSIX-compliance.

-P, --perf-rapport
genereert een prestatierapport naar stderr. Het rapport bestaat uit opmerkingen
over de kenmerken van de buigen invoerbestand, wat een ernstig verlies van
prestaties in de resulterende scanner. Als je de vlag twee keer geeft, doe je dat ook
ontvang opmerkingen over functies die tot kleine prestatieverliezen leiden.

Houd er rekening mee dat het gebruik van AFWIJZEN, %keuze yylineno, en variabele volgcontext (zie
het gedeelte Tekortkomingen / Bugs hieronder) brengt een aanzienlijke prestatiestraf met zich mee;
gebruik van meer(), de ^ bediener, en de -I vlag kleine prestaties met zich meebrengen
sancties.

-Ja, --geen standaard
veroorzaakt de verzuim regeren (die ongeëvenaarde scannerinvoer wordt herhaald stoer) te
onderdrukt. Als de scanner invoer tegenkomt die niet overeenkomt met een van de regels,
het wordt afgebroken met een fout. Deze optie is handig voor het vinden van gaten in scanners
regel ingesteld.

-T, --stdout
instrueert buigen om de scanner die het genereert naar standaarduitvoer te schrijven in plaats van
lex.jj.c.

-in, --uitgebreid
specificeert dat buigen naar moeten schrijven stderr een samenvatting van statistieken over de
scanner die het genereert. De meeste statistieken zijn betekenisloos voor de gewone man buigen
gebruiker, maar de eerste regel identificeert de versie van buigen (hetzelfde als gemeld door -V),
en op de volgende regel de vlaggen die zijn gebruikt bij het genereren van de scanner, inclusief de vlaggen die
zijn standaard ingeschakeld.

-w, --nu
onderdrukt waarschuwingsberichten.

-B, --partij
instrueert buigen om een ​​te genereren partij scanner, het tegenovergestelde van interactieve scanners
gegenereerd door -I (zie hieronder). Over het algemeen gebruik je -B als je bent zeker die uw
scanner zal nooit interactief worden gebruikt, en u wilt een Elke kleine stap levert grote resultaten op! meer
prestaties eruit. Als het in plaats daarvan uw doel is om er een uit te persen lot meer
prestaties, zou u de -Vgl or CF opties (hieronder besproken), welke
aanzetten -B toch automatisch.

-F, --snel
specificeert dat de snel Er moet gebruik worden gemaakt van een scannertabelrepresentatie (en stdio
omzeild). Deze weergave is ongeveer net zo snel als de volledige tabelweergave
(-F), en voor sommige reeksen patronen zal dit aanzienlijk kleiner zijn (en voor andere
groter). Als de patroonset zowel ‘trefwoorden’ als een allesomvattend bestand bevat,
"identifier"-regel, zoals in de set:

"case" retourneert TOK_CASE;
"schakelaar" retourneert TOK_SWITCH;
...
"standaard" retourneert TOK_DEFAULT;
[az]+ retourneer TOK_ID;

dan kun je beter de volledige tabelweergave gebruiken. Als alleen de
"identifier"-regel aanwezig is en u gebruikt vervolgens een hashtabel of iets dergelijks om te detecteren
de zoekwoorden kunt u beter gebruiken -F.

Deze optie is gelijk aan -Cfr (zie hieronder). Het kan niet worden gebruikt met -+.

-L, --interactief
instrueert buigen een . genereren interactieve scanner. Een interactieve scanner is er één van
die alleen vooruitkijkt om te beslissen welk token is gematcht als dat absoluut noodzakelijk is.
Het blijkt dat er altijd één extra karakter vooruit wordt gekeken, ook al heeft de scanner dat wel
al genoeg tekst gezien om het huidige token ondubbelzinnig te maken, is iets sneller dan
alleen vooruit kijken als dat nodig is. Maar scanners die altijd vooruit kijken, geven
vreselijke interactieve uitvoering; Wanneer een gebruiker bijvoorbeeld een nieuwe regel typt, is dit het geval
niet herkend als een nieuwelijntoken totdat ze binnenkomen ander token, wat vaak betekent
nog een hele regel typen.

Flex scanners zijn standaard ingesteld op interactieve tenzij je gebruik maakt van de -Vgl or CF tafel-
compressie-opties (zie hieronder). Dat komt omdat als je op zoek bent naar hoge-
prestaties zou u een van deze opties moeten gebruiken, dus als u dat niet deed, buigen
gaat ervan uit dat je liever wat runtime-prestaties inruilt voor intuïtief
interactief gedrag. Merk ook op dat jij kan niet . -I in combinatie met -Vgl or
-CF. Deze optie is dus niet echt nodig; het staat standaard aan voor al deze
gevallen waarin dit is toegestaan.

Merk op dat als isatty () retourneert false voor de scannerinvoer, flex zal terugkeren naar
batchmodus, zelfs als -I werd gespecificeerd. Om de interactieve modus hoe dan ook te forceren,
. %keuze altijd interactief (zie Opties hieronder).

Je kunt een scanner daartoe dwingen niet interactief zijn door te gebruiken -B (zie hierboven).

-L, --geen lijn
instrueert buigen niet te genereren #lijn richtlijnen. Zonder deze optie, buigen paprika's
de gegenereerde scanner met #line-richtlijnen, zodat foutmeldingen in de acties wel voorkomen
correct geplaatst zijn ten opzichte van het origineel buigen invoerbestand (als de
fouten zijn te wijten aan code in het invoerbestand), of lex.jj.c (als de fouten dat zijn flex's
fout - u moet dit soort fouten melden op het onderstaande e-mailadres).

-T, --spoor
merken buigen binnenlopen opsporen modus. Het zal veel berichten genereren stderr
over de vorm van de invoer en de daaruit voortvloeiende niet-deterministische en
deterministische eindige automaten. Deze optie is vooral bedoeld voor onderhoud buigen.

-V, --versie
drukt het versienummer af stdout en uitgangen. --versie is een synoniem voor -V.

-7, -7bit
instrueert buigen om een ​​7-bit scanner te genereren, dat wil zeggen een scanner die alleen kan herkennen
7-bit karakters in de invoer. Het voordeel van gebruiken -7 is dat van de scanner
tabellen kunnen tot de helft zo groot zijn als de tabellen die zijn gegenereerd met behulp van de -8 optie (zie
onderstaand). Het nadeel is dat dergelijke scanners vaak vastlopen of crashen als ze worden ingevoerd
bevat een 8-bits teken.

Houd er echter rekening mee dat, tenzij u uw scanner genereert met behulp van de -Vgl or CF tafel
compressie-opties, gebruik van -7 bespaart slechts een kleine hoeveelheid tafelruimte, en
uw scanner aanzienlijk minder draagbaar maken. Flex's standaardgedrag is om
genereer een 8-bits scanner, tenzij u de -Vgl or -CF, in welk geval buigen
standaard ingesteld op het genereren van 7-bit scanners, tenzij uw site altijd zo was geconfigureerd
8-bit scanners genereren (zoals vaak het geval zal zijn bij niet-Amerikaanse sites). Jij kan
vertel of flex een 7-bit of een 8-bit scanner heeft gegenereerd door de vlag te inspecteren
samenvatting in de -v uitvoer zoals hierboven beschreven.

Houd er rekening mee dat als u -Zie or -Cfe (die opties voor tabelcompressie, maar ook het gebruik van
equivalentieklassen zoals besproken, zie hieronder), flex genereert nog steeds standaard een
8-bit scanner, omdat bij deze compressie-opties meestal volledige 8-bit tabellen beschikbaar zijn
niet veel duurder dan 7-bit tabellen.

-8, -8bit
instrueert buigen om een ​​8-bit scanner te genereren, dat wil zeggen een scanner die 8-bit kan herkennen
karakters. Deze vlag is alleen nodig voor scanners die zijn gegenereerd met -Vgl or -CF, as
anders genereert flex standaard toch een 8-bits scanner.

Zie de bespreking van -7 hierboven voor het standaardgedrag van flex en de afwegingen
tussen 7-bits en 8-bits scanners.

-+, --c++
geeft aan dat u wilt dat flex een C++-scannerklasse genereert. Zie het gedeelte over
Hieronder vindt u het genereren van C++-scanners voor meer informatie.

-C[aefFmr]
regelt de mate van tabelcompressie en, meer in het algemeen, de afwegingen daartussen
kleine scanners en snelle scanners.

-Ca, --uitlijnen ("align") instrueert flex om grotere tabellen in de gegenereerde tabel in te ruilen
scanner voor snellere prestaties omdat de elementen van de tabellen beter zijn
afgestemd op geheugentoegang en berekeningen. Op sommige RISC-architecturen kan fetching
en het manipuleren van lange woorden is efficiënter dan met kleinere eenheden zoals
korte woorden. Met deze optie kan de grootte van de tabellen die door uw scanner worden gebruikt, worden verdubbeld.

-Ce, --ec direct buigen bouwen gelijkwaardigheid klassen, dat wil zeggen, sets karakters
die identieke lexicale eigenschappen hebben (bijvoorbeeld als de enige verschijning van
cijfers in de buigen invoer bevindt zich in de tekenklasse "[0-9]" en vervolgens de cijfers '0',
'1', ..., '9' worden allemaal in dezelfde equivalentieklasse geplaatst). Equivalentieklassen
geven meestal een dramatische vermindering van de bestandsgrootte van de finaletafel/object (doorgaans a
factor 2-5) en zijn qua prestaties behoorlijk goedkoop (één array-look-up per
teken gescand).

-Vgl specificeert dat de vol scannertabellen moeten worden gegenereerd - buigen zou niet
comprimeer de tabellen door gebruik te maken van de voordelen van soortgelijke overgangsfuncties
verschillende staten.

CF specificeert dat de alternatieve snelle scannerweergave (hierboven beschreven
onder de -F vlag) moet worden gebruikt. Deze optie kan niet worden gebruikt met -+.

-Cm, --meta-ecs direct buigen bouwen meta-equivalentie klassen, dat zijn sets
van gelijkwaardigheidsklassen (of tekens, als er geen gelijkwaardigheidsklassen worden gebruikt)
die vaak samen worden gebruikt. Meta-equivalentieklassen zijn vaak een grote overwinning
het gebruik van gecomprimeerde tabellen, maar deze hebben een matige impact op de prestaties (een of twee
"if"-tests en één array-lookup per gescand teken).

-Cr, --lezen zorgt ervoor dat de gegenereerde scanner dit doet bypass gebruik van de standaard I/O-bibliotheek
(stdio) voor invoer. In plaats van te bellen bang() or haal(), de scanner gebruikt de
lezen() systeemoproep, wat resulteert in een prestatiewinst die varieert van systeem tot systeem
systeem, maar is over het algemeen waarschijnlijk te verwaarlozen, tenzij u ook gebruik maakt van -Vgl or -CF.
gebruik -Kr kan vreemd gedrag veroorzaken als je bijvoorbeeld voorleest yyin gebruik
stdio voordat u de scanner aanroept (omdat de scanner elke tekst zal missen
uw vorige lezingen blijven achter in de stdio-invoerbuffer).

-Kr heeft geen effect als u definieert JJ_INPUT (zie De gegenereerde scanner hierboven).

Een eenzame -C specificeert dat de scannertabellen moeten worden gecomprimeerd, maar geen van beide
Er mogen equivalentieklassen noch meta-equivalentieklassen worden gebruikt.

De opties -Vgl or CF en -Cm samen geen zin hebben - er is geen mogelijkheid
voor meta-equivalentieklassen als de tabel niet wordt gecomprimeerd. Anders de
opties kunnen vrijelijk worden gemengd en zijn cumulatief.

De standaardinstelling is -Cem, die dat specificeert buigen gelijkwaardigheid zou moeten genereren
klassen en meta-equivalentieklassen. Deze instelling biedt de hoogste mate van
tafel compressie. U kunt sneller werkende scanners inruilen voor de prijs van
grotere tabellen, waarbij over het algemeen het volgende waar is:

langzaamste en kleinste
-Cem
-Cm
-ce
-C
-C{f,F}e
-C{f,F}
-C{f,F}a
snelste en grootste

Houd er rekening mee dat scanners met de kleinste tabellen meestal worden gegenereerd en gecompileerd
het snelst, dus tijdens de ontwikkeling zult u meestal de standaardwaarde maximaal willen gebruiken
compressie.

-Zie is vaak een goed compromis tussen snelheid en grootte voor productiescanners.

-uitvoer, --outputbestand=BESTAND
geeft flex opdracht om de scanner naar het bestand te schrijven uitgang in plaats van lex.jj.c. als u
combineren -o met de -t optie, waarna naar de scanner wordt geschreven stdout maar haar #lijn
richtlijnen (zie de -L optie hierboven) raadpleeg het bestand uitgang.

-Pvoorvoegsel, --voorvoegsel=STRING
verandert de standaard yy voorvoegsel gebruikt door buigen voor alle globaal zichtbare variabelen en
functienamen moeten in plaats daarvan zijn voorvoegsel. Bijvoorbeeld -Pfoe verandert de naam van yytekst
naar voettekst. Het verandert ook de naam van het standaarduitvoerbestand van lex.jj.c naar
lex.foo.c. Hier zijn alle betrokken namen:

yy_create_buffer
yy_delete_buffer
yy_flex_debug
yy_init_buffer
yy_flush_buffer
yy_load_buffer_state
yy_schakel_naar_buffer
yyin
yeleng
yylex
yylineno
ja jij
yyherstart
yytekst
yywrap

(Alleen als u een C++-scanner gebruikt yywrap en yyFlexLexer zijn aangetast.)
Binnen uw scanner zelf kunt u nog steeds verwijzen naar de globale variabelen en
functies die een van beide versies van hun naam gebruiken; maar extern hebben ze de
gewijzigde naam.

Met deze optie kunt u er eenvoudig meerdere aan elkaar koppelen buigen programma's in hetzelfde
uitvoerbaar. Houd er echter rekening mee dat het gebruik van deze optie ook de naam wijzigt jjwrap(), dus jij nu
Dan moet je ofwel geef uw eigen (toepasselijk genaamde) versie van de routine voor uw
scanner of gebruik %keuze noyywrap, als koppeling met -NS voorziet er niet langer in
jij standaard.

-Skeletbestand, --skel=BESTAND
overschrijft het standaard skeletbestand waaruit buigen bouwt zijn scanners.
Je hebt deze optie nooit nodig, tenzij je dat doet buigen onderhoud of ontwikkeling.

-X, --posix-compatibel
maximale compatibiliteit met POSIX lex.

--yylineno
volg het aantal lijnen in yylineno.

--yyclass=NAAM
naam van de C++-klasse.

--header-bestand=BESTAND
maak naast de scanner een C-headerbestand.

--tabellen-bestand[=BESTAND]
schrijf tabellen naar BESTAND.

-Dmacro[=defn]
#define macro defn (standaarddefn is '1').

-R, --hernieuwd
genereer een herintredende C-scanner

--bizonbrug
scanner voor bizon pure parser.

--bizon-locaties
inclusief yylloc-ondersteuning.

--standaard
initialiseer yyin/yyout naar stdin/stdout.

--noansi-definities oude stijl functie definities.

--noansi-prototypes
lege parameterlijst in prototypes.

--zelfstandig naamwoord
Voeg niet toe .

--geen functie
genereer geen bepaalde FUNCTIE.

buigen biedt ook een mechanisme voor het beheren van opties binnen de scannerspecificatie
zelf, in plaats van vanaf de flex-opdrachtregel. Dit gebeurt door het opnemen van %keuze
richtlijnen in het eerste deel van de scannerspecificatie. U kunt er meerdere opgeven
opties met een enkele %keuze richtlijn, en meerdere richtlijnen in het eerste deel van
uw flex-invoerbestand.

De meeste opties worden eenvoudigweg als namen weergegeven, eventueel voorafgegaan door het woord "nee" (met nr
tussenliggende witruimte) om hun betekenis teniet te doen. Een getal is gelijk aan flexvlaggen of
hun ontkenning:

7bit -7 optie
8bit -8 optie
uitlijnen -Ca optie
backup -b optie
batch-B optie
c++ -+ optie

geval of
hoofdlettergevoelig tegenovergestelde van -i (standaard)

hoofdlettergevoelig of
caseless -i optie

debug -d optie
standaard tegenovergestelde van -s optie
ecs -Ce-optie
snelle -F optie
volledige -f optie
interactieve -I optie
lex-compat -l optie
meta-ecs -Cm optie
perf-report -p optie
lees -Cr optie
stdout -t optie
uitgebreide -v optie
waarschuw het tegenovergestelde van de optie -w
(gebruik "%option nowarn" voor -w)

array gelijk aan "%array"
pointer gelijk aan "%pointer" (standaard)

sommige %opties functies bieden die anders niet beschikbaar zijn:

altijd interactief
instrueert flex om een ​​scanner te genereren die altijd rekening houdt met zijn invoer
"interactief". Normaal gesproken roept de scanner bij elk nieuw invoerbestand aan isatty () een
proberen te bepalen of de invoerbron van de scanner interactief is en dus
moet karakter voor karakter gelezen worden. Wanneer deze optie echter wordt gebruikt, is dat niet het geval
zo'n oproep wordt gedaan.

hoofd- geeft flex opdracht om een ​​standaard te bieden hoofd() programma voor de scanner, dat eenvoudigweg
gesprekken yylex(). Deze optie houdt in: noyywrap (zie hieronder).

nooit interactief
geeft flex de opdracht een scanner te genereren die zijn invoer nooit als "interactief" beschouwt
(nogmaals, er is niet gebeld isatty()). Dit is het tegenovergestelde van altijd interactief.

stack maakt het gebruik van startconditiestapels mogelijk (zie Startvoorwaarden hierboven).

standaard
indien ingesteld (dat wil zeggen, %keuze standaard) initialiseert yyin en ja jij naar stdin en stoer,
in plaats van de standaard van nul. Sommige bestaande lex programma's zijn afhankelijk van dit gedrag,
ook al is het niet compatibel met ANSI C, wat niet vereist is stdin en
stdout compile-time constant zijn.

yylineno
direct buigen om een ​​scanner te genereren die het nummer van de huidige regel bijhoudt
gelezen uit de invoer in de globale variabele yylineno. Deze optie wordt geïmpliceerd door:
%keuze lex-compatibel.

yywrap indien niet ingesteld (dat wil zeggen, %keuze noyywrap), zorgt ervoor dat de scanner niet belt yywrap() op een eind-
of-file, maar neem gewoon aan dat er geen bestanden meer zijn om te scannen (totdat de user
punten yyin bij een nieuw bestand en oproepen yylex() nog een keer).

buigen scant uw regelacties om te bepalen of u de WEIGEREN or meer() kenmerken.
De verwerpen en meer Er zijn opties beschikbaar om de beslissing of u al dan niet gebruikmaakt, terzijde te schuiven
de opties, door ze in te stellen (bijv. %keuze afwijzen) om aan te geven dat het kenmerk is
inderdaad gebruikt, of schakel ze uit om aan te geven dat ze daadwerkelijk niet worden gebruikt (bijv. %keuze
niet meer).

Drie opties gebruiken door tekenreeksen gescheiden waarden, gecompenseerd met '=':

%option outfile = "ABC"

is gelijk aan -oABC, en

%optievoorvoegsel = "XYZ"

is gelijk aan -PXYZ. Tenslotte

%optie yyclass="foo"

is alleen van toepassing bij het genereren van een C++-scanner ( -+ keuze). Het informeert buigen dat je hebt
afgeleide foo als een subklasse van yyFlexLexer, so buigen plaatst uw acties in het lid
functie foo::yylex() in plaats van yyFlexLexer::yylex(). Het genereert ook een
yyFlexLexer::yylex() member-functie die een runtime-fout genereert (door een beroep te doen op
yyFlexLexer::LexerError()) indien gebeld. Zie C++-scanners genereren hieronder voor meer informatie
informatie.

Er zijn een aantal opties beschikbaar voor pluispuristen die de schijn van pluisjes willen onderdrukken
onnodige routines in de gegenereerde scanner. Elk van de volgende, indien uitgeschakeld (bijv.
%keuze zelfstandig naamwoord ), resulteert erin dat de overeenkomstige routine niet in de gegenereerde routine verschijnt
scanner:

invoer, ongedaan
yy_push_state, yy_pop_state, yy_top_state
yy_scan_buffer, yy_scan_bytes, yy_scan_string

(hoewel yy_push_state() en vrienden verschijnen sowieso niet, tenzij je gebruikt %keuze stapel).

PRESTATIES OVERWEGINGEN


Het belangrijkste ontwerpdoel van buigen is dat het krachtige scanners genereert. Het is geweest
geoptimaliseerd voor het goed omgaan met grote sets regels. Afgezien van de effecten op de scanner
snelheid van de tafelcompressie -C hierboven geschetste opties, er zijn er een aantal
opties/acties die de prestaties verslechteren. Dit zijn, van duur naar minst:

WEIGEREN
%optie yylineno
willekeurige volgcontext

patroonsets waarvoor een back-up nodig is
%matrix
%optie interactief
%optie altijd interactief

'^' operator voor het begin van de regel
meer()

waarbij de eerste drie allemaal behoorlijk duur zijn en de laatste twee behoorlijk goedkoop. Opmerking
ook dat ongedaan maken() is geïmplementeerd als een routineoproep die potentieel nogal wat doet
werk, terwijl yloos() is een vrij goedkope macro; dus als je gewoon wat overtollige tekst terugstuurt
gescand, gebruik yloos().

WEIGEREN moet ten koste van alles worden vermeden als prestaties belangrijk zijn. Het is een bijzonder
dure optie.

Het verwijderen van een back-up is rommelig en kan vaak een enorme hoeveelheid werk zijn voor een
ingewikkelde scanner. In principe begint men met het gebruik van de -b vlag om een
lex.back-up bestand. Op de ingang bijvoorbeeld

%%
foo terugkeer TOK_KEYWORD;
foobar retourneert TOK_KEYWORD;

het bestand ziet er als volgt uit:

Staat #6 accepteert niet -
bijbehorende regelregelnummers:
2 3
out-transities: [ o ]
jam-overgangen: EOF [ \001-n p-\177 ]

Staat #8 accepteert niet -
bijbehorende regelregelnummers:
3
out-overgangen: [ a ]
jam-overgangen: EOF [ \001-` b-\177 ]

Staat #9 accepteert niet -
bijbehorende regelregelnummers:
3
out-overgangen: [ r ]
jam-overgangen: EOF [ \001-q s-\177 ]

Gecomprimeerde tabellen maken altijd een back-up.

De eerste paar regels vertellen ons dat er een scannerstatus is waarin deze een overgang kan maken
op een 'o' maar niet op een ander teken, en dat in die staat de momenteel gescande
tekst komt met geen enkele regel overeen. De status treedt op wanneer wordt geprobeerd de gevonden regels te matchen op
regels 2 en 3 in het invoerbestand. Als de scanner zich in die staat bevindt en dan iets leest
anders dan een 'o', zal het een back-up moeten maken om een ​​regel te vinden die overeenkomt. Met een beetje
Als je je hoofd krabt, kun je zien dat dit de staat moet zijn waarin het zich bevindt als het "fo" heeft gezien.
Wanneer dit is gebeurd en er iets anders dan een andere 'o' wordt gezien, zal de scanner dit hebben gedaan
om een ​​back-up te maken om eenvoudigweg de 'f' te matchen (volgens de standaardregel).

De opmerking over status #8 geeft aan dat er een probleem is wanneer "foob" is gescand.
Bij elk teken anders dan een 'a' zal de scanner een back-up moeten maken om dit te accepteren
"foe". Op dezelfde manier heeft de opmerking voor staat #9 betrekking op wanneer "fooba" is gescand en een
'r' volgt niet.

De laatste opmerking herinnert ons eraan dat het geen zin heeft om alle moeite van het verwijderen te doen
een back-up maken van de regels, tenzij we gebruiken -Vgl or -CF, omdat er geen prestatiewinst is
dit doen met gecomprimeerde scanners.

De manier om de back-up te verwijderen is door "foutregels" toe te voegen:

%%
foo terugkeer TOK_KEYWORD;
foobar retourneert TOK_KEYWORD;

fooba |
foef |
voor {
/* vals alarm, niet echt een trefwoord */
retourneer TOK_ID;
}

Het elimineren van back-ups uit een lijst met trefwoorden kan ook worden gedaan met behulp van een 'catch-all'-regel:

%%
foo terugkeer TOK_KEYWORD;
foobar retourneert TOK_KEYWORD;

[az]+ retourneer TOK_ID;

Dit is meestal de beste oplossing als dat nodig is.

Het maken van back-ups van berichten heeft de neiging zich in cascade te verspreiden. Met een ingewikkelde reeks regels is dat niet ongebruikelijk
honderden berichten ontvangen. Als je ze echter kunt ontcijferen, zijn er vaak maar een dozijn nodig
of zo regels om de back-up te elimineren (hoewel het gemakkelijk is om een ​​fout te maken en een
foutregel komt per ongeluk overeen met een geldig token. Een mogelijke toekomst buigen functie zal zijn
automatisch regels toevoegen om back-ups te elimineren).

Het is belangrijk om te onthouden dat u profiteert van de voordelen van het elimineren van alleen back-ups
als je elimineert elk voorbeeld van een back-up. Als je er maar één overhoudt, win je niets.

Veranderlijk afsluitende context (waarbij zowel de leidende als de afsluitende delen geen vast bestand hebben
lengte) brengt vrijwel hetzelfde prestatieverlies met zich mee als WEIGEREN (dwz substantieel). Dus wanneer
mogelijk een regel als:

%%
muis|rat/(kat|hond) run();

is beter geschreven:

%%
muis/kat|hond rennen();
rat/kat|hond rennen();

of als

%%
muis|rat/kat run();
muis|rat/hond rennen();

Merk op dat hier de speciale '|' actie doet niet enige besparing opleveren en zelfs kunnen opleveren
dingen erger (zie tekortkomingen / bugs hieronder).

Een ander gebied waarop de gebruiker de prestaties van een scanner kan verbeteren (en dat ook nog eens eenvoudiger is).
werktuig) komt voort uit het feit dat hoe langer de tokens bij elkaar passen, hoe sneller de scanner
zal rennen. Dit komt omdat bij lange tokens de verwerking van de meeste invoertekens duurt
plaats in de (korte) binnenste scanlus, en hoeft niet vaak door de
extra werk bij het opzetten van de scanomgeving (bijv. yytekst) voor de actie.
Roep de scanner op voor C-opmerkingen:

%x reactie
%%
int regel_getal = 1;

"/*" BEGIN(opmerking);

[^*\n]*
"*"+[^*/\n]*
\n ++regelnummer;
"*"+"/" BEGIN(INITIEEL);

Dit kan worden versneld door het te schrijven als:

%x reactie
%%
int regel_getal = 1;

"/*" BEGIN(opmerking);

[^*\n]*
[^*\n]*\n ++line_num;
"*"+[^*/\n]*
"*"+[^*/\n]*\n ++regelnummer;
"*"+"/" BEGIN(INITIEEL);

Nu in plaats van dat elke nieuwe regel de verwerking van een andere actie vereist, wordt de
newlines wordt "verdeeld" over de andere regels om de overeenkomende tekst zo lang te behouden
mogelijk. Let daar op toe te voegen regels wel niet Vertraag de scanner! De snelheid van de
scanner is onafhankelijk van het aantal regels of (modulo de overwegingen gegeven bij de
begin van dit gedeelte) hoe ingewikkeld de regels zijn met betrekking tot operators zoals
'*' en '|'.

Een laatste voorbeeld van het versnellen van een scanner: stel dat u door een bestand wilt scannen
met identificatiegegevens en trefwoorden, één per regel en zonder andere vreemde tekens,
en herken alle trefwoorden. Een natuurlijke eerste benadering is:

%%
als |
automatisch |
breken |
... enzovoort ...
vluchtig |
terwijl /* het een trefwoord is */

.|\n /* het is geen trefwoord */

Om de back-tracking te elimineren, introduceert u een allesomvattende regel:

%%
als |
automatisch |
breken |
... enzovoort ...
vluchtig |
terwijl /* het een trefwoord is */

[az]+ |
.|\n /* het is geen trefwoord */

Als het gegarandeerd is dat er precies één woord per regel is, kunnen we de waarde verkleinen
totaal aantal overeenkomsten met de helft door de herkenning van nieuwe regels samen te voegen met die van
de andere fiches:

%%
asm\n |
automatisch\n |
breken\n |
... enzovoort ...
vluchtig\n |
terwijl\n /* het een trefwoord is */

[az]+\n |
.|\n /* het is geen trefwoord */

Je moet hier voorzichtig zijn, omdat we nu het maken van back-ups in de scanner opnieuw hebben geïntroduceerd. In
bijzonder, terwijl we weet dat er nooit karakters in de invoerstroom zullen voorkomen
anders dan letters of nieuwe regels, buigen kan dit niet bedenken, en het zal mogelijk plannen
er moet een back-up worden gemaakt wanneer het een token zoals "auto" heeft gescand en dan het volgende teken is
iets anders dan een nieuwe regel of een letter. Voorheen zou het dan gewoon overeenkomen met de
"auto"-regel en klaar, maar nu heeft het geen "auto"-regel, alleen een "auto\n"-regel. Naar
Als we de mogelijkheid om een ​​back-up te maken elimineren, kunnen we alle regels dupliceren, maar dan zonder
laatste nieuwe regels, of, omdat we nooit verwachten een dergelijke input tegen te komen en dat dus ook niet doen
Hoe het geclassificeerd is, kunnen we nog een allesomvattende regel introduceren, en deze regel is dat niet
voeg een nieuwe regel toe:

%%
asm\n |
automatisch\n |
breken\n |
... enzovoort ...
vluchtig\n |
terwijl\n /* het een trefwoord is */

[az]+\n |
[az]+ |
.|\n /* het is geen trefwoord */

Samengesteld met -Cf, dit is ongeveer net zo snel als je kunt krijgen buigen scanner om hiervoor te gaan
bijzonder probleem.

Een laatste opmerking: buigen is traag bij het matchen van NUL's, vooral als een token bevat
meerdere NUL's. Het is het beste om regels te schrijven die overeenkomen kort hoeveelheden tekst als dat zo is
verwacht dat de tekst vaak NUL's zal bevatten.

Nog een laatste opmerking over de prestaties: zoals hierboven vermeld in de sectie Hoe de invoer
is Matched, dynamisch formaat wijzigen yytekst het herbergen van grote tokens is een langzaam proces
omdat het momenteel vereist dat het (enorme) token vanaf het begin opnieuw wordt gescand. Dus
als prestaties van cruciaal belang zijn, moet u proberen "grote" hoeveelheden tekst te matchen, maar dat lukt niet
"enorme" hoeveelheden, waarbij de grens tussen de twee ongeveer 8K tekens/token bedraagt.

GENEREREN C + + SCANNERS


buigen biedt twee verschillende manieren om scanners te genereren voor gebruik met C++. De eerste manier is
om eenvoudigweg een scanner te compileren die is gegenereerd door buigen met behulp van een C++-compiler in plaats van een C
compiler. U zou geen compilatiefouten mogen tegenkomen (meld eventuele gevonden fouten aan
het e-mailadres vermeld in het gedeelte Auteur hieronder). U kunt vervolgens C++-code gebruiken in uw
regelacties in plaats van C-code. Houd er rekening mee dat dit de standaardinvoerbron voor uw scanner is
stoffelijk overschot yyin, en standaard echoën wordt nog steeds uitgevoerd ja jij. Deze blijven allebei bestaan FILE *
variabelen en niet C++ streams.

U kunt ook gebruik maken van buigen om een ​​C++-scannerklasse te genereren met behulp van de -+ optie (of,
gelijkwaardig, %keuze c++), die automatisch wordt opgegeven als de naam van de flex
uitvoerbare bestanden eindigen op een '+', zoals flex++. Wanneer u deze optie gebruikt, wordt flex standaard ingesteld op
het genereren van de scanner voor het bestand lex.jj.cc in plaats van lex.jj.c. De gegenereerde scanner
bevat het headerbestand FlexLexer.h, die de interface voor twee C++-klassen definieert.

De eerste klasse, FlexLexer, biedt een abstracte basisklasse die de algemene scanner definieert
klasse-interface. Het biedt de volgende lidfuncties:

const teken* JJTekst()
retourneert de tekst van het meest recent overeenkomende token, het equivalent van yytekst.

int JJLeng()
retourneert de lengte van het meest recent overeenkomende token, het equivalent van yeleng.

int lijn() const
retourneert het huidige invoerregelnummer (zie %keuze yylineno), or 1 if %keuze
yylineno werd niet gebruikt.

komen te vervallen set_debug( int vlag )
stelt de foutopsporingsvlag voor de scanner in, gelijk aan het toewijzen aan yy_flex_debug
(zie het gedeelte Opties hierboven). Houd er rekening mee dat u de scanner moet bouwen met behulp van
%keuze debug om er foutopsporingsinformatie in op te nemen.

int debuggen() const
retourneert de huidige instelling van de foutopsporingsvlag.

Ook zijn er ledenfuncties beschikbaar die gelijkwaardig zijn aan yy_switch_to_buffer(), yy_create_buffer()
(hoewel het eerste argument een standaard::istream* objectaanwijzer en niet a BESTAND*),
yy_flush_buffer(), yy_delete_buffer(), en yyherstart() (opnieuw is het eerste argument a
standaard::istream* objectwijzer).

De tweede klasse gedefinieerd in FlexLexer.h is yyFlexLexer, die is afgeleid van FlexLexer.
Het definieert de volgende aanvullende lidfuncties:

yyFlexLexer( standaard::istream* arg_yyin = 0, std::ostream* arg_yyout = 0 )
construeert een yyFlexLexer object met behulp van de gegeven stromen voor invoer en uitvoer. Als
niet gespecificeerd, de streams zijn standaard ingesteld op cin en uit, respectievelijk.

virtueel int yylex()
vervult dezelfde rol yylex() doet voor gewone flexscanners: het scant de
invoerstroom, die tokens verbruikt, totdat de actie van een regel een waarde retourneert. als jij
een subklasse afleiden S oppompen van yyFlexLexer en toegang wilt krijgen tot de ledenfuncties en
variabelen van S binnen yylex(), dan moet je gebruiken %keuze yyclass="S" informeren
buigen waarvoor u die subklasse gaat gebruiken in plaats van yyFlexLexer. In dit geval,
in plaats van te genereren yyFlexLexer::yylex(), buigen genereert S::yylex() (en ook
genereert een dummy yyFlexLexer::yylex() dat roept yyFlexLexer::LexerError() if
genaamd).

virtueel komen te vervallen switch_streams(std::istream* nieuw in = 0,
std::ostream* nieuw_uit = 0) wijst opnieuw toe yyin naar nieuw in (indien niet nul) en ja jij naar
nieuw_uit (idem), waarbij de vorige invoerbuffer wordt verwijderd als yyin wordt opnieuw toegewezen.

int yylex( standaard::istream* nieuw in, std::ostream* nieuw_uit = 0 )
schakelt eerst de invoerstromen door switch_streams( nieuw in, nieuw_uit ) en
geeft de waarde van . terug yylex().

Daarnaast, yyFlexLexer definieert de volgende beveiligde virtuele functies die u kunt gebruiken
opnieuw definiëren in afgeleide klassen om de scanner aan te passen:

virtueel int LexerInvoer( teken* goed, int max_grootte )
leest tot max_grootte karakters in buf en retourneert het aantal gelezen tekens.
Om het einde van de invoer aan te geven, retourneert u 0 tekens. Let op: "interactieve" scanners
(Zie de -B en -I vlaggen) definiëren de macro JJ_INTERACTIEF. Als je opnieuw definieert
LexerInvoer() en moeten verschillende acties ondernemen, afhankelijk van of het wel of niet het geval is
scanner mogelijk een interactieve invoerbron aan het scannen is, kunt u testen op de
aanwezigheid van deze naam via #ifdef.

virtueel komen te vervallen LexerUitvoer( const teken* goed, int grootte )
schrijft uit grootte tekens uit de buffer goed, die, hoewel NUL-beëindigd, dat wel kan
bevatten ook "interne" NUL's als de regels van de scanner tekst kunnen matchen met NUL's erin
Hen.

virtueel komen te vervallen LexerFout( const teken* msg )
meldt een fatale foutmelding. De standaardversie van deze functie schrijft de
bericht naar de stroom cerr en uitgangen.

Merk op dat een yyFlexLexer object bevat zijn GEHELE scanstatus. Je kunt er dus gebruik van maken
objecten om inspringende scanners te maken. U kunt meerdere exemplaren van hetzelfde instantiëren
yyFlexLexer klasse, en u kunt ook meerdere C++-scannerklassen combineren in de
hetzelfde programma met behulp van de -P hierboven besproken optie.

Merk tot slot op dat de %matrix functie is niet beschikbaar voor C++-scannerklassen; je moet
. %wijzer (de standaard).

Hier is een voorbeeld van een eenvoudige C++-scanner:

// Een voorbeeld van het gebruik van de flex C++ scannerklasse.

%{
int mijnlijn = 0;
%}

tekenreeks \"[^\n"]+\"

ws [\t]+

alpha [A-Za-z]
graven [0-9]
naam ({alpha}|{dig}|\$)({alpha}|{dig}|[_.\-/$])*
num1 [-+]?{dig}+\.?([eE][-+]?{dig}+)?
num2 [-+]?{dig}*\.{dig}+([eE][-+]?{dig}+)?
nummer {num1}|{num2}

%%

{ws} /* spaties en tabbladen overslaan */

"/*" {
intc;

terwijl((c = yyinvoer()) != 0)
{
als(c == '\n')
++mijnlijn;

anders als(c == '*')
{
als((c = yyinvoer()) == '/')
te breken;
anders
ongedaan maken(c);
}
}
}

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

\n mijnlijn++;

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

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

%%

int main( int /* argc */, char** /* argv */ )
{
FlexLexer* lexer = nieuw yyFlexLexer;
terwijl(lexer->yylex() != 0)
;
0 terug;
}
Als je meerdere (verschillende) lexerklassen wilt maken, gebruik je de -P vlag (of de
voorvoegsel= optie) om ze allemaal een andere naam te geven yyFlexLexer naar een ander xxFlexLexer. Dat kan dan
omvatten in uw andere bronnen één keer per lexer-klasse, eerst hernoemd
yyFlexLexer als volgt:

#undef yyFlexLexer
#define yyFlexLexer xxFlexLexer
#erbij betrekken

#undef yyFlexLexer
#define yyFlexLexer zzFlexLexer
#erbij betrekken

als je bijvoorbeeld gebruikt %keuze voorvoegsel = "xx" voor een van uw scanners en %keuze
voorvoegsel = "zz" voor de andere.

BELANGRIJK: de huidige vorm van de scanklasse is experimenteel en kan veranderen
aanzienlijk tussen grote releases.

INCOMPATIBILITEITEN MET LEX EN POSIX


buigen is een herschrijving van de AT&T Unix lex tool (de twee implementaties delen er geen
code), met enkele uitbreidingen en incompatibiliteiten, die beide van belang zijn
degenen die scanners willen schrijven die acceptabel zijn voor beide implementaties. Flex is volledig
compatibel met POSIX lex specificatie, behalve dat bij gebruik %wijzer (de standaard),
een oproep naar ongedaan maken() vernietigt de inhoud van yytekst, wat in strijd is met de POSIX
specificatie.

In deze sectie bespreken we alle bekende gebieden van incompatibiliteit tussen flex, AT&T
lex en de POSIX-specificatie.

flex's -l optie schakelt maximale compatibiliteit met de originele AT&T in lex implementatie,
ten koste van een groot verlies in de prestaties van de gegenereerde scanner. Wij noteren hieronder welke
Incompatibiliteiten kunnen worden verholpen met behulp van de -l optie.

buigen is volledig compatibel met lex met de volgende uitzonderingen:

- De mensen zonder papieren lex interne scannervariabele yylineno wordt niet ondersteund tenzij -l
or %keuze yylineno is gebruikt.

yylineno moet per buffer worden onderhouden, in plaats van per scanner
(enkele globale variabele) basis.

yylineno maakt geen deel uit van de POSIX-specificatie.

- De invoer() routine is niet herdefinieerbaar, hoewel deze kan worden aangeroepen om tekens te lezen
volgen wat door een regel is geëvenaard. Als invoer() wordt geconfronteerd met een einde-
het normale indienen yywrap() verwerking is gedaan. Een ``real'' end-of-file wordt geretourneerd door
invoer() as EOF.

In plaats daarvan wordt de invoer bestuurd door het definiëren van de JJ_INPUT macro.

De buigen beperking dat invoer() kan niet opnieuw worden gedefinieerd, is in overeenstemming met de
POSIX-specificatie, die eenvoudigweg geen enkele manier specificeert om de
scannerinvoer anders dan door er een initiële toewijzing aan te maken yyin.

- De ongedaan maken() routine is niet herdefinieerbaar. Deze beperking is in overeenstemming met
POSIX.

- buigen scanners zijn niet zo nieuwkomers als lex scanners. In het bijzonder als u een
interactieve scanner en een interrupthandler die ver uit de scanner springt,
en de scanner vervolgens opnieuw wordt gebeld, krijgt u mogelijk de volgende melding:

fatale interne fout van de flexscanner: einde van buffer gemist

Om de scanner opnieuw te openen, gebruikt u eerst

yyherstart( yyin );

Merk op dat deze oproep alle gebufferde invoer weggooit; meestal is dit geen
probleem met een interactieve scanner.

Merk ook op dat flex C++ scannerklassen zijn herintredend, dus als het gebruik van C++ een optie is
voor jou zou je ze in plaats daarvan moeten gebruiken. Zie "C++-scanners genereren" hierboven voor
details.

- uitvoer() wordt niet ondersteund. Uitvoer van de ECHO macro wordt gedaan naar de bestandsaanwijzer
ja jij (standaard stout).

uitvoer() maakt geen deel uit van de POSIX-specificatie.

- lex ondersteunt geen exclusieve startvoorwaarden (%x), hoewel deze zich in de POSIX bevinden
specificatie.

- Wanneer definities worden uitgebreid, buigen plaatst ze tussen haakjes. Met Lex, de
volgende:

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

komt niet overeen met de tekenreeks "foo", omdat de regel dat wel is als de macro wordt uitgevouwen
gelijk aan "foo[AZ][A-Z0-9]*?" en de prioriteit is zodanig dat de '?' is
geassocieerd met "[A-Z0-9]*". Met buigen, de regel wordt uitgebreid naar "foo([AZ][A-
Z0-9]*)?" en dus komt de string "foo" overeen.

Merk op dat als de definitie begint met ^ of eindigt met $ dan is het niet uitgebreid
tussen haakjes, zodat deze operatoren in definities kunnen verschijnen zonder verlies
hun speciale betekenissen. Maar de , /, en < > Operators kunnen niet worden gebruikt in a
buigen definitie.

gebruik -l resulteert in de lex gedrag zonder haakjes rond de definitie.

De POSIX-specificatie is dat de definitie tussen haakjes staat.

- Sommige implementaties van lex toestaan ​​dat de actie van een regel op een aparte regel begint, if
het patroon van de regel bevat witruimte:

%%
foe|bar
{foobar_actie(); }

buigen ondersteunt deze functie niet.

- De lex %r (een Ratfor-scanner genereren) optie wordt niet ondersteund. Het is geen onderdeel van
de POSIX-specificatie.

- Na een oproep naar ongedaan maken(), yytekst is ongedefinieerd totdat het volgende token wordt gematcht,
tenzij de scanner is gebouwd met behulp van %matrix. Dit is niet het geval met lex of de
POSIX-specificatie. De -l optie maakt een einde aan deze incompatibiliteit.

- De voorrang van de {} (numeriek bereik) operator is anders. lex interpreteert
"abc{1,3}" als "komt overeen met één, twee of drie exemplaren van 'abc'", terwijl buigen
interpreteert het als "match 'ab' gevolgd door één, twee of drie keer dat 'c' voorkomt".
Dit laatste is in overeenstemming met de POSIX-specificatie.

- De voorrang van de ^ exploitant is anders. lex interpreteert "^foo|bar" als "match
ofwel 'foo' aan het begin van een regel, of 'bar' waar dan ook", terwijl buigen
interpreteert het als "match 'foo' of 'bar' als ze aan het begin van a staan
line". Dit laatste is in overeenstemming met de POSIX-specificatie.

- De speciale tabelgroottedeclaraties zoals %a gesteund door lex zijn niet vereist door
buigen scanners; buigen negeert ze.

- De naam FLEX_SCANNER is #define'd, zodat scanners kunnen worden geschreven voor gebruik met beide
buigen or Lex. Scanners zijn ook inbegrepen YY_FLEX_MAJOR_VERSION en JJ_FLEX_MINOR_VERSIE
geeft aan van welke versie buigen heeft de scanner gegenereerd (bijvoorbeeld voor de 2.5
release, deze definities zouden respectievelijk 2 en 5 zijn).

De volgende buigen functies zijn niet inbegrepen lex of de POSIX-specificatie:

C++-scanners
%keuze
startvoorwaardebereiken
startconditiestapels
interactieve/niet-interactieve scanners
yy_scan_string() en vrienden
yyterminate()
yy_set_interactive()
jj_set_bol()
JJ_AT_BOL()
< >
<*>
JJ_DECL
JJ_START
JJ_USER_ACTION
JJ_USER_INIT
#regelrichtlijnen
%{}'s rond acties
meerdere acties op een lijn

plus bijna alle flexvlaggen. Het laatste kenmerk in de lijst verwijst naar het feit dat
Met buigen je kunt meerdere acties op dezelfde regel zetten, gescheiden door puntkomma's, while
Met Lex, de volgende

foo handle_foo(); ++num_foos_gezien;

wordt (nogal verrassend) ingekort tot

foo handle_foo();

buigen beëindigt de actie niet. Acties die niet tussen accolades staan, zijn eenvoudigweg
beëindigd aan het einde van de regel.

DIAGNOSE


waarschuwing, regeren kan niet be op elkaar afgestemd geeft aan dat de gegeven regel niet kan worden geëvenaard omdat deze
volgt andere regels die altijd overeenkomen met dezelfde tekst. Bijvoorbeeld in de
De volgende "foo" kan niet worden gematcht omdat deze na een "catch-all"-identificatieregel komt:

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

gebruik WEIGEREN in een scanner onderdrukt deze waarschuwing.

waarschuwing, -s optie gegeven maar verzuim regeren wel be op elkaar afgestemd betekent dat het mogelijk is
(misschien alleen in een bepaalde startvoorwaarde) dat de standaardregel (overeenkomt met elke single
karakter) is de enige die overeenkomt met een bepaalde invoer. Sinds -s is gegeven,
vermoedelijk is dit niet de bedoeling.

afwijzen_gebruikt_maar_niet_gedetecteerd onbepaald or yymore_gebruikt_maar_niet_gedetecteerd onbepaald - Deze
Er kunnen fouten optreden tijdens het compileren. Ze geven aan dat de scanner gebruikt WEIGEREN or meer()
maar dat buigen heeft het feit niet opgemerkt, wat dat betekent buigen scande de eerste twee secties
op zoek naar voorvallen van deze acties en kon er geen vinden, maar op de een of andere manier sloop je
sommige in (via een #include-bestand bijvoorbeeld). Gebruik %keuze verwerpen or %keuze meer naar
geef aan flex aan dat u deze functies ook daadwerkelijk gebruikt.

buigen scanner vastgelopen - een scanner waarmee is gecompileerd -s is een invoerreeks tegengekomen die
werd door geen van de regels geëvenaard. Deze fout kan ook optreden als gevolg van interne problemen.

teken ook grote, overschrijdt YYLMAX - uw scanner gebruikt %matrix en een van de regels kwam overeen met a
tekenreeks langer dan de YYLMAX constant (standaard 8K bytes). Je kunt de waarde verhogen
door #define'ing YYLMAX in het definitiegedeelte van uw buigen invoer.

scanner vereist -8 vlag naar . de karakter 'X' - Uw scannerspecificatie omvat:
het herkennen van het 8-bits teken 'X' en u heeft de vlag -8 en uw scanner niet opgegeven
standaard ingesteld op 7-bit omdat u de -Vgl or CF opties voor tabelcompressie. Zie de
bespreking van de -7 vlag voor details.

buigen scanner terugduwen overloop - je gebruikte ongedaan maken() om zoveel tekst terug te duwen dat de
De buffer van de scanner kon niet zowel de teruggedrukte tekst als het huidige token vasthouden yytekst.
Idealiter zou de scanner in dit geval de grootte van de buffer dynamisch moeten aanpassen, maar op dit moment gebeurt dit wel
doet niet.

invoer buffer overloop, kan niet vergroten buffer omdat scanner toepassingen WEIGEREN - de scanner was
bezig met het matchen van een extreem groot token en moest de invoerbuffer uitbreiden. Dit
werkt niet met scanners die dit gebruiken AFWIJZEN.

fataal buigen scanner intern fout-einde of buffer gemiste - Dit kan gebeuren in een scanner
die opnieuw wordt ingevoerd nadat een lange sprong uit (of over) de activering van de scanner is gesprongen
kader. Voordat u de scanner opnieuw gebruikt, gebruikt u:

yyherstart( yyin );

of, zoals hierboven vermeld, schakel over naar het gebruik van de scannerklasse C++.

ook veel begin voorwaarden in <> construeren! - je hebt meer startvoorwaarden vermeld in een <>
construct dan bestaat (je moet er dus minstens één twee keer hebben vermeld).

Gebruik freebsd-lex online met behulp van onworks.net-services


Gratis servers en werkstations

Windows- en Linux-apps downloaden

  • 1
    fre:ac - gratis audio-omzetter
    fre:ac - gratis audio-omzetter
    fre:ac is een gratis audio-omzetter en cd
    ripper voor verschillende formaten en encoders.
    Het beschikt over MP3, MP4/M4A, WMA, Ogg
    Vorbis-, FLAC-, AAC- en Bonk-indeling
    steun, ...
    Download fre:ac - gratis audio-omzetter
  • 2
    matplotlib
    matplotlib
    Matplotlib is een uitgebreide bibliotheek
    voor het maken van statische, geanimeerde en
    interactieve visualisaties in Python.
    Matplotlib maakt gemakkelijke dingen gemakkelijk en
    moeilijk ding...
    Matplotlib downloaden
  • 3
    Botman
    Botman
    Schrijf uw chatbot-logica een keer en
    sluit het aan op een van de beschikbare
    berichtenservices, waaronder Amazon
    Alexa, Facebook Messenger, Slack,
    Telegram of zelfs jij...
    Botman downloaden
  • 4
    Joplin
    Joplin
    Joplin is een gratis en open source
    notities maken en to-do applicatie dat
    kan een groot aantal noten verwerken
    Markdown-indeling, organiseer ze in
    notitieboekjes en...
    Joplin downloaden
  • 5
    gerbv - een Gerber (RS-274X) kijker
    gerbv - een Gerber (RS-274X) kijker
    Gerbv is een open source Gerber-bestand
    (alleen RS-274X) kijker. Gerbv laat je
    laad meerdere bestanden op elkaar,
    metingen doen op de weergegeven afbeelding,
    enzovoort. ...
    Download gerbv - een Gerber (RS-274X) viewer
  • 6
    Iometer
    Iometer
    Analysetool voor I/O-prestaties.
    Doelgroep: ontwikkelaars, informatie
    Technologie, Wetenschap/Onderzoek, Systeem
    Beheerders. Gebruikersinterface: Win32
    (MS-Windows). programma...
    Iometer downloaden
  • Meer "

Linux-commando's

Ad