Как часть системы, которую я пишу, пользователи могут создавать свои собственные правила, которые будут запускаться при наступлении определенных событий.
Существует определенное количество объектов, которые они могут использовать для создания этих правил, каждый из которых имеет заданное количество свойств и методов:
Так что в качестве примера правила мы могли бы сказать:
«Если награда этого подразделения -« Различие », тогда установите все критерии для этого подразделения, чтобы присудить« Достигнуто »»
IF UNIT.award equals “Distinction”
THEN UNIT.criteria.set_award(‘A’)
«Иначе, если награда этого подразделения -« Достоинство », тогда установите вознаграждение по любому критерию для этого подразделения, название которого начинается с« P »или« M »-« Достигнут »».
IF UNIT.award equals “Merit”
THEN UNIT.criteria.filter(‘starts’, ‘name’, ‘P’, ‘M’).set_award(‘A’)
«Иначе, если эта награда за единицу равна‘ Pass, тогда назначьте оценку за любые критерии для этой единицы, чье имя начинается с P ’до« Достигнуто »».
IF UNIT.award equals “Merit”
THEN UNIT.criteria.filter(‘starts’, ‘name’, ‘P’).set_award(‘A’)
У меня проблема, я просто не уверен, как взять эту строку объекта, свойства & методы, например «UNIT.criteria.filter (« старт »,« имя »,« Р »). Set_award (« А »)» и преобразовать его во что-нибудь пригодное для использования.
Конечным результатом, в который я хотел бы преобразовать строку, было бы что-то вроде:
Поэтому я могу затем преобразовать это в фактические правильные объекты и вернуть соответствующие значения или запустить соответствующие методы.
Поскольку есть только определенное количество вещей, которые мне нужно поддерживать (по крайней мере, на данный момент), и мне не нужно ничего сложного, например, поддержки вычислений или переменных, создание системы Lexer кажется излишним, поэтому я подумал о том, чтобы просто использовать регулярное выражение для разделения всех разделов.
Таким образом, используя приведенные выше примеры, я мог бы сделать простое разбиение на символ «.», Но если этот символ используется в параметре метода, например «CRITERION.filter (‘ is ’,‘ name ’,‘ P.1 ’)», после чего он полностью облажается.
Я мог бы использовать менее распространенный символ, чтобы разделить их, например, двойное двоеточие или что-то вроде «::», но если по какой-то причине кто-то поместит это в параметр, это все равно вызовет ту же проблему. Я пытался создать регулярное выражение, которое разделяется на персонажа, только если оно не заключено в кавычки, но я не смог заставить его работать.
Итак, в основном мой вопрос: будет ли регулярное выражение лучшим способом сделать это? (Если так, может ли кто-нибудь помочь мне заставить его игнорировать указанный символ, если он находится в методе). Или есть другой способ сделать это легче / лучше?
Благодарю.
Я думаю, что язык ORM, такой как eloquent, может сделать это для вас.
Но если бы мне пришлось это сделать, то сначала я бы разделил, ЕСЛИ ЭТО ДРУГИЕ части.
Выход:
Я предполагаю, что «равно» может быть «не равно» или «больше», так что …
Я бы разбил первый бит вокруг этого.
/(?'ident'[a-z.]*?) (?'expression'equals|greater) (?'compare'[0-9a-z\“\”]+)/gi
Но взрыв вокруг «равных» сделает то же самое.
Тогда я бы взорвал вторую часть вокруг точек.
Предоставление:
Выдвиньте первые 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/
Надеюсь это поможет.
Других решений пока нет …