About Me

I am a computer programmer. I do programming professionally and for a laugh.

Technical stuff on programming, java, DSLs, etc...

Tuesday 30 March 2010

Another DSL Framework - tutorial 3

I went as far as defining a bit of the lisp language, up to the point where you can define a function and call it. Designing a language is not an easy task and it was never my intension to write a tool to replace the Java parser.

Where I see the DSLs to be most useful is to replace user interfaces that naturally fall into a language like area but utilized by end-users rather than programmers. For example, a scenario engine would be a very natural fit for a DSL where you have light weight nature of text to define scenarios and the power of a structured language. I will write more about how DSLs can very naturally replace some of the most cumbersome UIs.

Below is a snippet from the Lisp language. If you check out the project, all of this is in the class

com.leantell.lp.lisp.LispArithmeticLanguage.

Have fun, let me know if you do anything interesting with Language Processor.

Function defintion in Lisp;

addProduction("DEFUNC -> ( defun identifier ( IDENTIFIERS ) STM )", new Semantic() {
            @Override
            public java.util.List<Object> evaluateChildren(java.util.List<ParseNode> children) {
                  String name = ((String) children.get(2).evaluate()).toUpperCase();
                  List<String>parameters = (List<String>) children.get(4).evaluate();

                  ParseNode code = children.get(6);
                  Function function = new Function(name, parameters, code);

                  context.put(name, function);

                  List<Object> result = new ArrayList<Object>();
                  result.add(name);
                  return result;
            };

            @Override
            public Object evaluate(List<Object> childEvals) {
                  return childEvals.get(0);
            }
      });

Function call in Lisp;

addProduction("FUNCTION_CALL -> (identifier ATOMS )", new Semantic() {
      @Override
      public Object evaluate(List<Object> childEvals) {
            String name = ((String) childEvals.get(1)).toUpperCase();
            List<Object>values = (List<Object>) childEvals.get(2);

            Function function = (Function) context.get(name);
            List<String> parameters = function.getParameters();
            for (int i = 0; i < parameters.size(); i++) {
                  targetLanguage.setVariableValue(parameters.get(i),  values.get(i));
            }
            return function.getCode().evaluate();
      }
});

How to define and call a function;

            assertEquals("FACT", lisp.evaluate("(defun fact (x) (if (eq x 0) 1 (*  x (fact (- x 1)))))"));
            assertEquals(new BigInteger("1"), lisp.evaluate("(fact 0)"));
            assertEquals(new BigInteger("6"), lisp.evaluate("(fact 3)"));
            assertEquals(new BigInteger("24"), lisp.evaluate("(fact 4)"));

No comments:

Post a Comment

Followers