aboutsummaryrefslogtreecommitdiffstats
path: root/spec/grammar/UGI_GRAMMAR_v0.ebnf
diff options
context:
space:
mode:
Diffstat (limited to 'spec/grammar/UGI_GRAMMAR_v0.ebnf')
-rw-r--r--spec/grammar/UGI_GRAMMAR_v0.ebnf167
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