CS 214 Lab 3: Ada-95


Begin by opening the file year_codes.adb with a text editor. Take a moment to study it, to see how it implements our basic algorithm, paying special attention to the extra code needed to perform string I/O.

Our program will use a slightly expanded program structure from what we have seen previously:

   Program         ::=  Packages
                        procedure identifier;
                        Declarations
                        begin
                           Statements
                        end identifier;
   Declarations    ::=  Declaration ; Declarations | Ø
   Declaration     ::=  ConstantDec | VariableDec | SubprogramDec | ...
   SubprogramDec   ::=  ProcedureDec | FunctionDec
   Statements      ::=  Statement; MoreStatements
   MoreStatements  ::=  Statement; MoreStatements | Ø
Here, we see that functions and procedures can be defined within the Declarations of an Ada program, prior to the begin that marks the start of the main procedure's body.

To build function YearCode(), we will begin by giving a possible BNF for an Ada function definition:

   FunctionDec     ::=   FunctionHeading
                         Declarations
                         begin
                         Statements
                         end identifier
   FunctionHeading ::=   function identifier Parameters return Type is
   Parameters      ::=   ( ParamDecList ) | Ø
Note that the first identifier in the function's heading must match the identifier that appears in the function's end statement. Note also that if an Ada function requires no parameters, then no parentheses are needed in its declaration. Note finally that an Ada function's return-type is given near the end of the function's heading. Using this information, add a function stub for YearCode() (with parentheses) in the appropriate place within program YearCodes.

In an Ada declaration (variable, parameter, etc.), the identifiers being declared must precede the type. A simplified BNF for a sequence of Ada parameter declarations is as follows:

   ParamDecList    ::=   ParamDec MoreParamDecs
   MoreParamDecs   ::=   ; ParamDec MoreParamDecs | Ø
   ParamDec        ::=   identifier IdentifierList : Type
   IdentifierList  ::=   , identifier IdentifierList | Ø
   Type            ::=   integer | float | character | string | boolean | ...
From a procedural point of view, our YearCode() function has this specification:

Receive: year, a string.
Precondition: year is one of {freshman, sophomore, junior, senior}.
Return: The integer code corresponding to year (1, 2, 3 or 4).

The Ada type string can be used to declare a parameter whose value will be a character string. Using this information, declare parameter year within function YearCode().

To complete the stub, we need the syntax of the Ada if construct, which has a single form:

   IfStmt          ::=   if LogicalExpr then
                            Statements
                         ElsifPart
                         ElsePart
                         end if
   ElsifPart       ::=   Ø | elsif ( LogicalExpr ) then
                                Statements
                             ElsifPart
   ElsePart        ::=   Ø | else
                                Statements
The Ada if statement differs from those in the C-family in several ways. One is that the Ada if statement does not require parentheses, because the keyword if marks the beginning of the LogicalExpr and the keyword then marks its end.

Another difference is that multibranch selection can be accomplished in Ada using a single if statement, compared to multiple if statements in C-family languages. Ada provides a special keyword elsif for this purpose. A common "Gotcha" is mistakenly typing elseif which produces a syntax error!

To fill in the LogicalExpression of each if, we need to know its syntax, which is similar to those in C-family languages:

   Expression      ::=   LogicalExpr | Variable | Literal | ...  various other kinds of expressions
   LogicalExpr     ::=   RelationalExpr BoolCondition
   BoolCondition   ::=   BoolOp RelationalExpr | Ø
   BoolOp          ::=   and | or | xor | not | and then | or else
   RelationalExpr  ::=   Expression RelationalCond
   RelationalCond  ::=   RelationalOp Expression | Ø
   RelationalOp    ::=   = | /= | < | > | <= | >=
Our algorithm requires the equality relation, so use these productions to add an if statement to function YearCodes().

A common "Gotcha" is that Ada's string type is a good bit more restrictive than those in C-family languages: When performing an equality comparison (=) on fixed-length strings, the lengths of the strings being compared must match exactly in order for = to return true! Practically speaking, when you compare year to a string-literal, you may find it necessary to "pad" the string-literal with blanks to make it the same length as year.

To complete the function, it is necessary to know how to return a value from an Ada function. As in the C-family, Ada uses a return statement to accomplish this:

   ReturnStmt   ::=   return Expression
where the type produced by Expression must match the return-type of the function. Using this information, add the necessary return statement(s) to our function so that when it terminates, it will return the appropriate code for a given value of year.

Note finally that the productions to generate an Ada multi-branch if statement are quite different from those that generate a C-family if-else-if; where a C-family if-else-if is one if statement with a second if statement in its ElsePart, an Ada if-elsif is just a single if statement, whose ElsifPart is not empty. This difference stems from the different way Ada and C-family languages terminate their if constructs: an Ada if terminates at its end if, but C++/Java if have no special terminator.

Think carefully about how C++/Java end their if statements vs. how Ada ends its if statements. What advantages can you see to the Ada approach (i.e., using end if)? What disadvantages?



Compile and test your code for correctness:

   gnatmake year_codes.adb
Then use script to create a script.ada file in which you cat your source file, compile it, and show that it works correctly for valid and invalid values.

That concludes the Ada part of this lab.


Calvin > CS > 214 > Labs > 03 > Ada


This page maintained by Joel Adams.