[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Multi-file Compilation
Hi,
I need to compile multiple files simultaneously and build a single AST
representing the complete program spanning multiple source files.
The program is represented by a set of classes, each source file containing
one or more classes.
The solution I am thinking about is to have a production "program" that
serves no purpose at parse time, with a hidden alternative (classfile+), and
then perform a post-parse transformation, using that alternative to collect
all the tree roots into a list of 'classfile' nodes, with the "program"
production being the new AST root.
I have doubts however that this is really a good solution. Has anybody had
to do this before in SableCC, or does anybody see a better solution? Are
there any issues I should be aware of (e.g. EOF?) ?
P.S.: I have seen mentioned writing your own PushBackReader as a solution
for #includes. It didn't seem really relevant to my situation... or is it?
Thanks.
Othman
----- Original Message -----
From: "Etienne M. Gagnon" <egagnon@j-meg.com>
To: "sablecc-list" <sablecc-list@sable.mcgill.ca>
Sent: Saturday, March 04, 2000 10:11 PM
Subject: NEWS: Much improved conflict messages in SableCC 2.13
> Hi everyone.
>
> Another release. It was quick, but it is, I think, an interesting
release.
>
> I received a patch from Ben Menking <bmenking@bigfoot.com>. This patch
> contained some code to:
> - Indicate the current position in a production using a * symbol instead
of
> using a position number
> - Filtering out the state's irrelevant productions and displaying only
those
> that are directly involved in the conflict.
>
> This code needed improvement (see the ChangeLog). [I know, I'm picky].
> Anyway, while improving this code, I said to myself, why not also
implement a
> related feature that was initially meant for SableCC 3.0.
>
> The result is that, now SableCC 2.13 reports conflict in a much clearer
way.
> (1) It gets rid of irrelevant state items.
> (2) It clearly indicates the action beside each item (reduce/shift)
> (3) It indicates the parsing position using a "*" instead of an integer
>
> Finally, and not least:
>
> (4) It prints the shortest stack configuration that would expose the
conflict!
>
> The addition of (4) helps figuring out what is normally pretty difficult
to
> see: The question we normally ask, when SableCC reports a conflict, is
"what
> kind of program would cause this conflict"? (4) answers this question.
Thus,
> it gives us an intuitive context to see the conflict. :-)
>
> Here is a small example of ambiguous grammar, and the SableCC output (old
and
> new):
> ====================================
> // an obviously ambiguous grammar
> Tokens
> plus = '+';
> minus = '-';
> num = ['0'..'9']+;
>
> Productions
> exp = {plus} [lexp]:exp plus [rexp]:exp |
> {minus} [lexp]:exp minus [rexp]:exp |
> {num} num;
> ====================================
> ---OLD STYLE---
> $ java SableCC ambiguous.sablecc
> SableCC version 2.12
> [...]
> shift/reduce conflict on TPlus in {
> [PExp = PExp TPlus PExp]:1:TPlus,
> [PExp = PExp TPlus PExp]:1:TMinus,
> [PExp = PExp TPlus PExp]:1:EOF,
> [PExp = PExp TPlus PExp]:3:TPlus,
> [PExp = PExp TPlus PExp]:3:TMinus,
> [PExp = PExp TPlus PExp]:3:EOF,
> [PExp = PExp TMinus PExp]:1:TPlus,
> [PExp = PExp TMinus PExp]:1:TMinus,
> [PExp = PExp TMinus PExp]:1:EOF
> }
> ====================================
> ---NEW STYLE---
> $ java SableCC ambiguous.sablecc
> SableCC version 2.13
> [...]
> shift/reduce conflict in state [stack: PExp TPlus PExp *] on TPlus in {
> [ PExp = PExp * TPlus PExp ] (shift),
> [ PExp = PExp TPlus PExp * ] followed by TPlus (reduce)
> }
>
> NOTE:
> - NEW: the stack state is "in state [...]"
> - The lookahead is "on ..."
> - NEW: The parsing position is indicated by "*"
> - NEW: The action is shown (reduce/shift)
> - NEW: There are no spurious items
> ====================================
> EXPLANATION
>
> What the error message means is that if we have a program that starts with
the
> following:
>
> stack: PExp-1 TPlus PExp-2
> lookahead: TPlus
>
> e.g.: (pick here anything that looks like "PExp TPlus PExp")
>
> 3+4 (and an upcoming "+")
>
> then there is a shift/reduce conflict as you could have:
>
> [parentheses indicate a PExp]
> 3+(4+...)...
> i.e.: shift the "+" in [ PExp = PExp-2 * TPlus PExp-3 ]
> \4/ \+/ \.../
> In other words [PExp-2 TPlus PExp-3] will eventually be reduced to a PExp
(let
> say PExp-4), then the stack will look like
> [ PExp-1 TPlus PExp-4 ]
>
> or you could have
> (3+4)+...
> i.e.: reduce [ PExp = PExp-1 TPlus PExp-2 * ]
> \3/ \+/ \4/
>
> Neat, isn't it?
>
> Have fun resolving conflicts! (I'll use this version to resolve
Scriptonite
> conflicts http://scriptonite.sourceforge.net/).
>
> Etienne
> --
> ----------------------------------------------------------------------
> Etienne M. Gagnon, M.Sc. e-mail: egagnon@j-meg.com
> Author of SableCC: http://www.sable.mcgill.ca/sablecc/
> ----------------------------------------------------------------------
>