Universität Paderborn - Home Universität Paderborn
Die Universität der Informationsgesellschaft

Generating Software from Specifications WS 2013/14 - File CalendarSol7.fw

@=~
~p maximum_input_line_length = infinity

This file contains the specification of a calendar processor.
It reads a sequence of appointments, represents them by
a tree structure, and outputs the tree.

The following file contains some input for the processor
~O~<cal.ok~>~{~-
1.11.     20:00  "Theater"
Thu       14:15  "GSS lecture"
Weekday   12:05  "Dinner in Palmengarten"
Mon, Thu         "Dean's office"
31.12.    23:59  "Jahresende"
12/31     23:59  "End of year"
May 1            "Labour Day"
-- end of file
~}

TASK 1: 
Generate the processor and test it systematically.
Make sure that you test for every construct of the language 
at least one correct and one erroneous example.
Use several input files for the erroneous examples to
avoid cluttered output. 

~O~<cal1.err~>~{~-
1.11  20:00 "A"
1.11. 24:01 "B"
1.11. 20:00 "aa
thu   20:00 "A"
33.12. 20:00 "A"
~}
~O~<cal2.err~>~{~-
12.13. 20:00 "A"
12/33  20:00 "A"
13/12  20:00 "A"
Mai 1            "Labour Day"
- 
~}

The following file specifies the concrete syntax:
~O~<Calendar.con~>~{
Calendar:       Entry+.
Entry:          Date Event.

Date:           DayNum '.' MonNum '.' /
                MonNum '/' DayNum /
		Month DayNum /
                DayNames / 
                GeneralPattern.

DayNum:         Integer.
MonNum:         Integer.

DayNames:       DayName / DayNames ',' DayName.
DayName:        Day.

GeneralPattern: SimplePattern / SimplePattern Modifier.
SimplePattern: 'Weekday' / 'Weekend'.
Modifier:       '+' DayNames / '-' DayNames.

Event:          When Description / Description.
When:           Time / Time '-' Time.
~}

TASK 2: 
Check the meaning of the following token specifications.
Extend the input language by comments. What kind of comments
do you think fits best to the style of this language?
Specify it and test the processor.

The appointments of this language will usually be written one
per line. So, line comments would fit best to the language.
I specified Ada comments.

~O~<Calendar.gla~>~{
Description: C_STRING_LIT
Integer:     PASCAL_INTEGER
Day:         $Mon|Tue|Wed|Thu|Fri|Sat|Sun [mkDay]
Time:        $(([0-9]|1[0-9]|2[0-3]):[0-5][0-9]) [mkTime]
	     ADA_COMMENT
Month:       $Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec [mkMonth]
~}


TASK 3:
The C module below implements the two token coding functions
mkDay and mkTime. Understand what they compute.
Then extend your language by a facility to write abbreviated names of
months, too, e.g.
  May 1  "Labour Day"
Which specification types do you need to change?

A new alternative for Date is inserted in the concrete syntax (.con).
The token specification for Month is added (.gla).
The coding function is implemented in the C module (.h, .c)
Correct and erroneous test cases are added.

You can make the extensions according to the way the names of
Days are specified.

TASK 4:
Change the specification of the token Time. (Keep the current
specification, in order to undo this change after this experiment.)
Make time to be a nonterminal which derives the hours and minutes 
separated by a colon. Any checks, whether the time is correct may be
deferred to the semantic analysis phase.
Check carefully how the notation of Time now differs from the previous 
version. Which one do you prefer?

I inserted the productions
  Time:   Hour ':' Minute.
  Hour:   Integer.
  Minute: Integer.
into the concrete syntax and deleted the token specification for Time.
The check for correct time notations is then deferred to semantic
analysis. Now it is possible to insert white space into time notations
e.g. 10 : 25. I prefer the original notation.

~O~<Calendar.head~>==~{
#include "csm.h"
#include "Calendar.h"
~}
~O~<Calendar.h~>==~{
extern void mkDay (char *, int, int *, int*);
extern void mkTime (char *, int, int *, int*);
extern void mkMonth (char *, int, int *, int*);
~}
~O~<Calendar.c~>==~{
#include <string.h>
#include "Calendar.h"

void mkDay (char *d, int l, int *c, int *i)
{
    switch (d[0]) {
        case 'F': *i = 5; break;
        case 'M': *i = 1; break;
        case 'W': *i = 3; break;
        case 'S': *i = (d[1] == 'a'? 6 : 7); break;
        case 'T': *i = (d[1] == 'u' ? 2 : 4); break;
    }
}

void mkTime (char *t, int l, int *c, int *i)
{
   char *colon = strchr (t, ':');
   int hours, mins;

   *colon = '\0';
   hours = atoi (t);
   mins = atoi (colon + 1);
   *colon = ':';
   *i = hours*60 + mins;
}

void mkMonth (char *m, int l, int *c, int *i)
{
    switch (m[0]) {
        case 'A': *i = (m[1] == 'p' ? 4 : 8); break;
        case 'D': *i = 12; break;
        case 'F': *i = 2; break;
        case 'J': *i = (m[1] == 'a' ? 1 : (m[2] == 'n' ? 6 : 7)); break;
        case 'M': *i = (m[2] == 'r' ? 3 : 5); break;
        case 'N': *i = 11; break;
        case 'O': *i = 10; break;
        case 'S': *i = 9; break;
    }
}
~}

Generiert mit Camelot | Probleme mit Camelot? | Geändert am: 06.11.2013