F3: Recursive descent, tokenisering, avbildningar och undantag. Carl Nettelblad

Relevanta dokument
F2: Algoritmanalys, sökning, sortering, recursive descent Carl Nettelblad

F3: OU2, undantag, avbildningar, listor och träd. Carl Nettelblad

Parsing med Recursive Descent, Avbildningsklasser. Syntaxdiagram. Syntaxdiagram och kodning expression. Betrakta följande uttryck

Obligatorisk uppgift: Numerisk kalkylator

Obligatorisk uppgift: Numerisk kalkylator

Obligatorisk uppgift: Numerisk kalkylator

Obligatorisk uppgift 5

Det är principer och idéer som är viktiga. Skriv så att du övertygar rättaren om att du har förstått dessa även om detaljer kan vara felaktiga.

Objektorienterad programmering i Java Undantag Sven-Olof Nyström Uppsala Universitet Skansholm: Kapitel 11

Idag. Exempel, version 2. Exempel, version 3. Ett lite större exempel

Objektorienterad programmering i Java Undantag Sven-Olof Nyström Uppsala Universitet Skansholm: Kapitel 11

Obligatorisk uppgift 5: Symbolisk kalkylator

Felhantering TDDD78, TDDE30, 729A

Tentamen Programmeringsteknik II för STS Skrivtid: Inga hjälpmedel.

List.java. List.java. Printed by Tom Smedsaas

Föreläsning 3. Stack

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Programmering A. Johan Eliasson

Inlämningsuppgift MiniPlotter

Klassen BST som definierar binära sökträd med tal som nycklar och enda data. Varje nyckel är unik dvs förekommer endast en

Objektorienterad Programmering (TDDC77)

Command line argumenter. Objektorienterad Programmering (TDDC77) Vad blir resultatet? Nu då? Ahmed Rezine. Hösttermin 2016

Undantagshantering. Fördjupad Java. Fel. Undantag. Fånga Undantag. Grupper av Undantag

Undantagshantering. Fördjupad Java. Undantag. Fel. Grupper av Undantag. Fånga Undantag

Länkade strukturer, parametriserade typer och undantag

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

public boolean containskey(string key) { return search(key, head)!= null; }

Undantag. Engelska: exceptions. Skansholm: exceptionella händelser

Föreläsning 3. Stack

F4. programmeringsteknik och Matlab

Föreläsning 3 Innehåll. Generiska klasser. Icke-generisk lista ArrayList, skiss av implementering. Icke-generisk lista Risk för fel

Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din kod överst i högra hörnet på alla papper.

OOP Objekt-orienterad programmering

Kungl. Tekn. Högskolan Förel 1, bild 1 Föreläsning 1: Introduktion ffl Kursinnehåll ffl Javarepetition ffl Referenser ffl Nyckelordet static ffl Klass

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

SMD 134 Objektorienterad programmering

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

Föreläsnings 9 - Exceptions, I/O

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Erik Nilsson, Institutionen för Datavetenskap, LiU

Klassdeklaration. Metoddeklaration. Parameteröverföring

Föreläsning 3: Booleans, if, switch

Att skriva till och läsa från terminalfönstret

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Tentamen Programmeringsteknik 2 och MN Skrivtid: Inga hjälpmedel.

Tentamen Programmeringsteknik II Inledning. Anmälningskod:

Obligatorisk uppgift: Symbolisk kalkylator

Objektorienterad Programkonstruktion. Föreläsning 4 8 nov 2016

F2 Datatyper och variabler. ID1004 Objektorienterad programmering Fredrik Kilander

Tentamen , Introduktion till Java, dtaa98, dtea53

TUTORIAL: KLASSER & OBJEKT

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Det finns en referensbok (Java) hos vakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Det är principer och idéer som är viktiga. Skriv så att du övertygar rättaren att du har förstått dessa även om detaljer kan vara felaktiga.

1 Uppgift 1. a) Skapar ett Company-objekt med hjälp av den överlagrade konstruktorn. Du kan själv välja värden på instansvariablerna.

Tentamen Programmeringsteknik II och NV2 (alla varianter) Skriv bara på framsidan av varje papper.

Obligatorisk uppgift 5: Symbolisk kalkylator

Observera. Tentamen Programmeringsteknik II Skrivtid:

Repetition av OOP- och Javabegrepp

Grafik, grafiska användargränssnitt och rörliga bilder

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

F7: Rekursiv till iterativ, sammanfattning, genomgång av omtentan Carl Nettelblad

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Repetition av OOP- och Javabegrepp

