Talen en automaten/2011-12/producten/Rekenmachine

Uit Werkplaats
Ga naar: navigatie, zoeken

Page Break




Algolfrag.jpg

Talen en automaten

Erik Barendsen


 © comments



Rekenmachine

Charlie Gerhardus



Talen en automaten 2011-12







Charlie Gerhardus Informatica
 e-mail 

cursuspagina


Page Break





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;
}