# Part of bqn-libs: https://github.com/mlochbaum/bqn-libs # 0-BSD License # JSON: JavaScript Object Notation ⟨ Parse # JSON string to BQN Export # BQN value to JSON (also Parse⁼) ⟩⇐ # JSON numbers, strings, and lists correspond directly to BQN # Objects are represented as keys≍values # true, false, null are represented as <"true", <"false", <"null" # An empty list exports as "" if its fill is a space and [] otherwise ⟨Consts, ExportConst⟩ ← { val ← <¨ name ← "true"‿"false"‿"null" Consts ⇐ { i ← name ⊐ 𝕩 "Unknown constant" 𝕎 i = ≠name # 𝕎 formats errors i ⊏ val } cm ← "Enclosed value must be JSON constant"∾∾' '⊸∾¨"or "⊸∾⌾(¯1⊸⊑)name ExportConst ⇐ { i ← val⊸⊐⌾< 𝕩 cm ! i<≠val i ⊑ name } } ⟨UnEscape, Escape⟩ ← { in ← """\/bfrnt" out ← (3↑in)∾@+8‿12‿13‿10‿9 diff ← (out-in) ∾ 0 Basic ← { i ← in ⊐ 𝕩 "Unknown escape" ! ∧´𝕨≤i<≠in 𝕩 + 𝕨 × i ⊏ diff } hc ← "0Aa" hb ← ⥊hc+0≍˘10‿6‿6 # Hex boundaries, start and after-end ho ← 2/hc-0‿10‿10 # Corresponding offsets Hex ← { u 𝕊 𝕩: d ← 𝕩 /˜ m ← ≠` (4⥊0)⊸»⊸≠ »u t ← hb ⍋ d "String \u must be followed by 4 hex characters" ! ∧´1=2|t # Now m can't run past the end or self-intersect, # or it would have hit a closing quote or backslash v ← 16⊸×⊸+˜˝⌽ ⍉∘‿4⥊ d-t⊏ho w‿e ← Surrogate v ⟨(w+@-'u')⊸+⌾(u⊸/)𝕩, e⌾(u⊸/)m⟩ } sr ← 2⋆10 # Surrogate base/radix sb ← sr×52+2+↕3 # Surrogate character boundaries Surrogate ← { c ← (≠sb)|sb⍋𝕩 # 0 for non-surrogate, 1 then 2 for surrogate h ← 1=c # First half "Unmatched surrogate pair" ! (0∾h) ≡ (2=c)∾0 r ← 𝕩 - c⊏0∾sb # Numeric value of surrogates v ← r + »h×sr×(2⋆6)+r ⟨v, h⟩ } UnEscape ⇐ { e 𝕊 𝕩: u ← e ∧ 𝕩='u' (u𝕩≥@+32 xe‿dr ← e UnEscape 𝕩 # Escaped 𝕩; characters to drop sg ← ((1-˜(s>q∨eo∨dr)×+`)∾+´)s∧q # Start at s∧q; exclude q, eo, dr str ← sg ⊔ xe # Strings # Numbers and constants b ← s ∨ 𝕩∊@+9‿10‿13‿32 # Whitespace (blank) l ← ¬ b ∨ 𝕩∊"""{}[],:" # Word characters w ← »⊸< l # Word starts neg ← '-' = 𝕩 dig ← ('0'≤𝕩) ∧ 𝕩≤'9' m ← l ∧ (+`w)⊏0∾w/dig∨neg # Numbers n ← m∧w ⋄ k ← m(»∧«)dig CE ← {(! 𝕨 FE /⟜(/k))⍟(∨´) 𝕩} cns ← ce Consts (1-˜(m »⊸=v∊"{:" # Keys l ← (⍋g) ⊏ r # Container index j ← +`⊸× o # Object index (start at 1; 0 if list) keys ← ((q/(«c)×l⊏0∾j)∾1+´o) ⊔ strk str ← ⊑keys # Purely numeric lists l ⊏↩ ⍋⍋nm←0⌾⊑1(∾/∾˜)s(∨/⊣)u∊"]}""a" nn ← +´¬nm nl ← num⊔˜(1+´nm)∾˜0⊸<⊸×(1-nn)+(t='0')/l jj‿jn ← 2↑(1↓nm)⊔j Ob ← ⊑⟜keys⊸≍⍟(0<⊣) n ← jn Ob¨ 1↓nl # Build collections nv← n -˜○≠ vals←∾⟨cns,⊑nl,str,⌽n⟩ # Initial set of values f ← (l2 cannot be exported to JSON" ⟩ ExportNumber # Type 1: number !∘"Only numbers and arrays can be exported to JSON" ⟩