diff options
| author | Ahmed <git@gumx.cc> | 2026-06-14 01:49:48 +0300 |
|---|---|---|
| committer | Ahmed <git@gumx.cc> | 2026-06-14 01:49:48 +0300 |
| commit | 41f8d3025f041aaab98fcc3511cb6ec2198f76a7 (patch) | |
| tree | c147d5a547c3e2d7b49546157f324cbd80e88c48 /spec/grammar/UGI_GRAMMAR_v0.ebnf | |
init: vibed
Diffstat (limited to 'spec/grammar/UGI_GRAMMAR_v0.ebnf')
| -rw-r--r-- | spec/grammar/UGI_GRAMMAR_v0.ebnf | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/spec/grammar/UGI_GRAMMAR_v0.ebnf b/spec/grammar/UGI_GRAMMAR_v0.ebnf new file mode 100644 index 0000000..e37f87f --- /dev/null +++ b/spec/grammar/UGI_GRAMMAR_v0.ebnf @@ -0,0 +1,167 @@ +/* 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 |
