/* UGI Grammar v0 — W3C EBNF */ /* Generated from ugi_registry_v0.json */ /* Compatible with bottlecaps.de/rr/ui */ /* === Top-level === */ ugi_string ::= 'ugi:' version '@' handle ':' field_list version ::= digit+ ( '/' digit+ )? /* handle: alphanumeric, hyphens, underscores, dots */ handle ::= ( alpha | digit | '-' | '_' | '.' )+ field_list ::= field ( ',' field )* /* === Field dispatch === */ field ::= field_a | field_b | field_c | field_d | field_e | field_f | field_g | field_h | field_i | field_j | field_k | field_l | field_m | field_o | field_p | field_q | field_r | field_s | field_t | field_v | field_w | field_x | field_y | field_z /* === Common rules === */ odigit ::= [0-7] paid ::= '$' aspire ::= '+' odigit paid_aspire ::= paid aspire? modifier ::= paid_aspire | aspire alternative ::= '/' odigit /* custom sub-ID: ~ followed by 2+ alpha chars */ custom_sub ::= '~' alpha alpha alpha* /* sub-ID: 1-4 alpha chars */ sub_id ::= alpha alpha? alpha? alpha? /* === Per-field rules === */ /* a — Age (direct) */ field_a ::= 'a' odigit /* b — Build (special) */ field_b ::= 'b' odigit aspire? '/' odigit aspire? /* c — Clothing (direct) */ field_c ::= 'c' odigit ( alternative | aspire )? /* d — Editor / IDE (multi) */ field_d_entry ::= ( sub_id | custom_sub ) odigit ( aspire )? field_d ::= 'd' field_d_entry+ /* e — Education (direct) */ field_e ::= 'e' odigit ( aspire )? /* f — Food / Cooking (direct) */ field_f ::= 'f' odigit ( modifier )? /* g — Geek Specialization (special) */ g_domain ::= alpha alpha alpha? alpha? paid? g_custom ::= '~' alpha alpha alpha* field_g ::= 'g' ( g_domain | g_custom ) ( '/' ( g_domain | g_custom ) )* /* h — Hair (multi) */ field_h_entry ::= ( sub_id | custom_sub ) odigit ( aspire )? field_h ::= 'h' field_h_entry+ /* i — AI Stance (direct) */ field_i ::= 'i' odigit /* j — Gaming (multi) */ field_j_entry ::= ( sub_id | custom_sub ) odigit ( modifier )? field_j ::= 'j' field_j_entry+ /* k — Books (direct) */ field_k ::= 'k' odigit ( aspire )? /* l — Spoken Languages (multi) */ field_l_entry ::= alpha alpha odigit ( modifier )? field_l ::= 'l' field_l_entry+ /* m — Music (multi) */ field_m_entry ::= ( sub_id | custom_sub ) odigit field_m ::= 'm' field_m_entry+ /* o — Operating System (multi) */ field_o_entry ::= ( sub_id | custom_sub ) odigit ( modifier )? field_o ::= 'o' field_o_entry+ /* p — Programming Languages (multi) */ field_p_entry ::= ( sub_id | custom_sub ) odigit ( modifier )? field_p ::= 'p' field_p_entry+ /* q — Security / Hacking (direct) */ field_q ::= 'q' odigit ( alternative | modifier )? /* r — Religion (single) */ field_r ::= 'r' ( sub_id | custom_sub ) odigit /* s — Sex / Relationships (direct) */ field_s ::= 's' odigit ( alternative | aspire )? /* t — TV / Film (multi) */ field_t_entry ::= ( sub_id | custom_sub ) odigit field_t ::= 't' field_t_entry+ /* v — Politics (special) */ field_v ::= 'v' odigit '/' odigit /* w — Hardware (direct) */ field_w ::= 'w' odigit ( modifier )? /* x — Comics / Manga (multi) */ field_x_entry ::= ( sub_id | custom_sub ) odigit field_x ::= 'x' field_x_entry+ /* y — Fitness (direct) */ field_y ::= 'y' odigit ( modifier )? /* z — Maker / DIY (direct) */ field_z ::= 'z' odigit ( modifier )? /* === Block format === */ ugi_block ::= block_header newline block_first_line newline block_field_line+ block_footer block_header ::= '------- BEGIN UGI BLOCK -------' block_footer ::= '-------- END UGI BLOCK --------' block_first_line ::= 'v:' version ' @' handle ( ' ' block_geek_field )? block_geek_field ::= 'G' ( g_domain | g_custom ) ( '/' ( g_domain | g_custom ) )* block_field_line ::= block_field ( ' ' block_field )* newline block_field ::= alpha ( alpha | digit | '$' | '+' | '/' | '~' )+ /* === Terminals === */ alpha ::= [a-zA-Z] digit ::= [0-9] newline ::= #xD #xA | #xA