Я действительно не в восторге от использования синтаксиса компилятора для реализации DSL - извините, я знаю, что некоторым это нравится, и я с готовностью признаю, что это симпатичный трюк, но так легко написать свой собственный парсер, почему бы не сделать Это? Тогда у вас не будет случайных запятых и подчеркиваний, разбросанных по всему тексту.
Вот простой трюк, который я использовал для реализации простого синтаксиса, подобного описанному вами:
Прежде всего, посмотрите на ваши команды - обратите внимание, что большинство из них в формате "param имя существительного params"
Это очень хорошо отображается на methodName, objectName, params
Так что хорошей процедурой будет:
split sentence into string array s
for a line with a single word (if s.length == 1):
instantiate an object with that name
call a default method on that object
done
for a line with more than one word
instantiate the object s[1]
call method s[0] with s[2...] as parameters
done
Этот простой 5-10 или около того анализатор строк решит многие проблемы с типами DSL. Кроме того, вы можете легко добавлять функции:
Если параметры (2 ...) имеют форму «имя = значение», найдите параметр с именем «имя» и передайте «значение» для этого конкретного параметра. Это, вероятно, не будет работать в данном конкретном случае, но может быть полезно для других целей.
Если вашим однословным командам требуются параметры, попробуйте создать экземпляр s [0] как класс, даже если в нем есть несколько слов. Если это не удалось, вернитесь к алгоритму из нескольких слов выше.
У меня был один случай, когда мне нужно было хранить объекты после того, как они были созданы. Я использовал синтаксис:
find person:ana
(синтаксис может быть возвращен к исходному синтаксису путем сохранения таблицы сопоставления ана с человеком и проверки этой таблицы вместе с попыткой создания объектов)
и с тех пор ana была экземпляром класса person (другими словами, после создания экземпляра person и вызова для него метода find) я сохранил объект person в хэше под именем ana в следующий раз они использовали команду вроде:
talk ana
Сначала он будет искать в хеш-памяти, захватывать сохраненный там объект и вызывать «talk» для этого существующего объекта (в этот момент он может проверить, не установлен ли ana флаг «found», если нет, он может вернуть другое сообщение). Таким образом, у вас может быть несколько друзей, каждый со своей информацией о состоянии.
Эта система имеет некоторые ограничения, но все же она гораздо более гибкая, чем DSL в стиле Ruby, и ее совсем не сложно реализовать.