I have to create a DSL for non-programmers (customers of our company) that needs to provide some higher-level language features (loops, conditional expressions, variables ... - so it's not just a "simple" DSL).
Working with the DSL should be easy; people should be able to experiment with it and learn it by playing around. We want to achieve something similar to Macros in Microsoft Excel - many Excel users can create simple formulas, sums or calculations and have never worked with a "real" (general purpose) programming language.
Obviously not every Excel-user understands the more complicated built-in methods (like When()), but they can use simple methods like SUM() or AVG(). I want to achieve a similar effect with the DSL - uesrs should be able to intuitively work with it and define simple rules or perform simple calculations. At the same time the DSL should offer higher-level features for the more technically inclined - like loops, if-statements, possibly methods or lambdas.
And this leads me to my question(s): What language constructs are intuitive, easy to learn and understand?
In the current, experimental version of the DSL we tried a method-chaining approach, example: list.where(item -> item.value > 5).select(item -> item.name + " " + item.value)
).
Think of where
and select
as foreach
constructs where item
is a variable that represents the current item within the loop.
The reason we tried this approach first is that it would be easy to support code completion - whenever a user enters a period (.
), show a list of possible methods. However I'm not sure this concept meets my criteria of being intuitive and easy to understand and read.
Is it easier / more readable for users if there are no braces? (like in LINQ: from item in list where item.value > 5 select item.name + " " + item.value
). However in this case, there are no "boundaries" - in the prior example the user knows that the statement ends with the last closing brace - in this case, if he types more code after the select
part of the statement, he doesn'- know if it belongs to the statement or not (apart from the fact that the parser wouldn't know either and there had to be some sort of closure).
I hope my question is a bit clearer with these 2 examples - I'm looking for design guidelines, best practices, real-life experiences, probably research material of which language constructs are favorable to others - or some evaluation of pros and cons of certain language constructs.
I am not looking for information on how to create a DSL, on what parser generators I could use etc. and I also can't use an existing general-purpose language (Ruby, Python, ...) instead because of the way the DSL is used. (The DSL, when parsed, works directly with our object model - I won't go into details here since this question is already long enough as it is).
Edit: Perhaps I should point out that by "language constructs" I mean the syntax, the way something is written, not what kind of functionality the language should offer - we already have a list of featuers the DSL has to provide. The question is how these features are best expressed to allow the creation (and maintenance) of simple and complex formulas.