
- •2.2. Управляющие последовательности
- •12.3.3. Отсутствие элементов конструкций.
- •2.4. Терминальные символы
- •12.4.1. Символ из множества.
- •12.4.2. Символ, не принадлежащий множеству
- •12.4.3. Строка символов из множества.
- •12.4.4. Строка из одинаковых символов.
- •12.4.5. Операция конкатенации строк
- •2.5. Круглые скобки
- •2.6. Семантика языка
- •Int I, number;
- •Int number_string - номер последней обрабатываемой строки,
- •3. Пример программы разбора
- •14.2. Преобразование грамматики
- •14.3. Примеры преобразования грамматик на метаязыке
Int I, number;
float Digit, Float, Decimal;
Как видно из программы результат вычислений (действительное чис-
ло) записывается в переменную Decimal. В переменной Digit после анали-
за каждой цифры записывается ее значение. При формирование числа зна-
чение первой его цифры присваивается числу, и счетчик цифр в числе
number устанавливается равным единице. При дальнейшем разборе цифр их
значение прибавляется к предыдущему значению числа, умножаемому на 10,
и счетчик цифр увеличивается на 1. Последний используется для формиро-
вания из полученного числа Float дробной части, если разбираемое число
содержит десятичную точку.
В приведенном выше примере в семантике использовались только ин-
формация о терминальных символах грамматики. В этом случае невозможно
использовать более компактные варианты метаязыка для записи терминаль-
ных символов. Более компактная запись приведенного выше примера дости-
гается наличием возможности использования последней анализируемой лек-
семы исходного текста. Для этого используется указатель на char (по
умолчанию это token), который указывает на начало последней анализиру-
емой лексемы. При записи семантики можно использовать следующие гло-
бальные объекты.
Int number_string - номер последней обрабатываемой строки,
char * current_symbol - адрес последнего анализируемого символа,
char * token - последняя обрабатываемая лексема.
- 23 -
Имена этих объектов можно изменить при генерации, путем изменения фай-
ла конфигурации. Текст примера на метаязыке сократится, если использо-
вать глобальный объект token.
/* --------------------------------------------------------*/
<десятичное число> /*программа разбора десятичного числа*/
::= {09}
#{ Decimal = 0;
for ( i = 0; token[i] != '\0'; i++;)
{ Decimal *= 10;
Decimal += (*(token+i)) - 48;
};
}#
( .{09}
#{ for( i = 0; token[i] != '\0';i++;)
{ Decimal *= 10;
Decimal += (*(token+i)) - 48;
};
}#
';'
#{ for (j=1; j <= i; j++;)
Decimal /= 10;
}#
| ';'
)
/* -------------------------------------------------------- */
Если использовать стандартные функции работы со строками програм-
ма на метаязыке ещё более сократится. Понадобится еще одна переменная
char str[80];
/* --------------------------------------------------------*/
- 24 -
<десятичное число> /*программа разбора десятичного числа*/
::= {09}
#{ strcpy(str,token); }#
( .{09}
#{strcat(str,token);}#
';'
| ';'
)
#{ Decimal = atof(str);}#
/* -------------------------------------------------------- */
В следующих версиях предусмотрена ещё более компактная запись се-
мантики. Приведем программу на метаязыке без её обсуждения.
/* --------------------------------------------------------*/
<десятичное число> /*программа разбора десятичного числа*/
::= <String_decimal>;
#{ Decimal = atof(String_decimal);}#
char * <String_decimal>
::= {09} (.{09} | * )
/* -------------------------------------------------------- */
или
/* -------------------------------------------------------- */
char * <String_decimal>
::= {09} (.{09} | * )
#{ Decimal = atof(String_decimal);}#
/* -------------------------------------------------------- */
или
/* --------------------------------------------------------*/
/*программа разбора десятичного числа*/
float <Decimal> ::= {09} (.{09} | * )
/* -------------------------------------------------------- */
.
- 25 -