javascript - Safely parsing and evaluating user input -
i'm working on project that's templating domain-specific language. in project, take lines of user input in next form:
'{{index(1, 5)}}' '{{firstname()}} x. {{lastname()}}' '{{floating(-0.5, 0.5)}}' '{{text(5, "words")}}'
any command between double curly braces ({{ }}
) has corresponding javascript method should called when command encountered. (for example, function index(min, max) {...}
in case of first one).
i'm having hard time figuring out how safely take input , phone call appropriate function. know way i'm doing isn't safe. eval()
between 2 sets of curly braces.
how can parse these input strings such can flexibly match function phone call between curly braces , execute function parameters given, while still not blindly calling eval()
code?
i've considered making mapping (if command index()
, phone call function index() {}
), doesn't seem flexible; how collect , pass parameters (e.g. {{index(2, 5)}}
) if present?
this written in node.js.
this problem breaks downwards into:
parsing string
evaluating resulting function graph
dispatching each function (as part of #2 above)
parsing stringunfortunately, requirements have, parsing {{...}}
string quite complex. have @ to the lowest degree these issues deal with:
functions can nested {{function1(function2(), 2, 3)}}
.
strings can contain (escaped) quotes, , can contain commas, without requirement #1 above trivial approach finding discrete arguments (splitting on comma) won't work.
so...you need proper parser. seek cobble 1 advertisement hoc, parser generators come picture, peg.js or jison (those examples, not recommendations — did happen notice 1 of jison examples json parser, half battle). writing parser out of scope answering question on i'm afraid. :-)
evaluating resulting function graphdepending on tool use, parser generator may handle you. (i'm pretty sure peg.js , jison both would, instance.)
if not, after parsing you'll presumably end object graph of sort, gives functions , arguments (which might functions arguments...which might be...).
functiona 1 "two" functionb "a" functionc 42 functiond 27functiona there has 5 arguments, 3rd of functionb 2 arguments, , on.
your next task, then, evaluate functions deepest first (and @ same depth, left-to-right) , replace them in relevant arguments list result, you'll need depth-first traversal algorithm. deepest first , left-to-right (top-to-bottom in bullet list above) mean in list above, have phone call functionc first, functionb, functiond, , functiona.
dispatching each functiondepending 1 time again on tool use, may handle bit too. 1 time again suspect peg.js does, , wouldn't surprised if jison did well.
at point you're ready phone call function (no longer) has function calls arguments, you'll presumably have function name , array of arguments. assuming store functions in map:
var functions = { index: function() { /* ... */ }, firstname: function() { /* ... */ }, // ... };
...calling them easy bit:
functionresult = functions[functionname].apply(undefined, functionarguments);
i'm sorry not able "just x, , you're there," isn't trivial problem. throw tools @ it, wouldn't invent wheel myself.
javascript node.js parsing eval
No comments:
Post a Comment