-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.lisp
156 lines (136 loc) · 4.98 KB
/
parser.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
(in-package #:sawyer)
;;; TOML entries parser
;;; Parses a toml document into a set of the following kind of entries
;;; key-value : a key value pair, i.e. name = "sergio"
;;; table header : a regular table header, i.e. [person.info]
;;; array table header : an array table header, i.e [[social_media_account]]
(defstruct toml-key-value-entry key value)
(defstruct toml-table-header-entry headers)
(defstruct toml-array-table-header-entry headers)
(defstruct toml-array-entry entries)
(defstruct toml-inline-table-entry entries)
;;; primitive types
(defstruct toml-integer value)
(defstruct toml-float value)
(defstruct toml-string value type) ; :bare :literal :regular :literal-ml, :regular-ml
(defstruct toml-boolean value) ; :bare :literal :regular :literal-ml, :regular-ml
(defstruct toml-offset-datetime original-value)
(defstruct toml-local-datetime original-value)
(defstruct toml-local-date original-value)
(defstruct toml-local-time original-value)
(defun str-concat (list)
"Concatenates a list of strings or characters"
(format nil "~{~A~}" list))
(define-parser toml-document-parser
"Parse a TOML document (as produced by the lexer)"
(.do
(.skip-many (.is :newline))
(.let* ((body (.sep-by
(.or
'toml-table-header-entry-parser
'toml-array-table-header-entry-parser
'toml-key-value-entry-parser
)
(.many1 (.is :newline))
)))
(.do
(.skip-many (.is :newline))
(.eof)
(.ret body)))))
(define-parser toml-table-header-entry-parser
(.between
(.is :bracket-open)
(.is :bracket-close)
(.let* ((headers (.sep-by 'toml-key-parser (.is :dot))))
(.ret (make-toml-table-header-entry :headers headers)))))
(define-parser toml-array-table-header-entry-parser
(.between
(.is :double-bracket-open)
(.is :double-bracket-close)
(.let* ((headers (.sep-by 'toml-key-parser (.is :dot))))
(.ret (make-toml-array-table-header-entry :headers headers)))))
(define-parser toml-key-parser
(.or
'toml-literal-string-parser
'toml-string-parser
'toml-bare-keyword-parser))
(define-parser toml-literal-string-parser
(.let* ((string (.is :literal-string)))
(.ret (make-toml-string :value string :type :literal))))
(define-parser toml-bare-keyword-parser
(.let* ((string (.is :bare-keyword)))
(.ret (make-toml-string :value string :type :bare))))
(define-parser toml-string-parser
(.between
(.is :string)
(.is :string)
(.let* ((parts (.many
(.is :chars))))
(.ret (make-toml-string :value (str-concat parts) :type :regular))
)))
(define-parser toml-ml-literal-string-parser
(.between
(.is :multi-line-literal-string)
(.is :multi-line-literal-string)
(.let* ((parts (.many
(.is :chars))))
(.ret (make-toml-string :value (str-concat parts) :type :literal-ml))
)))
(define-parser toml-ml-string-parser
(.between
(.is :multi-line-string)
(.is :multi-line-string)
(.let* ((parts (.many
(.is :chars))))
(.ret (make-toml-string :value (str-concat parts) :type :regular-ml))
)))
(define-parser toml-array-parser
(.between
(.is :bracket-open)
(.is :bracket-close)
(.let* ((entries (.sep-by 'toml-value-parser (.is :comma))))
(.do
(.skip-many (.is :comma))
(.ret (make-toml-array-entry :entries entries))) )))
(define-parser toml-inline-table-parser
(.between
(.is :curly-brace-open)
(.is :curly-brace-close)
(.let* ((entries (.sep-by 'toml-key-value-entry-parser (.is :comma))))
(.ret (make-toml-inline-table-entry :entries entries)))))
(define-parser toml-value-parser
(.or
(.let* ((value (.is :number)))
(.ret
(if (integerp value)
(make-toml-integer :value value)
(make-toml-float :value value))))
(.let* ((value (.is :offset-date-time)))
(.ret (make-toml-offset-datetime :original-value value)))
(.let* ((value (.is :local-date-time)))
(.ret (make-toml-local-datetime :original-value value)))
(.let* ((value (.is :local-date)))
(.ret (make-toml-local-date :original-value value)))
(.let* ((value (.is :local-time)))
(.ret (make-toml-local-time :original-value value)))
(.let* ((value (.is :true)))
(.ret (make-toml-boolean :value t)))
(.let* ((value (.is :false)))
(.ret (make-toml-boolean :value nil)))
'toml-string-parser
'toml-literal-string-parser
'toml-ml-string-parser
'toml-ml-literal-string-parser
'toml-array-parser
'toml-inline-table-parser
))
(define-parser toml-key-value-entry-parser
(.let* ((k 'toml-key-parser)
(v (.do (.is :equal) 'toml-value-parser)))
(.ret (make-toml-key-value-entry :key k :value v))))
(defun parse-toml-file-to-entries (file)
(parse-toml-string-to-entries (read-file-into-string file)))
(defun parse-toml-string-to-entries (string)
(with-lexer (lexer 'toml-lexer string)
(with-token-reader (next-token lexer)
(parse 'toml-document-parser next-token))))