home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
l
/
l-coll1.zip
/
TOOLLIBR.ZOO
/
ToolLibrary
/
src
/
Parser.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-02
|
21KB
|
962 lines
/********************************************************************/
/**** ****/
/**** ****/
/**** 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;
}