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 Expressionwhere 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.adbThen 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