Obligatorisk uppgift: Symbolisk kalkylator

Relevanta dokument
Obligatorisk uppgift 5

Obligatorisk uppgift 5: Symbolisk kalkylator

Obligatorisk uppgift 5: Symbolisk kalkylator

Obligatorisk uppgift: Numerisk kalkylator

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

Observera. Tentamen Programmeringsteknik II Skrivtid:

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

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

Obligatorisk uppgift: Numerisk kalkylator

Obligatorisk uppgift: Numerisk kalkylator

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.

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.

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

Tentamen Programmeringsteknik II Skrivtid: Hjälpmedel: Java-bok (vilken som helst) Skriv läsligt! Använd inte rödpenna!

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

Tentamen Programmeringsteknik II Skrivtid: Hjälpmedel: Java-bok (vilken som helst) Skriv läsligt! Använd inte rödpenna!

TDDC77 Objektorienterad Programmering

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

Klasshierarkier - repetition

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

Inlämningsuppgift MiniPlotter

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

Klassdeklaration. Metoddeklaration. Parameteröverföring

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

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

Konstruktion av klasser med klasser

kl Tentaupplägg

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

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

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

2I1049 Föreläsning 5. Objektorientering. Objektorientering. Klasserna ordnas i en hierarki som motsvarar deras inbördes ordning

Parameteröverföring. Exempel. Exempel. Metodkropp

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

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

Programmering A. Johan Eliasson

Programstruktur och terminologi. Programmet producerar följande utskrift i terminalfönstret: Ett Javaprogram består av en eller flera klasser

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

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

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

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

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

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.

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

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

Objektorienterad programmering D2

Classes och Interfaces, Objects och References, Initialization

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

Klasshierarkier. Klasser kan byggas på redan definierade klasser

Tentamen Programmeringsteknik II Inledning. Anmälningskod:

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

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

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

Laboration 1: Figurer i hierarki

Tillämpad Programmering (ID1218) :00-13:00

Föreläsning 5 (6) Metoder. Metoder Deklarera. Metoder. Parametrar Returvärden Överlagring Konstruktorer Statiska metoder tostring() metoden javadoc

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

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

Introduktion C-programmering

Föreläsning 1 & 2 INTRODUKTION

F2 Datatyper och variabler. ID1004 Objektorienterad programmering Fredrik Kilander

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

Beräkningsvetenskap föreläsning 2

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

Tentamen i Programmering

LÖSNINGSFÖRSLAG TENTAMEN

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

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

Variabler som hör till enskilda objekt. Deklareras på översta nivån i klassen och i regel som private.

Repetition C-programmering

TENTAMEN I PROGRAMSPRÅK -- DVG C kl. 08:15-13:15

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Classes och Interfaces, Objects och References Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Programmering II (ID1019) :00-17:00

DAT043 - Föreläsning 7

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

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 14-18

PROMETHEUS. Ett typat, objektorienterat programmeringsspråk av Tim Andersson.

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

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

Objektorienterad programmering i Java

Översikt över Visual Basic

OMTENTAMEN I PROGRAMSPRÅK -- DVG C kl. 08:15-13: 15

1 Datorn som miniräknare. 1.1 Räkneoperationer. 1.2 Variabler

Tentamen ID1004 Objektorienterad programmering October 29, 2013

OOP Objekt-orienterad programmering

Rekursion och induktion för algoritmkonstruktion

Chapter 4: Writing Classes/ Att skriva egna klasser.

Datalogi I, grundkurs med Java 10p, 2D4112, Fiktiv tentamen, svar och lösningar och extra kommentarer till vissa uppgifter 1a) Dividera förs

Tentamen OOP

Abstrakt klass. DD2385 Programutvecklingsteknik Några bilder till föreläsning 4 31/ Exempel: Implementation av Schackpjäser.

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

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

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

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

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Checklista. Föreläsning 1-2 Innehåll. Programmering.

