-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlexer-strings.lisp
55 lines (51 loc) · 1.78 KB
/
lexer-strings.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
(in-package #:sawyer)
;;; Standard string within by "s
(define-lexer string-lexer (s)
("\"" (pop-lexer s :string))
("\\t" (values :chars #\tab))
("\\\\" (values :chars #\\))
("\\\"" (values :chars #\"))
("\\f" (values :chars #\formfeed))
("\\b" (values :chars #\backspace))
("\\n" (values :chars #\newline))
("\\r" (values :chars #\return))
("\\u(%x%x%x%x)" (values :chars (parse-to-unicode $1)))
("\\U(%x%x%x%x%x%x%x%x)" (values :chars (parse-to-unicode $1)))
("[^\\\"%n]+" (values :chars $$))
("$" (error "Unterminated string")))
;;; Multi line string within """s
(define-lexer multi-line-string-lexer (s)
("\"\"\"" (pop-lexer s :multi-line-string))
("\\%s*%n[%s%n]*" :next-token)
("\"" (values :chars #\"))
("\\t" (values :chars #\tab))
("\\\\" (values :chars #\\))
("\\\"" (values :chars #\"))
("\\f" (values :chars #\formfeed))
("\\b" (values :chars #\backspace))
("\\n" (values :chars #\newline))
("\\r" (values :chars #\return))
("\\u(%x%x%x%x)" (parse-to-unicode $1))
("\\U(%x%x%x%x%x%x%x%x)" (parse-to-unicode $1))
("[^\\\"]+" (values :chars $$))
("$" (error "unterminated string")))
;;; Multi line string literal within '''s
(define-lexer multi-line-literal-string-lexer (s)
("'''" (pop-lexer s :multi-line-literal-string))
;; escaped characters
("'" (values :chars #\'))
;; all other characters
("[^']+" (values :chars $$))
;; don't reach the end of file or line
("$" (error "unterminated string")))
;; parse to unicode
(defun parse-to-unicode (str)
(let ((scalar (parse-integer str :radix 16)))
(if (or
(and (>= scalar 0)
(<= scalar #xD7FF))
(and (>= scalar #xE000)
(<= scalar #x10FFFF)))
(code-char scalar)
(error "not a valid unicode scalar value")
)))