I wrote:
> > Surely the overhead of this is _tiny_. It's just a few simple
> > instructions on a CHARACTER and some INTEGERs. There's no object
> > creation, no garbage generated, no polymorphism, not even a feature
> > call. (Incidentally, every character is arleady tested against newline
> > in YY_SCANNER_SKELETON.read_character.)
Patrick Doyle wrote:
> Right, but this tiny overhead occurs for every single character. I
> haven't looked carefully at Eric's code, but if he has done it properly,
> this tiny overhead would still represent a sizeable fraction of the time
> required for scanning.
To help put this overhead into perspective, I ran this Linux command:
$ time wc /usr/bin/postgres
The word count program "wc" must compare every character against newline
and space, and maintain three counters. So it's doing _more_ than the
proposed extra functionality to be added to the Gobo scanner. It must
also do its own I/O, whereas we get this "for free" in the scanner
because it's already being done. Also, the Gobo scanner already includes
a test of each character against newline. So "wc" is doing _much_ more
than the proposed extra Gobo functionality.
(I chose to count the lines and characters in /usr/bin/postgres because
it's about a megabyte.)
Here are the results of the command:
2124 35326 1049820 /usr/bin/postgres
0.01user 0.01system 0:00.06elapsed 28%CPU
So it takes 0.06 seconds to read a megabyte and count the lines and
characters. I ran this again, so that the data was already in memory:
2124 35326 1049820 /usr/bin/postgres
0.02user 0.00system 0:00.02elapsed 68%CPU
Now it's 0.02 seconds. And even that is probably mostly file I/O.
The whole of EiffelBase is just under a megabyte of source code. In case
anyone didn't know, from version 4.5 ISE's compiler uses the Gobo
scanner. So it should add less than one-fiftieth of a second (probably
less than a hundredth of a second) to the time taken to precompile the
entire EiffelBase library if the Gobo scanner was keeping track of line
and column numbers. And some applications which already process
line/column numbers manually may even be speeded up, and will certainly
become slightly more compact and more reliable.
Regards,
Roger
--
Roger Browne - roger@... - Everything Eiffel
19 Eden Park Lancaster LA1 4SJ UK - Phone +44 1524 32428
On Tue, 25 Jan 2000, Roger Browne wrote:
> Eric Bezault wrote:
>
> > ... I didn't provide such
> > a facility in gelex because having something like
> > yylineno kept uptodate in the scanner engine would
> > have not been good for the performance of the generated
> > scanners, even those which don't need this facility,
> > because the engine would have had to test each
> > character read and see if it's not the new-line
> > character.
>
> Surely the overhead of this is _tiny_. It's just a few simple
> instructions on a CHARACTER and some INTEGERs. There's no object
> creation, no garbage generated, no polymorphism, not even a feature
> call. (Incidentally, every character is arleady tested against newline
> in YY_SCANNER_SKELETON.read_character.)
Right, but this tiny overhead occurs for every single character. I
haven't looked carefully at Eric's code, but if he has done it properly,
this tiny overhead would still represent a sizeable fraction of the time
required for scanning.
> Redefining a routine is never as easy as simply calling a query (and you
> have also described a situation where the routine may become
> polymorphic, making it slower than a hardwired line/column counter) so I
> don't favour this solution.
I think we could minimize the impact of the polymorphism. What you do is
start off with a new "skeleton which counts columns" (SWCC) class which
inherits from the normal skeleton class (which I'll call SKELETON). In
SWCC, you redefine the empty routine to count columns.
So far, this does not help. However, you can go backward in the call
graph, and redefine the routines which *call* that empty routine. Simply
redefine them with an identical body; this should cause SE to optimize the
two versions of the routine separately.
You can continue moving up the call chain, redefining things with
identical bodies, until you reach a point where the performance is
acceptable. Again, I have not looked at Eric's code, but I suspect that
this would not have to go very far.
Duplicating code is never elegant, but if performance is important, then
sometimes elegance loses out.
I should add that I'm not sure this technique would even help; I'm not
familiar enough with SE's optimizations to say for sure.
--
Patrick Doyle
doylep@...
On Tue, 25 Jan 2000, Alexander Kogtenkov wrote:
> In this case, there is no need in an empty feature
> that performs nothing. It means that there will be no
> overhead at all, unless someone (like me) needs to
> count columns.
You may know this already, but just to clarify...
SmallEiffel under -boost has no overhead for calling empty routines
anyway, unless they are polymorphic. SE can optimize these things away.
--
Patrick Doyle
doylep@...
Eric Bezault wrote:
> ... Now for the column numbers ...
> ... pretty much all the semantic actions will have
> to be equipped with instructions such as:
>
> \n {
> line := line + 1
> column := 1
> }
> [a-z]* {
> ...
> column := column + text_count
> }
>
> This is feasable and I actually aleady did it in a
> parser I wrote lately, but I agree that it is not
> simple.
I've "been there, done that" too. If the grammar has multi-line tokens
(multi-line strings, multi-line comments, etc) then keeping track of
line/column number manually can be tedious and error-prone.
On the other hand, having queries like 'yylineno' and 'yycharno'
available would be convenient and virtually foolproof. In the best
spirit of re-use, the fiddly work is done once and for all by the tool
writer rather than every time by the developer.
> ... I didn't provide such
> a facility in gelex because having something like
> yylineno kept uptodate in the scanner engine would
> have not been good for the performance of the generated
> scanners, even those which don't need this facility,
> because the engine would have had to test each
> character read and see if it's not the new-line
> character.
Surely the overhead of this is _tiny_. It's just a few simple
instructions on a CHARACTER and some INTEGERs. There's no object
creation, no garbage generated, no polymorphism, not even a feature
call. (Incidentally, every character is arleady tested against newline
in YY_SCANNER_SKELETON.read_character.)
A small complication is that 'unread_character' would also need to keep
track of newlines.
> I don't think that yacc nor bison provide a solution
> like they have with yylineno (although I may be wrong).
Ah, maybe that's why gcc only reports a line number (not a character
position) when an error occurs. I hate that!
> I said above that the problem with adding line
> and column counting in the scanner engine was
> that it would decrease the performance of the
> generated scanners, even those which don't need
> this facility.
Lots of scanners don't _use_ column counting, but there are few that
don't _need_ it! In any situation where error input may be encountered,
the column number is potentially useful. Only in those applications
where the data is _guaranteed_ correct is there no use for it.
> I might have another solution where the scanner
> engine calls an empty routine by default to take
> care of line and column counting, and this
> routine would be redefined to do the proper
> things in the generated scanner class if this
> facility is needed...
Redefining a routine is never as easy as simply calling a query (and you
have also described a situation where the routine may become
polymorphic, making it slower than a hardwired line/column counter) so I
don't favour this solution.
By the way, this is the kind of thing I'd be happy to code and send you
the patches. Are you actively encouraging others to do this kind of
work, or do you prefer to keep control of the integrity of the library
at this time?
Regards,
Roger
--
Roger Browne - roger@... - Everything Eiffel
19 Eden Park Lancaster LA1 4SJ UK - Phone +44 1524 32428
> > Line numbers: During scanner generation, for all
> > transitions that recognize
> > a line feed, add a line number increment action. (Is
> > transition handling
> > polymorphic? If yes, this comes for free; if no, it's still
> > a comparison, so
> > you can just make the check at the character input routine.)
>
> I'm afraid it's not that easy in practice. For efficiency
> reasons, there is no transition objects as such, but rather
> opaque table lookups. Therefore when the scanner engine
> reads indexes in the tables, it has no idea whether it's
> a new-line transition or not.
Hmm... how about automatically adding a rule that detects line ends? It
would have to run in parallel with the normal automaton, but the NDFA->DFA
conversion should be able to handle this. You'd need a special accept state
that executes the line change action but continues scanning; I'm not sure
how easy such a thing can be added to yacc, but it would be easy enough to
incorporate into the basic algorithms as described in the Dragon book.
> > Column numbers: Don't increment for every character.
> > Instead, increment the
> > column count by the current symbol character count
> > immediately before
> > communicating with the outside world (i.e. when reporting
> > an error, or when finishing a token).
>
> That doesn't work if the last token read contains a
> new-line character.
Now that's easy: Whenever a newline is recognized, set a flag so that the
column will be computed by doing a backwards search. Or have it remember the
current token length (i.e. up to and including the line end) so that it can
be subtracted from total token length to give the column number (modulo
fencepost errors).
Regards,
Joachim
--
This is not an official statement from my employer or from NICE.
Eric Bezault wrote:
> Do you mean that you just write some rules such as:
>
> \n line := line + 1
> "[^"]*" {
> ...
> line := line + text.occurrences ('%N')
> }
Yes, something like this.
> But if you look at yacc or bison, you will see that
> they provide a query yylineno that can be called in
> the semantic actions. What happens is that the updating
> of the attribute `line' is done automatically in the
> scanner engine instead of letting the user do it "by
> hand" in the semantic actions. I didn't provide such
> a facility in gelex because having something like
> yylineno kept uptodate in the scanner engine would
> have not been good for the performance of the generated
> scanners, even those which don't need this facility,
> because the engine would have had to test each
> character read and see if it's not the new-line
> character.
Of course, such an automatic facility should not be
provided.
> So the line numbering solution is efficient and not
> too difficult to implement. Now for the column numbers,
> I don't think that yacc nor bison provide a solution
> like they have with yylineno (although I may be wrong).
> Anyway, here again we have two solutions: either it's
> done automatically by the scanner engine which reads
> character by character and increment `line' and `column'
> accordingly, or we let the user to take care of that
> in the semantic actions. The first solution has the
> same drawbacks as for the line number. It will imply
> a performance penalty even for the generated scanners
> which don't need this facility.
Again, this would be a bad thing to have the built-in facility.
> However the second
> solution is more cumbersome than with the line numbers
> since pretty much all the semantic actions will have
> to be equipped with instructions such as:
>
> \n {
> line := line + 1
> column := 1
> }
> [a-z]* {
> ...
> column := column + text_count
> }
>
> This is feasable and I actually aleady did it in a
> parser I wrote lately, but I agree that it is not
> simple.
Yes, this is what my concerns are about.
> So, to answer your question, I'm not aware of a
> technique for counting column numbers which is
> both simple and efficient.
...
> I might have another solution where the scanner
> engine calls an empty routine by default to take
> care of line and column counting, and this
> routine would be redefined to do the proper
> things in the generated scanner class if this
> facility is needed.
I think there is one more way to achieve the desired
effect. If there were a feature that suplies characters
to the scanner, it would be possible to redefine it
and insert the column-counting facility. Maybe, such a
feature is already there, but I do not know which one.
In this case, there is no need in an empty feature
that performs nothing. It means that there will be no
overhead at all, unless someone (like me) needs to
count columns.
> However, in programs where
> several scanners for different languages sharing
> the same scanner skeleton are used, the above
> new routine may actually become polymorphic, and
> hence slowing down a scanner without line nor
> column number needed, even though its version
> of the routine does nothing.
This is true. From the other hand, there will be a
choice whether to supply additional information
to the end user though scanner would be a little
bit slower.
Regards,
Alexander Kogtenkov
Object Tools, Moscow
Durchholz, Joachim wrote:
...
> Column numbers: Don't increment for every character. Instead, increment the
> column count by the current symbol character count immediately before
> communicating with the outside world (i.e. when reporting an error, or when
> finishing a token).
It's easy to make a mistake because there may be too many rules. But then,
why not have "super" actions PRE and POST which are executed before and
after any other action (including the empty ones) respectively? Then there
will no problems with polymorphic feature call and speed penalty.
Regards,
Alexander Kogtenkov
Object Tools, Moscow
Dear Joachim,
> Line numbers: During scanner generation, for all transitions that recognize
> a line feed, add a line number increment action. (Is transition handling
> polymorphic? If yes, this comes for free; if no, it's still a comparison, so
> you can just make the check at the character input routine.)
I'm afraid it's not that easy in practice. For efficiency
reasons, there is no transition objects as such, but rather
opaque table lookups. Therefore when the scanner engine
reads indexes in the tables, it has no idea whether it's
a new-line transition or not.
> Column numbers: Don't increment for every character. Instead, increment the
> column count by the current symbol character count immediately before
> communicating with the outside world (i.e. when reporting an error, or when
> finishing a token).
That doesn't work if the last token read contains a
new-line character.
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
Dear Pat,
> As I said, the exception list (classes that cause
> the Gobo Eiffel parser to fail) is much shorter
> ... but not empty. Current problem is the following
> class declaration:
>
> class OLEDB_DBBINDING[MM-> MEMORY_MODEL creation make end]
>
> .
> .
> .
>
> ah wait a minute, just tried something. If I change
> the 'creation' to 'create', your new Gobo parser successfully
> parses it.
The syntax specified on ISE's web site uses `create'.
So there is a syntax error in your class declaration
above if you use `creation' instead of `create'. The
ISE parser accepts it probably because it considers
`create' and `creation' to be the same for migration
purposes, but since generic creation is a new construct
in the language, I think that this is a mistake to
accept `creation' here and only `create' should be used.
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
I've got a different idea.
Line numbers: During scanner generation, for all transitions that recognize
a line feed, add a line number increment action. (Is transition handling
polymorphic? If yes, this comes for free; if no, it's still a comparison, so
you can just make the check at the character input routine.)
Column numbers: Don't increment for every character. Instead, increment the
column count by the current symbol character count immediately before
communicating with the outside world (i.e. when reporting an error, or when
finishing a token).
Regards,
Joachim
--
This is not an official statement from my employer or from NICE.
Eric,
(btw, this is not a feature request, just asking for your opinion)
Do you think it is possible for yacc (or geyacc in particular) to
have the ability to provide an `expected' context in the event of
a parse error? An example parser message produced using this
information might be: "Found keyword `create'; expected one of
`class', 'feature', 'end'." (That's a goofy example, but I hope it makes
the point). This information would be rarely needed, so it could
remain computationally expensive. I usually provide this ability with
hand-coded recursive descent parsers, but it's much easier to do
that sort of thing in a hand-coded parser.
Thanks for your time,
Michael Garnett
eric bezault <eric-@...> wrote:
original article:http://www.egroups.com/group/gobo-eiffel/?start=17
> Patrick Flaherty wrote:
> > Could your Eiffel grammar be extended to handle agents
> > (eg, ~return(?))?
>
> I have updated the example in $GOBO/example/parse/eiffel
> so that it now supports the latest language extensions
> from ISE. I have added:
>
> . Tuple expression
> . Agents
> . Create keyword
> . Generic creation (in the generic constraint clause)
>
> I didn't check the shift/reduce conflits but I tried this new
> Eiffel parser with all Eiffel classes which are on my hard-disk
> (between 6,000 and 8,000 classes), including the classes which
> come with the 4 different Eiffel compilers (lastest releases
> and also older versions as well). I got no syntax error reported
> except for a couple of classes which really contained a syntax
> error and classes which are using `create' as an identifier
> instead of considering it a keyword. BTW, I've put a boolean
> attribute (`create_keyword') in the eiffel scanner class. If it
> is set to true (which is its default value) then the word `create'
> will be considered as a keyword, otherwise it will be understood
> as an identifier.
>
> Note that this is not because I didn't get any syntax error
> reported during my tests that the parser parses correctly.
> But there is a good chance that it does though.
>
> You will find attached to this message the files eiffel_scanner.l
> and eiffel_parser.y (I hope that eGroups will accept file attachment).
> You will have to copy them to $GOBO/example/parse/eiffel (or a copy
> of this directory) and run the scripts make_scanner.bat and
> make_parser.bat (or something similar under Linux) to regenerate
> the corresponding Eiffel classes.
>
> --
> Eric Bezault
> mailto:ericb@...
> http://www.gobosoft.com
Eric,
Thanx. This much reduced my list of exceptions.
What I'm parsing are all the Rosenberg Eiffel classes
of which there are some 3,500. And typically we use
every new ISE language extension. (That being the case,
maybe I want to figure out for myself how to extend
your Eiffel grammar).
As I said, the exception list (classes that cause
the Gobo Eiffel parser to fail) is much shorter
... but not empty. Current problem is the following
class declaration:
class OLEDB_DBBINDING[MM-> MEMORY_MODEL creation make end]
.
.
.
ah wait a minute, just tried something. If I change
the 'creation' to 'create', your new Gobo parser successfully
parses it. The list of classes where we've done this
is not long, so maybe I should get people here to change
their code since 'create' as opposed to 'creation' is
the latest-and-greatest.
pat
On Tue, 25 Jan 2000, Eric Bezault wrote:
> Patrick Doyle wrote:
> > You mentioned an empty routine that would be called to handle row and
> > column numbers. How about something like this:
> >
> > Call an empty routine for every character that is read. SE should be
> > smart enough to optimize this away to nothing; I don't know about the
> > others. If you want line numbering, use the technique you mentioned. If
> > you also want column numbering, put a "column := column + 1" in the
> > per-character routine and then put a "column := 1" in the linefeed handler
> > action.
>
> That's what I had in mind when I mentioned this empty
> routine.
Oh, I thought you had meant something more specific to line-and-column
counting, rather than a routine that is simply called for every character.
Sorry. :-)
--
Patrick Doyle
doylep@...
Patrick Flaherty wrote:
> Could your Eiffel grammar be extended to handle agents
> (eg, ~return(?))?
I have updated the example in $GOBO/example/parse/eiffel
so that it now supports the latest language extensions
from ISE. I have added:
. Tuple expression
. Agents
. Create keyword
. Generic creation (in the generic constraint clause)
I didn't check the shift/reduce conflits but I tried this new
Eiffel parser with all Eiffel classes which are on my hard-disk
(between 6,000 and 8,000 classes), including the classes which
come with the 4 different Eiffel compilers (lastest releases
and also older versions as well). I got no syntax error reported
except for a couple of classes which really contained a syntax
error and classes which are using `create' as an identifier
instead of considering it a keyword. BTW, I've put a boolean
attribute (`create_keyword') in the eiffel scanner class. If it
is set to true (which is its default value) then the word `create'
will be considered as a keyword, otherwise it will be understood
as an identifier.
Note that this is not because I didn't get any syntax error
reported during my tests that the parser parses correctly.
But there is a good chance that it does though.
You will find attached to this message the files eiffel_scanner.l
and eiffel_parser.y (I hope that eGroups will accept file attachment).
You will have to copy them to $GOBO/example/parse/eiffel (or a copy
of this directory) and run the scripts make_scanner.bat and
make_parser.bat (or something similar under Linux) to regenerate
the corresponding Eiffel classes.
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
Patrick Doyle wrote:
> You mentioned an empty routine that would be called to handle row and
> column numbers. How about something like this:
>
> Call an empty routine for every character that is read. SE should be
> smart enough to optimize this away to nothing; I don't know about the
> others. If you want line numbering, use the technique you mentioned. If
> you also want column numbering, put a "column := column + 1" in the
> per-character routine and then put a "column := 1" in the linefeed handler
> action.
That's what I had in mind when I mentioned this empty
routine.
> I think this should be efficient when it's not needed, and efficient and
> flexible when it is needed. It does suffer the performance hit for the
> polymorphic case you mentioned;
yes, this was my concern. If in the same program you have
a scanner with line and column numbering and another one
without it, the second scanner may suffer because of the
polymorphic call.
> it would be interesting to see how bad
> this hit really is.
Me too. Perhaps the overhead will be very small,
I don't know.
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
On Mon, 24 Jan 2000, Eric Bezault wrote:
> Actually the
> "by hand" solution is even more efficient than what
> would have been the solution with yylineno since in
> the rules we know when there is a chance to read a
> new-line or not, whereas the scanner engine doesn't
> know and has to test every character one by one.
>
> So the line numbering solution is efficient and not
> too difficult to implement. Now for the column numbers,
You mentioned an empty routine that would be called to handle row and
column numbers. How about something like this:
Call an empty routine for every character that is read. SE should be
smart enough to optimize this away to nothing; I don't know about the
others. If you want line numbering, use the technique you mentioned. If
you also want column numbering, put a "column := column + 1" in the
per-character routine and then put a "column := 1" in the linefeed handler
action.
I think this should be efficient when it's not needed, and efficient and
flexible when it is needed. It does suffer the performance hit for the
polymorphic case you mentioned; it would be interesting to see how bad
this hit really is.
--
Patrick Doyle
doylep@...
Dear Alexander,
> It's quite easy to implement source line tracking using
> GOBO scanner generator. From the other hand, it's
> much harder to track the current position in the line. Is
> there a simple and efficient way to do it?
It depends on what you mean by simple. In the case of
line numbers you said that it is quite easy to implement.
Do you mean that you just write some rules such as:
\n line := line + 1
"[^"]*" {
...
line := line + text.occurrences ('%N')
}
? This is usually the technique I use in my scanners.
But if you look at yacc or bison, you will see that
they provide a query yylineno that can be called in
the semantic actions. What happens is that the updating
of the attribute `line' is done automatically in the
scanner engine instead of letting the user do it "by
hand" in the semantic actions. I didn't provide such
a facility in gelex because having something like
yylineno kept uptodate in the scanner engine would
have not been good for the performance of the generated
scanners, even those which don't need this facility,
because the engine would have had to test each
character read and see if it's not the new-line
character. And moreover it is not too hard for the
user to add lines such as the ones in the example
above when he wants line numbering. Actually the
"by hand" solution is even more efficient than what
would have been the solution with yylineno since in
the rules we know when there is a chance to read a
new-line or not, whereas the scanner engine doesn't
know and has to test every character one by one.
So the line numbering solution is efficient and not
too difficult to implement. Now for the column numbers,
I don't think that yacc nor bison provide a solution
like they have with yylineno (although I may be wrong).
Anyway, here again we have two solutions: either it's
done automatically by the scanner engine which reads
character by character and increment `line' and `column'
accordingly, or we let the user to take care of that
in the semantic actions. The first solution has the
same drawbacks as for the line number. It will imply
a performance penalty even for the generated scanners
which don't need this facility. However the second
solution is more cumbersome than with the line numbers
since pretty much all the semantic actions will have
to be equipped with instructions such as:
\n {
line := line + 1
column := 1
}
[a-z]* {
...
column := column + text_count
}
This is feasable and I actually aleady did it in a
parser I wrote lately, but I agree that it is not
simple.
So, to answer your question, I'm not aware of a
technique for counting column numbers which is
both simple and efficient.
I said above that the problem with adding line
and column counting in the scanner engine was
that it would decrease the performance of the
generated scanners, even those which don't need
this facility. A solution would be to have yet
another scanner skeleton class where this facility
would be implemented, and then it would be up
to the user to inherit one skeleton class (with
line and column counting support) or another
(more efficient but without such facilities).
I'm not sure whether this is a good idea since
it doubles the number of scanner skeleton classes.
I might have another solution where the scanner
engine calls an empty routine by default to take
care of line and column counting, and this
routine would be redefined to do the proper
things in the generated scanner class if this
facility is needed. However, in programs where
several scanners for different languages sharing
the same scanner skeleton are used, the above
new routine may actually become polymorphic, and
hence slowing down a scanner without line nor
column number needed, even though its version
of the routine does nothing. But perhaps I should
try to implement it and do some benchmarks to see
what kind of performance we get afterall.
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
It's quite easy to implement source line tracking using
GOBO scanner generator. From the other hand, it's
much harder to track the current position in the line. Is
there a simple and efficient way to do it?
Thanks,
Alexander Kogtenkov
Object Tools, Moscow
Patrick Flaherty wrote:
> I don't seem to have received an updated grammar from
> you. At least it's not in the edep.zip you sent me
> nor do I find it in any of your other messages.
Oops, I thought it was in the edep.zip, but obviously
it wasn't. Sorry.
Durchholz, Joachim wrote:
> I'd be interested in an updated grammar as well.
OK, since there are several people interested in ISE's
extensions to be included in the Eiffel grammar provided
in the Gobo package, I'll delay the proofreading of the
french translation of OOSC2 and try to work on the Eiffel
grammar tonight or tomorrow night.
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
> From: Eric Bezault [mailto:ericb@...]
>
> BTW, are you using the Eiffel grammar that I sent you
> in private and that already supports the create keyword
> or are you using the version provided in the standard
> Gobo 1.5 delivery?
I'd be interested in an updated grammar as well.
Regards,
Joachim
--
This is not an official statement from my employer or from NICE.
Of course it does.
Thanks a lot,
David
On Sun, Jan 23, 2000 at 05:09:08PM +0100, Eric Bezault wrote:
>
> Does that answer your question?
>
> --
> Eric Bezault
> mailto:ericb@...
> http://www.gobosoft.com
>
eric bezault <eric-@...> wrote:
original article:http://www.egroups.com/group/gobo-eiffel/?start=8
> Dear Pat,
>
> > Could your Eiffel grammar be extended to handle agents
> > (eg, ~return(?))?
>
> I'm currently busy proofreading the french translation
> of OOSC2. As soon as I'm done with this task I'll try
> to include the latest ISE's extensions to the Eiffel
> grammar provided in the Gobo package. I'll let you
> know in this forum when it is ready and working. (Pat,
> if you want to receive the messages of this mailing
> list automatically by e-mail, you can subscribe by
> clicking on the "group info" button or directly at:
> http://www.egroups.com/group/gobo-eiffel/info.html.
> Otherwise you would have to visit this mailing list
> message Web page from time to time.)
>
> BTW, are you using the Eiffel grammar that I sent you
> in private and that already supports the create keyword
> or are you using the version provided in the standard
> Gobo 1.5 delivery?
I don't seem to have received an updated grammar from
you. At least it's not in the edep.zip you sent me
nor do I find it in any of your other messages. And so
I'm using the standard one from 1.5.
For the time being, the lack of the 'create' keyword is
not a problem in that, while it's not recognized, it
does not cause the parser to fail. And it's not something
I need to recognize. '~' (signaling an agent) does cause
the parser to fail.
pat
>
> --
> Eric Bezault
> mailto:ericb@...
> http://www.gobosoft.com
Dear Pat,
> Could your Eiffel grammar be extended to handle agents
> (eg, ~return(?))?
I'm currently busy proofreading the french translation
of OOSC2. As soon as I'm done with this task I'll try
to include the latest ISE's extensions to the Eiffel
grammar provided in the Gobo package. I'll let you
know in this forum when it is ready and working. (Pat,
if you want to receive the messages of this mailing
list automatically by e-mail, you can subscribe by
clicking on the "group info" button or directly at:
http://www.egroups.com/group/gobo-eiffel/info.html.
Otherwise you would have to visit this mailing list
message Web page from time to time.)
BTW, are you using the Eiffel grammar that I sent you
in private and that already supports the create keyword
or are you using the version provided in the standard
Gobo 1.5 delivery?
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
Eric,
Could your Eiffel grammar be extended to handle agents
(eg, ~return(?))? Currently, when I parse the following
line of code:
create l_return.make("return_19990414_19990419",~return(?))
I get the following error:
l:\pf\eiffel\test\ad_hoc_panel.e, line 207: parse error
Dear David,
> I use gelex to produce various filters. Most of the time I need to copy
> unmatched characters to a file instead of stdout (I do that by adding a
> .|\n rule to the scanner). I'ld like to know if there is a better way
> to do that? Is it possible to redifine the default rule?
This is a really good question. In the scanners that I wrote,
I usually use the same technique as you described: I put
a .|\n rule at the end of the scanner description.
As indicated in $GOBO/doc/gelex/matching_rules.html#default_rule,
the default action (provided that options nodefault nor -s have
not been specified) is to output the character to the standard
output. In order to achieve that, the scanner engine calls the
routine `echo' from the scanner skeleton class. So if you do not
call `echo' otherwise, you could consider it as your default_action
routine and redefine it. Note that this is more or less a hack.
In the next release I will add a routine `default_action' in
the scanner skeleton class which will be called instead of `echo'
when the default rule is matched. This new routine will look
like this:
default_action is
-- Action executed when the default rule is matched.
do
echo
end
That way you will just have to redefine `default_action' to
do what you want.
If you don't want to wait for the next release, you can still
patch your source code of `gelex' as follows and recompile it.
You just need to replace the line:
set_action ("echo")
by:
set_action ("default_action")
in routine `process_default_rule' in class LX_LEX_PARSER_SKELETON
(in cluster $GOBO/library/lexical/lex), and add the `default_action'
routine shown above to the class YY_SCANNER (in cluster
$GOBO/library/lexical/skeleton).
Does that answer your question?
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
Hello,
I use gelex to produce various filters. Most of the time I need to copy
unmatched characters to a file instead of stdout (I do that by adding a
.|\n rule to the scanner). I'ld like to know if there is a better way
to do that? Is it possible to redifine the default rule?
David
First, I'd like to thank you all for joining this mailing list.
I hope that this mailing list will be useful for those of you
who use the Gobo Eiffel Tools and Libraries, should you want to
share your experience with other users, report bugs, ask for help,
suggest improvements, etc.
Since I'm the author of the Gobo package, I'll make the first
announcement to this forum: I have put together a couple of
months ago a list of known bugs along with their workarounds
and fixes at http://www.gobosoft.com/eiffel/gobo/known_bugs.html.
Since the Gobo package is bug-free I don't expect this bug list
to grow too much :-). But nevertheless noone is perfect, so feel
free to visit this page from time to time.
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
Patrick Flaherty wrote:
> So there are two parents in my sample code: UTILITY and
> SELECTION_PREDICATE. I found by running with debug on
> that rule #45 fires for the first of these and rule #46 for
> the second. My problem: after each rule fires
> eg Parents: Class_type {some_action} | ...
> how do I recognize what the class_name was? I do not
> find it either in last_value or on the stack (yyvs).
Did you receive the edep example that I sent you?
If you look at the edep.y file, you'll see:
Class_type: Class_name Actual_generics_opt
{
class_name := dollar_string ($1)
if not generic_parameters.has (class_name) then
std.output.put_string (class_name)
std.output.put_character ('%N')
end
}
;
Class_name: E_IDENTIFIER
{ $$ := $1 }
;
In order to have access to the parent class names in
the semantic actions of the Parents construct, you'll
need to add the following line in the semantic action
of the Class_type:
$$ := $1
and then you can write:
> Parents: Class_type -- rule #45
{ print ($1) }
> | Parents Feature_adaptation_opt Class_type -- 46
{ print ($3) }
> | Parents Feature_adaptation_opt ';' Class_type -- 47
{ print ($4) }
> | Parents E_END Class_type -- 48
{ print ($3) }
> | Parents E_END ';' Class_type -- 49
{ print ($4) }
For further details about semantic actions and semantic
values, have a look at $GOBO/doc/geyacc/actions.html.
--
Eric Bezault
mailto:ericb@...http://www.gobosoft.com
I'm using the Eiffel grammar found in Gobo.
Want to recognize parent class names for a given
Eiffel text I'm parsing. And have a class that
begins as follows:
class
BENCHMARK_QUARTERLY_PREDICATE
inherit
UTILITY
SELECTION_PREDICATE[BENCHMARK_QUARTERLY_TABLE]
redefine
action
end
Parent rules (with added rules #s by me) are as
follows:
Parents: Class_type -- rule #45
| Parents Feature_adaptation_opt Class_type -- 46
| Parents Feature_adaptation_opt ';' Class_type -- 47
| Parents E_END Class_type -- 48
| Parents E_END ';' Class_type -- 49
So there are two parents in my sample code: UTILITY and
SELECTION_PREDICATE. I found by running with debug on
that rule #45 fires for the first of these and rule #46 for
the second. My problem: after each rule fires
eg Parents: Class_type {some_action} | ...
how do I recognize what the class_name was? I do not
find it either in last_value or on the stack (yyvs).
patrick flaherty