if (n==null) { return null; } else { return new Node(n.data, copy(n.next));

Outline. Objektorienterad Programmering (TDDC77) En frukt har ett namn. Man kan lägga en frukt i en korg... Hashing. Undantag. Ahmed Rezine.

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Grammatik. BNF-grammatik

Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din kod överst i högra hörnet på alla papper.

Testning av program. Verklig modell för programutveckling

Objektorienterad programmering i Java I. Uppgifter: 2 Beräknad tid: 5-8 timmar (OBS! Endast ett labbtillfälle) Att läsa: kapitel 5 6

Kopiering av objekt i Java

Konstruktion av klasser med klasser

JAVAUTVECKLING LEKTION 4

DIAGNOSTISKT PROV. Tid. Hjälpmedel. Antaganden. Rättning. Övrigt. Diagnostiskt Prov. Klockan Inga

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Muddy. Funktioner / metoder. Punktnotation. Evalueringsordning

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Objektorienterad Programmering (TDDC77)

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

Dagens text. Programmeringsteknik. Mer om Scanner-klassen. Dialogrutor (klassen JOptionPane) Bubbelsortering. Omslagsklasser.

Objektorienterad Programmering (TDDC77)

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

Tentamen i Programmering

Bankkonto - övning. Övning 2 Skriv en metod, geträntan, som returnerar räntan.

Tentamen OOP

kind spelling Scanning

Programmering för språkteknologer I, VT2012. Rum

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

TDDC77 Objektorienterad Programmering

F5: Debriefing OU2, repetition av listor, träd och hashtabeller. Carl Nettelblad

LÖSNINGSFÖRSLAG TENTAMEN

Föreläsning 2 Programmeringsteknik och C DD1316. Programmering. Programspråk

TENTAMEN OOP

Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din anmälningskod överst i högra hörnet på alla papper.

Lösningsförslag, tentamen FYTA11 Javaprogrammering

Fördjupad Java. Undantagshantering. Fel

Transkript:

F3: Recursive descent, tokenisering, avbildningar och undantag Carl Nettelblad 2017-04-03

Säg vad du vill göra Varför skriver vi kod? För att få datorn att göra det vi vill För att själva läsa koden För att andra ska läsa koden Varför läser vi kod? För att rätta fel För att förbättra/förändra den för nya behov För att använda den (anropa den) på rätt sätt

VAR TYDLIG! Mycket hellre än var smart

Typiska idiom Kolla att stacken antingen är tom, eller att den inte innehåller ett element som är lägre än det som ska läggas till och lägg i så fall till elementet, kasta annars ett undantag Lite rörigt?

Bättre? Kolla att stacken, om den inte är tom, inte innehåller ett element som är lägre än det som ska läggas till Kasta i så fall ett undantag Lägg till elementet Även om villkoret i punkt 1 är lite rörigt är det tydligt att vi räknar med att punkt 2 utförs

I kod if (stack.isempty() x < stack.get(stack.size()-1)) { stack.add(x); } else { throw new RuntimeException("Tried to push larger element"); }

I kod 2 if (!stack.isempty() && x > stack.get(stack.size()-1)) { throw new RuntimeException("Tried to push larger element"); } else { stack.add(x); }

I kod 3 if (!stack.isempty() && x > stack.get(stack.size()-1)) { throw new RuntimeException("Tried to push larger element"); } stack.add(x); Normalfallet är inte gömt i en if-sats Alla håller inte med, en del tycker att det är viktigare att en metod alltid avslutas på samma ställe vi kommer tillbaka till det Mer om OU1 nästa vecka

Obligatorisk uppgift 2 Numerisk kalkylator 7 * (5 + 9) 7 * 5 + 9 1 + (2 + (3 + (4 + (5 + 6)))) 1=x (variabeltilldelning åt höger, inte som Java) x + 3 sin(0.5=x)=y y ans (alltid svaret på föregående operation)

Vad ska göras? Läs en rad med ett uttryck Tolka det uttrycket Parsing, vi använder recursive descent som angreppssätt Använd en tokenizer för att dela upp uttrycket i ord Hantera fel systematiskt, med undantag (exceptions) Evaluera uttrycket Med de variabler som finns definierade Spara nya variabeltilldelningar Med avbildningsklasser (Map, TreeMap, HashMap)

Evaluering av aritmetiska uttryck a + (b 1) d e (f + g h)/4 Med prioritetsregler (vänster till höger, multiplikation före addition, parenteser har företräde), delas detta upp i följande uttryck: t 1 = b 1 t 2 = t 1 d t 3 = g h t 4 = f + t 3 t 5 = e t 4 t 6 = t 5 /4 t 7 = a + t 2 t 8 = t 7 t 6 Hur ska vi skriva ett program som hittar den ordningen?

Recursive descent a + (b 1) d e (f + g h)/4 Beskriv uttrycket utifrån, från lägst prioritet Tre termer a b 1 d e (f + g h)/4 Termerna ska beräknas för sig och adderas/subtraheras

Recursive descent Fortsätt nedåt Vi fortsätter att dela upp uttrycket i delar med högre och högre prioritet Nästa steg är faktorer, varje term består av en eller flera Exempel: Termen e (f + g h)/4 Ingående faktorer: e variabel f + g h uttryck 4 konstant Faktorerna beräknas var för sig och multipliceras/divideras sedan tillsammans.

Sammanfattning Ett uttryck En sekvens av en eller flera termer, åtskilda med + eller En term En sekvens av en eller flera faktorer, åtskilda med * eller / En faktor Ett tal eller ett uttryck omgivet av parenteser Rekursion!

Beskriva syntax BNF (Backus-Naur-form) expression ::= term [( + / - ) term]* Syntaxdiagram

Beskriva syntax Pseudokod ( nästan Java) double expression() double sum = term() while ( nästa tecken + eller - ) Läs förbi tecknet if ( det var ett + ) else sum = sum + term() sum = sum - term() Syntaxdiagram return sum Ett uttryck är en sekvens av en eller flera termer, åtskilda med + eller

Vad är viktigt här? Metoden term får inte läsa för långt term måste själv veta när den ska sluta Men som vi sett byggs en term av factor som i sin tur kan vara vilket uttryck (expression) som helst inom parentes Löser rekursionen det åt oss?

Term Pseudokod double term() double prod = factor() while ( nästa tecken * eller / ) Läs förbi tecknet if ( det var ett * ) else prod = prod*factor() prod = prod/factor() Syntaxdiagram return prod En term är en sekvens av en eller flera faktorer, åtskilda med * eller /

Factor Pseudokod double factor() if (nästa tecken ( ) else Läs förbi tecknet double val = expression() Läs förbi ) return val Syntaxdiagram return number() En faktor är ett tal eller ett uttryck omgivet av parenteser

Kommentarer Det är alltid nästa symbol som avgör vilken väg som ska väljas Inte titta i förväg Vi blandar inläsning av tecken och tal - man vet inte i förväg om man ska läsa ett tecken eller ett tal. Koden skall hoppa över blanktecken Det finns ingen syntaktisk beskrivning av tal Övning: konstruera kod/diagram för number

Kommentarer Hur vet man när ett uttryck är slut? Vad är basfallet/basfallen i rekursionen? Vad händer om man ger felaktiga indata? Vilka typer av fel kan förekomma?

Dela upp indata Vi vill läsa ord, tal, operatorer strunta i blanksteg 5+3, 5 + 3, 5+ 3, 5 + 3 ska se likadana ut för koden En fil eller det du skriver på tangentbordet blir en ström av tecken En tokeniser går från teckenströmmen till en ström av ord, tokens Vi har redan stött på Scanner Vad som är ett giltigt ord beror lite på tillämpningen. Är kod-exempel ett eller två ord?

Stokenizer Vi tillhandahåller en färdig klass Stokenizer som är en anpassning av standardklassen StreamTokenizer. Den är anpassad för det vi behöver i den här uppgiften. Följande olika typer av tokens/ord finns: Tal (number): börjar med siffra Ord (word): börjar med bokstav Radslut (EOL, end of line) Slut på strömmen (EOS, slut på infil/insträng) Övriga tecken

Stokenizer Tre viktiga konstruktorer: public Stokenizer() Läs från standard input (tangentbordet) public Stokenizer(String line) Läs strängen line public Stokenizer(FileReader r) Läs från den redan öppnade filen som representeras av r Ett objekt som väl skapats användas överallt där ett sådant objekt behövs Oavsett vilken konstruktor som användes

Tre huvudfamiljer av metoder int nexttoken() Gå framåt i strömmen boolean isxxx() Är aktuellt token av typen XXX (Number/Word/EOL/EOS) typ getxxx() Returnerar aktuellt tokeninnehåll. Ger fel om det inte matchar aktuell tokentyp. Går inte att ta reda på tal om det är ett ord, o.s.v.

Övriga metoder String tostring() Beskriver aktuellt token i textform med diverse information String gettoken() Aktuellt token som sträng String getprevioustoken() Närmast föregående token som sträng

Använda Stokenizer Det går lätt att hämta Stokenizer Dokumentation: http://www.it.uu.se/edu/course/homepage/prog2/publiccode/stokenizer/doc Källkod: http://www.it.uu.se/edu/course/homepage/prog2/publiccode/stokenizer/stokenizer.java Demonstrationsprogram http://www.it.uu.se/edu/course/homepage/prog2/publiccode/stokenizer/stokenizertest.java Med exempel på läsning från tangentbord, sträng och fil

Felhantering Olika språk och olika problem har olika filosofi om felhantering Är det viktigaste att programmet fortsätter köra? Kanske en bra idé att bara köra vidare, även om fel inträffar Inte säkert att det går/ger något rimligt resultat Är det viktigaste att programmet ger rätt svar? Se till att fel alltid rapporteras/hanteras

Hur kan vi hitta ett fel? Metoder kan returnera när något går fel if (x.move()!= STATUS_OK) { return false; } if (x.eat()!= STATUS_OK) { return false; } if (x.sleep()!= STATUS_OK) { } return false; Om vi glömmer att kolla feltillstånd, eller gör det på fel sätt, kan det vara väldigt svårt att hitta grundorsaken Det här sättet att hantera fel är vanligt i lågnivåspråk, som C Många farliga säkerhetsbuggar kommer av felaktig felhantering

Varför blir detta svårt? Flera lager av metoder kan anropa varandra Om kalkylatorn är rekursiv i flera led och använder Stokenizer, som använder Java-biblioteken för att läsa från en fil som finns på en USB-sticka som du tog ur datorn Vilken del av koden vet vad som är rätt sak att göra? Felet måste bubbla upp i flera lager av anrop Varje metod skulle behöva kunna returnera en beskrivning av vilka fel som inträffade Bökigt, ändå risk att någon glömmer

Javas lösning - Undantag En metod i Java kommunicerar med anroparen genom returvärdet och förändringar av de objekt som skickades in och genom att potentiellt kasta ett undantag (Exception) Eller mer exakt en Throwable (basklass till Exception) Vissa typer av drastiska fel som OutOfMemoryError och StackOverFlowError är Throwable, men inte Exception

Vad är då ett undantag? En instans av en klass Egentligen som vilken klass som helst Ärver (direkt/indirekt) från java.lang.exception Man talar om en subklass till Exception Klassens typ och innehåll beskriver ett fel som har inträffat Arv är mycket vanligt i objektorienterad programmering Det viktigaste är att en instans av en subklass kan användas överallt där basklassen används Varje FileNotFoundException är ett Exception. Men varje Exception är inte ett FileNotFoundException.

Klasshierarki java.lang.object java.lang.throwable java.lang.exception java.io.ioexception» java.io.filenotfoundexception java.lang.runtimeexception java.lang.error java.lang.virtualmachineerror» Java.lang.StackOverFlowError Naturligtvis många fler Mycket vanligt att skapa egna undantagsklasser

Inte vilken klass som helst Det är förstås bra att vi har ett sätt att kategorisera fel Java har inbyggt stöd i språket för att hantera undantag Undantag kan kastas När ett fel inträffar Metoden som kastar slutar köras Undantag propageras Från den metod som kastar, till den metod som anropade den, till den metod som anropade den

Fånga undantag Undantag kan fångas Den metod i anropskedjan som begriper sig på felet kan fånga det Slutar propagera Ibland vill man återkasta (vi kunde inte hantera hela felet, men vi städar upp lite på vägen) Då propagerar det vidare Ett undantag som inte fångas någonstans slutar i att hela programmet slutar köras och att ett fel skrivs ut Det har vi sett många gånger

Vad gör man när man fångar? Olika svar kan vara rätt Ovanligt: Fånga utan att göra någonting Ger fel som är svåra att felsöka Vanligt: Skriva ut (på skärmen eller i loggfil) att ett fel inträffade Försöka igen Använda någon typ av reservlösning För kalkylatorn: Rapportera felet och be användaren göra om

Tillbaka lite till SpecialStack Vi har redan kastat RuntimeException throw new RuntimeException("Stack is empty."); throw är det nya här, resten är helt vanlig Javakod som vi redan sett Skapa ett nytt objekt, anropa konstruktorn som tar en sträng Många undantagsklasser har konstruktorer som tar emot en sträng som fungerar som felmeddealnde

Hur borde vi ha gjort? Egen undantagsklass public class SpecialStackException extends RuntimeException { } public SpecialStackException(String msg) { } super(msg); // anropar basklassens konstruktor Inte mer än så! Bara en konstruktor som tar felmeddelandet.

Undantag i kalkylatorn I OU2 ska vi ha två egna undantagsklasser: public class SyntaxException extends RuntimeException { } public SyntaxException(String msg) { } super(msg); public class EvaluationException extends RuntimeException { public EvaluationException(String msg) { super(msg); } }

RuntimeException eller Exception Java skiljer egentligen på RuntimeException och Exception RuntimeException kan kastas var som helst Andra subklasser till Exception får bara kastas om de fångas eller om metoden anger throws i metodhuvudet Om SyntaxException ärvde från Exception skulle exempelvis metoden term behöva se ut något så här double term(stokenizer t) throws SyntaxException Vi skippar detta och väljer därför att ärva från RuntimeException

Var upptäcks syntaxfel i Inte där! kalkylatorn? Inte där heller! Men här! Däremot kan expression sluta för tidigt, om meningen var att läsa en hel rad

Vad kan gå fel? Slutparentes saknas Första token är varken startparentes eller ett tal Vad göra? Kasta SyntaxException!

Exempel i kod if (tokenizer.getchar()!= ) ) { throw new SyntaxException("Expected ) but found " + tokenizer.gettoken()); } Detta propageras tills det fångas

