I have an idea. I want to give our client the ability to specify pricing based on a number of variables by writing some simple code like this:
if customer.zip is "37208"
return 39.99
else
return 59.99
And in my code, I'd do something like this:
try {
$variables = array('customer' => array('zip' => '63901'));
$code = DSL::parse(DSL::tokenize($userCode))
$returnValue = DSL::run($code, $variables);
} catch (SyntaxErrorException $e) {
...
}
I guess what I'm wanting is to create a simple DSL in PHP that allows our customer to have a great deal of flexibility in setting pricing without having to have us code each and every case.
Here's the basic idea:
So do you know of any resources or frameworks for building a simple DSL in PHP? Any ideas where to begin?
Thanks!
The standard approach to building a DSL parser is to employ a parser generator aka a compiler-compiler to do the heavy lifting. This allows the developer to express the DSL in an abstract BNF-ish syntax, and not have to get into the nitty gritty of parsing and lexing.
Examples include Yacc in C, Regexp::Grammars in Perl, and ANTLR, which targets Java and several other languages, etc. The PHP option appears to be PHP-PEG.
Technical limitations aside, you might want to really think twice about giving this kind of programming power to (I presume) non-programmers. They will probably mess up in completely unpredictable ways and you'll be the one having to clean up the mess. At least guard it with lots of tests. And possibly legalese as well.
But you asked a question, so I'll try to answer that. There is a distinction to be made between internal style DSL's (What most people mean when they use the word DSL) and then external style DSL's (Which is more like a mini language). Ruby is famous for having a syntax that lends it self well to internal style DSL. PHP on the other hand, is quite bad in that regard.
That said, you can still do some stuff in PHP - The simplest is perhaps to just write up a library of functions and then have your customers write code in plain PHP, using that library. You would have to audit the code of course, but it would give all the benefits of using an existing runtime.
If that's not fancy enough, you will have to dig in to the heavy stuff. First you need a parser. If you know how, they can be hand written fairly easily, but unless you were forced to write one in school or you have a strange hobby of writing that kind of stuff just for fun (I do), it's probably going to take you a bit of work. The basic components of a parser is a tokenizer and some kind of automata (state machine) that arranges the tokens into a tree-structure (an AST).
Once you have your parsed structure, you need to evaluate it. Since this is a DSL, the number of features are limited and performance is probably not your biggest concern, you could write some object oriented code around the AST and leave it at that. Otherwise you have options like writing some sort of interpreter or cross-compile it into another format (PHP would be an obvious choice).
The tricky part all way through this is mostly in handling edge cases, such as syntax errors and report something meaningful back to the user. Again, just giving then access to a subset of PHP, will give you that for free, so consider that first.
If anyone else is looking for another option - consider using Twig for creating the DSL/parsing (http://twig.sensiolabs.org/) which is integrated to the Pico CMS (http://pico.dev7studios.com/#).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With