git.fiddlerwoaroof.com
Browse code

Subdividing parser.lisp

fiddlerwoaroof authored on 28/04/2016 03:02:49
Showing 3 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,148 @@
1
+(eval-when (:compile-toplevel :load-toplevel :execute)
2
+  ;; make sure these classes am ready to go!
3
+  (defclass day-entry ()
4
+    ((date :initarg :date)
5
+     (records :initarg :records)))
6
+
7
+  (defclass time-record ()
8
+    ((client :initarg :client)
9
+     (ranges :initarg :ranges)
10
+     (memo :initarg :memo)))
11
+
12
+  (defclass time-obj ()
13
+    ((hour :initarg :hour)
14
+     (minute :initarg :minute)
15
+     (second :initarg :second)))
16
+
17
+  (defclass date-obj ()
18
+    ((day-of-week :initarg :day-of-week)
19
+     (year :initarg :year)
20
+     (month :initarg :month)
21
+     (day :initarg :day)))
22
+
23
+  (defclass time-mod ()
24
+    ((amount :initarg :amount)
25
+     (unit :initarg :unit :type (member '(:hour :minute))))))
26
+
27
+(defgeneric unparse (token &optional stream)
28
+  (:method ((token time-mod) &optional stream)
29
+   (with-slots (amount unit) token
30
+     (format stream "~@d~a" amount unit)))
31
+  (:method ((token date-obj)  &optional stream)
32
+   (with-slots (day-of-week year month day) token
33
+     (format stream "~a ~2,'0d-~2,'0d-~2,'0d" day-of-week year month day)))
34
+  (:method ((token time-obj) &optional stream)
35
+   (with-slots (hour minute second) token
36
+     (format stream "~2,'0d:~2,'0d:~2,'0d" hour minute second)))
37
+  (:method ((token time-record) &optional stream)
38
+   (with-slots (client ranges memo) token
39
+     (format stream "~&   start@~{~a~^,~}~%   ~a: ~a~%"
40
+             (loop for (start . rest) in ranges
41
+                   for end = (car rest)
42
+                   for mod = (cadr rest)
43
+                   collect (format nil "~a--~a~a"
44
+                                   (unparse start)
45
+                                   (if end (unparse end) "")
46
+                                   (if mod (unparse mod) "")))
47
+             client memo)))
48
+  (:method ((token day-entry) &optional stream)
49
+   (with-slots (date records) token
50
+     (format stream "~&-- ~a~&~{~a~}~%"
51
+             (unparse date)
52
+             (mapcar #'unparse records)))))
53
+
54
+(make-simple-equality day-entry :test ==)
55
+(make-simple-equality time-record :test ==)
56
+(make-simple-equality time-obj :test eql)
57
+(make-equality date-obj
58
+  (day-of-week ==)
59
+  (year) (month) (day))
60
+(make-simple-equality time-mod :test eql)
61
+
62
+(defun make-day-entry (date records)
63
+  (make-instance 'day-entry :date date :records records))
64
+
65
+(defun make-time-record (ranges memo)
66
+  (make-instance 'time-record :client (car memo) :ranges ranges :memo (cadr memo)))
67
+
68
+(defun make-time-mod (amnt unt)
69
+  (setf unt (string-downcase unt))
70
+  (make-instance 'time-mod
71
+                 :amount amnt
72
+                 :unit (string-ecase unt
73
+                         ("min" :minute)
74
+                         ("mins" :minute)
75
+                         ("minutes" :minute)
76
+                         ("minute" :minute)
77
+                         ("hr" :hour)
78
+                         ("hrs" :hour)
79
+                         ("hour" :hour)
80
+                         ("hours" :hour))))
81
+
82
+(define-condition parsing-error (parse-error)
83
+  ((failed-chunk :initarg :failed-chunk :reader failed-chunk)))
84
+
85
+(define-condition invalid-whitespace (parsing-error) ()
86
+  (:report (lambda (condition stream)
87
+             (format stream "~s is invalid whitespace"
88
+                     (map 'list #'char-code (failed-chunk condition))))))
89
+
90
+(define-condition invalid-day-of-week (parsing-error)
91
+  ((day-of-week :initarg :day-of-week :reader day-of-week))
92
+  (:report (lambda (condition stream)
93
+             (format stream "~s is not a valid day of the week"
94
+                     (day-of-week condition)))))
95
+
96
+(defun make-date-obj (day-of-week year month day)
97
+  (let ((day-of-week (subseq day-of-week 0 3)))
98
+    (if (member day-of-week
99
+                '("Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun")
100
+                :test #'string-equal)
101
+      (make-instance 'date-obj :day-of-week day-of-week :year year :month month :day day)
102
+      (error 'invalid-day-of-week :day-of-week day-of-week))))
103
+
104
+(defun make-time-obj (hour minute &optional second)
105
+  (make-instance 'time-obj :hour hour :minute minute :second second))
106
+
107
+(defmethod-and-inverse == ((date-obj date-obj) (list list))
108
+  (with-slots (day-of-week year month day) date-obj
109
+    (every #'== (list day-of-week year month day) list)))
110
+
111
+(defmethod-and-inverse == ((time-obj time-obj) (list list))
112
+  (with-slots (hour minute second) time-obj
113
+    (every #'== (list hour minute second) list)))
114
+
115
+(define-printer (date-obj s)
116
+  ((with-slots (day-of-week year month day) date-obj
117
+     (format s "~a, ~2,'0d/~2,'0d/~2,'0d"
118
+             (subseq (string-capitalize day-of-week) 0 3)
119
+             year month day)))
120
+  ((with-slots (day-of-week year month day) date-obj
121
+    (format s "~a, ~2,'0d/~2,'0d/~2,'0d"
122
+            (subseq (string-capitalize day-of-week) 0 3)
123
+            year month day))))
124
+
125
+(define-printer (time-obj s)
126
+  ((with-slots (hour minute second) time-obj
127
+    (format s "~2,'0d:~2,'0d:~2,'0d"  hour minute second)))
128
+  ((with-slots (hour minute second) time-obj
129
+    (format s "~2,'0d:~2,'0d:~2,'0d"  hour minute second))))
130
+
131
+(define-printer (day-entry s)
132
+  ((with-slots (date records) day-entry
133
+    (format s "~d records for ~s" (length records) date)))
134
+  ((with-slots (date records) day-entry
135
+    (format s "~d records for ~s" (length records) date))))
136
+
137
+(define-printer (time-record s)
138
+  ((with-slots (client) time-record
139
+    (format s "For ~s" client)))
140
+  ((with-slots (client) time-record
141
+    (format s "For ~s" client))))
142
+
143
+(define-printer (time-mod s)
144
+  ((with-slots (amount unit) time-mod
145
+    (format s "~s ~s" amount unit)))
146
+  ((with-slots (amount unit) time-mod
147
+    (format s "~s ~s" amount unit))))
148
+
... ...
@@ -1,156 +1,5 @@
1 1
 (in-package #:tempores.parser)
2 2
 
3
-(eval-when (:compile-toplevel :load-toplevel :execute)
4
-  ;; make sure these classes am ready to go!
5
-  (defclass day-entry ()
6
-    ((date :initarg :date)
7
-     (records :initarg :records)))
8
-
9
-  (defclass time-record ()
10
-    ((client :initarg :client)
11
-     (ranges :initarg :ranges)
12
-     (memo :initarg :memo)))
13
-
14
-  (defclass time-obj ()
15
-    ((hour :initarg :hour)
16
-     (minute :initarg :minute)
17
-     (second :initarg :second)))
18
-
19
-  (defclass date-obj ()
20
-    ((day-of-week :initarg :day-of-week)
21
-     (year :initarg :year)
22
-     (month :initarg :month)
23
-     (day :initarg :day)))
24
-
25
-  (defclass time-mod ()
26
-    ((amount :initarg :amount)
27
-     (unit :initarg :unit :type (member '(:hour :minute))))))
28
-
29
-(defgeneric unparse (token &optional stream)
30
-  (:method ((token time-mod) &optional stream)
31
-   (with-slots (amount unit) token
32
-     (format stream "~@d~a" amount unit)))
33
-  (:method ((token date-obj)  &optional stream)
34
-   (with-slots (day-of-week year month day) token
35
-     (format stream "~a ~2,'0d-~2,'0d-~2,'0d" day-of-week year month day)))
36
-  (:method ((token time-obj) &optional stream)
37
-   (with-slots (hour minute second) token
38
-     (format stream "~2,'0d:~2,'0d:~2,'0d" hour minute second)))
39
-  (:method ((token time-record) &optional stream)
40
-   (with-slots (client ranges memo) token
41
-     (format stream "~&   start@~{~a~^,~}~%   ~a: ~a~%"
42
-             (loop for (start . rest) in ranges
43
-                   for end = (car rest)
44
-                   for mod = (cadr rest)
45
-                   collect (format nil "~a--~a~a"
46
-                                   (unparse start)
47
-                                   (if end (unparse end) "")
48
-                                   (if mod (unparse mod) "")))
49
-             client memo)))
50
-  (:method ((token day-entry) &optional stream)
51
-   (with-slots (date records) token
52
-     (format stream "~&-- ~a~&~{~a~}~%"
53
-             (unparse date)
54
-             (mapcar #'unparse records)))))
55
-
56
-
57
-(make-simple-equality day-entry :test ==)
58
-(make-simple-equality time-record :test ==)
59
-(make-simple-equality time-obj :test eql)
60
-(make-equality date-obj
61
-  (day-of-week ==)
62
-  (year) (month) (day))
63
-(make-simple-equality time-mod :test eql)
64
-
65
-
66
-(defun make-day-entry (date records)
67
-  (make-instance 'day-entry :date date :records records))
68
-
69
-(defun make-time-record (ranges memo)
70
-  (make-instance 'time-record :client (car memo) :ranges ranges :memo (cadr memo)))
71
-
72
-(defun make-time-mod (amnt unt)
73
-  (setf unt (string-upcase unt))
74
-  (make-instance 'time-mod
75
-                 :amount amnt
76
-                 :unit (string-ecase unt
77
-                         ("min" :MINUTE)
78
-                         ("mins" :MINUTE)
79
-                         ("minutes" :MINUTE)
80
-                         ("minute" :MINUTE)
81
-                         ("hr" :HOUR)
82
-                         ("hrs" :HOUR)
83
-                         ("hour" :HOUR)
84
-                         ("hours" :HOUR))))
85
-
86
-(define-condition parsing-error (parse-error)
87
-  ((failed-chunk :initarg :failed-chunk :reader failed-chunk)))
88
-
89
-(define-condition invalid-whitespace (parsing-error) ()
90
-  (:report (lambda (condition stream)
91
-             (format stream "~s is invalid whitespace"
92
-                     (map 'list #'char-code (failed-chunk condition))))))
93
-
94
-
95
-(define-condition invalid-day-of-week (parsing-error)
96
-  ((day-of-week :initarg :day-of-week :reader day-of-week))
97
-  (:report (lambda (condition stream)
98
-             (format stream "~s is not a valid day of the week"
99
-                     (day-of-week condition)))))
100
-
101
-(defun make-date-obj (day-of-week year month day)
102
-  (let ((day-of-week (subseq day-of-week 0 3)))
103
-    (if (member day-of-week
104
-                '("Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun")
105
-                :test #'string-equal)
106
-      (make-instance 'date-obj :day-of-week day-of-week :year year :month month :day day)
107
-      (error 'invalid-day-of-week :day-of-week day-of-week))))
108
-
109
-(defun make-time-obj (hour minute &optional second)
110
-  (make-instance 'time-obj :hour hour :minute minute :second second))
111
-
112
-(defmethod-and-inverse == ((date-obj date-obj) (list list))
113
-  (with-slots (day-of-week year month day) date-obj
114
-    (every #'== (list day-of-week year month day) list)))
115
-
116
-(defmethod-and-inverse == ((time-obj time-obj) (list list))
117
-  (with-slots (hour minute second) time-obj
118
-    (every #'== (list hour minute second) list)))
119
-
120
-(define-printer (date-obj s)
121
-  ((with-slots (day-of-week year month day) date-obj
122
-     (format s "~a, ~2,'0d/~2,'0d/~2,'0d"
123
-             (subseq (string-capitalize day-of-week) 0 3)
124
-             year month day)))
125
-  ((with-slots (day-of-week year month day) date-obj
126
-    (format s "~a, ~2,'0d/~2,'0d/~2,'0d"
127
-            (subseq (string-capitalize day-of-week) 0 3)
128
-            year month day))))
129
-
130
-(define-printer (time-obj s)
131
-  ((with-slots (hour minute second) time-obj
132
-    (format s "~2,'0d:~2,'0d:~2,'0d"  hour minute second)))
133
-  ((with-slots (hour minute second) time-obj
134
-    (format s "~2,'0d:~2,'0d:~2,'0d"  hour minute second))))
135
-
136
-(define-printer (day-entry s)
137
-  ((with-slots (date records) day-entry
138
-    (format s "~d records for ~s" (length records) date)))
139
-  ((with-slots (date records) day-entry
140
-    (format s "~d records for ~s" (length records) date))))
141
-
142
-(define-printer (time-record s)
143
-  ((with-slots (client) time-record
144
-    (format s "For ~s" client)))
145
-  ((with-slots (client) time-record
146
-    (format s "For ~s" client))))
147
-
148
-(define-printer (time-mod s)
149
-  ((with-slots (amount unit) time-mod
150
-    (format s "~s ~s" amount unit)))
151
-  ((with-slots (amount unit) time-mod
152
-    (format s "~s ~s" amount unit))))
153
-
154 3
 (defun .digit ()
155 4
   (.is #'digit-char-p))
156 5
 
... ...
@@ -28,6 +28,7 @@
28 28
   :components ((:file "package")
29 29
                (:file "generic-equals")
30 30
                (:file "macros")
31
+               (:file "parser-classes")
31 32
                (:file "parser")
32 33
                (:file "test-parser")
33 34
                (:file "mvc")