Программа-интерпретатор для учебного языка SPL, страница 12

              t1 = gen( JMC, 0 );

              stml();

              exam( '@' );

              TCD[t1].opd = tc;

              break;

    case WHILEL: get();

                 t1 = tc;

                 expr();

                 exam( DOL );

                 t2 = gen( JMC, 0);

                 stml();

                 gen( JMP, t1 );

                 TCD[t2].opd = tc;

                 exam( '@' );

                 break;

    default:

      printf( "Недопустимая лексема lex = %i в строке nst = %i!\n", lex, nst );

  }

  return;

}

void expr() {

  int neg = (lex == '-');

  if (lex == '+' || lex == '-')

    get();

  term();

  if (neg == 1)

    gen( OPR, 8 );

  while (lex == '+' || lex == '-') {

    neg = (lex == '+') ? 3 : 4;

    get();

    term();

    gen( OPR, neg );

  }

  return;

}

void term() {

  int op;

  fact();

  while (lex == '*' || lex == '/' || lex == '%') {

    op = (lex == '*') ? 5 : (lex == '/') ? 6 : 7;

    get();

    fact();

    gen( OPR, op );

  }

  return;

}

void fact() {

  int cp;

  odc *p;

  fnd *p1;

  char *nm;

  switch (lex) {

    case IDEN: nm = (char *)lval;

               get();

               if (lex == '(') {

                 get();

                 cp = (lex == ')') ? 0 : fctl();

                 exam( ')' );

                 p1 = eval( nm, cp );

                 gen( LIT, cp );

                 cp = gen( CAL, p1->start);

                 if (!p1->isd)

                 p1->start = cp;

               }

               else {

                 p = findob( nm );

                 gen( p->what == 1 ? LIT : p->what == 2 ? LDE : LDI, p->val );

               }

               break;

    case '(': get();

              expr();

              exam( ')' );

              break;

    case NUMB: gen( LIT, lval );

                                get();

                                break;

    case SQRL: get();

               exam( '(' );

               expr();

               gen( OPR, 11 );

               exam( ')' );

               break;

    default:

      printf( "Недопустимая лексема lex = %i в строке nst = %i!\n", lex, nst );

      exit( 0 );

  }

  return;

}

int fctl() {

  int cf = 1;

  expr();

  while (lex == ',') {

    get();

    expr();

    cf++;

  }

  return cf;

}

void prog() {

  fnd *p;

  while (lex != EOF)

    switch (lex) {

      case IDEN: dfunc();

                 break;

      case INTL: dvarb();

                 break;

      case CONSTL: dconst();

                   break;

      default:

        printf( "Недопустимая лексема lex = %i в строке nst = %d!\n",

                lex, nst );

        break;

    }

  p = fmain();

  adrnm = p->start;

  cpnm = p->cpt;

  return;

}

void dconst() {

  do {

    get();

    cons();

  } while (lex == ',');

  exam( ';' );

  return;

}

void cons() {

  int s;

  char *nm = (char *)lval;

  exam( IDEN );

  exam( '=' );

  s = (lex == '+') ? +1 : -1;

  if (lex == '+' || lex == '-')

    get();

  newob( nm, 1, s*lval );

  exam( NUMB );

  return;

}

void dvarb() {

  do {

    get();

    newob( (char *)lval, out ? 2 : 3, out ? cgv++ : ++clv );

    exam( IDEN );

  } while (lex == ',');

  exam( ';' );

  return;

}

void dfunc() {

  int cp;

  int st;

  char *nm = (char *)lval;

  get();

  out = 0;

  cp = param();

  st = body();

  out = 1;

  ptol = pto;

  defin( nm, cp, st );

  return;

}

int param() {

  int cp = 0;

  odc *p;

  exam( '(' );

  if (lex != ')') {

    newob( (char *)lval, 3, ++cp );

    exam( IDEN );

    while (lex == ',') {

      get();

      newob( (char *)lval, 3, ++cp );

      exam( IDEN );

    }

  }

  exam( ')' );

  for (p = ptol; p < pto; p++)

    p->val -= cp+3;

  return cp;

}

void exam( int lx ) {