 ! Copyright (C) 2022 John Benediktsson
 ! See http://factorcode.org/license.txt for BSD license
 
-USING: accessors arrays assocs bare combinators endian
-hashtables io io.encodings.binary io.encodings.string
-io.encodings.utf8 io.files io.streams.byte-array kernel math
-math.bitwise math.order math.parser multiline namespaces parser
-peg.ebnf sequences sets strings words words.constant ;
+USING: accessors arrays assocs combinators endian hashtables io
+io.encodings.binary io.encodings.string io.encodings.utf8
+io.files io.streams.byte-array kernel math math.bitwise
+math.order math.parser multiline namespaces parser peg.ebnf
+sequences sets strings words words.constant ;
 
 IN: bare
 

floats    = f32|f64
primitive = uints|ints|floats|bool|str|data|void|enum

optional  = "optional"~ type              => [[ <optional> ]]
list      = "list"~ type length?          => [[ first2 <list> ]]
map       = "map"~ type type              => [[ first2 <map> ]]

struct-field-name = alpha+                => [[ >string ]]
struct-field = struct-field-name ws ":"~ ws any-type => [[ >array ]]
struct-fields = (ws struct-field ws)*
struct    = "struct"~ ws "{"~ ws struct-fields ws "}"~ => [[ <struct> ]]

union-members = union-member (ws "|"~ ws union-member)* => [[ first2 swap prefix ]]
union-member  = any-type (ws "="~ ws number)? => [[ >array ]]
union     = "union"~ ws "{"~ ws ("|"?)~ ws union-members? ws ("|"?)~ ws "}"~ => [[ <union> ]]

aggregate = optional|list|map|struct|union

defined   = user-type-name => [[ user-types get ?at [ unknown-type ] unless ]]

any-type  = aggregate|primitive|defined

user-type-name = (alpha|digit)+     => [[ >string ]]
user-type = "type"~ ws user-type-name ws any-type
          => [[ first2 [ 2array ] 2keep swap user-types [ ?set-at ] change ]]

schema = (ws user-type ws)* => [[ <schema> ]]



SYMBOL: user-types

: lookup-user-type ( name -- type )
    user-types get ?at [ unknown-type ] unless ;

: insert-user-type ( name type -- )
    swap user-types [ ?set-at ] change ;

EBNF: (parse-schema) [=[

space     = [ \t\n]