Interface. Interface. Tobias Wrigstad (baserat på bilder från Tom Smedsaas) 3 december 2010

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

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

Användarhandledning Version 1.2

Transkript:

Informationsteknologi Programmeringsteknik II 22 augusti 2018 Obligatorisk uppgift: Symbolisk kalkylator Moment: Dynamiska strukturer (särskilt trädstrukturer), klasshierarkier, arv, dynamisk bindning, polymorfi, undantag samt att läsa och förstå kod. Uppgiften består av att i första hand sätta sig in i ett existerande program och sedan modifiera och bygga ut det. (Enligt många före detta studenter är detta en av de vanligaste första arbetsuppgifterna ni kommer att drabbas av när ni kommer ut verkligheten) Programmet blir betydligt större än de föregående programmen ni har skrivit och det slutliga programmet kommer att innehålla närmare 30 klasser. För att det skall gå att genomföra uppgiften krävs det att du följer de instruktioner som vi ger i både skriftlig och muntlig form. Du kommer med största sannolikhet att behöva flera genomläsningar av detta dokument för att förstå alla detaljer. Uppgiftsbeskrivning Du skall utveckla en kalkylator som, till skillnad från den numeriska kalkylatorn i uppgift 2, kan utföra symboliska operationer som derivering. I den numeriska kalkylatorn lästes och evaluerades uttryck direkt i parsern. I den här uppgiften ska ni i stället bygga upp en intern representation av det inlästa uttrycket och sedan evaluera den. Resultatet av en evaluering kommer att vara ett symboliskt uttryck och inte bara ett numeriskt värde. För uttryck med numeriska värden skall det fungera som tidigare. Exempel: Input : 2*(-3-1+6)/0.5 + 0.5 Result : 8.5 Input : log(exp(ans)) Result : 8.5 Input : 1=x Result : 1.0 Input : (sin(x)*sin(x) = y) + cos(x)*cos(x) Result : 1.0 Input : y Result : 0.7080734182735712 Input : exp(2.0*x)+x=y Result: 8.38905609893065 I språk som skall hantera uttryck behöver man ett explicit sätt att ange om man menar uttrycket som det står eller värdet av uttrycket. Antag att man i sista uttrycket i exemplet ovan vill att y skall få uttrycket exp(2.0*x)+x som värde, inte värdet av uttrycket (8.38905609893065). För detta för vi in en kvot-operator ("). Exempel: 1

Input : "(exp(2*x) + x) = y Result: exp(2.0*x)+x Input : y Result: exp(2.0*x)+x Input : ans Result: exp(2.0*x)+x Input : "y Result: y Värdet av ett kvotat utttryck är alltså uttrycket själv. Vi använder apostrofen ( ) som binär operator för derivering (se syntax-diagrammen nedan). (Observera att om man i Java-kod vill skriva en teckenkonstant som innehåller en apostrof så måste man sätta en backslash framför apostrofen: \.) Exempel: Input : exp(x*x+1) x Result: 0.0 Input : "exp(x*x +1) x Result : 2.0*x*exp(x*x+1.0) Input : "exp(x*x +1) = y Result : exp(x*x+1.0) Input : y x Result : 2.0*x*exp(x*x+1.0) Input : "y x Result : 0.0 Observera att deriveringsoperatorn evaluerar det som står till vänster därför blir resultatet av den första input-raden 0. Om man hela tiden vill att t ex x skall betyda x och inte värdet av x kan man ge x det symboliska värdet x: 2

Input : "x=x Result : x Input : sin(3*x) x Result : 3.0*cos(3.0*x) Input : x*x + "a*x = y Result : x*x+a*x Input : y Result : x*x+a*x Input : y x Result : 2.0*x+a Input : y x x Result : 2.0 Input : exp(y x x - 1) Result : 2.7182818284590455 Input : exp((y x x - x x)*x) + x Result : exp(x)+x I exemplet ovan har y fått värdet x*x + a*x. Hur skall vi göra om vi vill se vad y får för värde om vi ger x ett numeriskt värde? Vi behöver ett sätt att säga att vi vill ha värdet av värdet av y. Det kan vi göra med evaluerings-operatorn (&). Denna unära operator evaluerar sin evaluerade operand. Exempel: Input : y Result : x*x+a*x Input : &y *** Evaluation error: Undefined varible: a Input : 2 = a Result : 2.0 Input : &y Result : x*x+2.0*x Input : 3 = x Result : 3.0 Input : &y Result : 15.0 Input : "z = a Result : z Input : &y Result : 9.0+z*3.0 Input : 100 = z Result : 100.0 Input : &y Result : 9.0+z*3.0 Input : &&y Result : 309.0 3

Syntaxdiagram Syntaxen definieras av nedanstående diagram. Klassen Calculator (som är helt given) hanterar satser med följande syntax: statement EOL quit EOL vars file word assignment Kommandot file används för att läsa indata från en fil. 4

Parsern använder väsentligen samma syntaxdefinition som tidigare men med några tillägg. Metoden factor hanterar deriveringar och primary är kompletterad med eval- och kvotoperationerna. assignment expression expression term = word + eller term primary factor ( assignment ) * eller / funcion name factor variable primary number word unary operator primary I diagrammen står function name för sin, cos, exp, log, abs (absolutbelopp) samt unary operator för - (unärt minus), " (kvot) eller & (evalaluering). 5

Programdesign Intern representation av uttryck Programmet skall läsa uttrycken och bygga upp en internrepresentation som lämpar sig för evaluering. Ni skall använda en trädstruktur där operatorer och funktioner lagras i de interna noderna och konstanter och variabler i löven. Det matematisk uttrycket sin x + 5a 3(u + 1) = z = t skall skrivas in som sin(x) + 5*a - 3*(u+1) = z = t = = t z och representeras av vidstående träd. + * En utskrift av trädet (oevaluerat) blir sin(x) + 5.0*a - 3.0*(u+1.0) = z = t sin * 3 + x 5 a u 1 Naturligtvis skall även eval- kvot- och deriveringsoperatorerna representeras i trädet. Exempel: = " t Uttrycket "(sin(&x) x = y) = t = skall representeras som: y sin x & x Gemensamt för alla noder är (bl a) att de skall kunna evalueras men evaluering görs olika beroende på vad det är för typ av nod (konstant, variabel, addition,... ). Eftersom noderna ska kunna vara av olika typer (operatorer, funktioner, variabler, konstanter,... ) är det lämpligt att implementera dem i en klasshierarki med en generell basklass som skulle kunna kallas SymbolicExpression. Av layout-skäl använder vi dock det kortare namnet Sexpr eftersom detta kommer att vara oerhört frekvent i koden. Alla operationer (+, -,... ) och alla funktioner (sin, cos,... ) skall ha egna klasser. Det skall också finnas en klass för variabler och en för konstanter. Det finns tre tydligt urskiljbara grupper av noder: de med två operander (binära operatorer), de med en operand (funktioner och unära operatorer) och de utan operander (konstanter och variabler). Det är inte bara antalet operander (2, 1, 0) som är gemensamt för varje grupp utan även vissa metoder. Sålunda kan bl a tostring-metoderna skrivas 6

på samma sätt t ex för alla binära operatorer. Således skall man samla binära operatorer under klassen Binary och unära operatorer (inklusive funktioner) under klassen Unary. Eftersom funktioner och unära operatorer (unärt minus, kvot och evaluering) delvis skall hanteras på olika sätt (olika tostring()- metoder) så finns det två underklasser till Unary: Function och Operator. Av symmetriskäl är det lämpligt att samla konstanter och variabler under klassen Atom även om det nog inte finns så mycket som kan utnyttjas gemensamt mellan dessa två grupper. Det leder till följande design (ytterligare metoder behöver tillföras): Sexpr abstract String getname() abstract Sexpr eval(map) abstract int priority() Sexpr diff(sexpr) double getvalue() boolean isconstant() boolean isconstant(double) Atom abstract Unary abstract Binary abstract String tostring() Sexpr operand Sexpr left Sexpr right String tostring() Variable String ident Sexpr eval(map) String getname() Sexpr diff(sexpr) Operator abstract String tostring() Function abstract String tostring() Addition Subtraction Multiplication Division Constant Evaluation Sin Assignment double value Quotation Cos Differentiation Sexpr eval(map) String getname() Sexpr diff(sexpr) boolean isconstant() boolean isconstant(double) double getvalue() Negation Sexpr eval(map) String getname() Sexpr diff(sexpr) Exp Log Sexpr eval(map) Abs String getname() Sexpr eval(map) Sexpr diff(sexpr) String getname() Sexpr eval(map) String getname() int priority() Obs 1: Konstruktorer är inte angivna. Obs 2: Det är inte säkert att alla lövklasser ska implementera alla metoder. Differentiation, Assignment, Evaluation och Qotation ska t ex inte ha någon diff-metod. 7

Basklassen Sexpr bör således ha följande utseende. public abstract class Sexpr{... Ett exempel på en klass på mellannivån i hierarkin är Unary: public abstract class Unary extends Sexpr { protected final Sexpr operand; public Unary(Sexpr operand){ this.operand = operand; Hur bygger man internstrukturen? I detta program är det parserns uppgift att bygga internstrukturen. Parserns metoder skall alltså inte returnera beräknade värden utan referenser till skapade noder. Parsern skall alltså ha samma struktur (samma metoder) som i den numeriska kalkylatorn men den skall inte utföra några beräkningar metoderna skall i stället returnera referenser till de de skapade noderna, skall inte känna till mappen med variabelvärden och skall upptäcka syntaxfel som tidigare men inte beräkningsfel. (Den känner ju inte till några variabelvärden.) Ett anrop till statement skall alltså returnera en trädrepresentation av hela det uttryck som har skrivits på raden. Exempel: Parsermetoden expression får följande uteseende: public Sexpr expression() { Sexpr sum = term(); int c; while ((c=tokenizer.getchar())== + c == - ) { tokenizer.nexttoken(); if (c== + ) { sum = new Addition(sum, term()); else { sum = new Subtraction(sum, term()); return sum; Hur gör programmet för att skriva ut uttryck? Som vanligt använder man tostring()-metoder för att skapa textrepresentationer av de lagrade uttrycken. Dessa metoder gör i princip en inordertraversering av trädet. Ett problem är att i trädet är evalueringsordningen given av strukturen men i den externa representationen bestäms den av prioriteter och parenteser. Således måste tostring-metoderna, vid behov, sätta ut parenteser för att uttrycken skall bli korrekta. Initialt kan man göra det lätt för sig genom att alltid sätta ut parenteser men det blir inte så vackert. 8

Eftersom parenteshanteringen kan göras på samma sätt för alla unära respektive alla binära operatorer så placeras tostring-metoderna i klasserna Unary respektive Binary. Själva operatornamnet erhålles med getname() Så här ser klassen Operator ut med en simpleminded version (dvs en som sätter ut parenteser var sig det behövs eller ej) av tostring: public abstract class Operator extends Unary { public String tostring() { return getname() + "(" + operand.tostring() + ")";... Variabelvärden För att hålla reda på variablers värden skall en TreeMap användas som tidigare. (Varför lägger man inte värdet som en egenskap hos variabeln?) Eftersom variablerna identifieras av sitt namn och värden är symboliska uttryck blir deklarationen: Map<String,Sexpr> variables = new TreeMap<String,Sexpr>(); Variabellistan skall användas av evalueringsmetoderna (inte av parsern)! Klassen Calculator Klassen Calculator är given. Se http://www.it.uu.se/edu/course/homepage/prog2/ht18/assignments/symcalc/code/allfiles/calculator.java Den är mycket lik motsvarande klass i uppgift 3. Den centrala delen hanterar objekt av typen Sexpr i stället för typen double som i uppgift 3: Sexpr parsed = parser.assignment(); System.out.println("Parsed: " + parsed); // For debugging purposes Sexpr value = parsed.eval(variables); variables.put("ans", value); System.out.println("Result: " + value.tostring()); Till skillnad från i körexemplen i detta dokument skrivs alltså även resultatet av parsningen ut, vilket underlättar både vid felsökning och vid redovisningen. Symbolisk evaluering Som synes ovan evalueras ett lagrat uttryck genom att eval-metoden för dess rotnod anropas. Beroende på rotnodens typ kan eventuella operanders eval-metoder anropas. Dessa metoder utför helt enkelt en postordertraversering av trädet. En nods eval-metod avgör först vad som skall göras med operanderna. De flesta operatorers operander skall evalueras. Några undantag finns dock: tilldelningsoperatorn och deriveringsoperatorn som båda skall evaluera sin vänstra men inte sin högra operand (1+2 = a tilldelar värdet av 1+2 dvs 3 till variabeln a inte till värdet av variabel a) samt Quote-operatorn som inte evaluerar sin enda operand. 9

Till evalueringsmetodernas hjälp finns klassen Symbolic som har ett antal statiska metoder som utför olika symboliska operationer: symbolisk addition, subtraktion,.... Dessa metoder utför numeriska operationer när det går och gör förenklingar när det går men returnerar alltid ett uttryck av typ Sexpr. Exempel: Sinusklassens evalueringsmetod ser typiskt ut så här: public Sexpr eval(map<string,sexpr> map){ return Symbolic.sin(operand.eval(map)); och metoden sin i klassen Symbolic har följande utseende: public static Sexpr sin(sexpr arg){ if (arg.isconstant()) return new Constant(Math.sin(arg.getValue())); else return new Sin(arg); Observera att metoderna i Symbolic aldrig anropar någon eval-metod! Liknande metoder skrivs för de övriga funktionerna samt för alla aritmetiska operatorer. Om det är möjligt att utföra en numerisk beräkning ska det ske, annars får man utföra operationen symboliskt genom att skapa en ny nod av lämplig typ. Observera dock att metoden alltid måste returnera ett Sexpr, även om den lyckas beräkna ett numeriskt värde. De icke-aritmetiska operatorerna (=, " och &) behöver inte ha några metoder i klassen Symbolic. Exemplet ovan visar att det även finns ett behov av metoder som isconstant() och getvalue() i klassen Sexpr. Använd inte instanceof och inte heller typkastning utan utnyttja den dynamiska bindningen! När en variabel evalueras söker man efter den i variabellistan. Hittar man den där returnerar man dess värde, annars kastas ett undantag. Värdet som hämtas ur listan skall inte evalueras. En konstant evalueras alltid till sig själv. Att evaluera en tilldelning innebär att man evaluerar den vänstra operanden och lägger in dess värde i mappen som den högra operanden (variabeln). Det är sedan värdet av den evaluerade operanden som returneras. Derivering I parsern hanteras deriveringsoperationer av metoden factor som skapar deriveringsnoder (objekt av klassen Differentiation). Inplaceringen i syntaxdiagrammen gör att deriveringsoperatorn får en högre prioritet än multiplikation och division men lägre än unära operatorer. Deriveringsoperationen definieras ju olika för olika operatorer och funktioner. För att han- 10

tera det förser man (nästan) alla instanierbara klasser med en metod diff som definierar hur derivering av just detta element utförs. Deriveringsmetoden skall ha en parameter som anger vilken variabel man deriverar med avseende på. I deriveringsmetoden använder man de metoder för symboliska operationer som finns i klassen Symbolic. Klassen Sin:s deriveringsmetod ser ut så här: public Sexpr diff(sexpr x){ return Symbolic.mul(operand.diff(x), Symbolic.cos(operand)); Hur och var skall deriveringsmetoden definieras för den oderiverbara funktionen (abs) och de oderiverbara operatorerna (=, ", &, )? Användningen av derivering kommer att visa på nödvändigheten av förenkling. En begränsad sådan kan uppnås genom modifiering av metoderna för symboliska operationer i Symbolic. Förenkling då samtliga inblandade argument är konstanter sker redan, men även om endast den ena operanden till en binär operator är konstant kan det vara möjligt att förenkla. Ett sådant exempel är addition med noll, men vilka de övriga fallen är får ni lista ut själva. Krav för att bli godkänd på uppgiften 1. Programmet skall fungera i enlighet med specifikationen! Allt innehåll i den testfilen test.txt skall hanteras korrekt. 2. Koden skall följa kodkonventionerna och även på andra sätt vara lättläst. (Inga rader får vara längre än 80 tecken och inga metoder får vara längre än en skärmsida (med läslig font).) 3. Du skall använda den givna tokenizern (Stokenizer). 4. Du skall använda recursive descent som parsnings-metod. 5. Parsern skall innehålla en metod för varje syntaktisk enhet (varje enskilt syntaxdiagram) och metoderna skall ha de namn som anges där. 6. Du skall följa den givna klassdesignen i detalj, dvs alla klasser skall finnas med de angivna namnen och de angivna metoderna. 7. Det är förbjudet att använda instanceof och typkastningar mellan olika klasser. 8. Upprepa inte identisk eller nästan identisk kod i olika klasser varje klass skall bara definiera det som är speciellt för den. Tänk särskilt på detta i konstrukturer (utnyttja super!) och tostring-metoder! Arbetsgång 1. Kompilera och testkör den givna miniversionen och se vad som fungerar och vad som inte fungerar (bra). Läs koden och se till att du förstår hur den är uppbyggd. 2. Lägg till operationen subtraktion. Du måste både ändra i parsern (se hur du gjorde 11

i den numeriska kalkylatorn), skriva klassen Subtraction samt lägga till en metod i klassen Symbolic. 3. Skriv klassen Differentiation samt metoderna diff(sexpr) i klasserna. Obervera att deriveringsreglerna (diff-metoderna) skall använda sig av metoderna i klassen Symbolic. Förbättra metoderna i klassen Symbolic så att de utför triviala förenklingar. 4. Skriv de klasser som fattas i hierarkin. 5. Implementera priority()- och modifiera tostring()-metoderna så att de bara sätter ut parenteser vid behov. 6. Använd filen test.txt som indata. (Filen fanns med bland de filer du laddade ner från början.) 7. Redovisa! Redovisningen Vid redovisningen skall du Demonstrera att programmet fungerar med den senaste versionen av den givna testfilen och den givna Calculator-klassen. Observera att dessa två kan uppdateras under kursens gång så kontrollera att du har senaste innan du försöker redovisa. Du skall kunna beskriva hur parsern går igenom ett uttryck och hur eval-metoderna fungerar. Du skall kunna besvara följande frågor: 1. Varför är vissa metoder deklarerade som abstrakta i klassen Sexpr? Vad innebär det? 2. Metoderna priority() och isconstant() är implementerade i klassen Sexpr. I vilka klasser behöver dessa omdefinieras? 3. Instansvariablerna left och right i klassen Binary är deklarerade som protected. Vad innebär det? 4. Objektet variables är deklarerad som en Map men instansierad till en TreeMap. Varför är den inte instansierad till en Map? 5. Objektet variables skickas till alla eval-metoder men bara två använder den. Vilka? Varför skickas den ändå till alla? 6. Vad behöver göras för att lägga till en ny funktion (t ex tan(x))? 12