[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

On the subject of s-expr notation




ryan daum writes:
>
> Does anybody know of any successful experiments in attempting to
> run-time translate a subset of C-like (Algol-like, I guess) syntax
> down to a Lisp/Scheme notation?  It doesn't seem like it would be
> hard, but a google search isn't yielding much.
 
Sure, I've done it, and it's not terribly hard to do. What you want to
do is to parse your source language into a parse tree, and then walk
the parse tree and emit the desired s-exps. For example, in my little
language you can write some code like:

  {
    fun fact(n) {
      if (n = 0) {
  	1
      } else {
  	n * fact(pred(n))
      }
    }
    fact(5)
  }

which yields the following parse tree:

Rec
 ([|("fact", [|"n"|],
     If (Apply (Var "=", [|Var "n"; Lit 0|]), Lit 1,
      Apply (Var "*",
       [|Var "n"; Apply (Var "fact", [|Apply (Var "decr", [|Var "n"|])|])|])))|],
 Apply (Var "fact", [|Lit 5|]))

(Sorry about the ugliness of that expression.) When I pretty-print
this parse tree I print out an s-exp

  (letrec ((fun fact(n) (if (= n 0) e 1 (* n (fact (decr n)))))) (fact 5))

FYI: I print out s-exps because it was a little easier to write a
good-looking printer for s-exps than for my regular language. This is
just laziness on my part. :) If you're curious, here's a fragment of
what my printer looks like:

    let print e =
      let format x = Printf.printf x in
      let join = String.concat in 
      let rec loop e =
	match e with
	| Lit n -> format "%d" n
	| Var v -> format "%s" v
	| Fun(vs, body) ->
	    begin
	      format "(fun (%s) " (join " " (Array.to_list vs));
	      loop body;
	      format ")"
	    end
	| Let(v, expr, body) ->
	    begin
	      format "(let (%s " v;
	      loop expr;
	      format ")";
	      loop body;
	      format ")"
	    end
        [...]	      

> Background is that I'm thinking of selling a client on a product
> that uses an embedded Scheme interpreter, but the client is somewhat
> uncomfortable with having to maintain Scheme code in places.  I'm
> thinking wrapping the scheme syntax with a domain-specific-language
> which would merely be a mapping of the same Scheme code to a simple
> dynamically-typed C-like language, to make things easier to read for
> those unaccustomed to lisp-like notation.
> 
> Does this seem at all reasonable?

Sure, this is reasonable. I'd also advise making sure that the
syntactic constructs of your source language closely resemble
Scheme's, because that will simplify your translation -- ideally you
want each of your language constructs to map directly to a Scheme
construct.

-- 
Neel Krishnaswami
neelk@alum.mit.edu