json/parse.bend checks
raw source on the hub · import 0x729eecea86ea5a2cdba3a2856a313bca/json/parse.bend as Parse
json/parse: tokens to a value, one token per step, over an explicit stack of open arrays and objects: a loop, with no fuel and no recursion on the value. Lenient about commas and colons; strict about nesting and a single root.
3 imports
import Base import ./value.bend as V import ./lex.bend as Lex
Types
type Frame source · line 10 · raw
Data
an open array (its items, reversed) or an open object (its pairs, reversed, and the key awaiting its value)
FArr@items:0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json -> Frame
FObj@pairs:0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json -> @key:Maybe<&2, String> -> Frame
type P source · line 15 · raw
Data
the parser's state: an error was seen, the finished root, the open frames
P@bad:Bool -> @root:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json> -> @stack:List<&2, Frame> -> P
Definitions
def word source · line 19 · raw
@+raw:String -> 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json
a bare word as a value: null, true, false, else a number kept as text
def put source · line 25 · raw
@stack:List<&2, Frame> -> @root:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json> -> @v:0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json -> @bad:Bool -> P
a finished value lands in the innermost open frame, or becomes the root
def close_arr source · line 41 · raw
@stack:List<&2, Frame> -> @root:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json> -> @bad:Bool -> P
a ]: the innermost frame must be an array
def close_obj source · line 49 · raw
@stack:List<&2, Frame> -> @root:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json> -> @bad:Bool -> P
a }: the innermost frame must be an object with no key waiting
def step source · line 57 · raw
@tok:0x729eecea86ea5a2cdba3a2856a313bca/json/lex.Tok -> @st:P -> P
one token
def run source · line 86 · raw
@toks:List<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/lex.Tok> -> @st:P -> P
every token, in order
def result source · line 94 · raw
@bad:Bool -> @stack:List<&2, Frame> -> @root:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json> -> Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json>
the root, when nothing went wrong and nothing stayed open
def finish source · line 102 · raw
@st:P -> Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json>
the value once the tokens are over
def parse source · line 107 · raw
@s:String -> Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/json/value.Json>
a text as a value, or None when it is not JSON