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

}

В-четвертых, в синтаксическом анализе переписываются:

  • exam( BEGINL ) на exam( { );
  • exam( ENDL ) на exam( } ).

Изменение №2: Замена ключевого слова end, завершающего конструкции if и while, на @

Нужно заменить в конструкциях if и while фигурную скобку } на @:

if b%2 then z = z*a @;

Для этого переписывается функция get() (лексический анализ):

if (nch == '+' || nch == '-' || nch == '*' || nch == '/' ||

    nch == '%' || nch == '(' || nch == ')' || nch == ',' ||

    nch == ';' || nch == '=' || nch == '{' || nch == '}' ||

    nch == '@' || isspace( nch )) {

  lex = nch;

  nch = getc( PF );

}

и в функции stat() меняется exam( } ) на exam( @ ).

Изменение №3: Добавление своей собственной команды sqr — команды возведения в квадрат

Добавляется одиннадцатая (11ая) командаOPR 11. Эта команда возводит в квадрат число, которое лежит в вершине стека t.

Для осуществления задуманного вносятся изменения в синтаксическую диаграмму для FACT:

Регулярное выражение для FACT принимает вид:

FACT®’(’ EXPR ‘)’ | numb | iden [‘(’ [FCTL] ’)’] | sqr ’(’ EXPR ‘)’

Также добавляется новая лексема SQRL, соответствующая ключевому слову sqr:

enum {READL=257, PRITL, RETRL, IFL, THENL, WHILEL, DOL, CONSTL, INTL, IDEN, NUMB, SQRL};

В функции fact() добавляется еще одна инструкция case:

case SQRL:

     get();

     exam( '(' );

     expr();

     gen( OPR, 11 );

     exam( ')' );

     break;

а в функции operat( int a ):

case 11: st[t] = st[t]*st[t];

         break;

Изменение №4: Перевод ключевых слов на русский язык

Эта часть работы может оказаться самой сложной. Во время решения задачи перевода ключевых слов на русский язык возникают трудности:

  1. стандартная функция для обработки символов int isalpha( char ) (ctype.h) распознает только латинские буквы, и поэтому функция get(), считывая кириллический символ, прекращает работу всей программы, т. к. isalpha не понимает «русский язык»;

Напишем свою функцию int _isalpha( int ), которая возвращает единицу (1), если ею был получен в качестве аргумента кириллический символ (), и нуль (0) — был получен не кириллический символ. Во второй части расширенной таблицы ASCII для кириллицы отведены коды:

Код
Символ

128-159

160-175

224-239

Легко заметить, что получает наша функция _isalpha в качестве аргумента совсем другие коды. А именно:

Код
Символ

-128--97

-96--81

-32--17

Тогда пишется окончательный код функции _isalpha:

int _isalpha( int p ) {

  int t;

  t = 256+p;

  if ((t >= 128 && t <= 159) ||

    (t >= 160 && t <= 175) ||

    (t >= 224 && t <= 239) || isalpha( p ))

    return 1;

  else

    return 0;

}

  1. переписывается и стандартная функция int isdigit( ch ), так как она, например, кириллическую букву «Б» принимает за цифру.

Вот приведены коды для чисел от 1 до 10:

Код
Символ

48-57

Функция _isdigit принимает вид:

int _isdigit( int p ) {

  if (p >= 48 && p <= 57)

    return 1;

  else

    return 0;

}

  1. Функция int isspace( ch ) также привлекает внимание, потому что работает не так, как нужно. Пишется новая функция _isspace:

int _isspace( int p) {

  if (p == 9 || p == 10 || p == 32)