![]() |
|
Модераторы: bsa |
![]()
|
|
| Schweppes |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.4.2009 Репутация: нет Всего: нет |
Здравствуйте, уважаемые программисты! Обращаюсь к вам за помощью. Третий раз с нуля переписываю программу, и на третий раз совсем не могу придумать рационального решения.
Задача такая: Построить синтаксический анализатор для понятия текст_со_скобками. текст_со_скобками::= элемент | элемент текст_со_скобками элемент::= А | В | (текст_со_скобками) | [текст_со_скобками] | {текст_со_скобками} Всё это нужно сделать с использованием рекурсии. Никакими массивами пользоваться нельзя. Считывать с входного файла нужно посимвольно. В выходной файл будет занесена исходная последовательность символов + название ошибки, которая там встретится, если она есть. В файл протокола заносятся название использованных функций, с глубиной их рекурсивного вызова, тоесть чем вызов глубже, тем отступ больше. Пример входного файла: (A)(B){A} или [(A)] или [()] -- тут будет ошибка, так как внутри круглых скобок нет символа, программа остановится после закрывающих круглых скобок. В выходном файле должна быть последовательность до ошибки и название самой ошибки. Вот ещё пример: [({A(A)}]) тут ошибка в том, что закрывается квадратная скобка, когда должна закрываться круглая. Вот мой код:
Собственно вопрос. Как сделать функцию для круглых и фигурных скобок + проверка на некорректность, чтобы отслеживалась такая ошибка: {[(A)}] - скобки закрыты неправильно. Или хотя бы ((А))) - нет круглой открывающей. Если у кого то будет время - посмотрите пожалуйста. Заранее благодарен. |
|||
|
||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 5 Всего: 59 |
А просто A без скобок или AA или AB допустимо?
|
|||
|
||||
| Schweppes |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.4.2009 Репутация: нет Всего: нет |
Anikmar, просто А может быть; подряд идущих АА или АB может быть сколько угодно.
Если удастся, то можно реализовать ещё такую некорректную ситуацию: ((А)А) - ошибка, так как вторая А стоит между скобками, но в тоже время (A(A)) является правильной последовательностью. Вот ещё разные примерчики: )(A){AA} - программа должна остановиться после первого символа и вывести в выходной файл ошибку, что нет открывающей круглой скобки. А(А) - правильно А(А(А) - ошибка, так как нет закрывающей круглой скобки А({A)} - ошибка, так как фигурные или круглые скобки закрыты непрально. Это сообщение отредактировал(а) Schweppes - 19.4.2009, 22:58 |
|||
|
||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 5 Всего: 59 |
А рекурсия необходима? Без нее мне кажется проще.
|
|||
|
||||
| Schweppes |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.4.2009 Репутация: нет Всего: нет |
Anikmar, Тема рекурсии, так что использовать можно только её....И никаких массивов)
|
|||
|
||||
| kamre |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 330 Регистрация: 24.3.2006 Репутация: 2 Всего: 13 |
А почему это вдруг "((A)A)" считается ошибкой? S => E => (S) => (E S) => ((S) S) => ((E) S) => ((A) S) => ((A) E) => ((A) A) У меня пока вот так получается в коде на C++:
|
||||||
|
|||||||
| Schweppes |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.4.2009 Репутация: нет Всего: нет |
kamre, У вас используется структура? к сожалению её применять нельзя. Только Обычные сравнения при помощи рекурсий, как я начал делать...
|
|||
|
||||
| zim22 |
|
|||
|
depict1 ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2682 Регистрация: 15.1.2009 Где: Украина Репутация: 29 Всего: 69 |
структуру нельзя, а буст можно?
|
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 35 Всего: 223 |
У него используется готовый парсер (boost/spirit) Вам нужен 'метод рекурсивного спуска' - ищите Или скормите вашу граматику ANTLR - он вам выдаст готовый парсер, сделанный по этой технологии |
|||
|
||||
| Schweppes |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 19.4.2009 Репутация: нет Всего: нет |
zim22,
xvr, Ни бустов, ни парсеров нельзя. Надо делать в лоб) |
|||
|
||||
| xvr |
|
||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 35 Всего: 223 |
ANTLR и построит 'в лоб'. Правда не уверен, что программа, которую он сгенерит, будет похожа на написанную вручную В общем, метод рекурсивного спуска реализуется так: 1) Строим грамматику - 1 правило на каждый вариант:
2) На каждое правило делаем функцию, которая его отрабатывает. Функции строятся так: а) Есть 1 lookahead символ, по нему определяем, какую функцию звать б) Когда функция обработает этот lookahead, она читает следующий символ (и т.д.)
|
||||||
|
|||||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 5 Всего: 59 |
Мой вариант.
На все возхможные приколы не тестировал - но вроде основное отрабатывает.
|
|||
|
||||
| cupper |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 525 Регистрация: 29.11.2006 Репутация: нет Всего: 1 |
ватсон все элементарно, небуду писать код потомучто его будет много да и отлаживать пришлосьбы опишу логику как вы должны делать.
Создать следующие функции: Функция которая вызываеться если попалась открывающаяся круглая скобка ( (назовем ее "функция_(" ) Функция которая вызываеться если попалась открывающаяся фигурная скобка { ( (назовем ее "функция_{" ) Функция которая вызываеться если попалась открывающаяся квадратная скобка [ ( (назовем ее "функция_[" ) ... аналогичный функции для всех остальных видов открывающихся функций Далее что эти функции должны делать, распишу на примере одной, все остальный аналогичны, разницы только в видах скобок функция_( делает следующее: 1) считывает следующих за ней символ (если функция вызываеться сразу для следующего за ( символом то ненадо ничего считывать) 2) смотрим что это за символ: --2.1) если это ( то рекурсивно вызываем функция_( либо на этом символе лобо на символе следующим за этим (тут вы сами вольны выбрать логику програмы, и советую придерживаться выбранной, проще отслеживать алгоритм будет) -------- если это { то вызываем функция_{ либо на этом символе лобо на символе следующим за этим -------- и так проверка на все виды скобок -------- если это символ отличтный от допустимых открывающихся скобок то проверяем на его допустимость как символа A, B и т.д. -------- если это не допустимый символ (может быть закрывающаяся скобка или что либо иное) говорим RETURN ERROR --------2.1.1) сюда попадаем если считаный символ был удовлитворительной буквой (A, B и т.д.) --------------- считываем следующим за ним символ --------------- если это ( то рекурсивно вызываем функция_( --------------- если это { то вызываем функция_{ --------------- и так проверка на все виды скобок --------------- если это не скобка, проверяем являетьсяли символ допустимым A, B, и т.д. Если да то возвращаемся на 2.1.1 Если нет выходим из цыкла (на этом символе который не открывающаяся скобка и не допустимая буква) -------- Проверяем являетьсяли этот символ закрывающийся круглой скобкой ( (для функции функция_{ что это символ } и тогдалее для всех функций и соотвествующих им закрывающихся скобок) -------- Если да тогда благополучно выходим из это функции -------- если нет ГОВОРИМ RETURN ERROR (и собсно этот символ и есть первая ошибка) Это сообщение отредактировал(а) cupper - 20.4.2009, 21:08 |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 15 Всего: 101 |
Читайте xvr, у него наиболее приятный и осмысленный код, удовлетворяющий заданию.
Добавлено через 3 минуты и 43 секунды xvr, lookahead неплохо бы начально проинициализировать нулем. для понятности |
|||
|
||||
| Anikmar |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2513 Регистрация: 26.11.2006 Где: Санкт-Петербург Репутация: 5 Всего: 59 |
||||
|
||||
![]()
|
| Правила форума "C/C++: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |