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

Generating Software from Specifications WS 2013/14 - File CalendarCheck.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 performs some checks and computations
as required in Assignment 4, Exercise 11.

The following files contain correct input for the processor
~O~<cal.ok~>~{~-
1.11.     20:00  "Theater"
Thu       14:15  "GSS lecture"
1.5.	  9:15	 "Meeting"
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"
Weekday+Sat      "Work"
-- end of file
~}
~O~<cal1.ok~>~{~-
Thu   10:00 - 10:15 "Have a break"
~}

The following files contain erroneous input for the processor
~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"
- 
~}
~O~<cal3.err~>~{~-
31.4.  9:00  "not in April"
1.13.  9:00  "not in any year"
~}

The following file specifies the concrete syntax:
~O~<Calendar.con~>~{
Calendar:       Entries.
Entries:	Entries Entry / Entry.

Entry:		DateDescr When Description.

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

DayNum:         Integer.
MonNum:         Integer.

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

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

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

The non-literal tokens are specified as follows:
~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]
~}


A mapping specifications as described in the lecture material:
~O~<CalendarChecks.map~>~{
MAPSYM
Pattern ::= GeneralPattern SimplePattern.
MAPRULE
Date:           DayNum '.' MonNum '.' < $1 $2 >.
Date:           MonNum '/' DayNum     < $2 $1 >.
~}
The target rule of the rule mapping:
~O~<MapTarget.lido~>~{
RULE: Date ::= DayNum MonNum END;
~}

The correctness of time spans is checked.
~O~<CalendarChecks1.lido~>~{
RULE: When ::= Time '-' Time COMPUTE
  IF (LE (Time[2], Time[1]),
     message (ERROR, "wrong time span", 0, COORDREF));
END;
~}

Attributes <code>DayNum.val</code> and <code>MonNum.val</code> are
introduced to propagate the values of the
terminal <code>Integer</code> into a context where they can be compared:
~O~<CalendarChecks2.lido~>~{
ATTR val:int;
RULE: DayNum ::= Integer COMPUTE DayNum.val = Integer; END;
RULE: MonNum ::= Integer COMPUTE MonNum.val = Integer; END;

RULE: Date ::= DayNum MonNum COMPUTE
  IF (wrongDate (DayNum.val, MonNum.val),
      message (ERROR, "wrong date", 0, COORDREF));  
END;

RULE: Date ::= Month DayNum COMPUTE
  IF (wrongDate (DayNum.val, Month),
      message (ERROR, "wrong date", 0, COORDREF));  
END;
~}

INSERT SOLUTIONS OF ASSIGNMENT 4 HERE:
Use a single FunnelWeb macro for each subtask.

Subtask 1:
Store and print the number of days in the year:
~O~<CalCheck-1.lido~>~{

~}

Subtask 2:
Compute the minimal date that occurs in the input, 
by explicit bottom-up propagation:
~O~<CalCheck-2.lido~>~{
~}

Subtask 3:
Deactivate the solution of subtask 2.
Use a CONSTITUENTS-WITH construct to compute the earliest date
~O~<CalCheck-3.lido~>~{~-

~}

Subtask 4:
Propagate the minimal date down to each Date and output it there:
~O~<CalCheck-4.lido~>~{

~}

Subtask 5:
Deactivate the solution of subtask 4.
Propagate the minimal date down to every Date using an 
INCLUDING construct, and output it there:
~O~<CalCheck-5.lido~>~{

~}

Subtask 6:
Deactivate the solutions of subtasks 1 to 5.
Use Symbol computations wherever possible.
~O~<CalCheck-6.lido~>~{

~}

~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*);

extern int dayInYear (int day, int mon);
extern int wrongDate (int day, int mon);
~}
~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;
    }
}

/* day in year =  day + (month-1)*28 + delta[month-1] 
   Delta values for a
non-leap year:
int delta[] = {0,3,3,6,8,11,13,16,19,21,24,26,29};
leap year:
int delta[] = {0,3,4,7,9,12,14,17,20,22,25,27,30};
*/
int delta[] = {0,3,4,7,9,12,14,17,20,22,25,27,30};

int dayInYear (int day, int month)
{
  if (day <= 0 || day > 31 || month <= 0 || month > 12)
    return 1;
  return day + (month-1)*28 + delta[month-1];
}

int wrongDate (int day, int month)
{ 
  if (day <= 0 || day > 31 || month <= 0 || month > 12)
    return 1;

  if (dayInYear (day, month) > month*28 + delta[month])
    return 1;

  return 0;
}
~}

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