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

Re: Mapping lists during AST transformation



On Sat 2006-10-28 at 17:29h, Etienne Gagnon wrote on sablecc-user:
:
> If this doesn't work, it is probably because the "context" can only be
> determined by the "right" context (i.e. by tokens that follow id_list).

That's exactly the case, read below.

:
> Note 1: Your grammar seems strange to me.  Why would an expression
> be made of many expressions?  (Why is "expr = ...| id_list|... " in
> the first place?)

It's a typed functional language with (in particular) arithmetic
expressions, variables, tuples and lambda expressions.
For the lambda expressions I'd like to have the syntax

   <lambda expression> := <parameter list> "->" <expression>
   
like in

   x -> x + 2

or

   (a, b, c) -> a + b * c

where x and a, b, c are the respective formal parameters.
The parentheses around the parameters in the second example are just
for grouping, since "->" has higher precedence that ",".

(To illustrate further: The latter lambda expression would have the
type Number × Number × Number -> Number, and for example evaluating

   ((a, b, c) -> a + b * c)(1, 2, 3)

would yield 1 + 2 * 3 = 7.)

Now something like "a, b, c" can either be a tuple expression
(referencing the variables a, b and c) or the parameter list of a
lambda expression, depending on whether it is followed by "->" or not.
The problem is that by the time the parser sees what follows the list
it must have already reduced the list to some production.

My current approach is to let the grammar distinguish between tuple
expressions that match the syntax of parameter lists (this is
"id_list") and other tuple expressions. For example "a, b, 3" is a
tuple expression that doesn't match the syntax of parameter lists.

(If I don't make that distinction then of course I get conflicts
because the parser doesn't know whether "a, b, c" should be reduced to
a tuple expression (a list of variable-reference expressions) or to a
parameter list.)

So when an id_list is followed by an arrow ("->"), it becomes the
parameter list of a lambda expression, which is really just a list of
ids, and otherwise it becomes a tuple expression, which is a list of
expressions. In the latter case I'd like to convert the id* to an
expr* during the AST transformation instead of having to do that in
Java code.

As you say, I could change the language by requiring some prefix for
lambda expressions, e.g. a "lambda" keyword:

   lambda x -> x + 2
   lambda (a, b, c) -> a + b * c

But I'd rather keep the current syntax because it is nice, simple and
clean (from the user's point-of-view), and I'd also like to keep the
language keyword-free (and free from additional special punctuation).

> Note 2: I am sure that you realize that it is quite difficult to
> debug a grammar from just little fragments of it...

Well, having my grammar debugged wasn't exactly my concern :). I tried
to concentrate on discussing the particular feature I would like to
have (transforming lists), since my grammar is a little complex (over
200 lines) and reducing it to a minimal working example would require
some work.

I always wondered why the square brackets are needed in something like

   {-> New x.y([list.element])}

instead of just writing

   {-> New x.y(list.element)}

since SableCC knows that "list" is a list. The square brackets would
make sense if you something written inside the brackets would be
applied to every element of the list, and something outside would
be applide to the whole list. E.g. in

   {-> New x.y([New x.z(list.element)])}

an x.z would be constructed for each element and an x.y for the whole
list.

By the way: The "New" is also redundant, isn't it? I would find it
more natural (and less Java-esque) to just write {-> x.y(a.b)}.

-- Niklas Matthies