S12) L’EBNF de BPscript

Grammaire formelle du langage

Les productions clés

Un langage en développement actif a des divergences entre la spec et le code. Cet article les documente honnêtement — ce qui est implémenté, ce qui est prévu, ce qui diverge.

Où se situe cet article ?

Référence technique. Pour la notation EBNF, voir L3. Pour l’EBNF de BP3, voir B10. Spécification complète : BPSCRIPT_EBNF.md (v0.6).


La racine

 

scene = { directive | actor_directive | declaration | cv_instance
        | macro | backtick_orphan | comment }
        , subgrammar+ , [ template_section ] ;

 


Directives

 

directive      = "@" , directive_body ;
actor_directive = "@actor" , IDENT , actor_props+ ;
actor_props     = IDENT , ":" , actor_value ;
actor_value     = IDENT [ "(" , param_pairs , ")" ] ;

directive_body = IDENT                                    (* @core *)
               | "controls"                               (* @controls *)
               | "mode" , ":" , MODE                      (* @mode:random *)
               | IDENT , ":" , value                      (* @tempo:120 *)
               ;

value = INT | FLOAT | neg_number | IDENT | ratio ;
neg_number = "-" , ( INT | FLOAT ) ;
ratio = INT , "/" , INT ;

 

La directive @actor est le concept central (S3) :

@actor sitar  alphabet:sargam  scale:sargam_22shruti  transport:webaudio

 

Propriétés connues d’un acteur : alphabet (requis), scale (gamme/degrés → hauteur via tempérament,
si l’acteur a des hauteurs), sounds (définitions par terminal : timbre, percussions, échantillons), transport (requis),
eval (runtime des backticks ; si omis, les backticks de l’acteur ne sont pas évalués — défaut null).


Sous-grammaires et règles

 

subgrammar = rule+ , [ separator ] ;
separator  = "-----" , { "-" } ;

mode_directive = "@mode:" , MODE , [ "(" , mode_modifier , { "," , mode_modifier } , ")" ] ;
MODE = "ord" | "random" | "lin" | "sub1" | "sub" | "tem" | "poslong" ;

rule = [ guard ] , { context } , lhs , arrow , rhs
     , [ runtime_qualifier ] , { qualifier } ;

guard = "[" , flag_expr , "]" ;
flag_expr = IDENT | IDENT , comparator , value ;
arrow = "->" | "<-" | "<>" ;

 

Le mode est une directive de bloc @mode:X qui s’applique à la sous-grammaire suivante, jusqu’au
prochain séparateur -----. Il n’est pas un qualificateur inline de la règle.


Qualificateurs — [] moteur vs () runtime

 

engine_qualifier = "[" , engine_pair , { "," , engine_pair } , "]"
                 | "[" , tempo_op , "]" ;
engine_pair = ENGINE_KEY , ":" , raw_value | ENGINE_KEY ;

ENGINE_KEY = "mode" | "scan" | "speed" | "weight" | "on_fail"
           | "tempo" | "meter" | "scale" | "retro" | "rotate"
           | "keyxpand" | "repeat" | "failed" | "stop" | "goto"
           | "striated" | "smooth" ;

runtime_qualifier = "(" , runtime_pair , { "," , runtime_pair } , ")" ;
runtime_pair = RUNTIME_KEY , ":" , value ;

 

  • [] = moteur BP3, clés strictement réservées (ENGINE_KEY)
  • () = runtime/dispatcher (aval, hors dépôt), clés définies par controls.json
  • [] comme () sont suffixe sur un élément du RHS — pas de qualificateur préfixe ([X]A n’est pas supporté ; pour positionner un flag entre éléments, utiliser la forme instantanée ![X])

Le RHS

 

rhs_element = symbol_call | rest | prolongation | undetermined_rest
            | polymetric | backtick_inline | flag_mutation
            | simultaneous | trigger_in | symbol_with_trigger_in
            | capture | homomorphism_var
            | context_positive | context_negative
            | template_master | template_slave | nil_string ;

 

Simultanéité — syntaxe infixe

 

simultaneous = symbol_call , { "!" , sim_target } ;
sim_target = symbol | symbol_call ;

 

Sa!dha!spotlightSimultaneousGroup (primaire + secondaires). Le ! est infixe, pas standalone,
et exclusivement temporel : un secondaire est toujours un symbole (jamais une mutation de flag).
Les flags vont dans les qualificateurs [] de la règle.

Trigger entrant — forme standalone et attachée

 

trigger_in = "<!" , IDENT ;
symbol_with_trigger_in = symbol_call , "<!" , IDENT ;

 

Sa<!syncSymbolWithTriggerIn : un symbole qui attend un trigger entrant avant de se déclencher.


Lexèmes — pièges

  • Tiret - dans IDENT : autorisé dans les non-terminaux (LHS) uniquement. Pré-scan.
  • # dans IDENT : altérations (C#4). Attention avec l’alphabet plat.
  • _ dans IDENT : l’EBNF le permet mais BP3 rejette _ dans l’alphabet. Point bloquant connu.

Divergences connues

Sujet Spec Parser Statut
@+ Absent Accepté (legacy @controls) Legacy
INT négatif FLOAT seul a - Parser détecte - avant INT Spec à corriger
@mode → subgrammar Pas de lien formel parseSubgrammars(initialMode) Spec à corriger
Sa!dha ! standalone Infixe SimultaneousGroup Spec à corriger
on_fail, hooks, timeout Dans la spec Pas implémenté Prévu
Cross-rule braces Absent annotateUnbalancedBraces À documenter

Deux divergences anciennes sont désormais résolues dans la spec : Sa<!sync (forme attachée
SymbolWithTriggerIn) et la cv_instance (env1(...) = lib.type(...)) sont aujourd’hui décrites
par l’EBNF.


Ce qu’il faut retenir

  1. @actor est la directive centrale — lie alphabet, scale, sounds, transport
  2. [] = moteur (clés strictes), () = runtime (clés libres via controls.json)
  3. ! est infixe (Sa!dha), pas standalone, et exclusivement temporel (pas de mutation de flag)
  4. @mode:X est une directive de bloc, pas un qualificateur inline
  5. Divergences documentées entre spec et parser — le langage évolue activement

Glossaire

  • EBNF : Extended Backus-Naur Form — notation standard pour la syntaxe (ISO 14977)
  • SimultaneousGroup : Nœud AST pour Sa!dha!spotlight (primaire + secondaires, temporel)
  • SymbolWithTriggerIn : Nœud AST pour Sa<!sync (symbole + trigger entrant attaché)
  • ENGINE_KEY : Clé réservée pour les qualificateurs moteur []
  • raw_value : Valeur brute (tout texte jusqu’au , ou ]) pour les clés moteur

Liens dans la série

  • L3 — La notation EBNF
  • B10 — L’EBNF de BP3
  • S2 — Les tokens
  • S3 — La directive @actor
  • S10 — Le compilateur qui implémente cette grammaire
  • S13 (à venir) — L’AST produit par le parser

Prérequis : S2, L3
Temps de lecture : 10 min
Tags : #BPscript #EBNF #grammaire-formelle #spécification


Prochain article : S13 — L’AST de BPscript


Retour à l’index