l eksinė analizė ( sk e navimas)

93
1 Leksinė analizė (skenavimas) Pirmasis teksto supratimo žingsnis – atpažinti žodžius Vienu iš pagrindinių leksinio analizatoriaus užduočių, yra išskirti programos tekste tokenus tokenas yra leksemų rūšis (tokenas gali būti simboliu, operatoriumi, identifikatoriumi ar raktiniu žodžiu), tai simbolinė konstanta. komentarai ir tušti tarpai atmetami. Leksinis analizatorius Programos tekstas Tokenų srautas DO 10 I = 1,5 DO 10 I = 1.5

Upload: tekla

Post on 09-Jan-2016

40 views

Category:

Documents


5 download

DESCRIPTION

L eksinė analizė ( sk e navimas). DO 10 I = 1 ,5 DO 10 I = 1 .5. Pirmasis teksto supratimo žingsnis – atpažinti žodžius Vienu i š pagrindini ų leksinio analizatoriaus užduočių, yra išskirti programos tekste tokenus - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: L eksinė analizė  ( sk e navimas)

1

Leksinė analizė (skenavimas)

• Pirmasis teksto supratimožingsnis – atpažinti žodžius

• Vienu iš pagrindinių leksinio analizatoriaus užduočių, yra išskirti programos tekste tokenus– tokenas yra leksemų rūšis (tokenas gali

būti simboliu, operatoriumi, identifikatoriumi ar raktiniu žodžiu), tai simbolinė konstanta.

– komentarai ir tušti tarpai atmetami.

Leksinisanalizatorius

Programos tekstas

Tokenų srautas

DO 10 I = 1,5DO 10 I = 1.5

Page 2: L eksinė analizė  ( sk e navimas)

2

Leksinė analizė (skenavimas)PavyzdysPavyzdys

TokenasIDENTIFIERASSIGN_OPIDENTIFIERSUBTRACT_OPIDENTIFIERDIVISION_OPINIT_LITERALSEMICOLON

Leksemasum=oldsum-value/100;

sum = oldsum – value / 100;

Page 3: L eksinė analizė  ( sk e navimas)

3

Kaip aprašyti tokenus?

• Šablonas – tai taisyklė aprašanti tokeną atitinkančias leksemas.– Šioms taisyklėms aprašyti yra sukurtas

specialus žymėjimas – reguliarios išraiškos.– Programavimo kalbos atominiai vienetai –

tokenai yra aprašomi reguliariomis išraiškomis• Tarp tokenų reikia mokėti išskirti rezervuotus

žodžius, jei kalboje nėra rezervuotų žodžių, leksinė analizė tampa labai sudėtinga– Pavyzdžiui PL/I kalba:

IF THEN THEN THEN = ELSE; ELSE ELSE = THEN;

– FORTRAN kalba.

Page 4: L eksinė analizė  ( sk e navimas)

4

Kalba (apibrėžimai)

• Terminas alfabetas žymi bet kokią baigtinę simbolių aibę.– Aibė {0, 1} yra binarinis alfabetas– ASCII, EBCDIC yra kompiuteriniai alfabetai

• Alfabeto eilutė, tai baigtinė alfabeto simbolių seka.

• Kalba, tai bet kokia alfabeto eilučių aibė.– tuščia aibė irgi kalba!– tuščių eilučių aibė {ε} irgi kalba!– visi lietuvių kalbos sakiniai irgi sudaro kalbą.

Page 5: L eksinė analizė  ( sk e navimas)

5

Operacijos su kalbomis

• Kalbų L ir M junginys LUM={s|sєL arba sєM}• Kalbų L ir M konkatenacija LM={st|sєL ir tєM}

• Kalbos L Kleene uždarinys L*=Ui=0∞Li

– tai nulis arba daugiau konkatenacijų

• Kalbos L teigiamas uždarinys L+=Ui=1∞Li

– tai viena arba daugiau konkatenacijų – čia L0={ε}, Li=Li-1L.

Page 6: L eksinė analizė  ( sk e navimas)

6

Kalbų kūrimo pavyzdžiai

• Tegu L={A,B,...,Z,a,b,...,z} ir M={0,1,2,...,9}– Kadangi simbolį galima laikyti vienetinio ilgio

eilute, aibės L ir M yra baigtinės kalbos.1. LUM yra raidžių ir skaičių aibė2. LM yra aibė eilučių sudarytų iš raidės po kuria

seka skaičius3. L4 tai visų keturraidžių eilučių aibė4. L* aibė eilučių iš visų raidžių, tame tarpe ir

tuščia eilutė ε5. L(LUM)* aibė eilučių iš raidžių ir skaičių

prasidedanti raide6. M+ aibė eilučių sudarytų iš vieno ir daugiau

simbolių

Page 7: L eksinė analizė  ( sk e navimas)

7

Reguliarios išraiškos

• Daugumos programavimo kalbų leksinė struktūra gali būti apibrėžta reguliariomis išraiškomis.

• Reguliarios išraiškos yra apibrėžiamos virš tam tikro (nustatyto) alfabeto Σ– Dauguma programavimo kalbų alfabetu naudoja

ASCII arba Unicode• Jei re yra reguliari išraiška, tuomet L(re ) yra re

sugeneruota kalba (simbolinių eilučių rinkinys)

Page 8: L eksinė analizė  ( sk e navimas)

8

Reguliarios išraiškos

• Reguliari išraiška apibrėžiama tam tikromis taisyklėmis.1. tuščia eilutė ε yra reguliari išraiška2. simbolis, pavyzdžiui a yra reguliari išraiška3. Jei R ir S yra reguliarios išraiškos, tai reguliaria

išraiška bus ir1. R|S (reiškia R arba S) 2. RS (konkatenacija) 3. R* (nulis arba daug R tarpusavio konkatenacijų) 4. (R) (reguliarias išraiškas galima grupuoti)

• Reguliarias išraiškas galima įvardinti: vardas → r

Page 9: L eksinė analizė  ( sk e navimas)

9

Kalbų generavimo taisyklės

re L(re ) Pastabos

RS L(R)L(S)konkatenacij

a

R|S L(R)UL(S) junginys

R* L(R)*Kleene

uždarinys

Page 10: L eksinė analizė  ( sk e navimas)

10

Pavyzdžiai (1)

• Reguliari išraiška a|b reiškia aibę {a,b}

• Reguliari išraiška (a|b)(a|b) reiškia aibę {aa,ab,ba,bb} – aibę visų eilučių iš a ir b, kurių ilgis 2.

