git.fiddlerwoaroof.com
src/scalar.lisp
c816b8d5
 (in-package :cl-user)
0a47c44b
 (defpackage yaml.scalar
c816b8d5
   (:use :cl)
fe998b64
   (:export :parse-scalar :*yaml-11-integers*)
c816b8d5
   (:documentation "Parser for scalar values."))
0a47c44b
 (in-package :yaml.scalar)
c816b8d5
 
 ;;; Constants
 
 (defparameter +null+ nil
   "The NULL constant. Nil by default.")
 
 (defparameter +false+ nil
   "The falsehood constant. Nil by default.")
 
 ;;; Regular expressions or lists of names
 
23d3a77f
 (defparameter +quoted-scalar-styles+
   (list :single-quoted-scalar-style :double-quoted-scalar-style))
 
c816b8d5
 (defparameter +null-names+
   (list "null" "Null" "NULL" "~"))
 
 (defparameter +true-names+
   (list "true" "True" "TRUE"))
 
 (defparameter +false-names+
   (list "false" "False" "FALSE"))
 
 (defparameter +integer-scanner+
11d2ae66
   (ppcre:create-scanner "^([-+]?[0-9]+)$"))
c816b8d5
 
 (defparameter +octal-integer-scanner+
11d2ae66
   (ppcre:create-scanner "^0o([0-7]+)$"))
c816b8d5
 
 (defparameter +hex-integer-scanner+
11d2ae66
   (ppcre:create-scanner "^0x([0-9a-fA-F]+)$"))
c816b8d5
 
 (defparameter +float-scanner+
   (ppcre:create-scanner
11d2ae66
    "^[-+]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$"))
c816b8d5
 
eb71ef53
 (defparameter +nan-names+
   (list ".nan" ".NaN" ".NAN"))
 
0a47c44b
 (defparameter +positive-infinity-scanner+
11d2ae66
   (ppcre:create-scanner "^[+]?(\\.inf|\\.Inf|\\.INF)$"))
0a47c44b
 
 (defparameter +negative-infinity-scanner+
11d2ae66
   (ppcre:create-scanner "^-(\\.inf|\\.Inf|\\.INF)$"))
c816b8d5
 
 ;;; The actual parser
fe998b64
 (defvar *yaml-11-integers* nil)
 
 (defun parse-yaml-integer (string)
   (if (and *yaml-11-integers*
            (eql #\0 (elt string 0)))
       (if (every (lambda (it)
                    (member it '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7)))
                  string)
           (parse-integer string :radix 8)
           string)
       (parse-integer string)))
c816b8d5
 
23d3a77f
 (defun parse-scalar (string &optional (style :plain-scalar-style))
c816b8d5
   "Parse a YAML scalar string into a Lisp scalar value."
   (cond
23d3a77f
     ;; Quoted string
     ((member style +quoted-scalar-styles+)
      string)
c816b8d5
     ;; Null
     ((member string +null-names+ :test #'equal)
      +null+)
     ;; Truth and falsehood
     ((member string +true-names+ :test #'equal)
      t)
     ((member string +false-names+ :test #'equal)
      +false+)
     ;; Integers
0a47c44b
     ((ppcre:scan +integer-scanner+ string)
fe998b64
      (parse-yaml-integer string))
0a47c44b
     ((ppcre:scan +octal-integer-scanner+ string)
      (parse-integer (subseq string 2) :radix 8))
     ((ppcre:scan +hex-integer-scanner+ string)
      (parse-integer (subseq string 2) :radix 16))
c816b8d5
     ;; Floating-point numbers
c4b97458
     ((ppcre:scan +float-scanner+ string)
      (parse-number:parse-real-number string))
0a47c44b
     ;; Special floats
c816b8d5
     ((member string +nan-names+ :test #'equal)
0a47c44b
      (yaml.float:not-a-number))
     ((ppcre:scan +positive-infinity-scanner+ string)
      (yaml.float:positive-infinity))
     ((ppcre:scan +negative-infinity-scanner+ string)
      (yaml.float:negative-infinity))
     ;; Just a string
c816b8d5
     (t
      string)))