синтаксический анализатор мат.формул
- From
- George Shuklin (2:5030/744.46)
- To
- Svirskiy Taras ()
- Date
- 2000-02-26T09:38:56Z
- Area
- RU.ALGORITHMS
А, это ты Svirskiy! Вот что я тебе сказать хотел...
В 25 февраля 2000 01:12, Svirskiy Taras решил написать All:
ST> Может кто-нибудь знает, или писал алгоритм сабжа,
ST> или где об этом вообще почитать можно.
ST> Плиз, пмомогите, сильно надо.
Вот, лови. Не пинать. Писано в свое время для сдачи по ПОВС, посему возможны глюки.
Разбор по бинарному дереву
Принцип разбора
1*(2+3)*5-6*7+8
Наименее приоритетная операция + между 7 и 8
Рекуррентно вызовем себя для 1*(2+3)*5-6*7 и для 8, получившиеся числа сложем.
При вызове с числом просто его же и возвращаем
При бызове для 1*(2+3)*5-6*7 : Наимнее приоритетная оп. '-'
Вызываем себя же для 1*(2+3)*5 и для 6*7. Вычитаем. Возвращаем получившиеся.
далее я думаю понятно...
>> файло всякое начинается
int cmp (char* Line1,char * Line2)
//Проверяет, является ли line2 началом line1, если да, то возвр. 1
{
while (*Line2)
{
if (!*Line1) return 0;
if (*Line2++!=*Line1++) return 0;
}
return 1;
}
int Operator (char Line[],int pos)
{
//Возвращает приоритет операции
switch (Line[pos])
{
case'+': return 1;
case'-': return 1;
case'*': return 2;
case'/': return 2;
}
if (cmp (Line+pos,"sin")) return 3;
if (cmp (Line+pos,"cos")) return 3;
return 255;
}
/*************************************************/
float Val (char Line[], int Begin, int End,float x)
/************ Основная ф-ция *********************/
//На входе - Line выражение для разбора
//Begin,End - начало/конец строки для разбора
//x - в строке вместо 'x' будет подставлено
//указанное значение
{
int i;//счетчик
int deep=0;//глубина вложенности скобок
int deepest=255;//максимальная достигнутая глубина вложенности
int priority=255;//приоритет операции
int lowlest=-1;
char temp[255];
for (i=End;i>=Begin;i--)//начинаем разбирать с конча в начало
{
if (Line[i]==')'){deep++;continue;}//если скобка - пропускаем
if (Line[i]=='('){deep--;continue;}
if (Operator(Line,i)<255)//Если найден оператор
{
if (deep<deepest)//если он менее приоритетный
{
lowlest=i;
deepest=deep;
priority=Operator(Line,i);
continue;
}
if (deep<=deepest&&Operator(Line,i)<priority)
{
lowlest=i;
deepest=deep;
priority=Operator(Line,i);
continue;
}
}
}
if (priority==255)//не неайден ни один оператор - надо вернуть цифру.
{
for (i=Begin;i<=End;i++)
{
temp[i-Begin]=Line[i];
if (Line [i]=='x'||Line[i]=='X') return x;
}
temp[End-Begin+1]='\0';
return (float)atof (temp);
}
if (deepest!=0)//есть внешние скобки - по крайней мере одна пара.
return Val (Line,Begin+1,End-1,x);//сужаем размер рассматриваемой строки
//во всех других случаях имеем полноценное выражение
switch (Operator (Line,lowlest))
{
case 1: switch (Line[lowlest])
{
case '+': return Val(Line,Begin,lowlest-1,x)+Val(Line,lowlest+1,End,x);
case '-': return Val(Line,Begin,lowlest-1,x)-Val(Line,lowlest+1,End,x);
}
case 2: switch (Line[lowlest])
{
case '*': return Val(Line,Begin,lowlest-1,x)*Val(Line,lowlest+1,End,x);
case '/': return Val(Line,Begin,lowlest-1,x)/Val(Line,lowlest+1,End,x);
}
case 3:
if (strcmp (Line+lowlest,"sin")>0) return (float)sin (Val(Line,lowlest+4,End,x));
if (strcmp (Line+lowlest,"cos")>0) return (float)cos (Val(Line,lowlest+4,End,x));
}
}
>> файло всякое заканчивается
George.
--- GoldED+/W32 1.1.2
* Origin: time 0:00-8:00 freq time 2:00-8:00 phone 2738633 (2:5030/744.46)