– Kita šiai aibei atitinkanti reguliari išraiška aa|ab|ba|bb

• Reguliari išraiška a* reiškia aibę {ε,a,aa,aaa,...}

• Reguliari išraiška (a|b)* reiškia aibę visų galimų eilučių iš a ir b: {ε,a,b,aa,ab,bb,...}

– Kita šiai aibei atitinkanti reguliari išraiška (a*b*)*

Page 11: L eksinė analizė  ( sk e navimas)

11

Pavyzdžiai (2)

• Reguliari išraiška a|a*b reiškia aibę turinčią a ir eilutes turinčias nulį ar daugiau a ir besibaigiančias b

• Reguliari išraiška ba* reiškia aibę {b,ba,baa,baaa,...}

• Reguliari išraiška a*|b reiškia aibę {b,ε,a,aa,aaa,...}

• (0|1)*1 reiškia aibę binarinių skaičių besibaigiančių 1

Page 12: L eksinė analizė  ( sk e navimas)

12

Algebrinės reguliarių išraiškų savybės

• r|s=s|r – operatorius | komutatyvus• r|(s|t)=(r|s)|t – operatorius | asociatyvus• (rs)t=r(st) – konkatenacija asociatyvi• r(s|t)=rs|rt, (s|t)r=sr|tr – konkatenacija

distributyvi operatoriaus | atžvilgiu• εr=r, rε=r – konkatenacijos atžvilgiu, ε yra

vienetinis elementas • r*=(r|ε)* - ryšys tarp * ir ε• r**=r*

Page 13: L eksinė analizė  ( sk e navimas)

13

Pavyzdžiai

• Paskalio identifikatorių apibrėžianti reguliari išraiškaletter → A|B|...|Z|a|b|...|zdigit → 0|1|2|3|4|5|6|7|8|9id → letter(letter|digit)*

• Skaičius (pvz.: 1.89E-4) apibrėžianti reguliari išraiškadigit → 0|1|...|9digits → digit digit*

optional_fraction → .digits|εoptional_exponent → (E(+|-|ε)digits)|εnum → digits optional_fraction

optional_exponent

Page 14: L eksinė analizė  ( sk e navimas)

14

Sutrumpinimai

• R+ (vienas ar daugiau R)– a+ aprašo visas eilutes sudarytas iš vieno ar

daugiau a simbolių a, aa, aaa, ...– r* = r+|ε, r+ = rr*

• R? (nulis arba vienas R)– r? = r|ε

• [a-z], [A-Z], [0-9] (sutrumpintas simbolių klasės žymėjimas)– [abc] = a|b|c– [a-z] = a|b|...|z– Paskalio identifikatorius [A-Za-z] [A-Za-z0-9]*

Page 15: L eksinė analizė  ( sk e navimas)

15

Pavyzdys

• Skaičius (pvz.: 1.89E-4) apibrėžianti reguliari išraiška, naudojanti sutrumpinimusdigit → [0-9]digits → digit+optional_fraction → (.digits)?optional_exponent → (E(+|-)?digits)?num → digits optional_fraction

optional_exponent

Page 16: L eksinė analizė  ( sk e navimas)

16

Prioritetai

1. Operatoriai *, + ir ? turi aukščiausią prioritetą.

2. Konkatenacijos prioritetas žemesnis.3. | turi žemiausią prioritetą.• Visi operatoriai yra asociatyvūs iš kairės.

• Pavyzdžiui, šių susitarimų dėka išraiška (a)|

((b)*(c)) yra ekvivalenti a|b*c – Tai aibė eilučių kurias sudaro arba

vienintelis a, arba nulis arba keletas b, po kurių seka vienintelis c.

Page 17: L eksinė analizė  ( sk e navimas)

17

Leksinių analizatorių istorija

• LEX– Leksinis analizatorius sukurtas Lesk ir Schmidt iš

Bell Labs 1975 UNIX operacinei sistemai – Šiuo metu egzistuoja daugumoje operacinių

sistemų– LEX generuoja leksinį analizatorių - C kalba

parašytą programą – LEX nurodytoms reguliarioms išraiškoms įgalina

atlikti nurodytas veikas• JLex

– sukurtas Elliot Berk iš Princeton University 1996– tai Lex generuojantis leksinį analizatorių - Java

kalba parašytą programą– JLex pats parašytas Java kalba

Page 18: L eksinė analizė  ( sk e navimas)

18

JLexveikla

Tokenų apibrėžimas

Reguliarios Išraiškos

JLex

Java Failas: Scanner Class

(Yylex, leksinę analizę atlieka metodas yylex())

Tokenų atpažinimasRegular expression NFA DFA lexer

Page 19: L eksinė analizė  ( sk e navimas)

19

JLex aprašymo failo struktūra

vartotojo kodas (user code)%%JLex direktyvos (JLex directives)%%reguliarių išraiškų taisyklės (regular expression

rules)

• Komentarai – prasideda // – arba keletui eilučių /* */ galimi tik pirmose

dvejose dalyse

Page 20: L eksinė analizė  ( sk e navimas)

20

vartotojo kodas

• JLex suteikia vartotojui galimybę, esant reikalui, panaudoti savo parašytą programinį kodą.

• Vartotojo kodas bus be pakeitimų įrašytas į JLex išvesties failą, pačioje jo pradžioje.

• Dažniausiai tai būna:– paketų deklaracijos– import deklaracijos– Papildomos, vartotojo parašytos klasės

Page 21: L eksinė analizė  ( sk e navimas)

21

JLex direktyvos

• Šiame skyriuje pateikiami – makrosų apibrėžimai (macro definitions) –

reguliarių išraiškų sutrumpinti pavadinimai• naudojami apibrėžti kas yra raidės,

skaičiai ir tušti tarpai.– būsenų deklaracijos– analizatoriaus savybių pasirinkimai– standartinės leksinio analizatoriaus klasės

papildymai• Kiekviena JLex direktyva turi būti užrašoma

atskiroje eilutėje ir turi pradėti tą eilutę.

Page 22: L eksinė analizė  ( sk e navimas)

22

Reguliarių išraiškų taisyklės

• Šį skyrių sudaro taisyklių rinkinys nurodantis kaip suskaidyti įvesties srautą į tokenus.

• Reguliarių išraiškų taisyklės yra sudarytos iš trijų dalių:– būsenų sąrašas (nebūtinas)– reguliari išraiška– susieta veika (Java kodo fragmentai)

• Kiekviena veika turi grąžinti reikšmę apibrėžtą %type deklaracijoje esančioje antrojoje JLex aprašo dalyje.

• Jei veika nieko negrąžina, einamasis tokenas atmetamas ir leksinis analizatorius dar kartą iškviečia pats save.

[<būsenos>] <reg. išraiška> { <veika>}

Page 23: L eksinė analizė  ( sk e navimas)

23

JLex direktyvos (1)• Direktyva %{...%} leidžia vartotojui įrašyti Java

kodą tiesiai į leksinio analizatoriaus klasę.• Direktyvos naudojimo pavyzdys:%{ <kodas> %} • JLex įrašys Java kodą į sukuriamą leksinio

analizatoriaus klasę:class Yylex { ... <kodas> ... } • Tai leidžia aprašyti papildomus vidinius leksinio

analizatoriaus klasės kintamuosius ir metodus.• Pažymėtina, kad negalima naudoti kintamųjų vardų

prasidedančių yy – tokius vardus naudoja pati leksinio analizatoriaus klasė.

Page 24: L eksinė analizė  ( sk e navimas)

24

JLex direktyvos (2)

• Direktyva %init{ ... %init} leidžia vartotojui įrašyti Java kodą tiesiai į leksinio analizatoriaus klasės konstruktorių

%init{ <kodas>%init} • JLex įrašys Java kodą į sukuriamą leksinio

analizatoriaus klasės konstruktorių:class Yylex { Yylex () { ... <kodas> ... } • Ši direktyva leidžia atlikti papildomą leksinio

analizatoriaus klasės inicializaciją.

Page 25: L eksinė analizė  ( sk e navimas)

25

JLex direktyvos (3)

• Makrosų paskirtis:– vieną kartą apibrėžus reguliarią išraišką,

toliau atitinkamose vietose galima naudoti tik jos vardą (daugelį kartų).

– Praktiškai būtini didesnėms reguliarioms išraiškoms.

• Makrosų apibrėžimo formatas:<vardas> = <apibrėžimas>

– Makroso vardas yra identifikatorius, t.y. gali būti sudarytas iš raidžių, skaitmenų ir apatinių brūkšnių, bei turi prasidėti raide arba apatiniu brūkšniu.

– Makroso apibrėžimas turi būti teisingai užrašyta reguliari išraiška.

• Makrosų apibrėžimuose gali būti panaudoti kiti makrosai - {<vardas>}

Page 26: L eksinė analizė  ( sk e navimas)

26

JLex direktyvos (4)

• Leksinių būsenų pagalba kontroliuojamas reguliarių išraiškų atitikimas.

• Leksinių būsenų deklaravimo formatas%state state[0][, state[1], state[2], ...]• Leksinės būsenos vardas turi būti

identifikatorius. • Pagal nutylėjimą JLex pats deklaruoja vieną

būseną - YYINITIAL, kuria sukurtas leksinis analizatorius pradeda leksinę analizę.

• Jei būsenų sąrašas nenurodytas, reguliarios išraiškos atitikimas neribojamas.

• Jei būsenų sąrašas nurodytas, reguliariai išraiškai bus leidžiama atitikti tik tuomet, jei leksinis analizatorius bus vienoje iš nurodytų būsenų.

• Būsenų vardai turi būti unikalūs – tam tikslui patartina juos pradėti didžiaja raide.

Page 27: L eksinė analizė  ( sk e navimas)

27

JLex direktyvos (5)

• JavaCUP – sintaksinio analizatoriaus generatorius Java kalbai buvo sukurtas Scott Hudson iš Georgia Tech universiteto, ir išvystytas Frank Flannery, Dan Wang, ir C. Scott Ananian pastangomis. – Smulkiau apie šį įrankį:

http://www.cs.princeton.edu/~appel/modern/java/CUP/

• Suderinamumas su JavaCUP aktyvuojamas sekančia JLex direktyva

%cup

Page 28: L eksinė analizė  ( sk e navimas)

28

Simbolių ir eilučių skaičiavimo direktyvos

• Kartais naudinga žinoti kur tekste yra tokenas. Tokeno padėtis nusakoma jo eilutės ir jo pirmojo simbolio eilės numeriu tekste.

• Simbolių skaičiavimas aktyvuojamas direktyva “%char”– Sukuriamas kintamasis yychar (leks.

analizatoriaus);– jo reikšmė – pirmojo atitikusioje šabloną leksemoje

simbolio eilės numeris.• Eilučių skaičiavimas aktyvuojamas direktyva “%line”

– Sukuriamas kintamasis yyline;– jo reikšmė – atitikusios šabloną simbolinės eilutės

pirmosios eilutės eilės numeris.• Pavyzdys: “int” { return (new

Yytoken(4,yytext(),yyline,yychar,yychar+3)); }

Page 29: L eksinė analizė  ( sk e navimas)

29

Reguliarių išraiškų taisyklės

• Jei nuskaitymo metu simbolinei eilutei atitinka keletas taisyklių, jos skaidymas į tokenus vyksta pagal tą taisyklę, kuri atitinka ilgiausią tokeną.

• Jei keletas taisyklių atitinka to pačio ilgio simbolinę eilutę, pasirenkama ta taisyklė, kuri JLex aprašyme yra pirmoji (ankstesnės taisyklės turi aukštesnį prioritetą).

• JLex aprašyme reikia numatyti reguliarias taisykles visiems galimiems atvejams. – Jei leksinio analizatoriaus įvestis neatitiks jokiai

aprašytai taisyklei, leksinis analizatorius nutrauks darbą.

– Galima apsidrausti, JLex aprašymo pabaigoje patalpinus sekančią taisyklę:

. { java.lang.System.out.println("Unmatched input: " + yytext()); }– Čia taškas (.) nurodo atitikimą bet kokiai įvesčiai,

išskyrus naują eilutę (newline).

Page 30: L eksinė analizė  ( sk e navimas)

30

Reguliarios išraiškos (1)

• JLex alfabetas yra ASCII simboliai nuo 0 iki 127 imtinai.– Šie simboliai yra reguliarios išraiškos patys

sau.• Reguliariose išraiškose negalima tiesiogiai

naudoti tarpų - tarpas laikomas reguliarios išraiškos pabaiga. – Jei tuščias tarpas reikalingas reguliarioje

išraiškoje, jį reikia nurodyti tarp dvigubų kabučių: " "

• Sekantys simboliai yra meta simboliai, turintys JLex reguliariose išraiškose specialią reikšmę:

? * + | ( ) ^ $ . [ ] { } " \

Page 31: L eksinė analizė  ( sk e navimas)

31

Reguliarios išraiškos (2)

• ef viena po kitos einančios reguliarios išraiškos reiškia jų konkatenaciją.

• e|f vertikalus brūkšnys | nurodo kad atitikti gali arba išraiška e arba f.

• \b reiškia Backspace • \n reiškia newline • \t reiškia Tab • \f reiškia Formfeed • \r reiškia Carriage return • \^C reiškia Control character • \c - bet koks simbolis po \ reiškia save patį.

Page 32: L eksinė analizė  ( sk e navimas)

32

Reguliarios išraiškos (3)

• $ žymi eilutės pabaigą. – Jei reguliari išraiška baigiasi $ jos atitikimas

tikrinamas tik eilutės pabaigoje (t.y. iš kito galo).• . atitinka bet kokį simbolį išskyrus naują eilutę.

– Taigi, ši išraiška ekvivalenti [^\n]. • "..." metasimboliai tampa paprastais simboliais

dvigubose kabutėse. – Pažymėsime, kad \" reiškia simbolį "

• {vardas} nurodo čia bus išskleistas makrosas su nurodytu vardu.

• * pažymi Kleene uždarinį nurodantį nulį ar daugiau reguliarios išraiškos pasikartojimų.

• + nurodo vieną ar daugiau reguliarios išraiškos pasikartojimų.Taigi e+ yra ekvivalenti ee*

• ? nurodo, kad reguliari išraiška gali būti taikoma arba ne.

Page 33: L eksinė analizė  ( sk e navimas)

33

Reguliarios išraiškos (4)

• (...) skliaustai naudojami reguliarių išraiškų grupavimui.

• [...] pažymi simbolių klasę - reguliari išraiška atitinka visiems klasės simboliams.– Jei pirmasis simbolis [...] yra (^), tai nurodo

kad reguliari išraiška atitinka visiems simboliams išskyrus nurodytus skliaustuose.

• Pavyzdžiui, – [a-z] atitinka visas mažasias raides, – [^0-9] atitinka viską išskyrus skaičius, – [\-\\] atitinka -\, – ["A-Z"] atitinka tris simbolius: A-Z, – [+-] ir [-+] atitinka + ir -.

Page 34: L eksinė analizė  ( sk e navimas)

34

Pavyzdžiai

• “a|b” atitinka a|b bet ne a arba b• ^main atitiks leksemą “main” tik tuomet kai

ji bus eilutės pradžioje.• main$ atitiks leksemą “main” tik tuomet kai

ji bus eilutės pabaigoje.• [a bc] yra ekvivalentus a|" "|b|c

Page 35: L eksinė analizė  ( sk e navimas)

35

Susieta veika (action)

• Ši veika atliekama kai nurodytas šablonas yra atpažystamas

• Veika, tai Java sakiniai (standartiniai) grąžinantys tokenus.

Page 36: L eksinė analizė  ( sk e navimas)

36

Leksinis analizatorius

• JLex taisyklingai parašytą aprašą transformuoja į java programą vardu Yylex.

• Ši klasė turi du konstruktorius turinčius vieną argumentą - įvesties srautą (input stream) kuri reikia išskaidyti į tokenus. – Įvesties srautas gali būti atitinkamai arba

java.io.InputStream, arba java.io.Reader (pavyzdžiui StringReader).

– Konstruktorius java.io.Reader naudojamas jei įvesties sraute gali būti unicode simbolių.

• Sekantį tokeną iš įvesties srauto grąžina leksinio analizatoriaus metodas Yylex.yylex(). – Grąžinamos reikšmės tipas yra Yytoken.

Page 37: L eksinė analizė  ( sk e navimas)

37

Specialūs JLex kintamieji/metodai

• yytext() – grąžina simbolinę eilutę kuriai leksinis analizatorius rado atitikmenį (galima nustatyti šios simbolinės eilutės semantinę reikšmę)– t.y. tai tokeno, kurį grąžina yylex() leksema

• yylength() – grąžina atitiktos simbolinės eilutės ilgį

• yychar – saugo atitiktos eilutės (matched string) pradžios padėtį faile– tokeno pradžia: yychar– tokeno pabaiga: yychar + yylength()

• yylex() paprastai grąžina Yytoken klasės egzempliorių, nors galima deklaruoti ir kitą tipą direktyva %type

Page 38: L eksinė analizė  ( sk e navimas)

38

Tokenai

• Paprastai kiekvienas tokenas yra klasės Symbol iš paketo - java_cup.runtime elementas.

• Šį paketą eksportuoja analizatorius JavaCUP• Symbol klasėje nustatomi sveiki skaičiai

atitinkantys kiekvienam tokenui.• Pavyzdžiui, čia aprašytos sveiko tipo

konstantos, tokios kaip sym.ID, sym.IF

Page 39: L eksinė analizė  ( sk e navimas)

39

Reguliarios išraiškos pavyzdys

reguliariIšraiška{ veika }

• Pavyzdys:{IDENTIFIER}{ System.out.println("ID is ..."

+ yytext());}• Prasmė:

– Pirmuosiuose skliaustuose šablonas, kurio atitikmens ieškome;

– antruosiuose skliaustuose kodas, kuris bus vykdomas jei atitikmuo bus rastas.

Page 40: L eksinė analizė  ( sk e navimas)

40

Makrosų pavyzdžiai

• Apibrėžimas (antroji JLex aprašymo dalis):IDENTIFIER = [a-zA-z_][a-zA-Z0-9_]*LETTER=[A-Za-z_] DIGIT=[0-9]WHITESPACE= [ \t\n]ALPHA_NUMERIC={LETTER}|{DIGIT}

• Panaudojimas (trečioji JLex aprašymo dalis):{IDENTIFIER} {return new Token(ID,

yytext());

Page 41: L eksinė analizė  ( sk e navimas)

41

Būsenų deklaracijos (1)

• Kai kurioms simbolinėms eilutėms atitikmuo turi būti ieškomas su skirtingomis reguliariomis išraiškomis.

• Taigi reikia turėti galimybę pervesti leksinį analizatorių į įvairias būsenas, kuriose jis funkcionuotų skirtingai, t.y. naudotų kitas reguliarias išraiškas.

• Pradėdamas darbą leksinis analizatorius yra būsenoje YYINITIAL.

• Jei norime naudoti savo būsenas, aprašome jas antrojoje JLex aprašo dalyje.– Pavyzdžiui: %state COMMENTS

• Perėjimui tarp būsenų naudojamas metodas yybegin().

Page 42: L eksinė analizė  ( sk e navimas)

42

Būsenų deklaracijos (2)

• Pavyzdys:<YYINITIAL> "//" {yybegin(COMMENTS);}<COMMENTS> [^\n] {}<COMMENTS> [\n] {yybegin(YYINITIAL);}• Jei Yylex yra pradinėje YYINITIAL būsenoje ir

atpažysta //, tuomet jis pereina į būseną COMMENTS

• Jei jis yra būsenoje COMMENTS ir atpažysta bet kokį simbolį išskyrus \n, tuomet jokia veika neatliekama

• Jei jis yra būsenoje COMMENTS ir atpažysta \n, tuomet jis grįžta atgal į būseną YYINITIAL

Page 43: L eksinė analizė  ( sk e navimas)

43

minimal.lex

package Example;import java_cup.runtime.Symbol;%%%cup%%";" { return new Symbol(sym.SEMI); }"+" { return new Symbol(sym.PLUS); }"*" { return new Symbol(sym.TIMES); }"(" { return new Symbol(sym.LPAREN); }")" { return new Symbol(sym.RPAREN); }[0-9]+ { return new Symbol(sym.NUMBER, new

Integer(yytext())); }[ \t\r\n\f] { /* ignore white space. */ }. { System.err.println("Illegal character: "+yytext()); }

Page 44: L eksinė analizė  ( sk e navimas)

44

import java_cup.runtime.Symbol;

• Ši eilutė importuoja klasę Symbol.• Kai sintaksinis analizatorius iškviečia Yylex

sekančiam tokenui, Yylex objektas grąžina Symbol klasės egzempliorių.

Page 45: L eksinė analizė  ( sk e navimas)

45

Symbol klasė

• Symbol klasės egzempliorius turi keletą konstruktorių.

• "+" { return new Symbol(sym.PLUS); }– Paprasčiausias naudoja tik tokeno eilės numerį

(t.y. vieną iš sugeneruotos sym klasės konstantų)– Šioms konstantoms vardus duodame mes patys,

o reikšmes priskiria JavaCUP generuodamas sym.java failą.

• [0-9]+ { return new Symbol(sym.NUMBER, new Integer(yytext())); }

– Sudėtingesnis konstruktorius dar naudoja leksinę reikšmę kurią apibrėžia tam skirtas objektas• čia naudojamas Java objektas • gali būti naudojamas ir mūsų sukurtos klasės

objektas

Page 46: L eksinė analizė  ( sk e navimas)

46

minimal.lex tokenams atitinkantys sveiki skaičiai

//----------------------------------------------------// The following code was generated by CUP v0.10k// Sat Oct 02 09:56:56 EEST 2004//----------------------------------------------------

package Example;

/** CUP generated class containing symbol constants. */public class sym { /* terminals */ public static final int RPAREN = 6; public static final int error = 1; public static final int PLUS = 3; public static final int NUMBER = 7; public static final int SEMI = 2; public static final int LPAREN = 5; public static final int TIMES = 4; public static final int EOF = 0;}

Page 47: L eksinė analizė  ( sk e navimas)

47

Įvesties failo panaudojimas JLex/CUP

Page 48: L eksinė analizė  ( sk e navimas)

48

Anglų kalbos gramatika

A sentence is a nounphrase, a verb, and anoun phrase.

A noun phrase is anarticle and a noun.

A verb is…

An article is…

A noun is...

<S> ::= <NP> <V> <NP>

<NP> ::= <A> <N>

<V> ::= loves | hates | eats

<A> ::= a | the

<N> ::= dog | cat | rat

Page 49: L eksinė analizė  ( sk e navimas)

49

Gramatikos taikymas

• Gramatika yra taisyklių rinkinys nusakantis kaip sukonstruoti sintaksinį medį – a parse tree

• Medžio šaknyje (root) patalpiname aukščiausią hierarchijos elementą – t.y. <S>

• Gramatikos taisyklės nusako kaip toliau yra pridedami sekantys mazgai - vaikai. – Pavyzdžiui, taisyklė <S> ::= <NP> <V> <NP>

parodo kokia tvarka pridedami mazgai <NP>, <V> ir <NP> – t.y. <S> vaikai.

Page 50: L eksinė analizė  ( sk e navimas)

50

<S> ::= <NP> <V> <NP>

<NP> ::= <A> <N>

<V> ::= loves | hates|eats

<A> ::= a | the

<N> ::= dog | cat | rat

tokens

non-terminalsymbols

start symbol

a production

Page 51: L eksinė analizė  ( sk e navimas)

51

A Parse Tree

<S>

<NP> <V> <NP>

<A> <N><A> <N>

the dog the cat

loves

Page 52: L eksinė analizė  ( sk e navimas)

52

Kontekstiškai laisva gramatika(Context free grammar)

• Programavimo kalbų sintaksė aprašoma kontekstiškai laisvomis gramatikomis (CFG).

• CFG taisyklės yra daugumoje rekursyvios.• Sintaksinis analizatorius tikrina, ar programa

tenkina CFG taisykles ar ne. Jei tenkina, sintaksinis analizatorius kuria programai sintaksinį medį (parse tree)

• CFG aprašomos (Backus Naur Form), pavyzdžiui:assignment -> identifier := expressionexpression -> identifierexpression -> numberexpression -> expression + expression

• T.y. sintaksinis analizatorius tikrina, ar programą galima išvesti naudojantis nustatytos gramatikos BNF

Page 53: L eksinė analizė  ( sk e navimas)

53

Kontekstiškai laisvos gramatikos

Kontekstiškai laisvą gramatiką sudaro• V: baigtinis neterminalų skaičius• Σ: baigtinis terminalų skaičius• R: Baigtinis taisyklių skaičius, kurių bendra forma neterminalas -> {neterminalas, terminalas}*• S: pradinis neterminalas

Dauguma programavimo kalbų yra kontekstiškai laisvos

Page 54: L eksinė analizė  ( sk e navimas)

54

Kontekstiškai laisvos gramatikos komponentai

1. Tokenai (terminalai)2. Neterminalai3. Produkcijos4. Pradinis neterminalas

Gramatika nusakomaišvardinant jos produkcijas.

Tokenų eilutės pagimdytospradinio simbolio sudarogramatika apibrėžtą kalbą.

Pavyzdys:list → list + digit | list – digit | digitdigit → 0|1|2|3|4|5|6|7|8|9

Page 55: L eksinė analizė  ( sk e navimas)

55

BNF gramatikos apibrėžimas (1)

• BNF gramatiką sudaro keturios dalys:– Tokenų rinkinys– Non-terminal symbols rinkinys– Pradinis simbolis (start symbol)– Produkcijų (productions) rinkinys

• Tokenai yra mažiausi (atominiai) sintaksės vienetai.

• Neterminalai atstovauja stambesnius sintaksės vienetus– Vaizduojami nelygybių skliaustuose– gramatikos taisyklės apibrėžia kaip jie yra

išskleidžiami į tokenų literalus.

Page 56: L eksinė analizė  ( sk e navimas)

56

BNF gramatikos apibrėžimas (2)

• Satrtinis simbolis yra išskirtinis neterminalas sudarantis atitnkamos gramatikos parse tree šaknį.

• Produkcijos yra medžio konstravimo taisyklės.• Kiekviena turi kairiąją pusę, skirtuką

(separator) ::= ir dešiniąją pusę.– Kairioji pusė yra vienas neterminalas– Dešiniąją pusę gali sudaryti seka kurioje gali

būti kaip terminalai, taip ir neterminalai– Dešinės pusės narių seka nusako kokia

tvarka turi būti konstruojamas parse tree.

Page 57: L eksinė analizė  ( sk e navimas)

57

Hierarchinės programos struktūros išreiškimo rekursinėmis taisyklėmis

pavyzdys

• Kiekvienas identifikatorius (identifier) yra išraiška (expression).

• Kiekvienas skaičius (number) yra išraiška (expression).

• Jei expression1 ir expression2 yra išraiškos, tai išraiškomis yra ir expression1 + expression2 expression1 * expression2 (expression1).

Page 58: L eksinė analizė  ( sk e navimas)

58

Programavimo Kalbos Gramatika

• Išaiška gali būti (arba)– dviejų išraiškų suma– dviejų išraiškų sandauga– apskliausta išraiška– vienu iš kintamųjų a, b arba c

<exp> ::= <exp> + <exp> | <exp> * <exp> | ( <exp> ) | a | b | c

Page 59: L eksinė analizė  ( sk e navimas)

59

Pavyzdys

Šioje gramatikoje ištiesų yra šešios produkcijos.T.y. viena ši produkcija yra ekvivalenti šioms šešioms:

<exp> ::= <exp> + <exp> | <exp> * <exp> | ( <exp> ) | a | b | c

<exp> ::= <exp> + <exp><exp> ::= <exp> * <exp><exp> ::= ( <exp> )<exp> ::= a<exp> ::= b<exp> ::= c

Page 60: L eksinė analizė  ( sk e navimas)

60

BNF Realiems skaičiams

<real-number> ::= <integer-part> . <fraction><integer-part> ::= <digit> | <integer-part> <digit> <fraction> ::= <digit> | <digit> <fraction> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

Realaus skaičiaus 21.89 išvedimas: rašome išraiškų seką kurioseneterminalai žingsnis po žingsnio keičiami keičiami terminalais;

real-number integer-part . fraction integer-part digit . fraction digit digit . fraction 2 digit . fraction 2 1 . fraction 2 1 . digit fraction 2 1 . 8 fraction 2 1 . 8 digit 2 1 . 8 9

Page 61: L eksinė analizė  ( sk e navimas)

61

Empty

• Specialus neterminalas <empty> naudojamas kai numanoma, kad gramatika toliau nebeturi nieko daugiau generuoti.

• Šio neterminalo panaudojimo pavyzdys: if-then konstrukcija su galima else dalimi:

<if-stmt> ::= if <expr> then <stmt> <else-part>

<else-part> ::= else <stmt> | <empty>

Page 62: L eksinė analizė  ( sk e navimas)

62

Sukonstruojame gramatikąJava primityvių tipų deklaracijoms

float a;boolean a,b,c;int a=1, b, c=1+2;

<var-dec> ::= <type-name> <declarator-list> ;

<type-name> ::= boolean | byte | short | int | long | char | float | double

<declarator-list> ::= <declarator> | <declarator> , <declarator-list>

<declarator> ::= <variable-name> | <variable-name> = <expr>

Page 63: L eksinė analizė  ( sk e navimas)

63

EBNF

• papildoma sintaksė supaprastinanti produkcijų žymėjimą:– {x} reiškia nulį ar daugiau x pasikartojimų– [x] reiškia, kad x yra papildomas (t.y. x |

<empty>)– () naudojamas grupavimui– | reiškia pasirinkimą tarp alternatyvų– Šie meta simboliai kabutėse reiškia

atitinkamus tokenus

Page 64: L eksinė analizė  ( sk e navimas)

64

EBNF pavyzdžiai

<stmt-list> ::= {<stmt> ;}

<if-stmt> ::= if <expr> then <stmt> [else <stmt>]

<thing-list> ::= { (<stmt> | <declaration>) ;}

Page 65: L eksinė analizė  ( sk e navimas)

65

Sintaksinės analizės medis(Parse Tree)

• Kodėl reikalingas sintaksinės analizės medis? – Sintaksinio medžio struktūra išreiškia jo

generuojamos išraiškos semantiką.• Konstruojant parse tree pradinis simbolis

talpinamas medžio šaknyje• Pridedant neterminalams vaikų mazgus sekama

tam neterminalui skirtomis gramatikos konstrukcijomis

• Medis baigtas, kai visi jo lapai yra tokenai• Medžio lapai skaitomi iš kairės į dešinę – tai

sakinys kuriam sukonstruotas medis

Page 66: L eksinė analizė  ( sk e navimas)

66

Pavyzdys

<exp>

<exp> + <exp>

( <exp> )

<exp> * <exp>

( <exp> )

a b

((a+b)*c)

c

Page 67: L eksinė analizė  ( sk e navimas)

67

Sintaksinės analizės medis

assignment operator

=

expressionexpression

expression

+

identifier

position

identifier

initial

expression

identifier

rate

expression+

number

60

Sintaksiniame medyjeyra daug nereikalingos

informacijos

Sintaksinis analizatorius (parser) programai kuria tamtikrą sintaksinę struktūrą – sintaksinį medį (parse tree).

• Sintaksiniame medyje visiterminalai yra lapuose.• Kontekstiškai laisvoje gramatikoje(context free grammar) visi vidiniaimazgai yra neterminalai.

position = initial + rate + 60

Page 68: L eksinė analizė  ( sk e navimas)

68

Pavyzdys: gramatika generuoja du medžius

<exp>

<exp> + <exp>

c

<mulexp>

<exp> + <exp>

b

<mulexp> a

<mulexp>

<exp>

<exp> + <exp>

b

<mulexp>

<exp> + <exp>

a

<mulexp> c

<mulexp>

Deja pirmasis medis neatitinka įprasto sudėtiesoperatoriaus asociatyvumo

a + b + c

<exp> ::= <exp> + <exp> | <mulexp><mulexp> ::= <mulexp> * <mulexp>| (<exp>) | a | b | c

Page 69: L eksinė analizė  ( sk e navimas)

69

Asociatyvumo problema ištaisoma modifikuojant gramatiką taip, kad sudėčiai

medis augtų kairėn ir žemyn

<exp> ::= <exp> + <mulexp> | <mulexp><mulexp> ::= <mulexp> * <rootexp> | <rootexp><rootexp> ::= (<exp>)| a | b | c<exp>

<exp> + <mulexp>

b

<rootexp>

<exp> + <mulexp>

<mulexp> c

<rootexp>

a

<rootexp>

Ši gramatikaišraiškaia+b+c generuojateisingąmedį

Page 70: L eksinė analizė  ( sk e navimas)

70

Abstraktus sintaksinis medis

• Programavimo kalbos paprastai saugo supaprastintą sintaksinio medžio versiją vadinamą abstrakčiu sintaksiniu medžiu (abstract syntax tree).

• Tokiame medyje kiekvienam operatoriui skiriamas atskiras mazgas, o kiekvienam operandui skiriamas submedis.

Page 71: L eksinė analizė  ( sk e navimas)

71

<exp>

<exp> + <mulexp>

b

<rootexp>

<exp> + <mulexp>

<mulexp> c

<rootexp>

a

<rootexp> +

c

a

+

b

sintaksinis medis

abstraktus sintaksinis medis

Page 72: L eksinė analizė  ( sk e navimas)

72

JavaCUP (Construct Useful Parser)YACC analogas

• JavaCUP tai Java kalba parašytas generatorius (Bottom up Parser) sukuriantis Java kalba parašytą sintaksinį analizatorių.

JavaCUP Specifikacija(cup failas)

JavaCUPSintaksinis

analizatorius

Page 73: L eksinė analizė  ( sk e navimas)

73

CUP aprašymo struktūra

1. package ir import specifikacija (papildoma)

2. Vartotojo kodo komponentai (papildomi, leidžia vartotojui deklaruoti kodą, kuris bus įtrauktas į sugeneruotą sintaksinį analizatorių)

3. Simbolių sąrašai (terminalai ir neterminalai)4. Prioritetų deklaracijos (papildoma)5. Gramatika

Page 74: L eksinė analizė  ( sk e navimas)

74

package ir import specifikacija

• Specifikacija prasideda papildomomis package ir import deklaracijomis.

• Deklaracijos turi tą pačią sintaksę ir vaidina tą patį vaidmenį kaip ir Java kalboje.

• Deklaracija package nurodo kuriame pakete (ir kataloge) bus patalpintos CUP sukurtos sym ir parser klasės.

• Deklaracijoje import nurodyti paketai bus deklaruoti parser klasėje, tuo pačiu tais paketais galės naudotis CUP specifikacijoje patalpintas vartotojo Java kodas.

Page 75: L eksinė analizė  ( sk e navimas)

75

Vartotojo kodo komponentai (1)

• action code{: ... :} Leidžia įtraukti vartotojo kodą į CUP$actions klasę ir kuris savo ruožtu bus naudojamas gramatikoje esančiu kodu.– Ši dalis dažniausiai skiriama darbui su

simbolių lentele.

• parser code{: ... :} Ši dalis panaši į action code, tačiau kodas bus įtrauktas į klasę parser, todėl juo galės naudotis šios klasės metodai (pavyzdžiui, scan()).– Ši dalis dažnai skiriama standartinei

įvesčiai aptarnauti.

Page 76: L eksinė analizė  ( sk e navimas)

76

parser code{: ... :} pavyzdyje minimal.cup

parser code {: public static void main(String args[]) throws Exception { new parser(new Yylex(System.in)).parse(); }:}

Page 77: L eksinė analizė  ( sk e navimas)

77

Vartotojo kodo komponentai (2)

• init with{: ... :} Šioje dalyje pateikiamas kodas, kuris bus atliekamas pats pirmas, dar prieš analizatoriui užklausiant pirmojo tokeno.– Paprastai naudojama analizatoriui,

įvairioms lentelėms ir struktūroms inicijuoti

• scan with{: ... :} Nurodo kaip sintaksinis analizatorius turi užklausti leksinį analizatorių sekančio tokeno. – Šioje dalyje esantis kodas grąžinimui turi

naudoti tipą java_cup.runtime.Symbol

Page 78: L eksinė analizė  ( sk e navimas)

78

Simbolių sąrašai

• Šioje dalyje deklaruojamas kiekvienas naudojamos gramatikos terminalas ir neterminalas.terminal name1, name2, ...;terminal classname name1, name2, ...; non terminal name1, name2, ...;non terminal classname name1, name2, ...;

• Klasės naudojamos terminalų deklaracijose turi būti klasės java_cup.runtime.token poklasės.

• Klasės naudojamos neterminalų deklaracijose turi būti klasės java_cup.runtime.symbol poklasės.

Page 79: L eksinė analizė  ( sk e navimas)

79

Terminalų ir neterminalų vardams negalima naudoti CUP rezervuotus

žodžius:

"code", "action", "parser", "terminal", "non",

"nonterminal", "init", "scan", "with", "start",

"precedence", "left", "right", "nonassoc",

"import", "package"

Page 80: L eksinė analizė  ( sk e navimas)

80

Prioritetų deklaracijos (1)

• Yra trys prioriteto/asociatyvumo deklaracijų tipai:

precedence left terminal[, terminal...];precedence right terminal[, terminal...];precedence nonassoc terminal[, terminal...];

• Deklaracijų sąraše prioritetai auga iš viršaus į apačią

• Pavyzdžiui, jei nebus prioritetų, analizatorius nežinos kuria tvarka apskaičiuoti išraišką 3 + 4 * 8

• Jei terminalo nėra prioritetų deklaracijų sąraše, jo prioritetas laikomas mažiausiu.

Page 81: L eksinė analizė  ( sk e navimas)

81

Prioritetų deklaracijos (2)

• Produkcijos prioritetas yra laikomas lygiu žemiausio jos terminalų prioritetui.

• Jei produkcija neturi terminalų, jos prioritetas yra žemiausias.

• Pavyzdžiui, produkcijos expr ::= expr TIMES expr

prioritetas lygus TIMES prioritetui• Jei produkcijų prioritetai lygūs, toliau išraiškų

vertinimo tvarką nustato terminalų asociatyvumas.

Page 82: L eksinė analizė  ( sk e navimas)

82

Prioritetų deklaracijos (3)

• Yra trys asociatyvumo tipai: left, right ir nonassoc.

• Pavyzdžiui, jei PLUS asociatyvumas nustatytas left, tuomet 3 + 4 + 5 + 6 + 7 bus vertinama iš kairės į dešinę (pradedant 3 + 4); jei PLUS asociatyvumas nustatytas right bus vertinama iš dešinės į kairę (pradedant 6 + 7)

• Jei terminalas deklaruotas kaip nonassoc, tuomet sekantys vienas po kito jo taikymai su vienodu prioritetu bus interpretuojami kaip klaida.

• Pavyzdžiui, jei == asociatyvumas nustatytas nonassoc, tuomet 6 == 7 == 8 == 9 reikš klaidą.

Page 83: L eksinė analizė  ( sk e navimas)

83

Gramatikos produkcijos (1)

non_terminal symbol::= { actions, terminal symbols, non_terminal symbols } ;

• actions įterpiamos tarp skirtukų {: ... :}– action vykdoma tuomet, kai analizatorius

atpažįsta jai atitinkančią produkcijos dalį.• Kaip terminalai, taip ir neterminalai sąraše gali

būti pažymėti vardu atskirtu dvitaškiu. – Šis vardas atstovauja kode jo pažymėtą

objektą.

Page 84: L eksinė analizė  ( sk e navimas)

84

Gramatikos produkcijos (2)

• Jei neterminalas turi keletą produkcijų, jos deklaruojamos kartu ir atskiriamos iš dešinės (|) simboliu.

• Galima nurodyti analizatoriui kuriuo neterminalu jis turi pradėti darbą:

start with non_terminal;– Jei tokios deklaracijos nėra, analizatorius

pradeda darbą pirmąja produkcija.

Page 85: L eksinė analizė  ( sk e navimas)

85

Aritmetinių išraiškų su sveikais skaičiais interpretatorius

• Interpretatorius turi nuskaityti aritmetines išraiškas (besibaigiančias kabliataškiu) iš standartinės įvesties (standard input).

• Interpretatorius turi apskaičiuoti išraiškas ir resultatą išvesti į standartinę išvestį (standard output).

Page 86: L eksinė analizė  ( sk e navimas)

86

Aritmetinių išraiškų su sveikais skaičiais gramatika

expr_list::= expr_list expr_part | expr_part

expr_part ::= expr ';'

expr ::= expr '+' expr | expr '-' expr | expr '*' expr

| expr '/' expr | expr '%' expr | '(' expr ')' | '-' expr | number

Page 87: L eksinė analizė  ( sk e navimas)

87

Terminalų ir neterminalų deklaracija

• Pirmasis žingsnis aprašant sintaksinį analizatorių (kuriant jo specifikacijų failą) yra deklaruoti naudojamus terminalus ir neterminalus.

• Neterminalai:– expr_list, expr_part ir expr

• Terminalai:– SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD,

NUMBER, LPAREN, ir RPAREN• Šiuos terminalų vardus mes pasirinkome

patys JLex specifikacijų faile.– Jei terminalui nenurodome tipo, tai jis negali

įgyti reikšmės.

Page 88: L eksinė analizė  ( sk e navimas)

88

Terminalų ir neterminalų deklaracijapavyzdyje minimal.cup

• terminal SEMI, PLUS, TIMES, LPAREN, RPAREN;• terminal Integer NUMBER;

• non terminal expr_list, expr_part;• non terminal Integer expr;

Page 89: L eksinė analizė  ( sk e navimas)

89

Operatorių prioritetai ir asociatyvumas

• Mūsų naudojama gramatika nėra vienareikšmė.• Gramatika taps vienareikšme nustačius

operatorių prioritetus ir asociatyvumo taisykles.• Pavyzdžiui:

• Sakinių prioritetai auga iš viršaus į apačią.

precedence left PLUS, MINUS;precedence left TIMES, DIVIDE, MOD;precedence left UMINUS;

Page 90: L eksinė analizė  ( sk e navimas)

90

Leksinio analizatoriaus kuriamos klasės

• sym saugo terminalams skirtas konstantas• parser klasė realizuoja analizatorių

– ji yra java_cup.runtime.lr_parser poklasė• CUP$action klasė skirta kaip gramatikoje

nurodyto vartotojo kodo veikoms, taip ir veikų kodui deklaracijose.

Page 91: L eksinė analizė  ( sk e navimas)

91

Inerpretatoriaus kūrimas

• Apskaičiuoti išraiškas ir išvesti rezultatą galima tik su atitinkamu Java kodu.

• Šis Java kodas turi būti atitinkamose vietose patalpintas tarp žymių {: ir :}

expr:l PLUS expr:r{: RESULT=new Integer(l.intValue() + r.intValue()); :}

– Pirmasis neterminalas pažymėtas l, o antrasis r.

• Kiekvienos produkcijos kairioji pusė visuomet žymima identifikatoriumi RESULT– ši reikšmė (RESULT) priskiriama

analizatoriaus grąžinamam objektui Symbol.

Page 92: L eksinė analizė  ( sk e navimas)

92

min

imal

.cu

ppackage Example;import java_cup.runtime.*;parser code {:public static void main(String args[]) throws Exception {

new parser(new Yylex(System.in)).parse();}

:}terminal SEMI, PLUS, TIMES, LPAREN, RPAREN;terminal Integer NUMBER;non terminal expr_list, expr_part;non terminal Integer expr;precedence left PLUS;precedence left TIMES;expr_list ::= expr_list expr_part | expr_part;expr_part ::= expr:e {: System.out.println(" = "+e+";"); :} SEMI;expr ::= NUMBER:n {: RESULT=n; :}

| expr:l PLUS expr:r{: RESULT=new Integer(l.intValue() + r.intValue()); :}

| expr:l TIMES expr:r{: RESULT=new Integer(l.intValue() * r.intValue()); :}

| LPAREN expr:e RPAREN {: RESULT=e; :};

Page 93: L eksinė analizė  ( sk e navimas)

93

minimal.lex

package Example;import java_cup.runtime.Symbol;%%%cup%%";" { return new Symbol(sym.SEMI); }"+" { return new Symbol(sym.PLUS); }"*" { return new Symbol(sym.TIMES); }"(" { return new Symbol(sym.LPAREN); }")" { return new Symbol(sym.RPAREN); }[0-9]+ { return new Symbol(sym.NUMBER, new Integer(yytext())); }[ \t\r\n\f] { /* ignore white space. */ }. { System.err.println("Illegal character: "+yytext()); }