Laboration 6 - Formelkoll
Detta program ska läsa in molekylformler och kolla att dom är syntaktiskt
korrekta. I terminalfönstret ställs frågorna, t ex
Molekyl: Si(C3(COOH)2)4(H2O)7
Formeln är syntaktiskt korrekt
Molekyl: Ag7(FyOj6)17
Okänt atomnamn Fy vid radslutet Oj6)17
Molekyl: H1SO4
För litet tal vid radslutet SO4
Molekyl: Ca(OH)NO3
Saknad siffra vid radslutet NO3
Molekyl: Na(OH
Saknad högerparentes vid radslutet
Molekyl: Nacl
Saknad stor bokstav vid radslutet cl
När användaren trycker retur utan att ha skrivit någon formel ska slingan
brytas och programmet avslutas.
Syntaxanalys
Syntaxen för molekylformler kan beskrivas så här i BNF-notation:
<formel>::= <mol> \n
<mol> ::= <group> | <group><mol>
<group> ::= <atom> |<atom><num> | (<mol>) <num>
<atom> ::= <LETTER> | <LETTER><letter>
<LETTER>::= A | B | C | ... | Z
<letter>::= a | b | c | ... | z
<num> ::= 2 | 3 | 4 | ...
Ditt program ska läsa formeln tecken för tecken och med rekursiv
medåkning kolla syntaxen.
Eftersom det är lättast att läsa hela raden får du göra det och
sedan lägga in alla tecken i en kö. Avsluta med returtecknet, så här.
rad=raw_input("Molekyl:")
for tkn in rad: q.put(tkn)
q.put("\n")
Rekursiv medåkning innebär att huvudprogrammet gör anropet
readformel()
, att
readformel()
anropar
readmol()
som anropar
readgroup()
och sedan eventuellt sej själv,
att
readgroup()
antingen anropar
readatom()
eller läser en parentes och anropar
readmol()
etc -
allt enligt grammatiken. När ett syntaxbrott upptäcks genereras
ett särfall (
raise Exception,msg
) som fångas i
huvudprogrammet och där skrivs hela resten av kön ut.
Man måste ofta tjuvtitta på nästa tecken
för att veta vilken gren man ska följa i syntaxträdet och därför bör du
i klassen Queue
lägga till metoden peek()
som returnerar
första värdet men låter kön vara oförändrad.
Frivillig extrauppgift
Molekylvikten kan din formelkoll samtidigt räkna ut
om du låter alla metoder returnera ett tal, nämligen så här
-
readatom
returnerar en atomvikt med hjälp av hashtabellen
-
readnum
returnerar ett heltal
-
readgroup
returnerar vikten av en molekylgrupp, t ex Na eller (OH)2
-
readmol
returnerar vikten av en delmolekyl
-
readformel
returnerar hela molekylvikten
Nu ska körningen se ut så här.
Molekyl:Si(C3(COOH)2)4(H2O)7
Formeln är syntaktiskt korrekt
Molekylvikt: 658.466
En jätteprestation av................................. enligt............................ den ...............