2015-05-11 2 views
3

Как часть системы, которую я пишу, пользователи могут создавать свои собственные правила, которые будут выполняться при определенных событиях.Преобразование псевдокода в год использования (с использованием регулярного выражения?)

Есть определенное количество объектов, которые они могут использовать, чтобы создать эти правила, все из которых имеют определенное количество свойств и методов:

list of objects

Так как пример правило, мы могли бы говорят:

«если эта единица награда„Различение“, затем установить все критерии на данном аппарате наградить„Достигнуто“»

IF UNIT.award equals “Distinction” 
THEN UNIT.criteria.set_award(‘A’) 

«еще, если эта единица награда„Merit“, затем установить награду любых критериев на данном устройстве, имя которого начинается либо с„P“или„М“до" Выполнено»

IF UNIT.award equals “Merit” 
THEN UNIT.criteria.filter(‘starts’, ‘name’, ‘P’, ‘M’).set_award(‘A’) 

«еще, если этот блок награда «Pass затем установить награду любых критериев на данном устройстве, название которого начинается с буквы„Р“до" Выполнено»

IF UNIT.award equals “Merit” 
THEN UNIT.criteria.filter(‘starts’, ‘name’, ‘P’).set_award(‘A’) 

проблема, которую я имею, это я просто не знаю, как взять эту строку объекта, свойства &, например «UNIT.criteria.filter (« начинается »,« name »,« P »). Set_award (« A ») и преобразует его во что-то полезное.

Конечный результат я хотел бы преобразовать строку будет что-то вдоль линий:

example result

Так что я могу затем преобразовать, что в реальных соответствующих объектов и вернуть соответствующие значения или выполните соответствующие методы.

Поскольку есть только определенное количество вещей, которые мне нужно поддерживать (на данный момент, по крайней мере), и мне не нужно ничего сложного, как поддержка вычислений или переменные, кажется, слишком сложно создать систему Lexer, поэтому я думал просто используя регулярное выражение для разделения всех разделов.

Так, используя приведенные выше примеры, я мог бы сделать простой раздел по символу «.», Но если этот символ используется в параметре метода, например, «CRITERION.filter ('is', 'name', 'P.1')", после чего он полностью закручивает его.

Я мог бы использовать менее общий символ, чтобы разделить их, например, двойной двоеточие или что-то «::», но если по какой-либо причине кто-то помещает это в параметр, это все равно вызовет ту же проблему. Я попытался создать регулярное выражение, которое разбивается на символ, только если это не между кавычками, но я не смог заставить его работать.

Так что в основном мой вопрос: будет ли регулярное выражение лучшим способом для этого? (Если это так, может кто-нибудь помочь мне с тем, чтобы он игнорировал указанный символ, если он в методе). Или есть ли другой способ, которым я мог бы сделать это, было бы легче/лучше?

Спасибо.

+0

Возможно, вам следует искать «язык выражения». «Symfony» занимает место в верхней части моего googling, см., Например, http://jwage.com/post/76799775984/using-the-symfony-expression-language-for-a-reward. – JimmyB

+0

Нужно ли использовать Symfony, или его можно использовать отдельно? Поскольку мы используем другую систему в стиле CMS, поэтому я не могу установить целую структуру только для этого. Приветствия. –

+0

Не могу сказать. С быстрым взглядом он кажется довольно самодостаточным: https://github.com/symfony/expression-language – JimmyB

ответ

1

Я думаю, что язык ORM, такой как красноречивый, может сделать это для вас.

Но если бы мне пришлось это сделать, сначала я бы разделил части ЕСЛИ ТОЛЬКО ЭЛЕМ.Оставляя :

  1. UNIT.award равен «различия»
  2. UNIT.criteria.filter ('начинается', 'имя', 'P', 'М') set_award ('А')
  3. .

Я предполагаю, что «равные» также могут быть «не равными» или «большими», поэтому ... Я бы разделил первый бит вокруг этого.

/(?'ident'[a-z.]*?) (?'expression'equals|greater) (?'compare'[0-9a-z\“\”]+)/gi 

Но взорваться вокруг «равных» будет сделано то же самое.

Тогда я взорву вторую часть вокруг точек. Даяние:

  1. БЛОК Критерии
  2. фильтр (а, б, в, г)
  3. set_ward (е)

Поп от первой 2, чтобы получить объект и свойство а затем список возможных фильтров и действий.

Но, честно говоря, я бы разработал язык, который не смешивал бы свойства с действиями и фильтрами.

Что-то вроде:

IF object.prop EQUALS const|var 
THEN UPDATE object.prop 
WITH const|var [WHERE object.prop filter const|var [AND|OR const|var]] 

Eloquent делает это прямо в PHP:

DB::table('users') 
      ->where('id', 1) 
      ->update(['votes' => 1]); 

Так что, может быть, я хотел бы сделать что-то вроде:

THEN object.prop->filter(a,b,c,d)->set('award','A') 

Это позволяет легко разделить действия вокруг -> и свойства вокруг.

В любом случае ... Я делаю свое регулярное выражение на https://regex101.com/ Надеюсь, это поможет.

+0

Вот что я в итоге сделал. Я избавился от свойств и поместил все в методы, например. getCriteria(), getUnits() и т. д. ... и избавился от метода filter(), и все, что передается в методы get *(), становится фильтрами. Итак, я разбиваю точку сначала, чтобы разбить ее на части, затем я рекурсивную функцию, чтобы вызвать оставшийся метод объекта или результат последнего вызова. E.g. Qual.getUnits() getCriteria() getAward() -.. Называет getUnits() на кач OBJ - вызывает getCriteria() на массив единиц возвращаемых предыдущей строке - вызывает getAward() на массив критериев и т. Д. –

+0

Звучит как классный проект. – Joeri

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