[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: AST Transformations
Hi Roger,
Sorry about being silent so long time.
Productions can be transformed to more than one elements.
I think it will be more easy to explain this with an example, so i've
joind a file called tar.grammar in which some precisions are given.
> Hi Etienne, All,
>
> The new AST transformations are a great feature, and I'm just wondering
> who wrote it I can direct a few questions their way. SableCC is sorely
> in need of good documentation and I am happy to do this providing I
> don't have to reverse engineer everything that is released! It is also
> very difficult to understand the source code due to the lack of (i.e.
> non-existance of) comments.
>
> My main question is "Do you have to have a 'New' statement for each
> transform, or are there other shortcuts?".
No, there are other shortcuts. We have four differents alternative
transformations types (new, simple, list, null).
I've joined a SableCC3 example grammar based on arithmetic expressions, in
which all transformations types are specified(expression.grammar).
The new statement must appear at least once in alternative
transformations since the AST is composed by node(s) defined in Abstract
Syntax Tree section.
The only way to create new node in SableCC3 is to write 'New' followed by
a production name and optionnally '.alternative_name' if there is an
alternative name.
I hope that this could help you.
I you have any other question, i will be happy to help you.
Cheers,
Kevin
>I ask this because I see the
> mention of lists in the source, and also notice that the grammar allows
> more than one transformation to be defined per alternative:
>
> alt_transform =
> arrow [terms]: term*;
>
> Thanks,
>
> Roger
>
> On Wed, May 07, 2003 at 01:41:04PM -0400, Etienne Gagnon wrote:
> > Indrek Mandre wrote:
> > >What is the timeline of SableCC 3 anyway? When does it become available?
> >
> > The CST->AST stuff is ready. I should be making it public next week, if
> > everything goes well.
> >
> > You can think of most of the other wish-list items as SableCC X (where X >
> > 3)
> > wishes.
> >
> > :-)
> >
> > Etienne
> >
> >
> > --
> > Etienne M. Gagnon, Ph.D. http://www.info.uqam.ca/~egagnon/
> > SableVM: http://www.sablevm.org/
> > SableCC: http://www.sablecc.org/
> >
>
>
>
>
Package tar;
Helpers
tab = 9;
cr = 13;
lf = 10;
eol = [[cr + lf] + [cr + lf]];
white = [[' ' + tab] + eol];
lowercase = ['a' .. 'z'];
uppercase = ['A' .. 'Z'];
letter = uppercase;
digit = ['0'..'9'];
id_part = lowercase (lowercase | digit)*;
blank = (' ' | tab | eol)+;
Tokens
tar = 'tar';
id = id_part ('_' id_part)*;
minus = '-';
semicolon = ';';
l_bkt = '[';
r_bkt = ']';
letter = letter;
blank = blank;
Ignored Tokens
/* These tokens are simply ignored by the parser. */
blank;
/*****************/
Productions
/***********************************************************************
The first production of this section must be transformed to the first
production of Abstract Syntax Tree section
but it is not necessary to explicitely specify it if it has the same
name.
So, in this case, we should write :
grammar -> grammar
but the software automatically do it when nothing is specified.
So we have less things to do :-)
***********************************************************************/
/*#####*/
grammar = P.tar -> New grammar((P.tar.letter), (P.tar.id));
/*#####*/
/***********************************************************************
Here the production #tar# is supposed to be transformed to a list of #letter#
followed by a list of #id#.
Since the unique alternative of #options# is composed by
token #tar#, production #options# and production #files#,
we can get a list of letter by productions #options# transformations
and a list of id by production #files# one's.
As it can be notice here, there is no new statement in this transformation.
So the 'New' statement is not needed in all cases.
***********************************************************************/
/*#####*/
tar -> letter* id* = T.tar options files -> (options.letter) (files.id);
/*#####*/
/***********************************************************************
#options# is transformed to a list of letter.
So the alternative transformation #(letter)# means that we created a new list
in which we add all elements of #elem+#
So there is no more #options# node in the AST. They are all transformed to lists
of #letter#.
***********************************************************************/
/*#####*/
options -> letter* = minus letter+ -> (letter);
/*#####*/
/***********************************************************************
This transformation is similar production #tar# transformation
***********************************************************************/
/*#####*/
files -> id* = file_name+ semicolon? -> (file_name.id) ;
/*#####*/
/***********************************************************************
In this case, #file_name# is transformed to #id#. So we only get the already
existing #id# from the unique alternative.
***********************************************************************/
file_name -> id = l_bkt id r_bkt -> id;
/*****************/
Abstract Syntax Tree
grammar = letter* id*;
Package expressionlist;
Helpers
digit = ['0' .. '9'];
tab = 9;
cr = 13;
lf = 10;
eol = cr lf | cr | lf; // This takes care of different platforms
tous = [0 .. 0xffff];
blank = (' ' | tab | eol)+;
Tokens
l_par = '(';
r_par = ')';
plus = '+';
minus = '-';
mult = '*';
div = '/';
dot = '.';
comma = ',';
blank = blank;
number = digit+;
toto = 'toto';
titi = 'titi';
tata = 'tata';
Ignored Tokens
blank;
Productions
grammar -> grammar = exp_list -> New grammar((exp_list.exp));
exp_list -> exp* = exp exp_list_tail -> (exp exp_list_tail.exp);
exp_list_tail -> exp = comma exp -> exp;
exp = {plus} exp plus factor -> New exp.plus(exp, factor.exp) |
{minus} exp minus factor -> New exp.minus(exp, factor.exp) |
{factor} factor -> factor.exp;
factor -> exp = {mult} factor mult term -> New exp.mult(factor.exp, term.exp ) |
{div} factor div term -> New exp.div(factor.exp, term.exp ) |
{term} term -> term.exp;
term -> exp = {number} number dummy -> New exp.number(number) |
{exp} l_par exp r_par -> exp;
dummy -> = dummychild tata* -> ;
dummychild -> toto = toto titi -> Null;
Abstract Syntax Tree
grammar = exp+;
exp = {plus} [l]:exp [r]:exp |
{minus} [l]:exp [r]:exp |
{div} [l]:exp [r]:exp |
{mult} [l]:exp [r]:exp |
{number} number ;