1 Strengbehandling. 2 Plan Strengsøgning - Knuth-Morris-Pratt-algoritmen endelige tilstandsmaskiner - Boyer-Moore-algoritmen - Rabin-Karp-algoritmen Syntaksanalyse.

Slides:



Advertisements
Lignende præsentationer
Den danske befolknings syn på handicappedes rettigheder
Advertisements

VMS data Geografisk og tidsmæssig udvikling af indsatsen i tobisfiskeriet v/ dataspecialist Josefine Egekvist Sekretariat for myndighedsbetjening.
Atomer Et programmeret forløb. En måde at lære på.
1 Problemkompleksitet 2 Problemers kompleksitet En ineffektiv algoritme: køretiden vokser eksponentielt med input- størrelsen Et problem, der ikke kan.
v/ Professor Lars Ehlers, Aalborg Universitet
Velkommen hos Juvel A/S
Program Informationer χ2-test (chi-i-anden) Projekt 3
Bolig selskabernes Landsforening– Almene lejeboliger - Maj/Juni Almene lejeboliger - Danmarkspanelet - Maj/Juni 2010.
Trivselsundersøgelse og ledelsesevaluering
Funktioner Graf og forskrift Venstreklik på musen for at komme videre
1 Rekursion og algoritmedesign. 2 Rekursion Rekursiv definition af X: X defineres i termer af sig selv. Rekursion er nyttig, når en generel version af.
Sammenligning af to grupper – kapitel 7
1 Parsing. 2 Mål: Et program til indlæsning og beregning af aritmetiske udtryk Eksempel: Beregn (3*5 + 4/2) - 1 Løs et lettere problem først: Læs en streng.
1 Effektiv forrentning Kjeld Tyllesen PEØ, CBS Erhvervsøkonomi / Managerial Economics Kjeld Tyllesen, PEØ, CBS.
Algoritmer og Datastrukturer 2 Grådige Algoritmer [CLRS ] Gerth Stølting Brodal.

Representations for Path Finding in Planar Environments.
Sproghistorie Syntaks (struktur) Semantik (Indhold)
HUSKESPIL – den lille tabel
Titel: Arial, fed, skriftstr. 20, mørkegrå. Tekst: Arial, normal, fed eller kursiv, skriftstr. 10, 12 og 14 til print – 16 og 18 til projektor – mørkegrå.
Begreber og Redskaber 8. Plan for idag Sortering fortsat Comparable Søgning –Lineær søgning –Binær søgning.
 2 3  3 =  83  43  53  63  73  93  10 4.
