home *** CD-ROM | disk | FTP | other *** search
-
- /********************************************************************/
- /**** ****/
- /**** ****/
- /**** Program : Parser.c Baum ****/
- /**** ****/
- /**** Version : 01.15 ****/
- /**** ****/
- /**** Erstversion : 21.05.1988 ****/
- /**** ****/
- /**** Letzte Änderung : 05.08.1990 ****/
- /**** ****/
- /**** Compiliert mit : siehe MAKEFILE ****/
- /**** ****/
- /**** Gelinkt mit : Für Tool.Library ****/
- /**** ****/
- /********************************************************************/
- /**** ****/
- /**** ****/
- /**** Copyright by Rüdiger Dreier ****/
- /**** ****/
- /**** ****/
- /********************************************************************/
-
- /* 04.12.1989: Alle Konstanten außer e und x möglich */
- /* 19.12.1989: Fehler in PreCalc bei pi/e beseitigt */
-
- #include "ToolProto.h"
- #include <string.h>
- #include <exec/memory.h>
-
- extern struct Library *MathIeeeDoubBasBase;
- extern struct Library *MathIeeeDoubTransBase;
- int search(char *string);
-
- int search(char *string)
- {
- int i,a,Fehler=0;
- char VERGLEICH[38];
- if(strlen(string)==NULL)return(-1);
- strcpy(VERGLEICH,"xeintasinatanacossqrlogabssgnlnpi");
- for(i=0;i<=strlen(VERGLEICH)-1;i++)
- {
- Fehler=0;
- for(a=0;a<=strlen(string)-1;a++)
- {
- if(string[a]!=VERGLEICH[i+a])Fehler=-1;
- }
- if(Fehler==0)break;
- }
- if(Fehler==-1)i=-1;
- if(strlen(string)==1&&i>1)i=-1;
- return(i);
- }
-
- /* Diese Funktion arbeitet einen String ab und legt entsprechend einen */
- /* Baum im Speicher an. */
- LONG __asm ev(register __d0 LONG l,register __d1 LONG r,register __d2 struct Block *block)
- {
- char Hilfe[9];
- char Ziffern[100];
- struct Block *BL,*BR;
- LONG Fehler=0;
- int Pos1,Anzahl_Zeichen;
- char Exponent_gefunden;
-
- block->Links=l;
- block->Rechts=r;
-
- if(r<l)return(0);
-
- BL=(struct Block *)AllocMem(sizeof(struct Block),MEMF_CLEAR);
- if(BL==NULL)return(NO_MEM);
- BR=(struct Block *)AllocMem(sizeof(struct Block),MEMF_CLEAR);
- if(BR==NULL)
- {
- FreeMem((UBYTE *)BL,sizeof(struct Block));
- return(NO_MEM);
- }
-
- BR->String=BL->String=block->String;
- block->Left=BL;
- block->Right=BR;
-
- /* Test auf Additive Blöcke */
- if((Pos1=checkback('+','-',l,r,block->String))!=-1L)
- {
- LONG ll; /* Zum Speichern der linken Ecke */
- ll=l;
- /* Wenn ein entsprechendes Rechenzeichen gefunden wurde : */
- do
- {
- /* Testet auf a^+-b */
- /* Pos1==ll testet, ob ein ^ überhaupt im Bereich ist, */
- /* denn das kann nur passieren, wenn ^ eins vor l (orig) */
- /* ist. ll wird zwar immer erhöht, das Zeichen davor ist */
- /* dann aber garantiert ein +-. */
-
- if((block->String[Pos1-1]!='^'&&block->String[Pos1-1]!='e'&&block->String[Pos1-1]!='d') || Pos1==ll)
- {
- Exponent_gefunden=FALSE;
-
- /* Solange aufmultiplizieren, bis alle Blöcke abgearbeitet sind */
- Fehler|=ev(ll,Pos1-1L,BL); /* Subtrahiert Block bis Minuszeichen */
- Fehler|=ev(Pos1+1L,r,BR);
- if (block->String[Pos1]=='-')
- {
- block->RechenArt|=SUBT;
- }
- else
- {
- block->RechenArt|=ADDI;
- }
- }
- else
- {
- Exponent_gefunden=TRUE;
- }
- Pos1=checkback('+','-',l,Pos1-1L,block->String);
- }
- while(Exponent_gefunden&&Pos1!=-1L);
- if(!Exponent_gefunden)return(Fehler);
- }
-
-
- /* Test auf Multiplikative Blöcke */
- if((Pos1=checkback('*','/',l,r,block->String))!=-1L)
- {
- /* Wenn Punktrechnung gefunden wurde : */
- {
- Fehler|=ev(l,Pos1-1L,BL);
- Fehler|=ev(Pos1+1L,r,BR);
- /* Solange Berechnen, bis kein Block mehr da */
- if (block->String[Pos1]=='/')
- {
- block->RechenArt|=DIVI;
- }
- else
- {
- block->RechenArt|=MULT;
- }
- }
- return(Fehler);
- }
-
-
- /* Abfrage auf Potenz */
- /* Muß vor Abfrage auf Klammern sein */
- /* Getauscht : 07.09.1988 */
-
- if((Pos1=checkback('^','^',l,r,block->String))!=-1)
- {
- Fehler|=ev(l,Pos1-1L,BL);
- Fehler|=ev(Pos1+1L,r,BR);
- block->RechenArt|=POWE;
- return(Fehler);
- }
-
- /* Klammern um den Block ? */
- /* nicht korrekte Abfrage, aber sicherer */
- /* Korrekt: Auf schließende Klammer testen */
- /* Bearbeitet gleichen Block weiter */
-
- if (block->String[l]=='(')
- {
- block->Left=block->Right=0;
- FreeMem((UBYTE *)BL,sizeof(struct Block));
- FreeMem((UBYTE *)BR,sizeof(struct Block));
- if(!(block->String[r]==')'))
- {
- Fehler|=UNPAKLAM;
- Fehler|=(ev(l+1L,r,block));
- }
- else
- {
- Fehler|=(ev(l+1L,r-1,block));
- }
- return(Fehler);
- }
-
- FreeMem((UBYTE *)BL,sizeof(struct Block));
- block->Left=NULL;
- /* Abfrage der trigonometrischen Funktionen */
- /* Hier wird auf schließende Klammer getestet */
-
- Anzahl_Zeichen=0;
- Pos1=min(5,r-l);
- Hilfe[0]='_';
- while(Anzahl_Zeichen<=Pos1&&block->String[l+Anzahl_Zeichen]!='(')
- {
- Hilfe[Anzahl_Zeichen]=block->String[l+Anzahl_Zeichen];
- Anzahl_Zeichen++;
- }
- Hilfe[Anzahl_Zeichen]=0;
- Pos1=search(Hilfe);
-
- if(Pos1<31&&Pos1>1)
- {
- Fehler|=(ev(l+(LONG)Anzahl_Zeichen,r,BR));
- }
-
-
- switch(Pos1)
- {
- /* int */
- case 2:
- {
- block->RechenArt|=FLOO;
- /*Fehler|=(ev(l+3L,r,BR));*/
- break;
- }
-
- /* Sinus */
- case 6:
- {
- block->RechenArt|=SINU;
- /*Fehler|=(ev(l+3L,r,BR));*/
- break;
- }
-
- /* Cosinus */
- case 14:
- {
- block->RechenArt|=COSI;
- /*Fehler|=(ev(l+3L,r,BR));*/
- break;
- }
-
- /* Tangens */
- case 10:
- {
- block->RechenArt|=TANG;
- /*Fehler|=(ev(l+3L,r,BR));*/
- break;
- }
-
- /* Wurzel Sqr */
- case 17:
- {
- block->RechenArt|=SQRT;
- /*Fehler|=ev(l+3L,r,BR);*/
- break;
- }
-
- /* log */
- case 20:
- {
- block->RechenArt|=LOG1;
- /*Fehler|=ev(l+3L,r,BR);*/
- break;
- }
-
- /* abs */
- case 23:
- {
- block->RechenArt|=ABSO;
- /*Fehler|=(ev(l+3L,r,BR));*/
- break;
- }
-
- /* sgn */
- case 26:
- {
- block->RechenArt|=SIGU;
- /*Fehler|=(ev(l+3L,r,BR));*/
- break;
- }
-
- /* ArcSinus */
- case 5:
- {
- block->RechenArt|=ASIN;
- /*Fehler|=ev(l+4L,r,BR);*/
- break;
- }
-
- /* ACosinus */
- case 13:
- {
- block->RechenArt|=ACOS;
- /*Fehler|=ev(l+4L,r,BR);*/
- break;
- }
-
- /* ArcTangens */
- case 9:
- {
- block->RechenArt|=ATAN;
- /*Fehler|=(ev(l+4L,r,BR));*/
- break;
- }
-
- /* ln */
- case 29:
- {
- block->RechenArt|=LNAT;
- /*Fehler|=ev(l+2L,r,BR);*/
- break;
- }
-
- /* x */
- case 0:
- {
- block->RechenArt=X;
- break;
- }
-
- /* PI */
- case 31:
- {
- /* 07.09.1988 */
- block->Wert=PI;
- block->Valid=1;
- block->RechenArt=MKON;
- break;
- }
-
- /* E */
- case 1:
- {
- /* 07.09.1988 */
- block->Wert=E;
- block->Valid=1;
- block->RechenArt=MKON;
- break;
- }
-
- default:
- {
- /* Wenn der Block aus nur einen Zeichen besteht */
- if(r==l&&(block->String[l]>='a'&&block->String[l]<='z'))
- {
- /* Abfrage der Konstanten a-d */
- /* a-z */
- /* 05.10.1988 */
- Pos1=block->Konstante=(block->String[l]-96);
- if(Pos1<=0||Pos1>=26)Fehler|=NO_KONST;
-
- block->RechenArt=UKON;
- FreeMem((UBYTE *)BR,sizeof(struct Block));
- block->Right=NULL;
- }
-
- /* Nur noch Ziffern */
- if((block->String[l]>='0' && block->String[l]<='9')||block->String[l]=='.')
- {
- for (Pos1=l;Pos1<=r;Pos1++)
- {
- Ziffern[Pos1-l]=block->String[Pos1];
- }
- Ziffern[Pos1-l]=0;
- UmwStoF(&block->Wert,Ziffern);
- FreeMem((UBYTE *)BR,sizeof(struct Block));
- block->Right=NULL;
- block->RechenArt=ZIFF;
- }
- if(block->RechenArt==NULL)Fehler|=NO_FUNC;
- }
- /* ENDE default */
- }
- /* ENDE switch */
- return(Fehler);
- }
-
-
- VOID __asm Free_Block(register __a0 struct Block *First)
- {
- struct Block *Links,*Rechts;
-
- Links=First->Left;
- Rechts=First->Right;
-
- if(Links)Free_Block(Links);
- if(Rechts)Free_Block(Rechts);
-
- FreeMem((UBYTE *)First,sizeof(struct Block));
- }
-
- /* Gibt den Speicher wieder frei */
- VOID __asm Free_Konst(register __a0 APTR Zeiger)
- {
- FreeMem((char *)Zeiger,26*sizeof(DOUBLE));
- }
-
- /* Holt Speicher für Konstanten -> Null, wenn kein Erfolg */
- APTR Init_Konst()
- {
- APTR Zeiger;
- Zeiger=(APTR)AllocMem(26*sizeof(DOUBLE),MEMF_CLEAR);
- return(Zeiger);
- }
-
- /* Hilferoutine, die mit Zeigern auf DOUBLE arbeitet */
- LONG __asm Set_Konst_P(register __a0 APTR Zeiger,register __d0 LONG Nummer,register __d1 DOUBLE *Wert_P)
- {
- DOUBLE Wert;
- Wert=*Wert_P;
- return(Set_Konst(Zeiger,Nummer,Wert));
- }
-
- /* Setzt Konst-Nr. auf Wert */
- LONG Set_Konst(APTR Zeiger,LONG Nummer,DOUBLE Wert)
- {
- DOUBLE *Z;
- if(Nummer<=0||Nummer>=26)return(NO_KONST);
- Z=(DOUBLE *)Zeiger;
- Z[Nummer-1]=Wert;
- return(0);
- }
-
- struct Block * __asm Init_Mem(register __a0 char *string)
- {
- struct Block *FirstBlock;
- FirstBlock=(struct Block *)AllocMem((sizeof(struct Block)),MEMF_CLEAR);
- if(FirstBlock==NULL)return(0);
- FirstBlock->Rechts=strlen(string)-1;
- FirstBlock->String=string;
- return(FirstBlock);
- }
-
- LONG __asm Init_Block(register __a0 struct Block *Zeiger)
- {
- LONG Fehler;
- Fehler=ev(0L,strlen(Zeiger->String)-1L,Zeiger);
- return(Fehler);
- }
-
- /* Hilfsroutine, die das nächste Auftreten eines der beiden Zeichen sucht */
- LONG __asm check(register __d0 LONG z1,register __d1 LONG z2,
- register __d2 LONG l,register __d3 LONG r,
- register __a0 char *string)
- {
- int i,Klammern=0;
-
- for (i=l;i<=r;i++)
- {
- if (Klammern==0 && (string[i]==z1||string[i]==z2))
- {
- return(i); /* z1 gefunden */
- }
- if(string[i]=='(')
- {
- Klammern++; /* Auf anderer Klammerebene */
- }
- if(string[i]==')')
- {
- Klammern--;
- }
- }
- return(-1); /* Nicht gefunden */
- }
-
- /* Hilfsroutine, die das nächste Auftreten eines der beiden Zeichen sucht */
- /* Sucht von hinten.. */
- LONG __asm checkback(register __d0 LONG z1,register __d1 LONG z2,
- register __d2 LONG l,register __d3 LONG r,
- register __a0 char *string)
- {
- int i,Klammern=0;
-
- for (i=r;i>=l;i--)
- {
- if (Klammern==0 && (string[i]==z1 || string[i]==z2))
- {
- return(i); /* z1 gefunden */
- }
- if(string[i]=='(')
- {
- Klammern++; /* Auf anderer Klammerebene */
- }
- if(string[i]==')')
- {
- Klammern--;
- }
- }
- return(-1); /* Nicht gefunden */
- }
-
- /* Hilfsroutine, die Teile des Strings kopiert */
- VOID __asm copy(register __d0 LONG i,register __d1 LONG Anzahl,
- register __d2 char *Ziel,register __d3 char *Source)
- {
- int Schleife;
- for (Schleife=i;Schleife<i+Anzahl;Schleife++)
- {
- *(Ziel+Schleife-i)=*(Source+Schleife);
- }
- *(Ziel+Schleife-i)=0;
- }
-
-
- /* Liefert Vorzeichen zurück */
- double sgn(DOUBLE x)
- {
- DOUBLE Ergebnis;
- if(Cmp(x,0.0)==1)
- {
- Ergebnis=1.0;
- }
- else
- {
- if(Cmp(x,0.0)==-1)
- {
- Ergebnis=-1.0;
- }
- else
- {
- Ergebnis=0.0;
- }
- }
- return(Ergebnis);
- }
-
-
- LONG BereichsKontr(DOUBLE b)
- {
- if(Cmp(b,1.0)==1||Cmp(b,-1.0)==-1)
- {
- return(1);
- }
- return(0);
- }
-
-
- LONG __asm PreCalc(register __d0 struct Block *Zeiger,register __d1 APTR Konst)
- {
- DOUBLE Wert,links,rechts;
- LONG Valid=1,v1,v2,Fehler=0;
- Wert=Zeiger->Wert;
- Zeiger->Fehler=Fehler;
- if(Zeiger->Left )
- {
- Fehler=PreCalc(Zeiger->Left,Konst);
- links =Zeiger->Left->Wert;
- v1 =Zeiger->Left->Valid;
- }
- else
- {
- v1=1;
- }
-
- if(Zeiger->Right)
- {
- Fehler|=PreCalc(Zeiger->Right,Konst);
- rechts=Zeiger->Right->Wert;
- v2 =Zeiger->Right->Valid;
- }
- else
- {
- v2=1;
- /* Wenn rechts kein Block folgt, dann ist es der letzte Block */
- Wert=Zeiger->Wert;
- }
- if(v1&&v2)
- {
- switch(Zeiger->RechenArt)
- {
- case ADDI:
- {
- Wert=Add(links,rechts);
- break;
- }
- case SUBT:
- {
- Wert=Sub(links,rechts);
- break;
- }
- case MULT:
- {
- Wert=Mul(links,rechts);
- break;
- }
- case DIVI:
- {
- if(Tst(rechts))
- {
- Wert=Div(links,rechts);
- }
- else
- {
- Fehler|=DIVBYZERO;
- }
- break;
- }
- case POWE:
- {
- Wert=Pow(links,rechts);
- /* Testet, ob Fehler aufgetreten ist. 0 -> 0^x oder neg^bruch ! */
- if(Tst(Wert)==0&&Tst(links)!=0)Fehler|=POWERROR;
- break;
- }
- case SINU:
- {
- Wert=Sin(rechts);
- break;
- }
- case COSI:
- {
- Wert=Cos(rechts);
- break;
- }
- case TANG:
- {
- Wert=Tan(rechts);
- break;
- }
- case ASIN:
- {
- if(BereichsKontr(rechts))
- {
- Fehler|=ATRIG;
- }
- else
- {
- Wert=ASin(rechts);
- }
- break;
- }
- case ACOS:
- {
- if(BereichsKontr(rechts))
- {
- Fehler|=ATRIG;
- }
- else
- {
- Wert=ACos(rechts);
- }
- break;
- }
- case ATAN:
- {
- Wert=ATan(rechts);
- break;
- }
- case LOG1:
- {
- if(Cmp(rechts,0.0)<=0L)
- {
- Fehler|=LOGNEG;
- }
- else
- {
- Wert=Log10(rechts);
- }
- break;
- }
- case LNAT:
- {
- if(Cmp(rechts,0.0)<=0L)
- {
- Fehler|=LOGNEG;
- }
- else
- {
- Wert=Log(rechts);
- }
- break;
- }
- case ABSO:
- {
- Wert=Abs(rechts);
- break;
- }
- case SIGU:
- {
- Wert=sgn(rechts);
- break;
- }
- case SQRT:
- {
- if(Tst(rechts)==-1L)
- {
- Fehler|=SQRTNEG;
- }
- else
- {
- Wert=Sqr(rechts);
- }
- break;
- }
- case FLOO:
- {
- Wert=Floor(rechts);
- break;
- }
- case UKON:
- {
- if(Konst)Wert=GetKonst(Konst,(LONG)Zeiger->Konstante);
- break;
- }
- case X:
- {
- Wert=0.0;
- Valid=0;
- }
- }
- Zeiger->Fehler|=Fehler;
- if(Valid&&!Fehler)
- {
- Zeiger->Wert=Wert;
- Zeiger->Valid=1;
- }
- else
- {
- Zeiger->Valid=0;
- }
- }
- else
- {
- Zeiger->Valid=0;
- Zeiger->Wert=NULL;
- }
- return(Fehler);
- }
-
- /* Hilferoutine, die mit Zeigern auf DOUBLE arbeitet */
- VOID __asm GetKonst_P(register __a0 DOUBLE *Ziel,
- register __a1 APTR Konst,
- register __d0 LONG Nummer)
- {
- DOUBLE Wert;
-
- Wert=GetKonst(Konst,Nummer);
- Wert=Add(Wert,0.0);
- *Ziel=Wert;
- }
-
- DOUBLE __asm GetKonst(register __a0 APTR Konst,register __d1 LONG Nummer)
- {
- DOUBLE *Z;
- if(Nummer<=0||Nummer>=26)return(0.0);
- Z=(DOUBLE *)Konst;
- return(Z[Nummer-1]);
- }
-
-
- /* Hilferoutine, die mit Zeigern auf DOUBLE arbeitet */
- LONG __asm Calc_P(register __a0 DOUBLE *Ziel,
- register __a1 struct Block *Zeiger,
- register __a2 DOUBLE *x)
- {
- DOUBLE Wert;
- DOUBLE Ergebnis;
- struct Block *START;
-
- START=Zeiger;
- Wert=*x;
- Ergebnis=Calc(START,Wert);
- *Ziel=Ergebnis;
- return(Zeiger->Fehler);
- }
-
- DOUBLE Calc(struct Block *Zeiger,DOUBLE x)
- {
- DOUBLE Wert=0.0,links,rechts;
- LONG Fehler=0;
- /* Evt. die obige Zeile raus und dafür unten Zeiger->Fehler=0 */
-
- Zeiger->Fehler=0; /* Löscht Fehler alter Durchläufe */
-
- if(Zeiger->Valid==1)return(Zeiger->Wert); /* Schon berechnet */
- if(Zeiger->Left )
- {
- links=Calc(Zeiger->Left,x);
- Fehler|=Zeiger->Left->Fehler;
- }
- if(Zeiger->Right)
- {
- rechts=Calc(Zeiger->Right,x);
- Fehler|=Zeiger->Right->Fehler;
- }
- else
- {
- Wert=Zeiger->Wert;
- }
- switch(Zeiger->RechenArt)
- {
- case ADDI:
- {
- Wert=Add(links,rechts);
- break;
- }
- case SUBT:
- {
- Wert=Sub(links,rechts);
- break;
- }
- case MULT:
- {
- Wert=Mul(links,rechts);
- break;
- }
- case DIVI:
- {
- if(Tst(rechts))
- {
- Wert=Div(links,rechts);
- }
- else
- {
- Fehler|=DIVBYZERO;
- }
- break;
- }
- case POWE:
- {
- Wert=Pow(links,rechts);
- if(Tst(Wert)==0&&Tst(links)!=0)Fehler|=POWERROR;
- break;
- }
- case SINU:
- {
- Wert=Sin(rechts);
- break;
- }
- case COSI:
- {
- Wert=Cos(rechts);
- break;
- }
- case TANG:
- {
- Wert=Tan(rechts);
- break;
- }
- case ASIN:
- {
- if(BereichsKontr(rechts))
- {
- Fehler|=ATRIG;
- }
- else
- {
- Wert=ASin(rechts);
- }
- break;
- }
- case ACOS:
- {
- if(BereichsKontr(rechts))
- {
- Fehler|=ATRIG;
- }
- else
- {
- Wert=ACos(rechts);
- }
- break;
- }
- case ATAN:
- {
- Wert=ATan(rechts);
- break;
- }
- case LOG1:
- {
- if(Cmp(rechts,0.0)<=0)
- {
- Fehler|=LOGNEG;
- }
- else
- {
- Wert=Log10(rechts);
- }
- break;
- }
- case LNAT:
- {
- if(Cmp(rechts,0.0)<=0)
- {
- Fehler|=LOGNEG;
- }
- else
- {
- Wert=Log(rechts);
- }
- break;
- }
- case ABSO:
- {
- Wert=Abs(rechts);
- break;
- }
- case SIGU:
- {
- Wert=sgn(rechts);
- break;
- }
- case SQRT:
- {
- if(Tst(rechts)==-1L)
- {
- Fehler|=SQRTNEG;
- }
- else
- {
- Wert=Sqr(rechts);
- }
- break;
- }
- case FLOO:
- {
- Wert=Floor(rechts);
- break;
- }
- case UKON:
- {
- Wert=Zeiger->Wert;
- break;
- }
- case X:
- {
- Wert=x;
- }
- }
- Zeiger->Fehler|=Fehler;
- return(Wert);
- }
-
-
- LONG __asm AnzahlKlammern(register __a0 char *string)
- {
- int Laenge,Klammern;
- unsigned short i;
- Klammern=0;
- Laenge=strlen(string)-1;
- for(i=0;i<=Laenge;i++)
- {
- if(string[i]=='(')Klammern++;
- if(string[i]==')')Klammern--;
- }
- return(Klammern);
- }
-
- VOID __asm berechnen(register __a0 DOUBLE *Ziel,
- register __d0 UBYTE *string,
- register __d1 DOUBLE *var,
- register __d2 struct Konstanten *kon,
- register __d3 LONG *Fehler)
- {
- LONG f;
- DOUBLE Wert;
- DOUBLE Ruckgabe;
- struct Block *START;
-
- Wert=*var;
-
- START=Init_Mem(string);
- f=Init_Block(START);
- *Fehler=f;
-
- f=PreCalc(START,(APTR)kon); /* Nötig, um Konstanten einzubinden */
- Ruckgabe=Calc(START,Wert);
- *Fehler|=f;
-
- Free_Block(START);
-
- *Ziel=Ruckgabe;
- }
-
-