lalrpop/doc/pascal/sched.pas
Niko Matsakis 78779edfa9 add preliminary Pascal grammar and test harness
Caveats: requires uppercase keywords, cannot handle
comments, somewhat dated grammar
2016-03-22 04:42:17 -04:00

368 lines
6.6 KiB
ObjectPascal

PROGRAM a1 (input,output);
CONST
NotScheduled = ' ';
EmployeeMaxLen = 8;
FirstHour = 8;
LastHour = 17;
PastLastHour = 18;
TableDayWidth = 9;
TYPE
EmployeeType = ARRAY [EmployeeMaxLen] OF string;
HourType = 8..17;
ScheduleType = ARRAY [HourType, DayType] OF EmployeeType;
HourScanType = 8..18;
VAR
Schedule: ScheduleType;
KeepRunning: boolean;
Command: string;
PROCEDURE ReadString(VAR Str: string);
VAR
Ch: char;
BEGIN
Ch := ' ';
WHILE (Ch = ' ') AND NOT eoln DO
read(Ch);
IF Ch = ' ' THEN
Str := ''
ELSE
BEGIN
Str := '';
WHILE (Ch <> ' ') AND NOT eoln DO
BEGIN
Str := Str + Ch;
read(Ch)
END;
IF Ch <> ' ' THEN
Str := Str + Ch
END
END;
PROCEDURE ReadSchedClrArgs(
VAR StartDay, EndDay: DayType;
VAR StartHour, EndHour: HourType;
VAR Error: boolean);
VAR
InputHour: integer;
FUNCTION MapTo24(Hour: integer): HourType;
CONST
LastPM = 5;
BEGIN
IF Hour <= LastPM THEN
MapTo24 := Hour + 12
ELSE
MapTo24 := Hour
END;
BEGIN
ReadDay(input, StartDay);
ReadDay(input, EndDay);
IF (StartDay <> BadDay) AND (EndDay <> BadDay) THEN
BEGIN
read(InputHour);
StartHour := MapTo24(InputHour);
read(InputHour);
EndHour := MapTo24(InputHour);
Error := FALSE
END
ELSE
Error := TRUE;
readln
END;
PROCEDURE WriteDaysHeader;
CONST
DaysHeadMoveOver = 6;
AllowForDay = 3;
VAR
Day: DayType;
BEGIN
write(' ': DaysHeadMoveOver);
FOR Day := Sun TO Sat DO
BEGIN
write('[ ');
WriteDay(output, Day);
write(' ]', ' ': TableDayWidth - AllowForDay - 4)
END;
writeln
END;
FUNCTION SchedLegal(
VAR Schedule: ScheduleType;
StartDay, EndDay: DayType;
FirstHour, LastHour:
HourType): boolean;
VAR
ConflictFound: boolean;
DayScan: DayType;
HourScan: HourScanType;
BEGIN
DayScan := StartDay;
ConflictFound := FALSE;
REPEAT
HourScan := FirstHour;
WHILE NOT ConflictFound AND
(HourScan <= LastHour) DO BEGIN
ConflictFound :=
Schedule[HourScan, DayScan] <> NotScheduled;
HourScan := HourScan + 1
END;
DayScan := succ(DayScan)
UNTIL ConflictFound OR (DayScan > EndDay);
SchedLegal := NOT ConflictFound
END;
PROCEDURE SetSchedPart(
VAR Schedule: ScheduleType;
Employee: EmployeeType;
StartDay, EndDay: DayType;
FirstHour, LastHour:
HourType);
VAR
DayScan: DayType;
HourScan: HourType;
BEGIN
FOR DayScan := StartDay TO EndDay DO
FOR HourScan := FirstHour TO LastHour DO
Schedule[HourScan, DayScan] := Employee
END;
PROCEDURE DoSched(
VAR Schedule: ScheduleType);
VAR
Employee: EmployeeType;
StartDay, EndDay: DayType;
StartHour, EndHour: HourType;
Error: boolean;
BEGIN
ReadString(Employee);
ReadSchedClrArgs(StartDay, EndDay, StartHour, EndHour, Error);
IF Error THEN
writeln('*** Un-recognized day code. ',
'Command not performed. ***')
ELSE
IF SchedLegal(Schedule, StartDay, EndDay,
StartHour, EndHour) THEN
BEGIN
SetSchedPart(Schedule, Employee,
StartDay, EndDay, StartHour, EndHour);
writeln('>>> ', Employee, ' scheduled. <<<')
END
ELSE
writeln('*** Conflicts with existing schedule. ',
'Command not performed. ***')
END;
PROCEDURE DoClear(
VAR Schedule: ScheduleType);
VAR
StartDay, EndDay: DayType;
StartHour, EndHour: HourType;
Error: boolean;
BEGIN
ReadSchedClrArgs(StartDay, EndDay, StartHour, EndHour, Error);
IF Error THEN
writeln('*** Un-recognized day code. ',
'Command not performed. ***')
ELSE
BEGIN
SetSchedPart(Schedule, NotScheduled, StartDay, EndDay,
StartHour, EndHour);
writeln('>>> Clear performed. <<<');
END
END;
PROCEDURE DoUnsched(
VAR Schedule: ScheduleType);
VAR
Employee: EmployeeType;
Day: DayType;
Hour: integer;
Found: boolean;
BEGIN
readln(Employee);
Found := FALSE;
FOR Day := Sun TO Sat DO
FOR Hour := FirstHour TO LastHour DO
IF Schedule[Hour, Day] = Employee THEN
BEGIN
Schedule[Hour, Day] := NotScheduled;
Found := TRUE
END;
IF Found THEN
write('>>> ', Employee, ' removed from schedule. <<<')
ELSE
write('>>> ', Employee,
' was not on the schedule. <<<')
END;
PROCEDURE DoPrint(
VAR Schedule: ScheduleType);
VAR
Hour: HourType;
Day: DayType;
FUNCTION Map24to12(HourType: HourType): integer;
BEGIN
IF Hour < 13 THEN
Map24to12 := Hour
ELSE
Map24to12 := Hour - 12
END;
BEGIN
readln;
WriteDaysHeader;
FOR Hour := FirstHour TO LastHour DO
BEGIN
write(Map24to12(Hour):2, ':00 ');
FOR Day := Sun TO Sat DO
write(Schedule[Hour, Day],
' ': TableDayWidth - length(Schedule[Hour, Day]));
writeln
END
END;
PROCEDURE DoTotal(
VAR Schedule: ScheduleType);
VAR
Employee: EmployeeType;
Day: DayType;
Hour: integer;
Total: integer;
BEGIN
readln(Employee);
Total := 0;
FOR Day := Sun TO Sat DO
FOR Hour := FirstHour TO LastHour DO
IF Schedule[Hour, Day] = Employee THEN
Total := Total + 1;
writeln('>>> ', Employee,
' is scheduled for ', Total:1, ' hours. <<<<')
END;
BEGIN
SetSchedPart(Schedule, NotScheduled, Sun, Sat, FirstHour, LastHour);
write('==> ');
ReadString(Command);
KeepRunning := TRUE;
WHILE KeepRunning DO
BEGIN
IF Command = 'sched' THEN
DoSched(Schedule)
ELSE IF Command = 'clear' THEN
DoClear(Schedule)
ELSE IF Command = 'unsched' THEN
DoUnsched(Schedule)
ELSE IF Command = 'print' THEN
DoPrint(Schedule)
ELSE IF Command = 'total' THEN
DoTotal(Schedule)
ELSE IF Command = 'quit' THEN
BEGIN
writeln;
writeln('>>> Program terminating. <<<');
KeepRunning := FALSE
END
ELSE
BEGIN
readln;
writeln;
writeln('*** Command ', Command,
' not recognized. ***');
END;
write('==> ');
ReadString(Command)
END
END.