Задача A. Вирт
Условие
Лексемы языка программирования Вирт задаются следующим набором регулярных выражений
(для экранирования метасимволов использован символ '\',
например регулярное выражение - '\*\)' задает последовательность символов '*)'):
- цифра — [0-9]
- буква — [A-Za-z_]
- символ — [^'\n]|''
- символ из двух кавычек обозначает одну кавычку
- многострочный_комментарий — {[^}]*}
- многострочный_комментарий — \(\*[^(\*\))]*\*\)
- строчный_комментарий — //[^EOF\n]*[EOF\n]
- пробельные символы — [ \t\n\r]+
- идентификатор — {буква}({буква}|{цифра})*
- число — {цифра}+
- шестнадцатеричное_число — $[0-9A-Fa-f]+
- экспонента — [Ee][+-]?{число}
- вещественное_число — {число}\.{число}
- вещественное_число — {число}(\.{число})?{экспонента}
- символьная_литера — '{символ}'
- символьная_литера — #[{число}{шестнадцатеричное_число}]
- строка — '{символ}*'
- строка может иметь длину 0, 2 или более символов.
Цифра, буква, символ и экспонента являются вспомогательными символами и не являются лексемами языка.
Помимо лексем выводимых из этих правил в лексику языка также входят ключевые слова,
знаки операций и разделители, списки которых представлены ниже:
- begin, forward, do, else, end, for, function, if, array, of, procedure,
program, record, then, to, type, var, while, break, continue, downto, exit,
repeat, until
- and, div, mod, not, or, xor, +, -, *, /, ^,
+=, -=, *=, /=, <, >, <=, >=, =, <>, :=, @, .
- (, ), [, ], ;, :, .., (символ запятая ',')
Требуется написать программу, которая будет распознавать лексемы данного языка.
Программа должна пытаться составить текущую лексему из как можно большего числа символов,
например в строке '....' следует сначала распознать '..', а затем '.'.
В процессе распознавания может встретиться одна из следующих ошибок.
Код ошибки — описание ошибки:
- BadNL — Символ '\n' (новая строка) посреди символьной литеры/строки (строковой константы)
- BadEOF — Конец файла посреди строки/символьной литеры/многострочного комментария
- BadChar — Появление символа не являющегося продолжением текущей лексемы или началом новой
- NoExp — Отсутствие числа в экспоненте вещественного числа
(если за числом/вещественным числом встретился символ [Ee][+-]?,
то за ним должно следовать число)
- NoFract — Отсутствие числа в дробной части вещественного числа
(если за числом встретился символ точки '.', то за ним должно следовать число,
кроме того допустимым продолжением также является еще один символ точки '.',
в таком случае будут сформированы 2 лексемы число и разделитель '..',
любые другие продолжения должны вызвать ошибку NoFract)
- NoHex — Отсутствие шестнадцатеричных цифр в записи шестнадцатеричного числа
- NoCC — Отсутствие кода символа после #
- BadCC — Код символа не попадает в промежуток [0, 127]
Формат входного файла
Входной файл содержит N строк ASCII символов.
Формат выходного файла
Для каждой лексемы, за исключением пробельных символов и комментариев,
в порядке их появления во входном файле, выведите сообщение в формате
'Номер строки\tНомер столбца\tТип лексемы\tЛексема'
Номер строки/столбца - позиция первого символа лексемы во входном файле.
Нумерация строк и столбцов начинается с 1. Символ табуляции переводит курсор в ближайшую следующую позицию с номером P: P = 4 n+1
Для "значимых" типов лексем
выведите \tЗначение в формате, описанном ниже.
Тип лексемы и формат вывода Значения:
- Строка (string) - значение строки (символы кавычек,
обозначающие начало и конец строки, в значение строки не входят)
- Символьная литера (char) - значение символа, в виде соответствующего ASCII символа
- Число (integer) или шестнадцатеричное число (hex) - значение числа в десятичном представлении
- Вещественное число (real) - значение числа в формате '%.4E' (число представляется в виде
'ME[+-]P', где M — мантиса (число в промежутке (1, 10), за исключением числа 0.0000)
с ровно 4 знаками после запятой,
P — порядок (целое число с ровно 2 десятичными цифрами))
- Идентификатор (ident), знак операции (op), разделитель (sep) или
ключевое слово (keyword) - вывод значения не требуется
Сообщения для каждой лексемы выводить на новой строке.
В случае обнаружения ошибки выведите сообщение в формате
'Номер строки\tНомер столбца\tКод ошибки' и завершите работу программы
(выводить успешно распознанные лексемы до встречи ошибки нужно)
Для ошибок типа BadNL, Номер строки равен номеру строки, на которой началась строка.
Ошибка типа BadCC, должна возникнуть после считывания всего кода символа.
Ограничения
1 ≤ N ≤ 1000
Примеры тестов
№ |
Входной файл (input.txt ) |
Выходной файл (output.txt ) |
1 |
42 + 14.88
|
1 1 integer 42 42
1 4 op +
1 6 real 14.88 1.4880E+01
|
2 |
'new line in str
'
|
1 17 BadNL
|