Lengyelforma

A feladat

... megfogalmazását lásd a lengyel.fel fájlban:


(*

  Feladat:

          Aritmetikai kifejezés kiértékelése.

 

  A. Részletesebben:

  A1. Egy kif sztringben hagyományos infix kifejezés van.

      Ezt lexikális egységeire bontjuk (lexEgys): lexKif.

      A lexEgys-eket hagyományos Text-ben (lexKif) tároljuk:

      egy sor - egy lexikális egység bontásban.

  A2. Az elöbbi lexikális egységeket tartalmazó file-ból

      kiindulva elöállítjuk a post-fix lengyelformáját: pfKif.

      Ez is egy Text (pfKif), elöbbivel azonos konvencióval, azaz

      egy sor - egy lexikális egység.

  A3. A pfKif file-ból továbblépve kiszámoljuk a kifejezés

      értékét.

      Ha voltak a kifejezésben változók, akkor e programnak kell

      gondoskodnia az értékek beolvasásáról is.

 

  B. Még részletesebben:

  B1. Megengedett lexikális egységek. Azaz, amiket tartalmazhat

      a bemenö (kif) sztring:

      B1.1. Számkonstansok

      B1.2. Számváltozók (azonosítója egy betüböl álló szöveg)

      B1.3. Elemi aritmetikai müveleti jelek ('+','-','*','/','^')

      B1.4. Néhány valósértékü aritmetikai függvény ('Sin','Cos',

           'Sqrt','Tg','Pi'...)

  B2. A bemenö kifejezéssel szemben elvárt speciális feltételek:

      B2.1. Minden lexikális egység között pontosan egy szóköz van.

      B2.2. A függvények argumentumát kötelezö bezárójelezni.

      Pl.:

         a * Sin ( b * x + Pi / 2 ) - 5.4321

      B2.3. Kis- és nagybetüket nem különböztetünk meg.

      B2.4. A kifejezés előtt és után nincsen szóköz.

  B3. A lexikális egységek megjelenése a lexKif Text-ben: értékpár

      formájában.

        lexEgys --> (miféle + értéke)

      A miféle és hozzárendelt kódja:

      * Számkonstans: 0

      * Számváltozó: 1

      * Müvelet (és a zárójelek): 2

      Egy néhány lexikális egységre példa:

        ( 0 , '5.4321' )

        ( 1 , 'a' )

        ( 2 , 'Sin' )

      A lexKif file-ra példa:

        ( 1 , 'a' )

        ( 2 , '*' )

        ( 2 , 'Sin' )

        ( 2 , '(' )

        ( 1 , 'b' )

        ( 2 , '*' )

        ( 1 , 'x' )

        ( 2 , '+' )

        ...

        ( 0 , '5.4321' )

  B4. A lexikális egységek megjelenése a pfKif Text-ben: értékpár

      formájában.

        lexEgys --> (miféle + értéke)

      A pfKif file-ra példa:

        ( 1 , 'a' )

        ( 1 , 'b' )

        ( 1 , 'x' )

        ( 2 , '*' )

        ( 2 , 'Pi' )

        ( 0 , '2' )

        ( 2 , '/' )

        ( 2 , '+' )

        ( 2 , 'Sin' )

        ( 2 , '*' )

        ...

  C. Az egyes részfeladatokat (l. A1-A3.) önállóan futó programok

     végzik el. A kapcsolatot file-okon keresztül tartják.

     (Elképzelhetö, hogy a fent nevesített file-okon túl [lexKif, pfKif]

     továbbiak is célszerüek [pl. a müveleti táblát tartalmazó file,

     ami soronként felsorolja a legális operátorokat esetleg precedenciájukkal

     együtt; eképpen:

       + 5

       - 5

       * 6

       / 6

       ^ 7

       Pi 10

       Sin 10

       Cos 10

       Tg 10

       Sqrt 10

     )

 

*)


Az A1 részfeladat megoldása

A lengyelformával kapcsolatos dolgokat, amelyeket az egyes részfeladatok programjai egyfor­mán kell ismerjenek a lengyel.inc-ben található:

 


(*

  Lengyel.inc: Lengyelforma kiértékelés programjainak közös dolgai

*)

  Type  TFajta=(Szam,Valt,Muv,Vege);

  Const SFajta:Array [TFajta] of String=('Szam','Valt','Muv','Vege');

        KFajta:Array [TFajta] of Byte=(0,1,2,Ord(Vege));

  Type  TMuv=Record

               jel:String;

               prec:Byte

             End;

  Const MaxMuv=12;

  Type  TMuvTabla=Array [1..MaxMuv] of TMuv;

  Const EgyJeluek=7; {ennyi egy jelből álló operátor van,

                      amelyek az Op elején találhatók}

        Op:TMuvTabla=((jel:'(';prec:0),(jel:')';prec:0),

                      (jel:'+';prec:5),(jel:'-';prec:5),(jel:'*';prec:6),

                      (jel:'/';prec:6),(jel:'^';prec:7),

                      {innentől vannak a többjeles operátorok/fv.-ek:}

                      (jel:'PI';prec:10),(jel:'SIN';prec:10),

                      (jel:'COS';prec:10),(jel:'TG';prec:10),

                      (jel:'SQRT';prec:10));

  Type  OLexEgys=Object

                   mifele:TFajta;

                   ertek:String;

                   Constructor Letrehoz(mi:TFajta; er:String);

                   Destructor Lerombol;

                   Procedure Readln(Var f:Text);

                   Procedure Writeln(Var f:Text);

                 End;

        Constructor OLexEgys.Letrehoz(mi:TFajta; er:String);

        Begin

          mifele:=mi; ertek:=er;

        End;

        Destructor OLexEgys.Lerombol;

        Begin

        End;

        Procedure OLexEgys.Readln(Var f:Text);

          Var kod:Byte;

        Begin {Ef: a file-ban a lexEgys 1 sorban értékpár.

                   1. érték: számkód, 2. érték: szöveg}

          System.Readln(f,kod,ertek);

          mifele:=TFajta(kod);

        End;

        Procedure OLexEgys.Writeln(Var f:Text);

        Begin

          System.Writeln(f,KFajta[mifele],' ',ertek);

        End;

 


A lexikális elemekre bontás megoldása (lexKiert.pas):

 


Program LexikalisKiertekeles; {az A1. reszfeladat programja}

(*

… l. fent a lengyel.fel fájlban

*)


  Uses Newdelay,Crt,Crt22;

 

  {$i AltRutin.inc}

  {$i lengyel.inc -- a lengyelforma kiértékelés programjainak közös dolgai}

 

  Var   kif:String;  {billentyű input}

        lexKif:Text; {file output: Text-esített,

                      soregységre tördelt OLexEgys file}

  Const lexKifFn='lexKif.txt';

 

  Const tollSzin=Black;

        papirSzin=White;

        link=128;

 

  Function Beolvasas:String;

    Var i,j:Byte;

        ss,s:String;

  Begin

    UjLap('Lengyelforma -- kifejezés-beolvasás',0);

    Write('Kérem az aritmetikai kifejezést:');

    Readln(s);

    {nagybetűsit:}

    For i:=1 to Length(s) do s[i]:=UpCase(s[i]);

 

    {a műveleti jelek szóközökkel tagolása --ha még nem lenne--:}

    For i:=1 to MaxMuv do

    Begin

      ss:='';

      Repeat

        j:=Pos(Op[i].jel,s);

        If j>0 then

        Begin

          ss:=ss+Copy(s,1,j-1)+' '+Copy(s,j,Length(Op[i].jel))+' ';

          s:=Copy(s,j+Length(Op[i].jel),Length(s)-j-Length(Op[i].jel)+1)

        End;

      Until j=0;

      s:=ss+s

    End;

    {elő- és végszóközök levágása:}

    i:=1;

    While (i>0) and (s[i]=' ') do Inc(i);

    Delete(s,1,i-1);

    i:=Length(s);

    While (i>0) and (s[i]=' ') do Dec(i);

    Delete(s,i+1,Length(s)-i);

    {fölösleges szóközök elhagyása:}

    i:=1; {bármi, ami >0}

    While i>0 do

    Begin

      i:=Pos('  ',s); Delete(s,i,1);

    End;

 

    Beolvasas:=s

  End;

 

  Procedure FileMegnyitas(fN:String; Var f:Text);

    Var  hiba:Integer;

  Begin

    UjLap('Lengyelforma -- file-megnyitás',0);

    Repeat

      {$i-}

      Assign(f,fN); Reset(f);

      hiba:=IOResult;

      If hiba<>0 then

      Begin

        Rewrite(f);

        hiba:=IOResult;

        If hiba<>0 then

        Begin

          TextColor(Red+Blink);

          Writeln('A file nem nyitható meg:');

          Writeln('  Hibás file-név.');

          TextColor(tollSzin);

          BillreVar

        End

      End

        Else

      Begin

        Rewrite(f);

        TextColor(Red+Blink);

        Writeln('  Ilyen file már van. A file felülíródik.');

        TextColor(tollSzin);

        BillreVar

      End;

      {$i+}

    Until hiba=0;

  End;

 

  Function Elemez(le:String):TFajta;

    Var x:Real;

        i,siker:Integer;

  Begin

    Val(le,x,siker);

    If siker<>0 then

    Begin

      i:=1;

      While (i<=MaxMuv) and (Op[i].jel<>le) do Inc(i);

      If i<=MaxMuv then Elemez:=Muv

                   else Elemez:=Valt;

    End

      else

    Begin

      Elemez:=Szam

    End;

  End;

 

  Procedure Felbont(kif:String; Var lk:Text);

    {Ef: Minden lexikális egység között pontosan egy szóköz van.}

    Var miASzosz:TFajta;

        ig:Byte;

        le:String;

        leO:OLexEgys;

  Begin

    UjLap('Lengyelforma -- kifejezés-felbontás',0);

    ig:=Length(kif);

    While ig>0 do

    Begin

      ig:=Pos(' ',kif);

      If ig>0 then

      Begin

        le:=Copy(kif,1,ig-1);

        kif:=Copy(kif,ig+1,Length(kif)-ig);

        miASzosz:=Elemez(le);

      End

        else

      Begin

        le:=kif;

        kif:='';

        miASzosz:=Elemez(le);

      End;

      leO.Letrehoz(miASzosz,le);         A def. lásd előbb.

      leO.Writeln(lk);

      leO.Lerombol;

      {ellenőrző kiírás:}

      Writeln(KFajta[miASzosz],' (',SFajta[miASzosz],') ',le);

    End;

  End;

 

Begin

  UjLap('Lengyelforma',0);

  TextColor(tollSzin); TextBackground(papirSzin);

  kif:=Beolvasas;

  FileMegnyitas(lexKifFn,lexKif);

  Felbont(kif,lexKif);

  Close(lexKif);

End.


 

Minden hozzávaló letöltése: lengyel.zip.