Плюс
скобки.
Добавим обычные скобки. Форма Бэкуса-Наура такая:
<expr> := <term>
{<add_op><term>}
<term> :=
<signed_factor>{<mul_op><signed_factor>}
<signed_factor> :=
[<add_op>]<factor>
<factor> :=
<integer>|(<expr>)
Обратим внимание – скобки «описаны» в конце последней формы БН. Здесь при составлении программы будет дополнительная рекурсия – вызов функции expr.
Вот программа:
/****************************/
#include <stdio.h>
#include <stdlib.h>
#include "Str_ex.h"
#include "QnS.h"
int
I=0;
int
n=5;
char Lex[150]; /* Это для лексем */
char Res[250]; /* Это для результирующей постфиксной
польской строки */
char End[3]; /* Это конец строки в текстовом файле */
char Sign1[2]={43,0};
char
Sign2[2]={45,0};
char
Sign3[2]={42,0};
char
Sign4[2]={47,0};
char
Sign5[3]={43,85,0};
char
Sign6[3]={45,85,0};
void
expr();
/******************************/
/* sprintf(A,"n=%d",n);*/
/******************************/
/* Это - обработка формулы
со сложением-вычитанием и
умножением-делением, а также
с одним унарным плюсом или минусом (перед каждым числом).
Результат - в польской постфиксной
записи */
int J=1;
void NextLexema() /* Получает очередную лексему */
{
int R;
*Lex=0;
R=FindStrN("Pr.txt",End,Lex,100,J);
J++;
if(R<0)
{
*Lex=0;
WrStr("Lexema.txt",End," THE END! ",1); /* В тестовых
целях
пишем в файл */
return;
}
else
{
WrStr("Lexema.txt",End,Lex,1); /* В тестовых целях
пишем в файл */
};
}
void fact() /* Это множитель - конечный пункт рекурсии */
{
if(*Lex==40)
{
NextLexema();
expr();
if(*Lex!=41)
{
*Res=0;
sprintf(Res,"Lexema: %d
",J-1);
StrCat("ERROR - No Bracket
!!! ",Res);
}
else
{
NextLexema();
}
}
else
{
if(testnum_l(Lex)==0&&(*Lex>47&&*Lex<58)) /* Проверка - является ли целым числом */
{
StrCat(Lex,Res);
StrCat(" ",Res);
NextLexema();
}
else
{
if(*Lex==0)
{
*Res=0;
sprintf(Res,"Lexema: %d
",J-1);
StrCat("ERROR - 0-lexema,
probably phrase is not finished!
",Res);
}
else
{
*Res=0;
sprintf(Res,"Lexema: %d
",J-1);
StrCat("ERROR - Wrong lexema! ",Res);
}
};
};
}
void sfact() /* Это множитель со знаком (унарным) */
{
char
Lex1[150];
Lex1[0]=0;
if(*Lex==43||*Lex==45)
{
CpStr(Lex,Lex1);
NextLexema();
}
fact();
if(*Lex1!=0)
{
StrCat(Lex1,Res);
StrCat("U",Res);
StrCat(" ",Res);
}
}
void term() /* Обработка умножения-деления */
{
char
Lex1[150];
Lex1[0]=0;
sfact();
/*while(COMPstr("*",Lex)==0||COMPstr("/",Lex)==0)*/
while(*Lex==42||*Lex==47)
{
CpStr(Lex,Lex1);
NextLexema();
sfact();
StrCat(Lex1,Res);
StrCat(" ",Res);
}
}
void expr() /* Обработка сложения-вычитания */
{
char
Lex1[150];
Lex1[0]=0;
term();
/*while(COMPstr("+",Lex)==0||COMPstr("+",Lex)==0)*/
while(*Lex==43||*Lex==45)
{
CpStr(Lex,Lex1);
NextLexema();
term();
StrCat(Lex1,Res);
StrCat(" ",Res);
}
}
/********************************/
/* Обработка строки с польской обратной
записью */
int
iPF=1;
int
PostFix(char *S,int L,int N,char *Dest)
{
void * pSt;
char St[100];
int i,res;
int iPF1;
int iPF2;
int iPF3;
char *S1;
void *pS1;
/*char S2[50];
char S3[50];
char S4[100];*/
int r=0;
double F1,F2,F3;
if(*S==0)
{
WrStr("PostFix.txt",End,"Empty!",1);
return -2;
}
pS1=malloc(L);
if(pS1==NULL)
{
return
-1;
}
S1=(char *)pS1;
*S1=0;
/*WrStr("PostFix.txt",End,"Coming",1);*/
pSt=CreateStack(L*N);
while(iPF>0)
{
/*WrStr("PostFix.txt",End,"Cycle",1);*/
iPF1=CpWordN(S,S1,32,iPF);
if(iPF1<0)
{
break;
}
iPF++;
if(!(COMPstr(S1,Sign1)==0||COMPstr(S1,Sign2)==0||COMPstr(S1,Sign3)==0||COMPstr(S1,Sign4)==0||
COMPstr(S1,Sign5)==0||COMPstr(S1,Sign6)==0))
/* Если символ не знак, помещаем в стек */
{
for(i==0;i<100;i++)
*(St+i)=0;
CpStr(S1,St);
res=AddArrayToStackNoPart(pSt,St,100);
if(res!=100)
{
r=-3;
WrStr("PostFix.txt",End,"Stack
error!",1);
}
}
else /* Если символ - знак */
{
if(COMPstr(S1,Sign1)==0||COMPstr(S1,Sign2)==0||COMPstr(S1,Sign3)==0||COMPstr(S1,Sign4)==0)
{
for(i==0;i<100;i++) *(St+i)=0;
res=GetArrayFromStack(pSt,St,100);
if(res!=100)
{
r=-4;
WrStr("PostFix.txt",End,"Stack
error (getting)!",1);
}
F1=atol(St);
for(i==0;i<100;i++) *(St+i)=0;
res=GetArrayFromStack(pSt,St,100);
if(res!=100)
{
r=-5;
WrStr("PostFix.txt",End,"Stack
error (getting)!",1);
}
F2=atol(St);
if(COMPstr(S1,Sign1)==0) /* Если
сложение */
{
F3=F2+F1;
}
if(COMPstr(S1,Sign2)==0) /* Если
вычитание */
{
F3=F2-F1;
}
if(COMPstr(S1,Sign3)==0) /* Если
умножение */
{
F3=F2*F1;
}
if(COMPstr(S1,Sign4)==0) /* Если
деление */
{
F3=F2/F1;
}
sprintf(St,"%f",F3);
/*Кладем результат в стек*/
for(i==0;i<100;i++) *(St+i)=0;
res=AddArrayToStackNoPart(pSt,St,100);
if(res!=100)
{
r=-6;
WrStr("PostFix.txt",End,"Stack
error!",1);
}
}
if(COMPstr(S1,Sign5)==0||COMPstr(S1,Sign6)==0)
{
for(i==0;i<100;i++) *(St+i)=0;
res=GetArrayFromStack(pSt,St,100);
if(res!=100)
{
r=-4;
WrStr("PostFix.txt",End,"Stack
error (getting)!",1);
}
F1=atol(St);
if(COMPstr(S1,Sign6)==0) /* Если унарный
минус */
{
F3=-F1;
}
if(COMPstr(S1,Sign5)==0) /* Если
унарный минус */
{
F3=F1;
}
sprintf(St,"%f",F3);
/*Кладем результат в стек*/
for(i==0;i<100;i++) *(St+i)=0;
res=AddArrayToStackNoPart(pSt,St,100);
if(res!=100)
{
r=-6;
WrStr("PostFix.txt",End,"Stack
error!",1);
}
}
}
}
/*Извлекаем из стека результат*/
for(i==0;i<100;i++) *(St+i)=0;
res=GetArrayFromStack(pSt,St,100);
if(res!=100)
{
r=-7;
WrStr("PostFix.txt",End,"Stack
error (getting)!",1);
}
*S1=0;
StrCat(St,S1);
WrStr("PostFix.txt",End,"Result
in stack: ",1);
WrStr("PostFix.txt",End,S1,1);
/* Конец извлечения результата из стека*/
CpStr(S1,Dest);
DeleteStack(pSt);
free(pS1);
return r;
}
/*******************/
void
main(void)
{
Lex[0]=0;
Res[0]=0;
End[0]=13;
End[1]=10;
End[2]=0;
char dest[200];
NextLexema();
expr(); /* Это вход в разбор формулы */
if(*Lex!=0) /* Это если в конце разбора осталась лишняя
лексема (но не знак) */
{
*Res=0;
sprintf(Res,"Lexema: %d
",J-1);
StrCat("ERROR - More Lexemas!
",Res);
}
WrStr("Result.txt",End,Res,1); /* Записываем результирующую
польскую постфиксную строку
в файл */
PostFix(Res,100,100,dest);
WrStr("Result.txt",End,"А
число:",1);
WrStr("Result.txt",End,dest,1);
WrStr("LastLex.txt",End,Lex,1);
sprintf(dest,"Длина посл. лексемы = %d
",lenstr(Lex));
WrStr("LastLex.txt",End,dest,1);
return;
}
/******************************/
Папка этого проекта – Gramm3.