diff tests/agcl/parsifal/date_p1.syn @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/agcl/parsifal/date_p1.syn	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,246 @@
+{/*
+  Date Translator
+  Copyright (c) 1995-1999, Parsifal Software
+  All Rights Reserved
+  See the file COPYING for license and usage terms.
+
+  This program illustrates the use of AnaGram to translate a number of
+  different representations of data into a common format. The example
+  used shows how to translate any of a number of standard formats for
+  entering a date into a single format for further processing.
+
+  The parser illustrated here recognizes six basic date formats, and
+  for each, will supply the current year if the year is not given. If
+  months are entered by name, they may be spelled out in full, or
+  abbreviated in the customary manner. Text may be upper or lower case.
+  Spaces or tabs may be used freely between the elements of the dates.
+  Some examples of the six formats, as applied to the date June 26,
+  1999, are as follows:
+
+    June 26  jun 26    June 26, 1999  JUN 26, 99    jun26,1999
+    26 June  26 jun    26 June 1999   26 JUN 99     26jun99
+    26-June  26-Jun    26-June-99     26-JUN-1999
+    6/26     6/26/99   6/26/1999
+    6-26     6-26-99   6-26-1999
+    6.26     6.26.99   6-26.1999
+    6/26/'99 6-26-'99  6.26.'99
+    6/26 '99 6-26 '99  6.26 '99
+    26/6     26/6/99   26/6/1999
+    26-6     26-6-99   26-6-1999
+    26.6     26.6.99   26.6.1999
+    26/6 '99 26-6 '99  26.6 '99
+    26 vi    26 vi 99  26 vi 1999     26 VI 99      26VI99
+    26 vi '99
+
+  If CHKDATE encounters a date of the form 2/3/99, it interrogates a
+  switch to determine whether to interpret this in the European manner
+  (March 2, 1999) or the American manner (February 3, 1999). Where the
+  form is obvious, as in 6/26/98 or 26/6/98 it ignores the switch.
+
+  CHKDATE also recognizes dates consisting of a month and year only.
+  Where month and year cannot be distinguished from month and day,
+  CHKDATE will assume month and day. When the year is given as a two
+  digit number, 0 to 49 are assumed to refer to the coming 21st century
+  and 50-99 are 20th century dates.  To force recognition as month and
+  year, use an apostrophe or use more than 2 digits for the year:  Aug
+  14 is the 14th of the month, Aug '14 is August 2014. For the
+  beginning of WWI, use Aug 1914
+
+  CHKDATE operates on a string in memory and stores the month, day and
+  year in the variables mon, day, and yr respectively.
+
+  checkDate() sets up the input pointer for CHKDATE and calls it.
+  checkDate() then checks for error and adds 2000 to the year if the
+  year specified was less than 50, otherwise it adds 1900 to the year
+  if the year specified was less than 100. It returns non-zero in case
+  of error and zero otherwise.
+
+  main() simply reads a string from stdin, and passes it to
+  checkDate(). If there is no error, it prints the date in a standard
+  format and loops forever.
+
+*/}
+
+[
+  pointer input                     // input string in memory
+  ~case sensitive                   // ignore case
+  disregard white space             // skip blanks and tabs
+  lexeme {month, roman, number}     // except inside names and numbers
+  ~diagnose errors                  // diagnostics not necessary
+  parser name = chkdate
+]
+
+
+eof         = 0                     // standard asciz string terminator
+white space = ' ' + '\t'            // blanks and tabs
+punctuation = '-' + '/' + '.'
+letter = 'a-z'
+
+i = 'i'
+v = 'v'
+x = 'x'
+
+date string $
+ -> date, eof
+
+date
+ // Feb 23, Feb 98
+ -> month:m, number:d  ={
+    if (d > days[m] || d==0) day=0, yr=d;  //  (change to accommodate d = 0, made Dec. 11/99)
+    else day=d, mon = m, yr = thisYear;
+ }
+
+ // Feb '23
+ -> month:m, '\'', number:y                   =day = 0, mon = m, yr = y;
+ -> month:m, '/', number:y                    =day = 0, mon = m, yr = y;    // Feb/99  (change made Dec. 11/99)
+
+ // Feb 17, 98
+ -> month:m, number:d, ',', number:y          =day = d, mon = m, yr = y;
+ -> month:m, number:d, '/', number:y          =day = d, mon = m, yr = y;   // Feb 17/99  (change made Dec. 11/99)
+
+ // 18 Aug
+ -> number:d, month                             =day = d, yr = thisYear;
+
+ // 18-Aug
+ -> number:d, punct, month                      =day = d, yr = thisYear;
+
+ // 18 aug '95
+ -> number:d, month, '\''?, number:y                   =day = d, yr = y;
+ -> number:d, month, '/'?, number:y                    =day = d, yr = y;   // 18 feb /95  (change made Dec. 11/99)
+
+
+ // 18-aug 75  or //18-aug 1923
+ -> number:d, punct, month,
+      matchPunctuation, '\''?, number:y                =day = d, yr = y;
+
+ // 6-11
+ -> number:m, punct, number:d                            =monthDay(m,d);
+
+ // 6 '99 or 6-'99
+ -> number:m, punct?, '\'', number:y            =day = 0, mon=m, yr = y;
+
+ // 6-6-44 or 6-6-'44
+ -> number:m, punct, number:d,
+      matchPunctuation, '\''?, number:y            =monthDayYear(m,d,y);
+
+ // 6-11'44
+ -> number:m, punct, number:d,
+      '\'', number:y                               =monthDayYear(m,d,y);
+
+ // 6 ix
+ -> number:d, roman:m                  =mon = m, day = d, yr = thisYear;
+
+ // 6 ix 94
+ -> number:d, roman:m, number:y               =mon = m, day = d, yr = y;
+
+ // vi 44 or vi '44
+ -> roman:m, '\''?, number:y                  =day = 0, mon = m, yr = y;
+
+(int) month
+month
+ -> "jan", letter?...          =1;
+ -> "feb", letter?...          =2;
+ -> "mar", letter?...          =3;
+ -> "apr", letter?...          =4;
+ -> "may"                      =5;
+ -> "jun", letter?...          =6;
+ -> "jul", letter?...          =7;
+ -> "aug", letter?...          =8;
+ -> "sep", letter?...          =9;
+ -> "oct", letter?...          =10;
+ -> "nov", letter?...          =11;
+ -> "dec", letter?...          =12;
+
+
+punct
+ -> punctuation: c                                       =matchChar = c;
+
+matchPunctuation
+ -> punctuation:c  ={
+    if (matchChar != c) PCB.exit_flag = AG_SYNTAX_ERROR_CODE;
+ }
+
+(int) number
+ -> '0-9':d                                                      =d-'0';
+ -> number:n, '0-9':d                                     =10*n + d-'0';
+
+
+(int) roman
+  -> i, x                       =9;
+  -> i, v                       =4;
+  -> units
+
+
+(int) units
+  -> i                          =1;
+  -> v                          =5;
+  -> x                          =10;
+  -> units:x, i                 =x+1;
+
+{
+
+#include <time.h>
+
+#define SYNTAX_ERROR
+
+int    days[13]  = {0,31,29,31,30,31,30,31,31,30,31,30,31};
+char  *monthName[13] = {NULL, "January", "February", "March", "April",
+          "May", "June", "July", "August", "September", "October",
+          "November", "December"};
+int    mon = 0, day = 0, yr = 0;
+int    thisYear;
+int    european = 0;
+int    matchChar = 0;
+
+void monthDay(int m, int d) {
+  if (m <= 12 && d > days[m]) day=0, mon = m, yr = d;
+  else if (m > 12 || european ) day = m, mon =d , yr = thisYear;
+  else mon=m, day=d, yr=thisYear;
+}
+
+void monthDayYear(int m, int d, int y) {
+  if (m > 12 || european) day = m, mon = d;
+  else mon = m, day = d;
+  yr = y;
+}
+
+int checkDate(char *input) {
+  PCB.pointer = (unsigned char *) input;
+  chkdate();
+  if (PCB.exit_flag != AG_SUCCESS_CODE) return 1;     /* fail on error */
+  if (mon > 12) return 1;
+  if (day > days[mon]) return 1;
+  if (yr < 50) yr += 2000;
+  else if (yr < 100 ) yr += 1900;
+  return 0;
+}
+
+int main(int argc, char *argv[]) {
+  char input[82];
+  time_t timeOfDay;
+  int k;
+
+  for (k = 1; k < argc; k++) {
+    switch (*argv[k]++) {
+    case '/':
+    case '-':
+      if (*argv[k] == 'e') european = 1;
+      break;
+    }
+  }
+/*  Determine current year */
+
+  timeOfDay = time(NULL);
+  thisYear = localtime(&timeOfDay)->tm_year;
+
+/* Loop forever, reading input strings and converting them */
+  while (1) {
+    gets(input);
+    if (feof(stdin)) break;
+    if (checkDate(input)) printf("%-30s Bad date\n", input);
+    else if (day) printf("%-30s %s %d, %d\n", input, monthName[mon], day, yr);
+    else printf("%-30s %s %d\n", input, monthName[mon], yr);
+  }
+  return 0;
+}
+}