I am New to Ada and I am attempting to convert the code in a compiler tutorial on Recursive Decent Parser to Ada. Porting the tutorial, “Let’s Build a Compiler” by Jack W Crenshaw has been a favorite way for me to learn many languages. I had everything working up to Chapter three, using single character tokens. The move to multi-character tokens has been troublesome.
I have code something like this sudo code:
procedure GetName is
token: Ada.Strings.Unbounded;
begin
while IsAlNum(Look) loop
Token := Token & Look;
GetChar;
end loop
end GetName;
Now I know Ada intended for strings to be static. But I need to be able to concatenate each new character taken from the input to the collection of characters in Token. Look is the global look-ahead value (the last character inputted).
Thanks for you help. Also, are there any good Ada tutorials or recipes sites on the net? I’ve read Lovelace and Ada for C programmers. The Ada RMs are a bit formal and only show specifications not use…
Thanks again!
At the end of this question, it looks like you are asking for help in Ada string processing.
Yes, Ada strings are indeed best handled as static strings, rather than resizable buffers. There are three typcial ways to deal with this.
The first is to make a really big
Stringbuffer, with a separateNaturalvariable to hold the logical length of the string. This is kind of a pain, and is somewhat error prone, but is at least faster than C’s method of constantly scanning for a null at the end of the buffer.The second is to just punt and use Ada.Strings.Unbounded.Unbounded_String. This is what most folks do, as it is easiest if you are used to thinking of things in a procedural way.
The third, (which I prefer when possible) is to handle your strings functionally. The main insight you need here is that Ada
Strings are indeed static, but you can control their lifetime, and you can dynamically make static strings whenever you want, if you program functionally.For instance, I can create a new
Tokenstring of whatever length I want (with theoretically infinite lookahead) by doing something like the following:This isn’t always the most efficient method of string handling (too much stack usage), but it is often the easiest.
In practice, scanning and parsing is actually kind of a special-case application, where ugly things one typically avoids, like buffers (method 1) and gotos, are often advisable.