Talen en automaten/2011-12/producten/Rekenmachine
Uit Werkplaats
< Talen en automaten | 2011-12 | producten
Rekenmachine
Charlie Gerhardus
Talen en automaten 2011-12
Het verslag
Bestand:CharlieGerhardus Rekenmachine.pdf
rekenmachine.woorden
Syntax:
* = herhaal 1x of meer ? = herhaal 0x of meer % = niet verplicht ! = negeer
Woorden
!woord_troep([' ''\t''\r']*) woord_plus ('+') woord_min ('-') woord_keer ('*') woord_deel ('/') woord_open ('(') woord_sluit (')') label_cijfers {'0'-'9'} woord_getal( [label_cijfers]* ( ',' [label_cijfers]* )% )
rekenmachine.grammatica
De non-terminals zorgen er in deze syntax niet voor dat er een kind aan de boom word toegevoegd. Om een kind toe te voegen schrijven we zijn naam gevolgd door zijn inhoud tussen haaken. Het beginpunt moet ook worden aangegeven.
begin (non_terminal) non_terminal {kind<inhoud>} % = niet verplicht | = of
Grammatica:
begin (regel_wiskunde) regel_wiskunde {(links< links<regel_getal> regel_keerdeel >|links<regel_getal>) regel_plusmin%} regel_plusmin {op<woord_plus|woord_min> rechts<regel_plusmin_rechts>} regel_plusmin_rechts { links<links<regel_getal> regel_keerdeel> | links<regel_getal> regel_plusmin% } regel_keerdeel {op<woord_keer|woord_deel> rechts< links<regel_getal> regel_keerdeel% >} regel_haakjes {troep<woord_open> regel_wiskunde troep<woord_sluit>} regel_getal {woord_getal|regel_haakjes}
rekenmachine.cpp
/* rekenmachine.cpp * * Door: Charlie Gerhardus * * Een rekenmachine. * Woorden: rekenmachine.woorden * Grammatica: rekenmachine.grammatica * * Om dit programma te kunnen bouwen is de alternative standaard bibliotheek 'cgom' vereist. Deze is nogal groot en dus niet bijgevoegd. * */ //invoegen: cgom /* * cgom bevat twee klassen waar wij in geintresseerd zijn. * * cgom::verwoord * cgom::verwerk * * verwoord behandeld de individueele woorden in de rekenmachine taal. * verwerk creeert een boom aan de hand van een grammatica. */ #include <cgom.h> //de taal cgom::verwoord taal_verwoord; cgom::verwerk taal_verwerk; //toon de boom voor extra effect void prefix(int i) //dit zorgt ervoor dat vader en kind te onderscheiden zijn { for (unsigned int ii=0;ii<i;ii++) { cgom::scherm::schrijf(" "); } } void toon_boom(cgom::boom<cgom::type::labelset>::rups& r, int t=0) //dit tekend een boom { //naam en waarden prefix(t); cgom::scherm::schrijf(cgom::treeks(r.naam())+cgom::treeks(":\n")); for (unsigned int i=0;i<r.data().aantal();i++) { prefix(t+1); cgom::scherm::schrijf(cgom::treeks(r.data().naam_van_index(i))+cgom::treeks(" = ")+cgom::treeks(r.data()[r.data().naam_van_index(i)])+cgom::treeks("\n")); } //kinderen for (unsigned int i=0;i<r.aantal_kinderen();i++) { r.daal(r.kind_van_index(i)); toon_boom(r, t+1); r.stijg(); } } //lees de taal bool maak_taal() { /* * cgom::treeks cgom::bestand::als_tekst(const char*); * * lees een bestand en geeft deze als string. * cgom::treeks is een soort std::string. */ if (!cgom::verwoord::lees_regels(taal_verwoord, cgom::bestand::als_tekst("[0>rekenmachine.woorden").als_tekst())) { cgom::scherm::schrijf("fout: in .woorden!\n"); return false; } taal_verwerk.registreer_woorden(taal_verwoord); if (!cgom::verwerk::lees_regels(taal_verwerk, cgom::bestand::als_tekst("[0>rekenmachine.grammatica").als_tekst())) { cgom::scherm::schrijf("fout: in .grammatica!\n"); return false; } return true; } /* * Dit is de interrestante functie. * * De pseudocode versie met uitleg van deze functie is in het werkstuk te vinden. */ double bereken_recursief(cgom::boom<cgom::type::labelset>::rups& r, bool l_in=false, double l=0.0) { //waarden double links; //diep genoeg? if (r.data().heeft("woord_getal")) { return (double)r.data()["woord_getal"]; } //links if (!l_in) { r.daal("links"); links = bereken_recursief(r); r.stijg(); } else { links = l; } //operatie? if (r.heeft_kind("op")) { r.daal("rechts"); r.daal("links"); double rechts_links = bereken_recursief(r); r.stijg(); r.stijg(); r.daal("op"); if (r.data().heeft("woord_plus")) { links = links+rechts_links; } else if (r.data().heeft("woord_min")) { links = links-rechts_links; } else if (r.data().heeft("woord_keer")) { links = links*rechts_links; } else if (r.data().heeft("woord_deel")) { links = links/rechts_links; } r.stijg(); //verder? r.daal("rechts"); if (r.heeft_kind("op")) { links = bereken_recursief(r, true, links); } r.stijg(); } return links; } void bereken(cgom::boom<cgom::type::labelset>::rups& r) { double antwoord = 0.0; antwoord = bereken_recursief(r); cgom::scherm::schrijf(cgom::treeks("antwoord: ")+cgom::treeks(antwoord)+cgom::treeks("\n")); } void verwerk_invoer(const char* invoer) { //waardes cgom::verwoord vwoord = taal_verwoord; cgom::verwerk vwerk = taal_verwerk; //maak woordenlijst if (!vwoord.verwerk(invoer)) { cgom::scherm::schrijf("fout: ongeldig woord!\n"); return; } //maak boom if (!vwerk.verwerk_woorden(vwoord)) { cgom::scherm::schrijf("fout: ogeldige berekening!\n"); return; } //toon boom! cgom::boom<cgom::type::labelset>::rups kr = vwerk.resultaat().kruiper(); toon_boom(kr); //bereken! cgom::boom<cgom::type::labelset>::rups kruiper = vwerk.resultaat().kruiper(); bereken(kruiper); } //beginpunt int main(int argc, char* args[]) { //lees taal if (!maak_taal()) { cgom::scherm::schrijf("fout: in woorden/grammatica!\n"); return 1; } //lees while (true) { //verkrijg invoer cgom::scherm::schrijf("# "); cgom::treeks invoer = cgom::scherm::lees_regel(); //stoppen? if (invoer.vergelijk("stop")) { break; } verwerk_invoer(invoer.als_tekst()); } return 0; }