git.fiddlerwoaroof.com
Browse code

Parser enhancements, adding converters for tagged objects and handling quoted scalar values.

Jason Melbye authored on 20/08/2016 02:03:43
Showing 2 changed files
... ...
@@ -6,10 +6,44 @@
6 6
   (:import-from :libyaml.macros
7 7
                 :with-parser
8 8
                 :with-event)
9
-  (:export :parse-string)
9
+  (:export :parse-string
10
+	   :register-scalar-converter
11
+	   :register-sequence-converter
12
+	   :register-mapping-converter)
10 13
   (:documentation "The YAML parser."))
11 14
 (in-package :yaml.parser)
12 15
 
16
+(defvar +scalar-converters+ (make-hash-table :test #'equalp))
17
+(defvar +sequence-converters+ (make-hash-table :test #'equalp))
18
+(defvar +mapping-converters+ (make-hash-table :test #'equalp))
19
+
20
+(defun scalar-converter (tag)
21
+  (gethash tag +scalar-converters+))
22
+
23
+(defun convert-scalar (string tag &optional (style :plain-scalar-stype))
24
+  (let ((converter (scalar-converter tag)))
25
+    (if converter
26
+	(funcall converter string)
27
+	(yaml.scalar:parse-scalar string style))))
28
+
29
+(defun sequence-converter (tag)
30
+  (gethash tag +sequence-converters+))
31
+
32
+(defun convert-sequence (list tag)
33
+  (let ((converter (sequence-converter tag)))
34
+    (if converter
35
+	(funcall converter list)
36
+	list)))
37
+
38
+(defun mapping-converter (tag)
39
+  (gethash tag +mapping-converters+))
40
+
41
+(defun convert-mapping (hashtable tag)
42
+  (let ((converter (mapping-converter tag)))
43
+    (if converter
44
+	(funcall converter hashtable)
45
+	hashtable)))
46
+
13 47
 ;;; The parser
14 48
 
15 49
 (defun signal-reader-error (parser)
... ...
@@ -94,31 +128,32 @@
94 128
          t)
95 129
         |#
96 130
         ;; Scalar
97
-        ((:scalar-event &key anchor tag value)
98
-         (declare (ignore anchor tag))
131
+        ((:scalar-event &key anchor tag value length plain-implicit quoted-implicit style)
132
+         (declare (ignore anchor length plain-implicit quoted-implicit))
99 133
          (setf (first contexts)
100 134
                (append (first contexts)
101
-                       (list (yaml.scalar:parse-scalar value)))))
135
+                       (list (convert-scalar value tag style)))))
102 136
         ;; Sequence start event
103
-        ((:sequence-start-event &key anchor tag)
104
-         (declare (ignore anchor tag))
105
-         (push (list) contexts))
137
+        ((:sequence-start-event &key anchor tag implicit style)
138
+         (declare (ignore anchor implicit style))
139
+         (push (list tag) contexts))
106 140
         ;; Mapping start event
107
-        ((:mapping-start-event &key anchor tag)
108
-         (declare (ignore anchor tag))
109
-         (push (list) contexts))
141
+        ((:mapping-start-event &key anchor tag implicit style)
142
+         (declare (ignore anchor implicit style))
143
+         (push (list tag) contexts))
110 144
         ;; End events
111 145
         ((:sequence-end-event)
112
-         (let ((con (pop contexts)))
146
+         (destructuring-bind (tag &rest seq) (pop contexts)
113 147
            (setf (first contexts)
114 148
                  (append (first contexts)
115
-                         (list con)))))
149
+                         (list (convert-sequence seq tag))))))
116 150
         ((:mapping-end-event)
117
-         (let ((con (pop contexts)))
151
+         (destructuring-bind (tag &rest plist) (pop contexts)
118 152
            (setf (first contexts)
119 153
                  (append (first contexts)
120
-                         (list
121
-                          (alexandria:plist-hash-table con :test #'equal))))))
154
+                         (list (convert-mapping
155
+				(alexandria:plist-hash-table plist :test #'equalp)
156
+				tag))))))
122 157
         ;; Do nothing
123 158
         ((t &rest rest)
124 159
          (declare (ignore rest)))))
... ...
@@ -126,5 +161,14 @@
126 161
 
127 162
 ;;; The public interface
128 163
 
164
+(defun register-scalar-converter (tag converter)
165
+  (setf (gethash tag +scalar-converters+) converter))
166
+
167
+(defun register-sequence-converter (tag converter)
168
+  (setf (gethash tag +sequence-converters+) converter))
169
+
170
+(defun register-mapping-converter (tag converter)
171
+  (setf (gethash tag +mapping-converters+) converter))
172
+
129 173
 (defun parse-string (yaml-string)
130 174
   (parse-tokens (parse-yaml yaml-string)))
... ...
@@ -15,6 +15,9 @@
15 15
 
16 16
 ;;; Regular expressions or lists of names
17 17
 
18
+(defparameter +quoted-scalar-styles+
19
+  (list :single-quoted-scalar-style :double-quoted-scalar-style))
20
+
18 21
 (defparameter +null-names+
19 22
   (list "null" "Null" "NULL" "~"))
20 23
 
... ...
@@ -48,9 +51,12 @@
48 51
 
49 52
 ;;; The actual parser
50 53
 
51
-(defun parse-scalar (string)
54
+(defun parse-scalar (string &optional (style :plain-scalar-style))
52 55
   "Parse a YAML scalar string into a Lisp scalar value."
53 56
   (cond
57
+    ;; Quoted string
58
+    ((member style +quoted-scalar-styles+)
59
+     string)
54 60
     ;; Null
55 61
     ((member string +null-names+ :test #'equal)
56 62
      +null+)