Convert pseudocode to usable (using regex?)

As part of the system I am writing, users can create their own rules that will be executed when certain events occur.

There are many objects they can use to create these rules, all of which have a specific number of properties and methods:

list of objects

So, as an example of a rule, you can say:

"if this unit's award is Distinction, then set all the criteria for that unit's award to Achieved

IF UNIT.award equals "Distinction"
THEN UNIT.criteria.set_award(β€˜A’)

      

"else, if this unit's award is" Merit ", then set the award of any criteria on this device, whose name starts with" P "or" M "before" Achieved "

IF UNIT.award equals "Merit"
THEN UNIT.criteria.filter(β€˜starts’, β€˜name’, β€˜P’, β€˜M’).set_award(β€˜A’)

      

"else, if this piece reward is" Pass "then set the reward of any criterion on this device whose name starts from" P "to" Achieved "

IF UNIT.award equals "Merit"
THEN UNIT.criteria.filter(β€˜starts’, β€˜name’, β€˜P’).set_award(β€˜A’)

      

The problem I am facing is that I am just not sure how to take this string of object, properties and methods for example. "UNIT.criteria.filter (" starts "," name "," P ") .set_award (" A ") and converts it to something useful.

The end result identifier that would like to convert the string would be something like this:

example result

So I can convert this to actual correct objects and return the appropriate values ​​or run the appropriate methods.

Since there are only a certain number of things I need to support (for now at least) and I don't need anything complicated like computation support or variables, it seems too hard to create a Lexer system, so I thought to just use a regex to separating all sections.

So, using the examples above, I could make a simple split into "." character, but if that character is used in a method parameter, eg. "CRITERION.filter ('is,' name, 'P.1)" and then completely spins it.

I could use a less general character to separate them, like double colons or something "::", but if, for whatever reason, someone puts this in a parameter, it will still cause the same problem. I've tried to create a regex that breaks on a character only if it's not between quotes, but I couldn't get it to work.

So basically my question is, would a regex be the best way to do this? (If so, can anyone help me to make it ignore the specified character if it's in the method). Or is there another way I could do this, would it be easier / better?

Thank.

+3


source to share


1 answer


I would have thought that an ORM language like eloquent could do this for you.

But if I had to do this, then I would split the IF THEN ELSE parts first. Output:

  • UNIT.award is "Distinction"
  • UNIT.criteria.filter ("starts", "name", "P", "M") .set_award ("A)

I am guessing that "equal" can also be "not equal" or "greater", so ... I would split the first bit around that.

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

      

But explosion in equals will do the same.

Then I will blow up the second part around the points. Providing:

  • BLOCK
  • criteria
  • filter (a, b, c, d)
  • set_ward (e)

Dump the first 2 to get an object and property, then a list of possible filters and actions.



But honestly, I would develop a language that doesn't mix properties with actions and filters.

Something like:

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

      

Eloquent does it right in php:

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

      

So maybe I would do something like:

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

      

This makes it easier to separate actions around β†’ and properties around.

Anyway ... I am using my Regex at https://regex101.com/ Hope this helps.

+1


source







All Articles