(* OpenUI specification in EBNF notation *)

openui_document = "{"
  id_field ","
  version_field ","
  type_field
  [ "," attrs_field ]
  [ "," children_field ]
  [ "," ]
"}" ;

ui_element = "{"
  id_field ","
  type_field
  [ "," attrs_field ]
  [ "," children_field ]
  [ "," ]
"}" ;

version_field = '"version"' ":" version_value ;
version_value = /"[0-9]+\.[0-9]+\.[0-9]+"/ ;

id_field = '"id"' ":" id_value ;
type_field = '"type"' ":" type_value ;
attrs_field = '"attrs"' ":" "{" [ attribute_list ] "}" ;
children_field = '"children"' ":" "[" [ ui_element_list ] "]" ;

(* ID: camelCase alphanumeric string *)
id_value = /"[a-z][A-Za-z0-9]*"/ ;

(* Type: html tags, kebab-case, or PascalCase *)
type_value = /"(?:[a-z][a-z0-9]*(?:-[a-z0-9]+)*|[A-Z][A-Za-z0-9]*(?:-[a-z][a-z0-9]*)?)"/ ;

(* Attributes: key-value pairs. Attribute key syntax identifies input,
   output, or behavior categories. Values are strings or null. *)
attribute_list = attribute_pair { "," attribute_pair } [ "," ] ;
attribute_pair = attr_key ":" attr_value ;
attr_key = string ;
attr_value = string | null ;

ui_element_list = ui_element { "," ui_element } [ "," ] ;

string = /"(?:[^"\\]|\\["\\\/bfnrt]|\\u[0-9a-fA-F]{4})*"/ ;
null = "null" ;