Fånga i kod Om ett uttryck är ogiltigt är det koden som bad om att parsa uttrycket som kan hantera felet I en tänkt main-metod i lösningen while (true) { try { } System.out.print("? "); double value = expression(); System.out.println("Value: " + value); } catch (SyntaxException se) { System.out.println("Syntax error: " + se.getmessage(); // Skip to end of line... } Koden under catch körs bara om ett SyntaxException inträffar. Om inget undantag inträffar, körs den inte. Om ett annat undantag inträffar, fortsätter det att propageras. Varför är det viktigt att ordna Skip to end of line?

Fånga undantag Varför skriver vi inte catch (Exception e) i stället? Då hanterar vi alla fel. Men vi vet inte vad felet egentligen är. Är åtgärden att läsa till slutet av raden och sedan frågan efter nästa uttryck rätt i alla situationer?

Undantag eller assert Undantag är ett sätt att hantera fel Fel som det går att undvika, som antas kunna hända i normal drift assert är ett sätt att uttrycka saker som alltid ska gälla Kan användas av automatiska verktyg för att analysera koden Om man kör koden med vissa inställningar kastas ett Error (inte Exception) Inte meningen att det ska fångas eller något man ska lita på, bara ett sätt att identifiera misstag under utveckling Skillnad på fel under körning och logiska fel/misstag i koden

Avbildningar - Map Vi har använt arrayer och listor (ArrayList) Java har inbyggt stöd för fler datastrukturer Avbildningar bland de mest användbara Nycklar av en datatyp Högst ett värde per nyckel i avbildningen Samma värde kan förekomma för flera nycklar Vanligt att nycklarna är strängar Namn och tillhörande värden I kalkylatorn kan det vara variabelnamn och deras värden

I kod import java.util.treemap; import java.util.hashmap; HashMap<String, Double> vars = new HashMap<String, Double>(); vars.put("x", 15.0); vars.put("y", vars.get("x")); if (!vars.containskey("y")) { System.out.println("Strange, key just added does not exist."); }

Försöka läsa nyckel som inte finns if (vars.get("z") == null) { System.out.println("Getting a key which does not exist yields null, not an Exception"); } Fel som bara indikeras med nullvärde, stor risk att man får ett NullPointerException när det värde man plockade ut ska användas Svårt att se att det berodde på att det saknades i avbildningen Att spara det utplockade värdet i en double ger detta

double och Double double är en primitiv typ Vi kan inte lagra referenser till primitiva typer i Java java.lang.double är en klass Kapslar in en double ( boxing ) I en ArrayList, HashMap eller liknande lagras alltid objekttyperna

Sammanfattning Kod ska vara tydlig Nästa uppgift: numerisk kalkylator Rekursiv parsning av tokens Undantag hjälper oss att skriva rak kod Utan att missa att hantera felen Avbildningar är flexibla datastrukturer