SDP - Repetition Sockets Trådning Delegater Remoting Sprogteori Repetition/Otto Knudsen
Sockets Logiske endepunkter mellem server og klient På applikationsniveauet betragtes Sockets som pålidelige Sockets optræder parvis Til en Socket er der via en NetworkStream knyttet både en StreamReader StreamWriter Klientens StreamReader er forbundet til serverens StreamWriter og omvendt Repetition/Otto Knudsen
Sockets - Arkitektur Repetition/Otto Knudsen
Sockets - Serversiden Repetition/Otto Knudsen Skab en TcpListener på port 20001 (fx) TcpListener server = new TcpListener(IPAddress.Any, 20001); server.Start(); Vent på forespørgsel fra klient while(true) { Socket klient = server.AcceptSocket(); } Skab StreamReader og StreamWriter ud fra Socket NetworkStream stream = new NetworkStream(klient); StreamReader reader = new StreamReader(stream); StreamWriter writer = new StreamWriter(stream); writer.AutoFlush = true; Send og modtag via StreamReader og StreamWriter reader.ReadLine(); writer.WriteLine(); Luk strømme og Sockets Repetition/Otto Knudsen
Sockets - Klientsiden Skab en Socket til serveren TcpClient server = new TcpClient(”localhost”, 20001); Skab StreamReader og StreamWriter ud fra Socket NetworkStream stream = server.GetStream(); StreamReader reader = new StreamReader(stream); StreamWriter writer = new StreamWriter(stream); writer.AutoFlush = true; Send og modtag via StreamReader og StreamWriter reader.ReadLine(); writer.WriteLine(); Luk strømme og Socket Repetition/Otto Knudsen
Flere samtidige klienter Server class Server { public static void) { TcpListener server = new TcpListener(IPAddress.Any, 20001) server.Start(); while (true) { Socket klient = server.AcceptSocket(); new Thread(new ThreadStart(new ClientHandler(klient).Run)).Start(); } Repetition/Otto Knudsen
Flere samtidige klienter ClientHandler class ClientHandler { private Socket incoming; public ClientHandler(Socket incoming) { this.incoming = incoming; } public void Run() { // Instantiér ind- og ud-strøm while (true) { // Kommunikér Repetition/Otto Knudsen
Hvorfor trådning? Performance Responsivness Repetition/Otto Knudsen
Succeskriterier Forbedring af performance Forbedring af responsivness Opgaverne skal være uafhængige Jo flere afhængige opgaver, jo mindre forbedring Forbedring af responsivness Responsivness er et spørgsmål om oplevelse Jo længere tid en opgave tager, jo mindre virksom opleves applikationen, hvis brugeren ikke har noget at lave eller se på Repetition/Otto Knudsen
Fordele Overvågningssystemer med flere uafhængige opgaver Muliggør brugerinteraktion via BGF Muliggør serverhåndtering af flere samtidige klienter Udnytter flerprocessor-systemer optimalt Repetition/Otto Knudsen
Ulemper Trådene afvikles uafhængigt af hverandre Afviklingsrækkefølgen synes vilkårlig Samspillet mellem tråde er ofte meget kompleks Problemer med safety og liveness Repetition/Otto Knudsen
Trådskifte CPU’en skifter til en ny tråd … Efter et givent tidsrum, eller Når en tråd venter på færdiggørelsen af en opgave, fx en I/O-operation … Repetition/Otto Knudsen
Processer vs. Tråde Der er mindst to former for samtidighed: Multiprocessing Multithreading Repetition/Otto Knudsen
Multiprocessing Samtidighed på tværs af applikationer Til heavy-weight opgaver (IIS, SQL, Server, …) Hver proces eksekverer én enkelt tråd Repetition/Otto Knudsen
Multithreading Samtidighed i applikationer Forskellige tråde udfører forskellige opgaver Perfekt til light-weight opgaver (Metodekald, UI-opdateringer, …) Repetition/Otto Knudsen
Multithreading Samtidighed i .NET Tråde håndteres af CLR Tråde har deres egen stak (locals), men deler globals og heap Repetition/Otto Knudsen
Instantiering af tråde Tråde kaldes ikke, de startes … Man kan derfor ikke medsende parametre, modtage returværdi og fange exceptions på sædvanlig vis Trådet kode skal håndtere fejl … Uhåndterede fejl vil terminere applikationen Gør designet simpelt … Trådning er et minefelt – fælles ressourcer giver anledning til kritiske sektioner, race conditions, deadlock, … Repetition/Otto Knudsen
Instantiering af tråde public static void Main() { Thread t; t = new Thread(new ThreadStart(Run)); t.Start() } public static void Run() { // kode Repetition/Otto Knudsen
Trådes livscyklus Repetition/Otto Knudsen
Trådsikre klasser Problem Hvis en tråd afbrydes, medens den arbejder på et objekt, er der risiko for, at objektet efterlades i en inkonsistent tilstand. Dette kan give problemer, når en anden tråd forsøger at få tilgang til objektet Repetition/Otto Knudsen
Trådsikre klasser Løsning Løsningen er at forhindre mere end én tråd ad gangen i at få tilgang til de kritiske områder i koden Repetition/Otto Knudsen
Single Threaded Execution Vha. lock(obj) opnår en tråd eneret på et objekt – en lås Låsen frigives, når tråden forlader det kritiske område eller ved kald af metoden Monitor.Wait(obj) på objektet. Kritiske områder på samme objekt deler samme lås! Repetition/Otto Knudsen
Liveness problemer Starvation (udhungring) Dormancy (dvale) En tråd, som er i tilstanden ready, får aldrig lejlighed til at køre, fordi der findes andre tråde med højere prioritet Dormancy (dvale) En tråd, som er i tilstanden blocked on wait, vækkes aldrig med Monitor.Pulse() Deadlock (hårdknude) To eller flere tråde kæmper om flere fælles ressourcer, og hver tråd efterspørger på samme tid disse ressourcer Premature Termination (for tidlig død) En tråd termineres for tidligt og hindrer derved andre tråde i at blive vækket. (Evig dvale) Repetition/Otto Knudsen
Brug af lock() Nødvendig, hvis man vil lave "trådsikre klasser" Ej omkostningsfrit: Kræver CPU-kraft langsommere programafvikling "Hellere for mange synkroniserede blokke end for få!" MEN - pas på deadlocks Repetition/Otto Knudsen
lock vs. Monitor.Enter/Exit lock(obj) er et alias for: try { Monitor.Enter(obj); // kode ... Monitor.Exit(obj); } catch { } finally { Repetition/Otto Knudsen
Monitor Monitor Formål indkapsler fælles ressourcer som private attributter og sikrer trådene enetilgang vha. lock() til de kritiske områder Formål Overvågning af trådes adgang til fælles ressourcer Repetition/Otto Knudsen
Monitor Objekt, hvor de fælles ressourcer er samlet som attributter Der er udelelig adgang til monitorens kritiske områder Én monitor-lock pr. kritisk område Repetition/Otto Knudsen
Early notification Problem Konsekvens Løsning Konklusion Monitor.Pulse() sendes før betingelserne for Monitor.Wait er opfyldt Konsekvens Wait-tråden vækkes før tid Løsning Gentjek betingelserne for Monitor.Wait, når Wait-tråden vækkes Konklusion Anvend altid while (i stedet for if) i forbindelse med check af wait-betingelser Repetition/Otto Knudsen
Early notification Repetition/Otto Knudsen Bufferen er tom! C1-tråden er i Wait-tilstand P-tråden generer et nyt element og kalder monitorens synkroniserede put-metode C1-tråden underrettes via Pulse, og tråden går i ready-tilstand P-tråden forlader monitorens put-metode og slipper objekt-låsen på monitoren Bufferen indeholder nu ét element! Trådskifte! C2-tråden trækker et element fra bufferen ved at kalde monitorens get-metode C2-tråden forlader monitorens get-metode og slipper objekt-låsen på monitoren Der er ingen elementer i bufferen! C1 fortsætter nu fra Wait i monitorens get-metode i forsøget på at trække endnu et element fra bufferen … Dette er ikke muligt! Repetition/Otto Knudsen
Guarded Suspension public void Put(int data) { lock(this) { while (queue.Full) Monitor.Wait(this); if (queue.Empty) Monitor.PulseAll(this); this.queue.Enqueue(data); } Repetition/Otto Knudsen
Guarded Suspension public void Get(int data) { lock(this) { while (queue.Empty) Monitor.Wait(this); if (queue.Full) Monitor.PulseAll(this); this.queue.Dequeue(data); } Repetition/Otto Knudsen
Design af trådet applikation Anvend Producer-Consumer mønstret Anvend de 10 gode trådråd Husk den gyldne regel Repetition/Otto Knudsen
10 gode trådråd Bestem tråde Bestem trådmetoder Bestem fælles ressourcer Bestem monitorer - Én monitor for hver uafhængig fælles ressource Bestem monitor-klasser Bestem kritiske sektioner Bestem Wait/Pulse – Et par for hver tilstand, som kræver, at en tråd venter på en anden Fordel Wait og Pulse (Husk ”Guarded Suspension”-mønstret) Lav pseudo-kode for monitor-klassernes metoder Lav pseudo-kode for tråd-klassernes run-metoder Repetition/Otto Knudsen
Den gyldne UI-regel UI-baserede .NET-applikationer Den tråd, som har skabt UI’en ejer UI’en – Ingen anden tråd må tilgå UI’ens kontrolelementer … Repetition/Otto Knudsen
Delegater Delegater er objekter, der refererer til en metode – tænk ”funktionspointer” delegate private void MinMethod(...) { . } - med delegater kan man kalde en underliggende metode på en typesikker måde - med delegater kan man arbejde med metodereferencer på en objektorienteret facon Repetition/Otto Knudsen
Window Forms Hvordan ved en knap, hvilken metode den skal kalde ved et click-event? Det ved den heller ikke! Den kalder metoden bagved delegaten … Button Click: delegate private void btnAdd_Click(object sender, EventArgs e) { int i, j, k; i = int.Parse(this.txtNumber1.Text); j = int.Parse(this.txtNumber2.Text); k = i + j; System.Windows.Forms.MessageBox.Show("Sum = " + k); } Repetition/Otto Knudsen
Delegat-baseret kode i VS . this.btnAdd = new Button(); this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); Repetition/Otto Knudsen
Remoting Klienten ser serveren som en assembly (dll) Client.exe (.NET) Server.exe (.NET) Klienten ser serveren som en assembly (dll) Referencen sættes på sædvanlig vis … Serveren gør dll’en tilgængelig på flg. måder Tjeneste på en server, der svarer på kald fra klienter. Effektivt! Integreret i en web-tjeneste, der kaldes via URL. ”Firewall-venligt”! Repetition/Otto Knudsen
Komponent-dll MBR-objekter arver fra MarshalByRefObject MBV-objekter skal være Serializable namespace Komponent { public class Beregningsobjekt : System.MarshalByRefObject { private static int Objekttæller = 0; private int ObjektID; // Konstruktør public Beregningsobjekt() { this.ObjektID = ++Objekttæller; } public DataObjekt HentDataObject() { return new DataObjekt(); namespace Komponent { [System.Serializable()] public class DataObjekt { . } Repetition/Otto Knudsen
Remoting - arkitektur Generel arkitektur Proxy, stub, formattering og channel kan ændres. Fx er en binær formattering, der både understøttes af TCP og HTTP, mere effektiv end en tekstbaseret (XML) Server stub remoting formatter listener Client proxy remoting formatter channel Repetition/Otto Knudsen
Remoting - Design Designbeslutning: MBRO eller MBVO? Gængs praksis: Med andre ord: ”Hvor skal objekterne leve?” MBRO lever på serveren MBVO lever på klienten Gængs praksis: Beregninger sker på serveren MBRO Fx søgning og køb på en ehandel Tilstande bevares på klienten MBVO Fx indkøbskurv på en ehandel håndteres af klienten Repetition/Otto Knudsen
MBRO - muligheder Server-activated object (SAO) også betegnet ”Wellknown objects” Singleton: Ét serverobjekt til alle klienter Trådproblemer SingleCall: Ét objekt pr. metodekald Nemmeste løsning; men mindst effektivt Tilstand opretholdes vha. filer eller database Client-activated object (CAO) Activated: Ét objekt pr. klient Levetidsproblem – Leasing understøttes ikke af IIS Repetition/Otto Knudsen
MBVO - muligheder Egenudviklede klasser .NET collection og db-klasser Kan udføre special-opgaver på klienten .NET collection og db-klasser Eksempelvis DataSet er en meget brugbar klasse til at overføre data … Repetition/Otto Knudsen
Minimér udrulning på klienten Hvad skal udrulles på klienten? Som udgangspunkt: Konkrete implementationer af alle MBRO- og MBVO-klasser Dette vil vi som regel gerne minimere … Mulige tilgange: Definér MBRO vha. interfaces og udrul Interface.dll Definér MBVO vha. .NET-klasser som fx DataSet Repetition/Otto Knudsen
Design - Server Minimér antal kald fra klient til server, da: Ethvert kald går via netværket Ethvert kald er et potentielt nyt server-objekt Ethvert kald involverer marshalling Enhver reference til en property er også et kald Svartider er uforudsigelige … Retningslinjer: Færre og større metoder Metoder er transaktioner – Commit/Rollback før return Repetition/Otto Knudsen
Design - Klient Anvend factory-klasser og .config-filen Factory-klasser skjuler instantieringslogik Konfigurationsfilen kan specificere URL, formattering, channels, osv. Konfigurationsfilen kan redirigere new til at instantiere på serveren Repetition/Otto Knudsen
MathLibrary.dll namespace MathLibrary { public class SimpleMath : MarshalByRefObject { private static int classCount = 0; private int instanceCount; public SimpleMath() { this.instanceCount = ++SimpleMath.classCount; } public int Add(int a, int b) { return a + b; public int Sub(int a, int b) { return a - b; public int Count { get { return this.instanceCount; } } Repetition/Otto Knudsen
SAO - Wellknown Objects namespace MathServer { class Program { static void Main(string[] args) { ChannelServices.RegisterChannel(new HttpChannel(20001), false); RemotingConfiguration.RegisterWellKnownServiceType(typeof(SimpleMath), "SimpleMath.soap", WellKnownObjectMode.SingleCall); } namespace MathKlient { class Program { static void Main(string[] args) { RemotingConfiguration.RegisterWellKnownClientType(typeof(SimpleMath), "http://localhost:20001/SimpleMath.soap"); SimpleMath math = new SimpleMath(); } Repetition/Otto Knudsen
SAO – Activator.GetObject namespace MathServer { class Program { static void Main(string[] args) { ChannelServices.RegisterChannel(new HttpChannel(20001), false); RemotingConfiguration.RegisterWellKnownServiceType(typeof(SimpleMath), "SimpleMath.soap", WellKnownObjectMode.SingleCall); } namespace MathKlient { class Program { static void Main(string[] args) { ISimpleMath math = (ISimpleMath)(Activator.GetObject( typeof(ISimpleMath), "http://localhost:20001/SimpleMath.soap")); } Repetition/Otto Knudsen
Remoting gennem interface namespace IMathLibrary { public interface ISimpleMath { int Add(int a, int b); int Sub(int a, int b); int Count {get;} } namespace MathLibrary { public class SimpleMath : MarshalByRefObject, IMathLibrary.ISimpleMath private static int classCount = 0; private int instanceCount; public SimpleMath() {this.instanceCount = ++SimpleMath.classCount; } public int Add(int a, int b) {return a + b;} public int Sub(int a, int b) {return a - b;} public int Count { get { return this.instanceCount; } } } Repetition/Otto Knudsen
CAO namespace MathServer { class Program { static void Main(string[] args) { ChannelServices.RegisterChannel(new HttpChannel(20001), false); RemotingConfiguration.RegisterActivatedServiceType(typeof(SimpleMath)); } namespace MathKlient { class Program { static void Main(string[] args) { RemotingConfiguration.RegisterActivatedClientType(typeof(SimpleMath), "http://localhost:20001"); SimpleMath math = new SimpleMath(); } Repetition/Otto Knudsen
Serveropsætning med .config-filen Konfigurér og start serveren vha: RemotingConfiguration.Configure("???.exe.config", false); <system.runtime.remoting> <application> <service> <wellknown mode="SingleCall" objectUri="SimpleMath.soap" type="MathLibrary.SimpleMath, MathLibrary" /> <!-- <activated type="MathLibrary.SimpleMath, MathLibrary" /> --> </service> <channels> <channel ref="http" port="20001" /> </channels> </application> </system.runtime.remoting> Repetition/Otto Knudsen
Klientopsætning med .config-filen Konfigurér klient vha. nedenstående og skab remote-objekt med new: RemotingConfiguration.Configure("???.exe.config", false); </system.runtime.remoting> <application> <client displayName="MathKlientConfig"> <wellknown type="SimpleMath, MathLibrary" url="http://localhost:20001/SimpleMath.soap" /> </client> <channels> <channel ref="http" /> </channels> <!-- <client url="http://localhost:20001"> <activated type="SimpleMath, MathLibrary"></activated> --> </application> Repetition/Otto Knudsen
Remoting med web-server Den letteste måde at lave remoting er vha. IIS: IIS .DLL Klient.exe URL Server Repetition/Otto Knudsen
Hvordan? Der er fire punkter … Lav en komponent-dll til remoting Lav en web-applikation til at host’e dll’en Konfigurér web-serveren På klienten refereres til dll’en og objekterne skabes på serveren Repetition/Otto Knudsen
Design af web-serveren Beregningsobjekter lever på serveren Ét objekt pr. klient Dataobjekter overføres til klienten Marshalling Klient Data Data Beregn kald Proxy Stub Server Repetition/Otto Knudsen
Terminologi Beregningsobjekter er single-call MBRO Hvert RPC genererer et nyt beregningsobjekt på serveren Dataobjekter er MBVO De serialiseres og flyttes fysisk til klienten Repetition/Otto Knudsen
Konfiguration af web-serveren Tilføj følgende til web.config: Konfigurér IIS til at mappe til URL’ens extension, (.rem), til remoting URL-forespørgslen mappes nu til MathLibrary.SimpleMath <system.runtime.remoting> <application> <service> <wellknown mode="SingleCall" objectUri="SimpleMath.rem" type="MathLibrary.SimpleMath, MathLibrary"> </wellknown> </service> </application> </system.runtime.remoting> Repetition/Otto Knudsen
Konfiguration af klienten Sæt referencen til dll’en på sædvanlig vis tilgå objektet vha. RegisterWellKnownClientType() og new eller Activator.GetObject() eller konfigurér vha. .config-filen herunder: <system.runtime.remoting> <application> <client> <wellknown type="MathLibrary.SimpleMath, MathLibrary" url="http://localhost/MathService/SimpleMath.rem"> </wellknown> </client> </application> </system.runtime.remoting> Repetition/Otto Knudsen
Bemærk Hosting på IIS forsimpler udviklingen Nyt objekt for hvert kald forsimpler håndtering af hukommelse Nyt objekt for hvert kald forhindrer bevarelse af tilstand – mere skalérbart, men tilstande skal nu bevares i en fil, database eller på klienten … Repetition/Otto Knudsen
Sproghistorie Syntaks (struktur) Semantik (Indhold) Repetition/Otto Knudsen
Sproghistorie Sprog Lavniveau (maskinkode) Højniveau (C#, Java, Pascal, osv.) Maskinuafhængig kode, som omsættes til maskinkode via kompilering, fortolkning eller en mellemting af disse Repetition/Otto Knudsen
Sprogteori – Kompiler Kompiler Kildekode –> Kompiler –> Binær kode Repetition/Otto Knudsen
Sprogteori – Kompiler Kompilertyper Single Pass Multi Pass Load and go Debugging Optimering Repetition/Otto Knudsen
Sprogteori – Kompiler Kompiler Analyse (nedbryde) Leksikalsk analyse Scanning, Tokenizing Syntaksanalyse – Parsing Hierarkisk analyse Semantisk analyse Syntese (sammensætte) Repetition/Otto Knudsen
Sprogteori – EBNF BNF EBNF Backus-Naur-Form Extended Backus-Naur-Form Udvidet med { } og [ ] Findes i flere varianter Repetition/Otto Knudsen
Sprogteori - Analyse Leksikalsk analyse Syntaksanalyse – Parsing Opsplitning af input i brikker Syntaksanalyse – Parsing Sammensætning af brikker til sætninger, som opfylder en velbeskrevet struktur (mønster) Repetition/Otto Knudsen
EBNF – Elementer En EBNF-grammatik består af Produktionsregler Terminaler Nonterminaler Startsymbol Repetition/Otto Knudsen
EBNF – Produktionsregler Afsluttes med punktum | betegner valgmuligheder { } betegner nul eller flere gentagelser [ ] betegner nul eller én forekomst ( ) anvendes til at samle enheder Repetition/Otto Knudsen
EBNF – Eksempel Medlemsliste-EBNF medlemsliste = medlem {medlem}. medlem = navn fødselsår [kategori] ";". navn = bogstav {bogstav}. fødselsår = ciffer, ciffer, ciffer, ciffer. kategori = "junior"|"senior". bogstav = "a"|...|"å"|"A"...|"Å". ciffer = "0"|...|"9"|. Repetition/Otto Knudsen
EBNF EBNF-grammatikken Syntaktiske regler Beskriver, hvordan ”byggeklodserne” sammensættes … Semantiske regler Beskriver hvilke sammensætninger, der giver mening … Repetition/Otto Knudsen
EBNF Semantiske krav i EBNF-grammatikken Undgå derfor: Kan komplicere i unødig grad Undgå derfor: at inddrage semantiske krav, hvis det går ud over overskueligheden at rense helt for semantiske krav, hvis det går ud over forståeligheden Balancér overskuelighed og forståelighed! Repetition/Otto Knudsen
Syntaksstyret indlæsning Kontrol af, hvorvidt inddata overholder de syntaktiske krav beskrevet i EBNF-grammatikken 3 metoder Regelstyret indlæsning Tabelstyret indlæsning State Pattern "Single Symbol Lookahead" Repetition/Otto Knudsen
Syntaksstyret indlæsning Metode: Indlæsning af brikker Haves: Abstrakt beskrivelse af, hvorledes inddata skal se ud (EBNF) Konkret inddata-strøm Mål: Kontrol af overensstemmelse mellem konkret inddata og abstrakt beskrivelse (EBNF) Strategi: Konkretisér EBNF’en og abstrahér over inddata Repetition/Otto Knudsen
Syntaksstyret indlæsning Begreber Brik: Udeleligt sprogelement. Følge af tegn, som har selvstændig betydning i forhold til inddata Leksem: Brikkens værdi: Den originale streng, som indeholder en brik. Det er som regel det længste leksem, der afgør en brik. Repetition/Otto Knudsen
Syntaksstyret indlæsning Konkretisering af EBNF Fjern alle produktionsregler, hvor en brik findes på venstresiden Fjern derved overflødiggjorte produktionsregler Indsæt de valgte brikker på pladserne svarende til terminalerne Repetition/Otto Knudsen
EBNF – Eksempel 1 Medlemsliste-EBNF Konkretiseret EBNF Valgte brikker medlemsliste = medlem {medlem}. medlem = navn fødselsår [kategori] ";". navn = bogstav {bogstav}. fødselsår = ciffer, ciffer, ciffer, ciffer. kategori = "junior"|"senior". bogstav = "a"|...|"å"|"A"...|"Å". ciffer = "0"|...|"9"|. Konkretiseret EBNF medlem = navn fødselsår [kategori] semikolon. kategori = junior|senior. Valgte brikker semikolon, navn, fødselsår, junior, senior, andet, slut Repetition/Otto Knudsen
EBNF – Eksempel 2 Talfølge-EBNF Konkretiseret EBNF Valgte brikker talfølge = tal {"," tal}. tal = [fortegn] ciffer {ciffer} ["." ciffer {ciffer}]. ciffer = "0" | ... | "9". fortegn = "+" | "-". Konkretiseret EBNF talfølge = tal {komma tal}. tal = [fortegn] heltal [punktum heltal]. fortegn = plus | minus. Valgte brikker komma, heltal, punktum, plus, minus, andet, slut Repetition/Otto Knudsen
EBNF – Produktionsregler Typer af produktionsregler Rekursiv Regel, der beskrives vha. sig selv Regulær Regel med gentagelser { } Simpel Alle andre regler Repetition/Otto Knudsen
EBNF-grammatikker Typer af EBNF-grammatikker Direkte rekursiv Grammatik, der indeholder en rekursiv produktionsregel Indirekte rekursiv Grammatik, der indeholder en produktionsregel, der anvender en non-terminal, der andetsteds direkte eller indirekte refererer til reglen Regulær Ej-rekursiv grammatik, der indeholder regulære produktionsregler Simpel Alle andre grammatikker Repetition/Otto Knudsen
Regelstyret indlæsning Betegnelser f, f1, f2, … , fn betegner en følge af brikker og non-terminaler n betegner en non-terminal b betegner en brik s betegner en non-terminal eller en brik betegner den tomme mængde betegner den tomme følge Repetition/Otto Knudsen
Regelstyret indlæsning first Mængden af brikker, som følgen kan starte med follow Mængden af brikker, som kan efterfølge en given non-terminal eller brik Repetition/Otto Knudsen
first n = f1f2 n = f1|f2 n1 = [f1] n2 = {f1} first(b) = {b} first(n) = first(f1f2) = first(f1), f1 ≠ first(n) = first(f1f2) = first(f1) first(f2) n = f1|f2 first(n) = first(f1|f2) = first(f1) first(f2) n1 = [f1] first(n1) = first(|f1) = first(f1) n2 = {f1} first(n2) = first(|f1n2) = first(f1) Repetition/Otto Knudsen
first Buttom-up-strategi first(navn) = {navn} ... osv. med alle brikkerne first(kategori) = first(junior|senior) = first(junior) first(senior) = {junior, senior} first(medlem) = first(navn fødselsår [kategori] semikolon) = first(navn) = {navn} first(medlemsliste) = first(medlem {medlem}) = first(medlem) = {navn} Repetition/Otto Knudsen
follow n = f1sf2 n = f1[s]f2 n = f1{s}f2 n = f1{s} follow(startsymbol) = n = f1sf2 n = f1[s]f2 n = f1{s}f2 follow(s) indeholder first(f2) follow(s) indeholder follow(n), hvis f2 kan være n = f1{s} follow(s) indeholder first(s) Repetition/Otto Knudsen
follow Top-down-strategi follow(medlemsliste) = follow(medlem) = first({medlem}) = first(medlem) = {navn} follow(medlem) = follow(medlemsliste) = follow(medlem) = {navn} follow(navn) = first(fødselsår) = {fødselsår} follow(fødselsår) = first([kategori] semikolon) = {junior, senior, semikolon} follow(kategori) = first(semikolon) = {semikolon} follow(semikolon) = follow(medlem) = {navn} follow(junior) = follow(kategori) = {semikolon} follow(senior) = follow(kategori) = {semikolon} Repetition/Otto Knudsen
Eksempel – first/follow Sportsklub-EBNF sportsklub = medlem {medlem}. medlem = navn junior semikolon | navn senior semikolon. Brikker: navn, junior, senior, semikolon Bottom-up: first(navn) = {navn} first(junior) = {junior} first(senior) = {senior} first(semikolon) = {semikolon} first(medlem) = {navn} first(sportsklub) = {navn} Top-down: follow(sportsklub) = Ø follow(medlem) = {navn} follow(navn) = {junior, senior} follow(junior) = {semikolon} follow(senior) = {semikolon} follow(semikolon) = {navn} Repetition/Otto Knudsen
Krav til EBNF-grammatikken Lad n = f1|f2 så må der gælde, at first(f1) first(f2) = En EBNF opfylder krav 1, hvis alle produktionsregler med valgmuligheder opfylder krav 1 Repetition/Otto Knudsen
Krav til EBNF-grammatikken Hvis n kan være den tomme følge så må der gælde, at first(n) follow(n) = En EBNF opfylder krav 2, hvis alle produktionsregler , der kan være tomme, opfylder krav 2 Repetition/Otto Knudsen
Krav til EBNF-grammatikken Hvis krav 1 og 2 ikke er opfyldte Omskriv EBNF’en vha. venstrefaktorisering Lav ny EBNF … Repetition/Otto Knudsen
Venstrefaktorisering Givet n = ff1 | ff2| ... | ffn | andet (valgmulighed med fælles præfix f) Erstat n med følgende: n = f tmp | andet tmp = f1 | f2 | ... | fn Gentag indtil alle produktionsregler er renset for valgmuligheder med fælles præfix Bemærk, at produktionsregler med { } og [ ] implicit indeholder en valgmulighed Repetition/Otto Knudsen
Regelstyret indlæsning Baserer sig på 7 regler: Erklær en metode for hver produktionsregel, (non-terminal) [ ] medfører en if-sætning { } medfører en while-sætning | medfører en if-elseif-konstruktion Kan håndtere rekursive grammatikker Repetition/Otto Knudsen
Tabelstyret indlæsning Gør brug af tilstandstabel Gør brug af aktionstabel Gør brug af "Single Symbol Lookahead" Krav 1 og 2 stilles til grammatikkerne Kan ikke håndtere rekursive grammatikker Repetition/Otto Knudsen
Tabelstyret indlæsning Tilstandstabel Indeholder tilstandsovergange Tilstandsovergange beskriver, hvilke tilstande der efterfølger den aktuelle tilstand ved givent inddata Aktionstabel Indeholder aktioner Aktioner beskriver, hvad programmet skal udføre i en given tilstand ved givent inddata Repetition/Otto Knudsen