Реализация синтаксического блока. Применение конечного автомата, страница 6

<litem>     à <lfactor> & {G2} <lfactor2>

<litem>     à <lfactor>

<lfactor2> à <lfactor> {G3} &  {G2} <lfactor2>

<lfactor2> à <lfactor> {G3}

<lfactor>   à  <arithm>  <   {G2} <arithm> {G3}

<lfactor>   à  <arithm>  >   {G2} <arithm> {G3}

<lfactor>   à  <arithm>  =   {G2} <arithm> {G3}

<lfactor>   à  <arithm>  <= {G2} <arithm> {G3}

<lfactor>   à  <arithm>  >= {G2} <arithm> {G3}

<lfactor>   à  <arithm>  <> {G2} <arithm> {G3}

<arithm> à <item> + {G2} <item2>

<arithm> à <item> - {G2} <item2>

<arithm> à <item>

<item2> à <item> {G3}+ {G2} <item2>

<item2> à <item> {G3}- {G2} <item2>

<item2> à <item> {G3}

<item> à <factor> * {G2} <factor2>

<item> à < factor> / {G2} < factor 2>

<item> à < factor>

<factor2> à <factor> {G3} *  {G2} <factor2>

<factor2> à <factor> {G3} /  {G2} <factor2>

<factor2> à <factor> {G3}

<factor> à  <prim>  **  {G2} <factor> {G3}             //возведение в степень

<factor> à  <prim>

<prim> à  - {G2} <prim> {G3}

<prim> à  ! {G2} <prim> {G3}

<prim> à  F {G2} (<expr>){G3}                               //функция одной переменной

<prim> à  D {G2} (<expr>,<expr>){G3}                 //функция двух переменных

<prim> à  (<expr>)

<prim> à  l {G1}

И наконец, изменения в тексте программы

#include <stdio.h>

.   .   .

char stack[80], *top,  /* стек знаков операций */

     ibuf[80],  *pr,   /* входной буфер        */

     obuf[80],  *pw;   /* выходной буфер       */

void expr(void), litem(void), lfactor(void),

   operand(void), arithm(void),

   item(void), item2(void), factor(void),

     factor2(void), prim(void), ident(void);

.   .   .

   item();

   if (*pr=='+' || *pr=='-'){

                  *top++ = *pr++;

                  item2();

   }

Головная процедура

 .  .  .

     strcpy(ibuf,Edit1->Text.c_str());

     pr=ibuf; pw=obuf; top=stack;

     expr();

     *pw='\0';

     Edit2->Text= obuf;

            .   .   .

void expr(void){

litem();

if (*pr=='|'){

       *top++ = *pr++;

litem2();

}

}

void litem2(void){

litem();

*pw++=*--top;

if (*pr=='|'){

            *top++ = *pr++;

litem2();

 }

}

void litem(void){

lfactor();

if (*pr=='&'){

               *top++ = *pr++;

               lfactor2();

}

}

void lfactor2(void){

lfactor();

*pw++=*--top;

if (*pr=='&'){

               *top++ = *pr++;

               lfactor2();

}

}

void lfactor(void){

arithm();

if (*pr =='='|| *pr=='#'|| *pr=='>'|| *pr=='<'){

*top++ = *pr++;

              arithm();

              *pw++ = *--top;

}

}

void arithm(void){

item();

if (*pr=='+' || *pr=='-'){

*top++ = *pr++;

 item2();

}

}

void item2(void){

 item();

 *pw++ = *--top;

 if (*pr=='+' || *pr=='-'){

*top++ = *pr++;

item2();

}

}

void item(void){

factor();

if (*pr=='*' || *pr=='/'){

     *top++ = *pr++;

     factor2();

}

}

void factor2(void){

 factor();

 *pw++ = *--top;

 if (*pr=='*' || *pr=='/'){

     *top++ = *pr++;

     factor2();

 }

}

void factor(void){

prim();

if (*pr=='^'){

        *top++ = *pr++;

        factor();

        *pw++ = *--top;

}

}

void prim(void){

if (*pr=='-'){

        *top++ = '_'; pr++; //меняем минус - на унарный минус _

        prim();

        *pw++ = *--top;

}else

if (*pr=='!'){

        *top++ = *pr++;

        prim();

        *pw++ = *--top;

}else

if (*pr=='('){

       pr++;

       expr();

       if(*pr==')') pr++;

       else ErrMes("Нарушен баланс скобок");

}else

if (*pr=='F'){

       *top++ = *pr++;

       if(*pr=='(') {pr++;

                   expr();

if(*pr==')'){ pr++;*pw++ = *--top;}

else ErrMes ("Нарушен баланс скобок");

} else ErrMes ("Нет отрывающей скобки");

}else

if (*pr=='D'){

       *top++ = *pr++;

       if(*pr=='('){ pr++;

expr();

                   if(*pr==','){

pr++;

     expr();

       if(*pr==')'){ pr++; *pw++ = *--top;}

       else ErrMes ("Нарушен баланс скобок");

} else ErrMes ("Нет запятой");

       } else ErrMes ("Нет открывающей скобки");

}else

if( isalpha(*pr) || isdigit(*pr)) *pw++ = *pr++;

ErrMes ("Неверный операнд");

}

Что нужно изменить в программе для КП?

#define G1 FPRT; NS

#define G2 *top++=symbol; NS

#define G3 fprintf(out,"%02d ",*--top);pos=sprintf(postr,"%02d ",*top);postr+=pos

Вместо

 *pr=='*'

писать

 symbol==MUL и т.д.

Ввести глобальные переменные

int stack[80], *top;

и перед вызовом

Snt();

вставить

top=stack;

Еще один пример: реализация функций, у которых аргументом является список из двух и более элементов.

.  .  .

<prim> à  - {G2} <prim> {G3}

<prim> à  ! {G2} <prim> {G3}

<prim> à  F {G2} (<expr>){G3}                      //функция одной переменной

<prim> à  D {G2} (<expr>,<expr>){G3}         //функция двух переменных

<prim> à  M {G2} (<expr>,<listexpr>){G32}  //функция двух и более переменных

<prim> à  (<expr>)

<prim> à  l {G1}

.  .  .

<listexpr> à  <expr>{G31}, (<listexpr> | <expr>){G31}

void prim(void){

     if (*pr=='M'){

         *top++=*pr++;

         if(*pr=='('){ pr++; expr();

                if (*pr==','){pr++;  listexpr();

                      if(*pr==')'){ pr++; --top;

                      }

                }

          }

      }else   .   .    .

}

void listexpr(void){

  expr();

  *pw++=*(top-1);

  if(*pr==','){

    pr++;

    listexpr();

  }

}

Здесь:

#define G1 *pw++=*pr++

 #define G2 *top++=*pr++

#define G3 * pw++=*--top

#define G31 * pw++=*(top-1)

#define G32 --top

Для КП:

#define G1 FPRT; NS

#define G2 *top++=symbol; NS

#define G3 fprintf(out,"%02d ",*--top);pos=sprintf(postr,"%02d ",*top);postr+=pos

#define G31 fprintf(out,"%02d ",*(top-1));pos=sprintf(postr,"%02d ",*(top-1));postr+=pos

#define G32 top--