

I want to spend a few minutes talking to you about the syntax of the languages we are writing interpreters for. These languages will all use a variant of the syntax of the languages Lisp and Scheme. These languages have adopted a very simple syntax, called s-expression syntax. The advantage of this syntax is that there is almost nothing to it: there are no special symbols used for marking blocks and the like -- everything is done with parentheses; there are no infix operators -- everything is written in prefix notation.
So, for example, the factorial function is written:
(defun (fact n)
(if (= n 0)
1
(* n (fact (- n 1)))))

Thus, (= n 0) is actually an abbreviation for
(= . (n . (0 . ()))).
Unlike in ML it is possible for the right-hand argument not to be a list.
Either side of the dot can be an arbitrary sexpression.
This is essentially the same as the situation with the bracket-and-bar
notation for lists in rex. Any time a | occurs before a
pair of square brackets, [], rex deletes all three, and puts
a comma in place of the bar.

datatype sexp =
Atom of atom
| $ of (sexp * sexp)
and atom =
Nil
| Symbol of string
| Number of number
and number =
Int of int
| Real of real
I refer to this datatype as an intermediate syntax, since it is
neither concrete, nor abstract, though it is closer to the former. In
fact it is the abstract syntax of s-expressions, but not of the
language we are building.
To parse an input string, you call the function
SexpParser.parse_string_for_sexp that is loaded as part
of the new binary sml-sexp. For example:
- SexpParser.parse_string_for_sexp "(* 3 4)"; val it = Atom (Name "*") $ Atom (Number (Int 3)) $ Atom (Number (Int 4)) $ Atom Nil : ConcTerms.sexpWhile we could send this value directly to the interpreter, we have already discussed the advantage of a more abstract syntax. What is this expression really? It is an operator, "*", applied to two operands, "3" and "4". It is your job, as the first step of each phase of the project, to write a function that translates programs in the intermediate syntax to abstract syntax. For the full language, as constructed in phase 3 of the project, the abstract syntax of "calculator expressions" is given by the types:
datatype vname = Vname of string;
datatype operator = Operator of string
datatype cexpression =
Cdata of number
| Cvar of vname
| Cappl of operator * cexpression list
So, for example:
- SexpParser.parse_string_for_sexp "(* 3 4)";
val it =
Atom (Symbol "*") $ Atom (Number (Int 3)) $ Atom (Number (Int 4)) $ Atom Nil
: SexpParser.sexp
- SyntaxConverter.convert_expression it;
val it = Cappl (Operator "*",[Cdata (Int 3),Cdata (Int 4)])
: AbstractSyntax.cexpression
- SexpParser.parse_string_for_sexp "(+ (* 3 4) 2)";
val it =
Atom (Symbol "+") $
(Atom (Symbol "*") $
Atom (Number (Int 3)) $ Atom (Number (Int 4)) $ Atom Nil) $
Atom (Number (Int 2)) $ Atom Nil : SexpParser.sexp
- SyntaxConverter.convert_expression it;
val it =
Cappl
(Operator "+",
[Cappl (Operator "*",[Cdata (Int 3),Cdata (Int 4)]),
Cdata (Int 2)])
: AbstractSyntax.cexpression
Similarly, there is an abstract syntax data type for the commands of the language:
datatype ccommand =
Cexpression of cexpression
| Cdefine of vname * cexpression
| Cdefun of operator * vname list * cexpression
| Cbindings
| Cexit
- SexpParser.parse_string_for_sexp "(define x (+ (* 3 4) 2))";
val it =
Atom (Symbol "define") $
Atom (Symbol "x") $
(Atom (Symbol "+") $
(Atom (Symbol "*") $
Atom (Number (Int 3)) $ Atom (Number (Int 4)) $ Atom Nil) $
Atom (Number (Int 2)) $ Atom Nil) $ Atom Nil : SexpParser.sexp
- SyntaxConverter.convert_command it;
val it =
Cdefine
(Vname "x",
Cappl
(Operator "+",
[Cappl (Operator "*",[Cdata (Int 3),Cdata (Int 4)]),
Cdata (Int 2)]))
: AbstractSyntax.ccommand
- SexpParser.parse_string_for_sexp "(defun (f x y) (+ (* 3 x) y))";
val it =
Atom (Symbol "defun") $
(Atom (Symbol "f") $ Atom (Symbol "x") $ Atom (Symbol "y") $ Atom Nil) $
(Atom (Symbol "+") $
(Atom (Symbol "*") $ Atom (Number (Int 3)) $ Atom (Symbol "x") $ Atom Nil) $
Atom (Symbol "y") $ Atom Nil) $ Atom Nil : SexpParser.sexp
- SyntaxConverter.convert_command it;
val it =
Cdefun
(Operator "f",[Vname "x",Vname "y"],
Cappl
(Operator "+",
[Cappl (Operator "*",[Cdata (Int 3),
Cvar (Vname "x")]),
Cvar (Vname "y")])) : AbstractSyntax.ccommand

|
|
This page copyright ©1999 by Joshua S. Hodas. It was built on a Macintosh. Last rebuilt on Wednesday, March 3, 1999 at 2:00 PM. |
http://cs.hmc.edu/~hodas/courses/cs131/lectures/lecture11.html | |