1

I'm building a node app in which users are (ideally) able to define styling - for geographic data - using a series of JSON objects:

{
    "style":
        {
            "test": "year",
            "condition": "<= 1954 AND >= 1936",
            "color": "red"
        }
}

In the case above, I like to evaluate that style as

if (year <= 1954 && year >= 1936){
    object.color = red;
}

Is there an easy way to parse + evaluate such expressions/build them from such an object? I'm especially interested in letting people string together complex expressions built using <=, >=, ||, && etc.

I'd like to avoid using eval(), if possible.

2
  • 1
    You might want to check out my project language called Bianca: github.com/aaditmshah/bianca. It parses a program and spits out a JSON AST, which is kind of the exact opposite of what your program does. Nevertheless it may give you some valuable insights. Commented Jul 4, 2013 at 4:27
  • I definitely will check it out! Thanks! Commented Jul 4, 2013 at 4:42

2 Answers 2

6

If you don't wish to use eval, you would have to write your own little parser and create a definition language like this:

"condition": ["and", ["<=", 1954], [">=", 1936]],

This is a partial implementation you could consider:

function do_and(args, value)
{
  for (var i = 0; i < args.length; ++i) {
    if (!evaluate(args[i], value)) {
      return false;
    }
  }
  return true;
}

function evaluate(condition, value)
{
  switch (condition[0]) {
    case "and":
      return do_and(condition.slice(1), value);

    case "<=":
      return value <= condition[1];

    case ">=":
      return value >= condition[1];
  }
}

This is how you would use it:

var style = {
    "test": "year",
    "condition": ["and", ["<=", 1954], [">=", 1936]],
    "color": "red"
}, context = {
  "year": 1940
};    

if (evaluate(style.condition, context[style.test])) {
  console.log(style.color); // "red"
}

Demo

Sign up to request clarification or add additional context in comments.

2 Comments

It's not clear from your answer whether you expect the user to provide this or the parser to parse into this format - the former is easier, of course :).
@nrabinowitz writing the parser didn't take that long, so I've included a partial implementation :)
1

Something like

var obj = JSON.parse(str);
switch (obj.style.operator){
    case '=':
    if (window[obj.style.condition] === obj.style){//assuming that the conditions are global
        object.color = obj.style;
    }
    break;
    ...
}

2 Comments

Cool, I've implemented something similar but do you have any ideas as to how I can do more complex expressions? E.g. say a user wants to test if a certain value is >= 1954 OR <= 1936. I really don't want to write a case for every possible permutation.
@sir_kitty Then why didn't post about the complex expression instead of the one you can already do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.