2010-02-05 2 views
8

Я играю с написанием приключений MUD/text (пожалуйста, не смейтесь) в Ruby. Может ли кто-нибудь дать мне какие-либо указания относительно элегантного решения на основе oop для синтаксического анализа входного текста?Элегантный командный синтаксический анализ в текстовой игре на основе ООП

Мы говорим о нечем более сложном, чем «положить палочку на стол», здесь. Но все должно быть мягким; Я хочу продлить набор команд безболезненно, позже.

Мои текущие мысли, немного упрощены:

  1. Каждый класс элемент (окно, стол, комната, игрок) знает, как распознать команду, которая «принадлежит» к нему.

  2. Класс игры понимает своего рода язык, предметно-ориентированного с участием таких действий, как «двигаться объект X внутри объекта Y», «показать описание объекта X» и т.д.

  3. Класс игра просит каждого пункт в комнате, если он распознает команду ввода. Сначала сказать «да».

  4. Затем он передает управление методу в классе элементов, который обрабатывает команду. Этот метод перефразирует команду в DSL, передает ее обратно игровому объекту, чтобы это произошло.

Должны быть изношенные, элегантные способы сделать это. Однако, похоже, Google ничего не может понять.

+0

Как сноска, волосатый бит с моим текущим планом реализует действия, которые включают в себя два объекта. – Shadowfirebird

+1

Вы можете начать с http://stackoverflow.com/questions/tagged/natural-language и посмотреть, к чему это ведет. – dmckee

+0

Ta! Я только что добавил этот тег к вопросу. – Shadowfirebird

ответ

3

Interpreter design pattern является наиболее объектно-ориентированным подходом к разбору, что я знаю, но я уверен, что эксперты компилятора укажут алгоритмы, которые являются более мощными.

+0

Я мусор в шаблонах дизайна, и мой поисковик не смог этого увидеть. Я обязательно посмотрю на это, та. – Shadowfirebird

+0

Действительно, шаблон интерпретатора выглядит как дерево выражений в процессе компиляции! хороший. Для компилятора это похоже на реализацию straighforward. (после разбора символа строки) –

+0

Я все еще пытаюсь применить этот шаблон к моему проекту, но он выглядит скорее так, как будто это была идея, на которую я нащупывал. Тем не менее, это не так, как разбор строки команды. – Shadowfirebird

0

Split его на лексемы как формат будет всегда:
[команда] [object1] ([Отсносящийся] [object2])

Можно вызвать метод [команда] на [object1] в вашей комнате и передайте ему [object2], если это применимо.

+0

Это очень соблазнительно. Но «включите свет». Или, если на то пошло, было бы очень приятно принять «включить свет». – Shadowfirebird

+1

Вы можете сделать это, просто удалив то, что обычно называют «стоп-словами» из строки. Такие слова, как «the», «an», «on». В этом случае все, что осталось от предложения «теперь включить этот свет там», будет «поворотным». Конечно, это может быть слишком много, но в этом конкретном случае * отсутствие * слова «выключено» сообщает вам все, что вам нужно знать. –

+0

@Jorg: На самом деле это почти то, что делает мой текущий подход, за исключением того, что вместо этого он обнаруживает «начинать слова». Итак (для упрощения) класс света ищет /light.*(on|off)/. Может быть, у вас все в порядке, и я этого не сделаю. – Shadowfirebird

1

Для устных переводчиков я предпочитаю этот простой, не все тот элегантный образ. Шаблоны в динамических языках, как правило, содержат меньше коробок и линий, чем шаблоны GOF.

class Thing 

    # Handle a command by calling the method "cmd_" + command. 
    # Raise BadCommand exception if there is no method for that command. 

    def handle_command(command, args) 
    method_name = "cmd_#{command}" 
    raise BadCommand, command unless respond_to?(method_name) 
    send(method_name, args) 
    end 

    def cmd_quit(args) 
    # the code for command "quit" 
    end 

    def cmd_list(args) 
    # the code for command "list" 
    end 

    ... 

end 

Таким образом, добавление новой команды просто добавляет новый метод. Нет необходимости корректировать таблицы или заявления о случаях.

+2

Это выглядит как причуда, как причудливый три пути между посетителем, стратегией и командованием, но, как вы сказали: на выразительном языке (я не покупаю «динамическую» часть *, что * много, это, вероятно, выглядело бы столь же элегантно в Scala, F # или Haskell), это просто не такая уж большая сделка. Помните: шаблон - это не что иное, как программа, которую вы хотите написать, но ваш язык не позволяет вам. Ну, Руби * * позволяет тебе. –

+0

@Jorg, хорошо сказано. Я копаю это определение шаблона. Это твое? –

+3

Я так не думаю. Эта точная * формулировка * может быть моей, но идея общая. Фактически, если вы открываете свою копию GoF на стр. 4 и читаете последний параграф раздела 1.1, это фактически указано там. Классический напыщен на этом http://blog.plover.com/prog/design-patterns.html с этим ответом http://www.cincomsmalltalk.com/userblogs/ralph/blogView?entry=3335803396, а затем этот http: //blog.plover.com/prog/johnson.html. И, конечно же, знаменитая презентация Норвига: http://norvig.com/design-patterns/ –

0

Ok. Значит, вам нужна семантика? (поворот - действие, светлый объект, аргумент ... (я отношусь к вашему комментарию к dbemerlin)).

Почему бы не определить грамматику? humm ... Я думаю, что lex и yacc - это не вариант? (так как это вовсе не ООП, а то, что вы хотите сделать, это «скомпилировать» пользовательский ввод для получения чего-либо - выполнить код, который изменит данные в комнате и вывести результат)

У вас может быть ООП дизайн для вашего объекта и его действия (например, все объекты имеют метод .describeMe() ..), а кроме того - входной парсер + компилятор.

Я полностью исключаю эту тему?

Редактировать: после просмотра шаблона интерпретатора, указанного Марком Симаном, кажется, что это путь, который вы хотите в ООП. (но вы несколько заново изобрете колесо)

+0

Я посмотрел на lex и yacc. Но у них болит голова, и это должно быть забавным проектом.Плюс, если я правильно понимаю, они привязывают меня к гораздо более строгой грамматике, чем на самом деле на английском языке. Я полагаю, что моя золотая цель заключается в том, чтобы пользователь мог набирать «на стол, чтобы положить палочку», пониматься ... или, по крайней мере, попытаться поместить таблицу на палочку;) – Shadowfirebird

2

Похоже, вам нужен парсер.

Разделить входную строку на токены (слова). Затем подавайте токены, по одному за раз, на конечный автомат. Я нахожу, что push-down automata - довольно интуитивный и мощный способ написать такую ​​stm.

+0

Любые предложения относительно того, как Я начинаю изучать концепцию государственных машин? Конечно, запись в Википедии - это данность. – Shadowfirebird

+1

Я беру комментарий к википедии. Страница на pushdown automata выглядит увлекательно, но она написана по высокой математике. – Shadowfirebird

+1

@Shadow: http://stackoverflow.com/questions/1669/learning-to-write-a-compiler - это каноническая страница для ресурсов компилятора на SO. Но вам нужно специализироваться и не может быть хорошо обработан. Этот ответ технически корректен, но не очень полезен, потому что обработка естественного языка, как известно, сложна и имеет свою собственную культуру и язык. – dmckee

Смежные вопросы