Søgning & sortering Intro søgning Lineær søgning Binær søgning
GP5, Martin Lillholm 1 Grundlæggende Programmering (GP) Efterår 2005 Forelæsning 5 Slides ligger på nettet. Du er velkommen til at printe dem nu. Vi begynder.
Pleje og Sundhed Gennemførte719 Inviterede895 Svarprocent80% FREDERICIA KOMMUNE MTU og Psykisk APV 2012 Rapportspecifikationer.
1 UNION-FIND. 2 inddata: en følge af heltalspar (p, q); betydning: p er “forbundet med” q uddata: intet, hvis p og q er forbundet, ellers (p, q) Eksempel.
GP 10, 7/ Grundlæggende programmering Efterår 2001 Forelæsning 10 onsdag 7/ kl. 9:15 – 12:00.
1 Powerpointserie om In-line færdiggørelse ved Heatsettrykning Avisrotation Magasindybtryk Den Grafiske Højskole.
Induktion og rekursion
FEN IntroJava AAU1 Java grundelementer Variable og datatyper Sætninger og udtryk Metoder.
Trivselsundersøgelse og ledelsesevaluering Anæstesiologisk Afdeling Flere ledere
ETU 2008 | Elevtilfredshedsundersøgelse Erhvervsskolen Nordsjælland HTX (Teknisk Gymnasium) - Hillerød Baseret på 313 besvarelser.
Endelige Automater Simple sprog (regulære sprog) kan beskrives vha. Regulære udtryk. Regulære sprog kan altid parses vha endelige automater. Nondeterministik.
1 Borgerpanelet i Silkeborg Kommune.
Finansiel vurdering af investeringer
1 Sortering I elementære metoder. 2 Plan Terminologi Elementære metoder til sortering -sortering ved udvælgelse -sortering ved indsættelse -Shellsort.
Anvendelser I Leg og spil.
Begreber og Redskaber 2. Plan for idag Noget om bestanddelene i et programmeringssprog Syntaksbeskrivelse af java Næste gang: –Binære tal –Repræsentation.
Matematik B 1.
Claus Brabrand, ITU, Denmark Mar 10, 2009EFFECTIVE JAVA Effective Java Presentation Workshop Claus Brabrand [ ] ( “FÅP”: First-year Project.
Algoritmer og Datastrukturer 2 Gerth Stølting Brodal Mønstergenkendelse [CLRS, kapitel , 32.4]
1 Vi ser nu på en general graf Men antager at alle afstande er heltallige (Det er ikke så restriktivt) Algoritmen leder efter den mindst mulige dækningsdistance.
Rapporter (Access, del 5). RHS – Informationsteknologi – Udgangspunkt Vi har oprettet en database Vi har defineret en eller flere tabeller, og.
1 Tråde 2 Plan Trådbegrebet Synkronisering Koordinering Eksempel: et flertrådet spil.
Grunde til at jeg elsker dig
Januar 2009 MandagTirsdagOnsdagTorsdagFredagLørdagSøndag Uge 2. Anette Ø. Kl Tina H. Lone M. 6 Kl Britt H. 7 Kl Vinnie G. Gerda.
GP 11, 14/ Grundlæggende programmering Efterår 2001 Forelæsning 11 onsdag 14/ kl. 9:15 – 12:00.
Sproghistorie Syntaks (struktur) Semantik (Indhold)
Lektion 7 Læsestof: Kopier fra Caranno
Fundamentale datastrukturer
Strengsøgning.
1 Sortering. 2 Sortering ved fletning (merge-sort) 7 2 | 9 4  | 2  2 79 | 4   72  29  94  4.
1 Fundamentale datastrukturer. 2 Definitioner: abstrakt datatype, datastruktur Elementære datastrukturer og abstrakte datatyper : arrays, stakke, køer,
Procestræ under afvikling af cp init login shell cp cp src dest.
Paradigmer i Programmering 2. Sammensatte typer Tupler og lister Programmering med rekursion Programmering med pipe-lines Programmering med polymorfe.
1 Søgning II 2 Plan Søgning ved nøgletransformation (hashing) –Hashfunktioner –Kollisionsstrategier –Effektivitet –Hashing i Java ( class HashTable )
1 Kap. 4, Jordens Tyngdefelt = Torge, 2001, Kap. 3. Tyngdekraftens retning og størrelse g (m/s 2 ) Acceleration Tyngdepotentialet (W): evene til at udføre.
Økonometri 1: Specifikation og dataproblemer1 Økonometri 1 Specifikation og dataproblemer 2. november 2004.
Anvendelser I Leg og spil.
03 – Udtryk og metoder. 2 NOEA2009Java-kursus – Udtryk og metoder Udtryk i Java Java har standard udtrykene… Værditildeling Subrutiner og funktionskald.
Side Grundlæggende teoretisk statistik Hypotesetest: Test i 2 populationer.
Længste plateau En klassisk problemstilling (Gries, 1981) - og her i Java!!! Denne opgave drejer sig om at bestemme længden af det længste plateau i en.
Grundlæggende programmering Forår 2002
I o p o DAIMI, AU, November 1999Programkonstruktion I9E.1 Konstruktion og brug af klasser – en stak og en HP-regnemaskine push pop.
 Michael E. Caspersen, 2000Introducerende objektorienteret programmering6A.1 Programmering med interfaces – en stak og en HP-regnemaskine push pop.
Programmering med interfaces – en stak og en HP-regnemaskine push pop.
Sproghistorie Syntaks (struktur) Semantik (Indhold)
Algoritmer og Datastrukturer 2
Algoritmer og Datastrukturer 2
Præsentationens transcript:

1 Strengbehandling

2 Plan Strengsøgning - Knuth-Morris-Pratt-algoritmen endelige tilstandsmaskiner - Boyer-Moore-algoritmen - Rabin-Karp-algoritmen Syntaksanalyse (parsing) og oversættelse - syntaksanalyse ved rekursiv nedstigning - oversættelse

3 En streng er en lineær sekvens af “tegn”. En tekststreng er en streng bestående af bogstaver, tal og specialtegn. En binær streng er en streng bestående af værdierne 0 og 1. Givet en streng på N tegn, a, kaldet teksten, og en streng på M tegn, p, kaldet mønsteret. Typisk er N >> M. Eksistens: Forekommer p i a ? Optælling: Hvor mange gange forekommer p i a ? Søg: Find en forekomst af p i a. Søg-alle: Find alle forekomster af p i a. Strengsøgning

4 Eksempler på strengsøgning Binær streng: find i Tekststreng: find gjkmxorzeoa i kvjlixapejrbxeenpphkhthbkwyrwamnugzhppfxiyjya nhapfwbghxmshwrlyujfjhrsovkvveylnbxnawavgizyv mfohigeabgksfnbkmffxjffqbualeytqrphyrbjqdjqavct gxjifqgfgydhoiwhrvwqbxgrixydzbpajnhopvlamhhfa voctdfytvvggikngkwzixgjtlxkozjlefilbrboignbzsudss vqymnapbpqvlubdoyxkkwhcoudvtkmikansgsutdjyt hzlapawlvliygjkmxorzeoafeoffbfxuhkzukeftnrfmocyl culksedgrdivayjpgkrtedehwhrvvbbltdkctq

5 Find Hooligan i Hoola-Hoola girls like Hooligans Hooligan.... Hooligan I alt: 39 tegnsammenligninger Eksempel på strengsøgning

6 Check, for hver mulig position i teksten, om mønsteret matcher fra denne position og fremad. Strengsøgning ved rå kraft int brutesearch(char p[], char a[]) { int i, j, M = p.length, N = a.length; for (i = 0; i <= N-M; i++) { for (j = 0; j < M; j++) if (p[j] != a[i+j]) break; if (j == M) return i;} return N; } 0ii+MN 0M a: p: ≤i+j j

7 match: forøg både i og j med 1. mismatch: sæt i tilbage, og sæt j til 0. Bemærk fejl i lærebogen! ( i -= j-1 skal være i -= j ) for (i = j = 0; i < N && j < M; i++, j++) if (p[j] != a[i]) { i -= j; j = -1; } return j == M ? i-M : N; Anden implementation (samme algoritme) 0i-j i N 0M a: p: j

8 Analyse af brutesearch Køretid afhænger af tekst og mønster (2) Gennemsnitlige tilfælde (fast mønster, tilfældig tekst): Søg efter * 00* 0* * 0* * 00* Langt mønster: cirka 2*N bitsammenligninger. [ Sedgewick & Flajolet: “Analysis of Algorithms”, 1996 ] (1) Værste tilfælde: Søg efter * Cirka M*N bitsammenligninger.

9 Strengsøgning i Java public int indexOf(String str, int fromIndex) { char v1[] = value, v2[] = str.value; int max = offset + (count - str.count); if (fromIndex >= count) return -1; if (fromIndex < 0) fromIndex = 0; if (str.count == 0) return fromIndex; int strOffset = str.offset; char first = v2[strOffset]; int i = offset + fromIndex; startSearchForFirstChar: while (true) { while (i <= max && v1[i] != first) i++; if (i > max) return -1; int j = i + 1, end = j + str.count - 1; int k = strOffset + 1; while (j < end) if (v1[j++] != v2[k++]) { i++; continue startSearchForFirstChar; } return i - offset;} }

10 Eksempel på søgning Find p = a = : : : : : : : : : : : : : Meget arbejde er overflødigt. For eksempel opdages det 2 gange, at delstrengen 10 er delstreng i teksten (linje 4 og 6). Alle understregede tests er overflødige (17 ud af 37).

11 Observationer Vi ønsker i hvert skridt, at skubbe p så langt til højre som muligt. Hvor langt kan bestemmes uafhængigt af a. De sidst læste tegn i a er kendt, da de har matchet p indtil nu. Vi behøver aldrig at gå baglæns i a, kun i p. Det aktuelle tegn i a kan dog sammenlignes med flere tegn i p.

12 int kmpsearch(char p[], char a[]) { int i, j, M = p.length, N = a.length; initnext(p); for (i = j = 0; i < N && j < M; i++, j++) while (j >= 0 && p[j] != a[i]) j = next[j]; return j == M ? i-M : N; } Knuth-Morris-Pratt (1970) KMP Lad next[j] angive den position i p, der skal fortsættes med i tilfælde af en mismatch for p[j]. Så kan søgealgoritmen formuleres således: idet indholdet af tabellen next bestemmes inden søgningen (med initnext ), og next[0] = -1.

13 Kompleksitet af KMP KMP søgning bruger aldrig mere end 2N tegnsammenligninger. Bevis: For hver værdi af i øges j med 1, eller mindskes ud fra next -tabellen. For hvert i foretages altså højst 2 sammenligninger. 0iN next[j] M a:a: p:p: j i' ≠

14 Tabellen next p = i next[i] * * * * * * *

15 Algoritme til bestemmelse af next[i] : Lad en kopi af p ’s første i tegn glide hen over p ’s første i tegn, startende i det andet tegn i p. Stop, hvis alle overlappende tegn matcher. next[i] er da antallet af overlappende tegn. Initialisering af next 0iN a:a: M p:p: j ≠ next[j] M p:p: j next[j] er længden af det længste præfiks i p[0:j- 1], der også er suffiks i p[0:j-1].

16 void initnext(char p[]) { int i, j, k, M = p.length; next[0] = -1; for (i = 1; i < M; i++) { for (j = i-1; j > 0; j--) { for (k = 0; k < j && p[k] == p[i-j+k]; k++) ; if (k == j) break; } next[i] = j;} } Simpel initialisering af next j tegn j p:p: p:p: i k0 0Mi-j M

17 Mere effektiv initialisering af next next kan bestemmes ved at matche p med sig selv. Snedig algoritme! i j tegn j p:p: p:p: 0 i-j Lige før tildelingen next[i] = j har vi, at de første j tegn i p, dvs. p[0],..., p[j-1], matcher de sidste j tegn af de første i tegn i p, dvs. p[i-j ],..., p[i-1 ]. void initnext(char p[]) { int i, j, M = p.length; next[0] = -1; for (i = 0, j = -1; i < M; i++, j++, next[i] = j) while (j >= 0 && p[j] != p[i]) j = next[j]; }

18 Algoritmen i initnext tager ikke årsagen til en mismatch i betragtning. Hvis teksten f.eks. starter med 1011, og vi søger efter , siger next[3], at vi næste gang skal prøve at matche med p[1]. Men vi ved, at denne match vil mislykkes. Derfor bør next[3] i stedet for være 0 (= next[1] ). Forbedring af initnext (Knuth) Løkken i initnext ændres til for (i = 0, j = -1; i < M; i++, j++, next[i] = p[i] == p[j] ? next[j] : j) if (j >= 0 && p[j] != p[i]) j = next[j]; i j tegn j p:p: p:p: 0 i-j p[i] != p[j]

19 Forbedring af tabellen next p = i next[i] (før)next[i] (nu) * * * * * * *

20 Find Hooligan i Hoola-Hoola girls like Hooligans Hooligan.... Hooligan I alt: 33 tegnsammenligninger (39 med brutesarch ) Eksempel på KMP-søgning

21 Endelige tilstandsmaskiner En endelig tilstandsmaskine (FSA = Finite State Automaton) er karakteriseret ved 1. en endelig mængde af tilstande 2. en starttilstand 3. en eller flere sluttilstande 4. en endelig mængde af inputsymboler 5. en funktion, move, der afbilder mængden af par, bestående af et inputsymbol og en tilstand, på mængden af tilstande move(input, state) state

22 En FSA kan repræsenteres ved hjælp af en tabel. move -tabel: input\state En FSA til genkendelse af mønsteret Starttilstand: 0 Sluttilstand: Søgeeksempel:

23 (1) Byg en FSA ud fra mønsteret (2) Kør FSA på teksten KMP ved hjælp af FSA Tidsforbrug: O(N). int kmpsearch(char p[], char a[]) { int i, state, M = p.length, N = a.length; initmove(p); for (i = state = 0; i < N && state < M; i++) state = move[a[i] == '0' ? 0 : 1][state]; return state == M ? i-M : N; }

24 Bygning af FSA Efterfølgertilstande til tilstand i : * match, så i+1 * mismatch, så den FSA-tilstand, der svarer til “længst mulige match” (tag højde for mismatch) Eks. FSA for Tilstand : gå til tilstand : gå til tilstand for (tilstand 2), husk tilstand for (X = 1). Tilstand : gå til tilstand : gå til tilstand for (tilstand 2), husk tilstand (X = 1). (disse er efterfølgere af forrige X)

25 void initmove(char p[]) { move = new int[2][p.length]; int X = 0; for (int i = 0; i < p.length; i++) { int match = p[i] == '0' ? 0 : 1; int mismatch = match == 0 ? 1 : 0; move[match][i] = i+1; move[mismatch][i] = move[mismatch][X]; X = move[match][X]; } } initmove() Match-tilstanden i move er unødvendig. Repræsenter kun mismatch-tilstande, next. Herved fremkommer algoritmerne i lærebogen.

26 Endelig tilstandsmaskine til indlæsning af decimaltal (f.eks.: ) Start 0 Fortegn læst 1 Læsning af heltalsdel 2 Punktum læst 3 Læsning af decimaldel 4 Slut 5 fortegn ciffer punktum ciffer andet cifferpunktum ciffer andet punktum andet

27 int stateTable[][] = {{1,0,0,0,0}, {2,2,2,4,4}, {3,3,3,0,0}, {0,0,5,0,5}}; int charClass(char c) { return c == '+' || c == '-' ? 0 : Character.isDigit(c) ? 1 : c == '.' ? 2 : 3; } Tabelstyret indlæsning af decimaltal Tilstand 0: starttilstand Tilstand 1: fortegn læst Tilstand 2: læsning af heltalsdel Tilstand 3: punktum læst Tilstand 4: læsning af decimaldel Tilstand 5: sluttilstand (tegn af klasse 3 læst)

28 float inReal() throws IOException { int state = 0, wholePart = 0, sign = 1; float decimalPart = 0, exp = 0.1; while (true) { char c = (char) System.in.read(); int action = actionTable[charClass(c)][state]; switch(action) { case 0: break; case 1: if (c == '-') sign = -1; break; case 2: wholePart = 10*wholePart + Character.digit(c,10); break; case 3: decimalPart += Character.digit(c,10)*exp; exp *= 0.1; break; case 4: return sign*(wholePart + decimalPart); case 5: throw new IOException("syntax error"); } state = stateTable[charClass(c)][state];} } inReal int actionTable[][] = {{1,5,5,5,5}, {2,2,2,3,3}, {0,0,0,5,5}, {5,5,4,5,4}};

29 En af de mest effektive algoritmer til strengsøgning. Benyttes i de fleste tekstredigeringsprogrammer. Eks: Find p = i a = : : : : : : I alt: 16 sammenligninger. KMP: 19 sammenligninger Boyer-Moore (1975) I stedet for (som KMP) at gå fra venstre mod højre i mønsteret kan det ofte bedre betale sig at gå fra højre mod venstre.

30 BM kan i lighed med KMP implementeres ved brug af et next -array. Bedre er dog i mange tilfælde at benytte en heuristik, der, givet et mismatchet tegn i teksten samt mønsteret, kan beslutte, hvor mange tegn, der skal springes fremad i teksten. Der springes altid mindst 1 tegn fremad. Implementering

31 Eks. Find Hooligan Hoola-Hoola girls like Hooligans Hooligan skip[H] = 7, skip[o] = 5, skip[l] = 4,skip[i] = 3, skip[g] = 2, skip[a] = 1,skip[n] = 0, skip[ alle andre tegn ] = 8. I alt: 12 tegnsammenligninger (33 med KMP) Lad skip[c] indeholde det antal tegn, der skal springes fremad i teksten i tilfælde af, at det aktuelle tegn c i teksten ikke matcher med det aktuelle tegn i mønsteret. Arrayet skip kan bestemmes alene ud fra mønsteret - altså forud for søgningen i teksten. Hvis et tegn c ikke forekommer i mønsteret, er skip[c] lig med mønsterets længde. Ellers er skip[c] lig med det mindste antal tegn, c skal flyttes til højre i mønsteret for at blive det sidste.

32 Implementering i Java int bmsearch(char p[], char a[]) { initskip(p); int i, j, M = p.length, N = a.length; for (i = j = M-1; j >= 0; i--, j--) while (a[i] != p[j]) { i += Math.max(skip[a[i]], M-j); if (i >= N) return N; j = M-1; } return i+1; } void initskip(char p[]) { int M = p.length; for (int i = 0; i < 256; i++) skip[i] = M; for (int j = 0; j < M; j++) skip[p[j]] = M-j-1; } Bemærk fejlene i lærebogen.

33 Kompleksitet af BM BM bruger aldrig mere end M+N tegnsammen- ligninger, og cirka N/M, hvis alfabetet ikke er lille, og mønsteret er langt. [ Tiden aftager, jo længere mønsteret er! ] Dette gælder dog kun for Boyer og Moores originale algoritme. Den præsenterede algoritme kan i værste fald bruge cirka MN sammenligninger.

34 Rabin-Karp (1981) Ide: Brug hashing. * beregn hashværdi for hver mulig deltekst af længde M i teksten * sammenlign med hashværdien for mønsteret * der er ikke behov for nogen hashtabel

35 Problem: En fuldstændig sammenligning er nødvendig ved kollision. Afhjælpning: Benyt en meget stor (virtuel) tabelstørrelse. (dog ikke så stor, at der sker aritmetisk overløb). Problem: Hashfunktionen afhænger af M tegn. Løsning: Beregn hashfunktion for i+1 ud fra hash- funktion for i (forbedrer køretiden fra N*M til N+M). Eks: “tabelstørrelse” = 97, M = 5. Find Hashværdi = 18 (mod 97) = 84 (mod 97) = 94 (mod 97) = 76 (mod 97) = 18 (mod 97) = 84 (mod 97) = ( *10000)* = (84 - 3*9)* = 579 = 94 (mod 97) = (94 - 1*9)* = 76 (mod 97) = (76 - 4*9)* = 18 (mod 97)

36 Beregning af hashværdi Antag at en hashværdi er beregnet ud fra h = a[i]d M-1 + a[i+1] d M a[i+M-1], hvor d er antallet af mulige tegn. Den næste værdi af h a[i+1]d M-1 + a[i+2] d M a[i+M-1]d + a[i+M] kan da bestemmes ud fra h: (h - a[i]d M-1 )d + a[i+M]

37 Implementering af RK i Java int rksearch(char p[], char a[]) { int q = , d = 256; int i, dM = 1, h1 = 0, h2 = 0; int M = p.length, N = a.length; for (i = 1; i < M; i++) dM = (d*dM) % q; for (i = 0; i < M; i++) { h1 = (h1*d + p[i]) % q; h2 = (h2*d + a[i]) % q; } for (i = 0; h1 != h2; i++) { h2 = (h2 + d*q - a[i]*dM) % q; h2 = (h2*d + a[i+M]) % q; if (i > N-M) return N; } return i; } NB. Testen h1 != h2 bør udvides til h1 != h2 || !String.valueOf(p). equals(String.valueOf(a,i,M))

38 Kompleksitet af RK Rabin-Karp-algoritmen er lineær med meget stor sandsynlighed.

39 Empirisk undersøgelse af algoritmernes effektivitet Søgning i “The Oxford English Dictionary” (2nd Edition), cirka 570 millioner tegn. Algoritme “to be or not to be” “data” Rå kraft Knuth-Morris-Pratt Boyer-Moore Rabin-Karp Boyer-Moore-Horspool fra G. H. Gonnet & R. Baeza-Yates: Handbook of Algorithms and Data Structures in Pascal and C, Addison-Wesley 1991.

40 Boyer-Moore-Horspool int bmhsearch(char p[], char a[]) { int i, j, k; int M = p.length, N = a.length; initskip(p); for (i = M-1; i < N; i += Math.max(skip[a[i]], M-j)) { for (j = M-1, k = i; j >= 0 && a[k] == p[j]; j--) k--; if (j == -1) return k+1; } return N; } Forsimpling af Boyer-Moore's algoritme. Kun de tegn i a, som sammenlignes med p[M-1], benyttes til at springe fremad i a.

41 Syntaksanalyse Mål: Et program til indlæsning og beregning af aritmetiske udtryk (AE). Løs et lettere problem først: Læs en streng og undersøg, om den er et lovligt AE.

42 Benyt en kontekstfri grammatik til at beskrive AE: ::= | + | - ::= | * | / ::= | ( ) Grammatik for aritmetiske udtryk Grammatikken er beskrevet ved produktionsregler og består af (1) nonterminale symboler: expression, term, factor og number. (2) terminale symboler: +, -, *, /, ( og ). (3) metasymboler: ::=,, og |.

43 En streng er et aritmetisk udtryk, hvis det ved hjælp af produktionsreglerne er muligt at udlede strengen ud fra expression, dvs. ud fra expression i en række skridt nå frem til strengen ved i hvert skridt at erstatte et nonterminal-symbol med et af alternativerne på højresiden af en produktion for dette symbol. Syntaksanalyse Syntakstræ for (3*5+4/2)-1 expression term - expression factor term ( expression ) factor term + expression1 3 * 5 term 4 / 2

44 Syntaksdiagrammer expression: term + - term: factor * / factor: number expression ( )

45 Et rekursivt Java-program til syntaksanalyse kan konstrueres direkte ud fra syntakstræerne. Syntaksanalyse ved rekursiv nedstigning (top-down parsing) void expression() { term(); while (token == PLUS || token == MINUS) if (token == PLUS) { getToken(); term(); } else { getToken(); term(); } } static final int PLUS = 1, MINUS = 2, MULT = 3, DIV = 4, LPAR = 5, RPAR = 6, NUMBER = 7, EOS = 8; int token;

46 void factor() { if (token == NUMBER) ; else if (token == LPAR) { getToken(); expression(); if (token != RPAR) error("missing right paranthesis"); } else error("illegal factor: " + token); getToken(); } void term() { factor(); while (token == MULT || token == DIV) if (token == MULT) { getToken(); factor(); } else { getToken(); factor(); } }

47 StringTokenizer str; void parse(String s) { str = new StringTokenizer(s,"+-*/() ",true); getToken(); expression(); } Eksempel på kald: parse("(3*5+4/2)-1");

48 void getToken() { String s; try { s = str.nextToken(); } catch(NoSuchElementException e) { token = EOS; return; } if (s.equals(" ")) getToken(); else if (s.equals("+")) token = PLUS; else if (s.equals("-")) token = MINUS; else if (s.equals("*")) token = MULT; else if (s.equals("/")) token = DIV; else if (s.equals("(")) token = LPAR; else if (s.equals(")")) token = RPAR; else { try { Float.valueOf(s); token = NUMBER; } catch(NumberFormatException e) { error(”number expected"); }

49 Beregning af aritmetiske udtryk Beregning kan opnås ved få simple ændringer af syntaksanalyse-programmet. Analysemetoderne skal returnere med deres tilhørende værdi (i stedet for void ). float valueOf(String s) { str = new StringTokenizer(s,"+-*/() ",true); getToken(); return expression(); } Eksempel på kald: float r = valueOf("(3*5+4/2)-1");

50 float term() { float v = factor(); while (token == MULT || token == DIV) if (token == MULT) { getToken(); v *= factor(); } else { getToken(); v /= factor(); } return v; } float expression() { float v = term(); while (token == PLUS || token == MINUS) if (token == PLUS) { getToken(); v += term(); } else { getToken(); v -= term(); } return v; }

51 float factor() { float v; if (token == NUMBER) v = value; else if (token == LPAR) { getToken(); v = expression(); if (token != RPAR) error("missing right paranthesis"); } else error("illegal factor: " + token); getToken(); return v; }

52 void getToken() { String s; try { s = str.nextToken(); } catch(NoSuchElementException e) { token = EOS; return; } if (s.equals(" ")) getToken(); else if (s.equals("+")) token = PLUS; else if (s.equals("-")) token = MINUS; else if (s.equals("*")) token = MULT; else if (s.equals("/")) token = DIV; else if (s.equals("(")) token = LPAR; else if (s.equals(")")) token = RPAR; else { try{ value = Float.valueOf(s).getFloat(); token = NUMBER; } catch(NumberFormatException e) { error(”number expected"); }

53 Ugeseddel 8 4. november november Læs kapitel 29 og 30 i lærebogen (side ) Løs følgende opgaver 1. Opgave 19.3, 19.4 og Opgave 21.1 og