tlaplus-community / tree-sitter-tlaplus

A tree-sitter grammar for TLA⁺ and PlusCal
MIT License
57 stars 10 forks source link

Grammar railroad diagram #67

Closed mingodad closed 1 year ago

mingodad commented 1 year ago

Using this script https://github.com/mingodad/plgh/blob/main/json2ebnf.js (with quickjs) and with some manual fixes we can have a navigable railroad diagram.

Copy and paste the EBNF shown bellow on https://www.bottlecaps.de/rr/ui on the tab Edit Grammar the click on the tab View Diagram to see/download a navigable railroad diagram.

//
// From tree-sitter-tlaplus/src/grammar.json
//
//
// EBNF to generate railroad diagram at https://www.bottlecaps.de/rr/ui
//
source_file ::=  ( leading_extramodular_text?   (  ( module trailing_extramodular_text?  )  ) +  )  |  ( extends?  _unit*  ) 
comment ::=  (   (  '\*'.* )  ) 
block_comment ::=  (   (  '(*'  )  )  ( pcal_algorithm |  block_comment_text ) *  (   (  '*)'  )  ) 
block_comment_text ::=   (  ( (   (  [^*()]|[^*][)]|[(][^(*]|[*][)][ #x09]*(
|
)?[ #x09]*[(][*] )  )  |  (   (  '*' )  )  |  (   (  '(' )  )  |  (   (  ')' )  )  ) +  ) 
module ::=  single_line 'MODULE'  (  identifier )  single_line extends?  _unit*  double_line
single_line ::=  "-----*"
double_line ::=  "=====*"
def_eq ::=  '=='  |  '≜' 
set_in ::=  '\in'  |  '∈' 
gets ::=  '<-'  |  '⟵'  |  '←' 
forall ::=  '\A'  |  '\forall'  |  '∀' 
exists ::=  '\E'  |  '\exists'  |  '∃' 
temporal_forall ::=  '\AA' 
temporal_exists ::=  '\EE' 
all_map_to ::=  '|->'  |  '⟼'  |  '↦' 
maps_to ::=  '->'  |  '⟶'  |  '→' 
langle_bracket ::=  '<<'  |  '〈'  |  '⟨' 
rangle_bracket ::=  '>>'  |  '〉'  |  '⟩' 
rangle_bracket_sub ::=  '>>_'  |  '〉_'  |  '⟩_' 
case_box ::=  '[]'  |  '□' 
case_arrow ::=  '->'  |  '⟶'  |  '→' 
colon ::=  ':' 
address ::=  '@' 
label_as ::=  '::'  |  '∷' 
placeholder ::=  '_' 
keyword ::=  'ASSUME'  |  'ELSE'  |  'LOCAL'  |  'UNION'  |  'ASSUMPTION'  |  'ENABLED'  |  'MODULE'  |  'VARIABLE'  |  'AXIOM'  |  'EXCEPT'  |  'OTHER'  |  'VARIABLES'  |  'CASE'  |  'EXTENDS'  |  'SF_'  |  'WF_'  |  'CHOOSE'  |  'IF'  |  'SUBSET'  |  'WITH'  |  'CONSTANT'  |  'IN'  |  'THEN'  |  'CONSTANTS'  |  'INSTANCE'  |  'THEOREM'  |  'COROLLARY'  |  'DOMAIN'  |  'LET'  |  'UNCHANGED'  |  'BY'  |  'HAVE'  |  'QED'  |  'TAKE'  |  'DEF'  |  'HIDE'  |  'RECURSIVE'  |  'USE'  |  'DEFINE'  |  'PROOF'  |  'WITNESS'  |  'PICK'  |  'DEFS'  |  'PROVE'  |  'SUFFICES'  |  'NEW'  |  'LAMBDA'  |  'STATE'  |  'ACTION'  |  'TEMPORAL'  |  'OBVIOUS'  |  'OMITTED'  |  'LEMMA'  |  'PROPOSITION'  |  'ONLY' 
identifier ::=  [0-9_]*[A-Za-z][A-Za-z0-9_]*
extends ::=  'EXTENDS'  ( identifier ( ','  identifier ) *  ) 
_unit ::=  variable_declaration |  constant_declaration |  recursive_declaration |  use_or_hide |  local_definition |  _definition |  assumption |  theorem |  module |  single_line
local_definition ::=  'LOCAL'  _definition
_definition ::=  operator_definition |  function_definition |  instance |  module_definition
variable_declaration ::=  ( 'VARIABLE'  |  'VARIABLES'  )  ( identifier ( ','  identifier ) *  ) 
constant_declaration ::=  ( 'CONSTANT'  |  'CONSTANTS'  )  ( _id_or_op_declaration ( ','  _id_or_op_declaration ) *  ) 
recursive_declaration ::=  'RECURSIVE'  ( _id_or_op_declaration ( ','  _id_or_op_declaration ) *  ) 
operator_declaration ::=  ( (  identifier )  ( '('  ( placeholder ( ','  placeholder ) *  )  ')'  )  )  |  ( (  prefix_op_symbol )  placeholder )  |  ( placeholder (  infix_op_symbol )  placeholder )  |  ( placeholder (  postfix_op_symbol )  ) 
_id_or_op_declaration ::=  identifier |  operator_declaration
operator_definition ::=  ( ( (  identifier )  (  ( '('  ( _id_or_op_declaration ( ','  _id_or_op_declaration ) *  )  ')'  ) ?  )  )  |  ( (  prefix_op_symbol )  (  identifier )  )  |  ( (  identifier )  (  infix_op_symbol )  (  identifier )  )  |  ( (  identifier )  (  postfix_op_symbol )  )  )  def_eq (  _expr ) 
function_definition ::=  (  identifier )  '['  ( quantifier_bound ( ','  quantifier_bound ) *  )  ']'  def_eq (  _expr ) 
quantifier_bound ::=  ( ( identifier ( ','  identifier ) *  )  |  tuple_of_identifiers )  set_in (  _expr ) 
tuple_of_identifiers ::=  langle_bracket ( identifier ( ','  identifier ) *  )  rangle_bracket
instance ::=  'INSTANCE'  identifier ( 'WITH'  ( substitution ( ','  substitution ) *  )  ) ? 
substitution ::=  ( identifier |  prefix_op_symbol |  infix_op_symbol |  postfix_op_symbol )  gets _op_or_expr
_op_or_expr ::=  _op |  _expr
_op ::=  prefix_op_symbol |  infix_op_symbol |  postfix_op_symbol |  lambda
subexpr_prefix ::=  ( subexpr_component |  proof_step_ref )  '!'  ( ( subexpr_component |  subexpr_tree_nav )  '!'  ) * 
subexpr_component ::=  identifier |  bound_op |  bound_nonfix_op |  prefix_op_symbol |  infix_op_symbol |  postfix_op_symbol
bound_op ::=  (  identifier )  ( '('  ( _op_or_expr ( ','  _op_or_expr ) *  )  ')'  ) 
bound_nonfix_op ::=  ( (  prefix_op_symbol )  '('  _expr ')'  )  |  ( (  infix_op_symbol )  '('  _expr ','  _expr ')'  )  |  ( (  postfix_op_symbol )  '('  _expr ')'  ) 
subexpr_tree_nav ::=  langle_bracket |  rangle_bracket |  child_id |  colon |  address |  operator_args
child_id ::=  [0-9]+
operator_args ::=  '('  ( _op_or_expr ( ','  _op_or_expr ) *  )  ')' 
lambda ::=  'LAMBDA'  ( identifier ( ','  identifier ) *  )  ':'  _expr
module_definition ::=  ( (  identifier )  (  ( '('  ( _id_or_op_declaration ( ','  _id_or_op_declaration ) *  )  ')'  ) ?  )  )  def_eq (  instance ) 
_expr ::=  _number |  string |  boolean |  _primitive_value_set |  parentheses |  label |  subexpression |  proof_step_ref |  identifier |  bound_op |  bound_nonfix_op |  prefixed_op |  bound_prefix_op |  bound_infix_op |  bound_postfix_op |  bounded_quantification |  unbounded_quantification |  choose |  finite_set_literal |  set_filter |  set_map |  function_evaluation |  function_literal |  set_of_functions |  record_literal |  set_of_records |  record_value |  except |  prev_func_val |  tuple_literal |  step_expr_or_stutter |  step_expr_no_stutter |  fairness |  if_then_else |  case |  let_in |  conj_list |  disj_list
_subscript_expr ::=  identifier |  bound_op |  bound_nonfix_op |  prefixed_op |  parentheses |  finite_set_literal |  set_filter |  set_map |  function_literal |  set_of_functions |  record_literal |  set_of_records |  except |  tuple_literal |  step_expr_or_stutter |  step_expr_no_stutter
prefixed_op ::=  (  subexpr_prefix )  (  ( identifier |  bound_op |  bound_nonfix_op )  ) 
_number ::=  nat_number |  real_number |  binary_number |  octal_number |  hex_number
nat_number ::=  [0-9]+
real_number ::=  [0-9]*'.'[0-9]+
binary_number ::=  ( '\b'  |  '\B'  )  (  [0-1]+ ) 
octal_number ::=  ( '\o'  |  '\O'  )  (  [0-7]+ ) 
hex_number ::=  ( '\h'  |  '\H'  )  (  [0-9a-fA-F]+ ) 
string ::=  '"'  ( (  [^"#x0A] )  |  escape_char ) *  (  '"'  ) 
escape_char ::=  (  '\\'  )  (  . ) 
boolean ::=  'TRUE'  |  'FALSE' 
_primitive_value_set ::=  string_set |  boolean_set |  nat_number_set |  int_number_set |  real_number_set
string_set ::=  'STRING' 
boolean_set ::=  'BOOLEAN' 
nat_number_set ::=  'Nat'  |  'ℕ' 
int_number_set ::=  'Int'  |  'ℤ' 
real_number_set ::=  'Real'  |  'ℝ' 
label ::=   (  ( (  ( (  identifier )  (  ( '('  ( identifier ( ','  identifier ) *  )  ')'  ) ?  )  )  )  label_as (  _expr )  )  ) 
subexpression ::=  subexpr_prefix subexpr_tree_nav
parentheses ::=  '('  _expr ')' 
bounded_quantification ::=   (  ( (  ( forall |  exists )  )  (  ( quantifier_bound ( ','  quantifier_bound ) *  )  )  ':'  (  _expr )  )  ) 
unbounded_quantification ::=   (  ( (  ( forall |  exists |  temporal_forall |  temporal_exists )  )  (  ( identifier ( ','  identifier ) *  )  )  ':'  (  _expr )  )  ) 
choose ::=   (  ( 'CHOOSE'  ( identifier |  tuple_of_identifiers )  ( set_in _expr ) ?  ':'  _expr )  ) 
finite_set_literal ::=  '{'  ( _expr ( ','  _expr ) *  ) ?  '}' 
set_filter ::=   (  ( '{'  (  quantifier_bound )  ':'  (  _expr )  '}'  )  ) 
set_map ::=  '{'  (  _expr )  ':'  (  ( quantifier_bound ( ','  quantifier_bound ) *  )  )  '}' 
function_evaluation ::=   (  ( _expr '['  ( _expr ( ','  _expr ) *  )  ']'  )  ) 
function_literal ::=  '['  ( quantifier_bound ( ','  quantifier_bound ) *  )  all_map_to _expr ']' 
set_of_functions ::=  '['  _expr maps_to _expr ']' 
record_literal ::=  '['  ( ( identifier all_map_to _expr )  ( ','  ( identifier all_map_to _expr )  ) *  )  ']' 
set_of_records ::=  '['  ( ( identifier ':'  _expr )  ( ','  ( identifier ':'  _expr )  ) *  )  ']' 
record_value ::=   (  ( _expr '.'  identifier )  ) 
except ::=  '['  (  _expr )  'EXCEPT'  ( except_update ( ','  except_update ) *  )  ']' 
except_update ::=  (  ( '!'  except_update_specifier )  )  '='  (  _expr ) 
except_update_specifier ::=  ( except_update_record_field |  except_update_fn_appl ) + 
except_update_record_field ::=  '.'  identifier
except_update_fn_appl ::=  '['  ( _expr ( ','  _expr ) *  )  ']' 
prev_func_val ::=  '@' 
tuple_literal ::=  langle_bracket ( _expr ( ','  _expr ) *  ) ?  rangle_bracket
step_expr_or_stutter ::=  '['  _expr ']_'  _subscript_expr
step_expr_no_stutter ::=  langle_bracket _expr rangle_bracket_sub _subscript_expr
fairness ::=  ( 'WF_'  |  'SF_'  )  _subscript_expr '('  _expr ')' 
if_then_else ::=   (  ( 'IF'  (  _expr )  'THEN'  (  _expr )  'ELSE'  (  _expr )  )  ) 
case ::=   (  ( 'CASE'  case_arm ( case_box case_arm ) *  ( case_box other_arm ) ?  )  ) 
case_arm ::=   (  ( _expr case_arrow _expr )  ) 
other_arm ::=   (  ( 'OTHER'  case_arrow _expr )  ) 
let_in ::=   (  ( 'LET'  (  ( operator_definition |  function_definition |  module_definition |  recursive_declaration ) +  )  'IN'  (  _expr )  )  ) 
conj_list ::=  _indent conj_item+  _dedent
conj_item ::=  _bullet bullet_conj _expr
bullet_conj ::=  '/\'  |  '∧' 
disj_list ::=  _indent disj_item+  _dedent
disj_item ::=  _bullet bullet_disj _expr
bullet_disj ::=  '\/'  |  '∨' 
lnot ::=  '\lnot'  |  '\neg'  |  '~'  |  '¬' 
union ::=  'UNION' 
powerset ::=  'SUBSET' 
domain ::=  'DOMAIN' 
negative ::=  '-' 
negative_dot ::=  '-.' 
enabled ::=  'ENABLED' 
unchanged ::=  'UNCHANGED' 
always ::=  '[]'  |  '□' 
eventually ::=  '<>'  |  '⋄' 
prefix_op_symbol ::=  lnot |  union |  powerset |  domain |  enabled |  unchanged |  always |  eventually |  negative_dot
bound_prefix_op ::=   (  ( (  lnot )  (  _expr )  )  )  |   (  ( (  ( union |  powerset )  )  (  _expr )  )  )  |   (  ( (  domain )  (  _expr )  )  )  |   (  ( (  negative )  (  _expr )  )  )  |   (  ( (  ( enabled |  unchanged |  always |  eventually )  )  (  _expr )  )  ) 
implies ::=  '=>'  |  '⟹'  |  '⇒' 
plus_arrow ::=  '-+->'  |  '⇸'  |  '⥅' 
equiv ::=  '\equiv'  |  '≡' 
iff ::=  '<=>'  |  '⟺'  |  '⇔' 
leads_to ::=  '~>'  |  '⇝'  |  '↝' 
land ::=  '/\'  |  '\land'  |  '∧' 
lor ::=  '\/'  |  '\lor'  |  '∨' 
assign ::=  ':='  |  '≔' 
bnf_rule ::=  '::='  |  '⩴' 
eq ::=  '=' 
neq ::=  '/='  |  '#'  |  '≠' 
lt ::=  '<' 
gt ::=  '>' 
leq ::=  '<='  |  '=<'  |  '\leq'  |  '≤' 
geq ::=  '>='  |  '\geq'  |  '≥' 
approx ::=  '\approx'  |  '≈' 
rs_ttile ::=  '|-'  |  '⊢' 
rd_ttile ::=  '|='  |  '⊨' 
ls_ttile ::=  '-|'  |  '⊣' 
ld_ttile ::=  '=|'  |  '⫤' 
asymp ::=  '\asymp'  |  '≍' 
cong ::=  '\cong'  |  '≅' 
doteq ::=  '\doteq'  |  '≐' 
gg ::=  '\gg'  |  '≫' 
ll ::=  '\ll'  |  '≪' 
in ::=  '\in'  |  '∈' 
notin ::=  '\notin'  |  '∉' 
prec ::=  '\prec'  |  '≺' 
succ ::=  '\succ'  |  '≻' 
preceq ::=  '\preceq'  |  '⪯' 
succeq ::=  '\succeq'  |  '⪰' 
propto ::=  '\propto'  |  '∝' 
sim ::=  '\sim'  |  '∼' 
simeq ::=  '\simeq'  |  '≃' 
sqsubset ::=  '\sqsubset'  |  '⊏' 
sqsupset ::=  '\sqsupset'  |  '⊐' 
sqsubseteq ::=  '\sqsubseteq'  |  '⊑' 
sqsupseteq ::=  '\sqsupseteq'  |  '⊒' 
subset ::=  '\subset'  |  '⊂' 
supset ::=  '\supset'  |  '⊃' 
subseteq ::=  '\subseteq'  |  '⊆' 
supseteq ::=  '\supseteq'  |  '⊇' 
compose ::=  '@@' 
map_to ::=  ':>' 
map_from ::=  '<:' 
setminus ::=  '\\' 
cap ::=  '\cap'  |  '\intersect'  |  '∩' 
cup ::=  '\cup'  |  '\union'  |  '∪' 
dots_2 ::=  '..'  |  '‥' 
dots_3 ::=  '...'  |  '…' 
plus ::=  '+' 
plusplus ::=  '++' 
oplus ::=  '\oplus'  |  '(+)'  |  '⊕' 
ominus ::=  '\ominus'  |  '(-)'  |  '⊖' 
mod ::=  '%' 
modmod ::=  '%%' 
vert ::=  '|' 
vertvert ::=  '||'  |  '‖' 
minus ::=  '-' 
minusminus ::=  '--' 
amp ::=  '&' 
ampamp ::=  '&&' 
odot ::=  '\odot'  |  '(.)'  |  '⊙' 
oslash ::=  '\oslash'  |  '(/)'  |  '⊘' 
otimes ::=  '\otimes'  |  '(\X)'  |  '⊗' 
mul ::=  '*' 
mulmul ::=  '**' 
slash ::=  '/' 
slashslash ::=  '//' 
bigcirc ::=  '\bigcirc'  |  '◯' 
bullet ::=  '\bullet'  |  '●' 
div ::=  '\div'  |  '÷' 
circ ::=  '\o'  |  '\circ'  |  '∘' 
star ::=  '\star'  |  '⋆' 
excl ::=  '!!'  |  '‼' 
hashhash ::=  '##' 
dol ::=  '$' 
doldol ::=  '$$' 
qq ::=  '??'  |  '⁇' 
sqcap ::=  '\sqcap'  |  '⊓' 
sqcup ::=  '\sqcup'  |  '⊔' 
uplus ::=  '\uplus'  |  '⊎' 
times ::=  '\X'  |  '\times'  |  '×' 
wr ::=  '\wr'  |  '≀' 
cdot ::=  '\cdot'  |  '⋅' 
pow ::=  '^' 
powpow ::=  '^^' 
infix_op_symbol ::=  implies |  plus_arrow |  equiv |  iff |  leads_to |  land |  lor |  assign |  bnf_rule |  eq |  neq |  lt |  gt |  leq |  geq |  approx |  rs_ttile |  rd_ttile |  ls_ttile |  ld_ttile |  asymp |  cong |  doteq |  gg |  ll |  in |  notin |  prec |  succ |  preceq |  succeq |  propto |  sim |  simeq |  sqsubset |  sqsupset |  sqsubseteq |  sqsupseteq |  subset |  supset |  subseteq |  supseteq |  compose |  map_to |  setminus |  cap |  cup |  dots_2 |  dots_3 |  plus |  plusplus |  oplus |  ominus |  mod |  modmod |  vert |  vertvert |  minus |  minusminus |  amp |  ampamp |  odot |  oslash |  otimes |  mul |  mulmul |  slash |  slashslash |  bigcirc |  bullet |  div |  circ |  star |  excl |  hashhash |  dol |  doldol |  qq |  sqcap |  sqcup |  uplus |  times |  wr |  cdot |  pow |  powpow |  map_from
bound_infix_op ::=   (  ( (  _expr )  (  implies )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( plus_arrow |  equiv |  iff |  leads_to )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( land |  lor )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( assign |  bnf_rule |  eq |  neq |  lt |  gt |  leq |  geq |  approx |  rs_ttile |  rd_ttile |  ls_ttile |  ld_ttile |  asymp |  cong |  doteq |  gg |  ll |  in |  notin |  prec |  succ |  preceq |  succeq |  propto |  sim |  simeq |  sqsubset |  sqsupset |  sqsubseteq |  sqsupseteq |  subset |  supset |  subseteq |  supseteq )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  compose )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( map_to |  map_from )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( setminus |  cap |  cup )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( dots_2 |  dots_3 )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( plus |  plusplus |  oplus )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( ominus |  mod |  modmod |  vert |  vertvert |  minus |  minusminus )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( amp |  ampamp |  odot |  oslash |  otimes |  mul |  mulmul |  slash |  slashslash |  bigcirc |  bullet |  div |  circ |  star |  excl |  hashhash |  dol |  doldol |  qq |  sqcap |  sqcup |  uplus |  times )  )  (  _expr )  )  )  |   (  ( (  _expr )  (  ( wr |  cdot |  pow |  powpow )  )  (  _expr )  )  ) 
sup_plus ::=  '^+'  |  '⁺' 
asterisk ::=  '^*' 
sup_hash ::=  '^#' 
prime ::=  "'" 
postfix_op_symbol ::=  sup_plus |  asterisk |  sup_hash |  prime
bound_postfix_op ::=   (  ( (  _expr )  (  ( sup_plus |  asterisk |  sup_hash |  prime )  )  )  ) 
assumption ::=  ( 'ASSUME'  |  'ASSUMPTION'  |  'AXIOM'  )  ( (  identifier )  def_eq ) ?  _expr
theorem ::=  ( 'THEOREM'  |  'PROPOSITION'  |  'LEMMA'  |  'COROLLARY'  )  ( (  identifier )  def_eq ) ?  ( _expr |  assume_prove )  _proof? 
assume_prove ::=  'ASSUME'  (  ( ( _expr |  new |  inner_assume_prove )  ( ','  ( _expr |  new |  inner_assume_prove )  ) *  )  )  'PROVE'  (  _expr ) 
inner_assume_prove ::=  ( identifier label_as ) ?  assume_prove
new ::=  ( 'NEW'  |  level |  ( 'NEW'  level )  )  ( ( identifier set_in _expr )  |  _id_or_op_declaration ) 
level ::=  'CONSTANT'  |  'VARIABLE'  |  'STATE'  |  'ACTION'  |  'TEMPORAL' 
_proof ::=  terminal_proof |  non_terminal_proof
terminal_proof ::=  'PROOF' ?  ( ( 'BY'  'ONLY' ?  use_body )  |  'OBVIOUS'  |  'OMITTED'  ) 
non_terminal_proof ::=  'PROOF' ?  _begin_proof proof_step*  qed_step
proof_step ::=  _begin_proof_step proof_step_id ( definition_proof_step |  have_proof_step |  witness_proof_step |  take_proof_step |  suffices_proof_step |  case_proof_step |  pick_proof_step |  use_or_hide |  instance ) 
definition_proof_step ::=  'DEFINE' ?  ( operator_definition |  function_definition |  module_definition ) + 
have_proof_step ::=  'HAVE'  _expr
witness_proof_step ::=  'WITNESS'  ( _expr ( ','  _expr ) *  ) 
take_proof_step ::=  'TAKE'  _bound_or_identifier_list
suffices_proof_step ::=  'SUFFICES' ?  ( _expr |  assume_prove )  _proof? 
case_proof_step ::=  'CASE'  _expr _proof? 
pick_proof_step ::=  'PICK'  _bound_or_identifier_list ':'  _expr _proof? 
_bound_or_identifier_list ::=  ( quantifier_bound ( ','  quantifier_bound ) *  )  |  ( identifier ( ','  identifier ) *  ) 
qed_step ::=  _begin_proof_step proof_step_id 'QED'  _proof? 
use_or_hide ::=  ( ( 'USE'  'ONLY' ?  )  |  'HIDE'  )  use_body
use_body ::=  use_body_expr |  use_body_def |  ( use_body_expr use_body_def ) 
use_body_expr ::=  ( _expr |  module_ref )  ( ','  ( _expr |  module_ref )  ) * 
use_body_def ::=  ( 'DEF'  |  'DEFS'  )  ( ( _op_or_expr |  module_ref )  ( ','  ( _op_or_expr |  module_ref )  ) *  ) 
module_ref ::=  'MODULE'  identifier
proof_step_id ::=  '<'  (  [0-9]+|'+'|'*' )  (  '>'  )  (  [a-zA-Z]|[0-9]* )  (  '.'* ) 
proof_step_ref ::=  '<'  (  [0-9]+|'*' )  (  '>'  )  (  [a-zA-Z]|[0-9]+ ) 
pcal_algorithm ::=  _pcal_p_algorithm |  _pcal_c_algorithm
_pcal_p_algorithm ::=  pcal_algorithm_start (  identifier )  pcal_var_decls?  pcal_p_definitions?  pcal_p_macro*  pcal_p_procedure*  ( pcal_p_algorithm_body |  pcal_p_process+  )  'end'  'algorithm'  _notify_pcal_algorithm_end ';' ? 
_pcal_c_algorithm ::=  pcal_algorithm_start (  identifier )  '{'  pcal_var_decls?  pcal_c_definitions?  pcal_c_macro*  pcal_c_procedure*  ( pcal_c_algorithm_body |  pcal_c_process+  )  '}'  _notify_pcal_algorithm_end
pcal_algorithm_start ::=  (   (  ( '--algorithm'  |  ( '--fair'  'algorithm'  )  )  )  )  _notify_pcal_algorithm_start
pcal_p_definitions ::=  'define'  _definition+  'end'  'define'  ';' ? 
pcal_c_definitions ::=  'define'  '{'  _definition+  '}'  ';' ? 
pcal_p_macro ::=  pcal_macro_decl pcal_p_algorithm_body 'end'  'macro'  ';' ? 
pcal_c_macro ::=  pcal_macro_decl pcal_c_algorithm_body ';' ? 
pcal_macro_decl ::=  'macro'  (  identifier )  '('  ( (  identifier )  ( ','  (  identifier )  ) *  ) ?  ')' 
pcal_p_procedure ::=  pcal_proc_decl pcal_p_algorithm_body 'end'  'procedure'  ';' ? 
pcal_c_procedure ::=  pcal_proc_decl pcal_c_algorithm_body ';' ? 
pcal_proc_decl ::=  'procedure'  (  identifier )  '('  ( pcal_proc_var_decl ( ','  pcal_proc_var_decl ) *  ) ?  ')'  pcal_proc_var_decls? 
pcal_p_process ::=  ( 'fair'  '+' ?  ) ?  'process'  (  identifier )  ( '='  |  set_in )  _expr pcal_var_decls?  pcal_p_algorithm_body 'end'  'process'  ';' ? 
pcal_c_process ::=  ( 'fair'  '+' ?  ) ?  'process'  '('  (  identifier )  ( '='  |  set_in )  _expr ')'  pcal_var_decls?  pcal_c_algorithm_body ';' ? 
pcal_var_decls ::=  ( 'variable'  |  'variables'  )  pcal_var_decl ( ( ';'  |  ','  )  pcal_var_decl ) *  ';' ? 
pcal_var_decl ::=  identifier ( ( '='  |  set_in )  _expr ) ? 
pcal_proc_var_decls ::=  ( 'variable'  |  'variables'  )  ( pcal_proc_var_decl ( ';'  |  ','  )  ) + 
pcal_proc_var_decl ::=  identifier ( '='  _expr ) ? 
pcal_p_algorithm_body ::=  'begin'  _pcal_p_stmts
_pcal_p_stmts ::=  ( _pcal_p_stmt ';'  ) *  _pcal_p_stmt ';' ? 
pcal_c_algorithm_body ::=  ( '{'  _pcal_c_stmt ( ';'  _pcal_c_stmt ) *  ';' ?  '}'  ) 
_pcal_p_stmt ::=  _pcal_label?  _pcal_p_unlabeled_stmt
_pcal_c_stmt ::=  _pcal_label?  ( _pcal_c_unlabeled_stmt |  pcal_c_algorithm_body ) 
_pcal_label ::=  (  ( identifier ':'  )  )  ( '+'  |  '-'  ) ? 
_pcal_p_unlabeled_stmt ::=  pcal_assign |  pcal_p_if |  pcal_p_while |  pcal_p_either |  pcal_p_with |  pcal_await |  pcal_print |  pcal_assert |  pcal_skip |  pcal_return |  pcal_goto |  pcal_proc_call |  pcal_macro_call
_pcal_c_unlabeled_stmt ::=  pcal_assign |  pcal_c_if |  pcal_c_while |  pcal_c_either |  pcal_c_with |  pcal_await |  pcal_print |  pcal_assert |  pcal_skip |  pcal_return |  pcal_goto |  pcal_proc_call |  pcal_macro_call
pcal_assign ::=  pcal_lhs assign _expr ( vertvert pcal_lhs assign _expr ) * 
pcal_lhs ::=  identifier ( ( '['  _expr ( ','  _expr ) *  ']'  )  |  ( '.'  identifier )  ) * 
pcal_p_if ::=  'if'  _expr 'then'  _pcal_p_stmts ( 'elsif'  _expr 'then'  _pcal_p_stmts ) *  ( 'else'  _pcal_p_stmts ) ?  'end'  'if' 
pcal_c_if ::=   (  ( 'if'  '('  _expr ')'  _pcal_c_stmt ( 'else'  _pcal_c_stmt ) ?  )  ) 
pcal_p_while ::=  'while'  _expr 'do'  _pcal_p_stmts 'end'  'while' 
pcal_c_while ::=  'while'  '('  _expr ')'  _pcal_c_stmt
pcal_p_either ::=  'either'  _pcal_p_stmts ( 'or'  _pcal_p_stmts ) +  'end'  'either' 
pcal_c_either ::=   (  ( 'either'  _pcal_c_stmt ( 'or'  _pcal_c_stmt ) +  )  ) 
pcal_p_with ::=  'with'  _pcal_with_vars 'do'  _pcal_p_stmts 'end'  'with' 
pcal_c_with ::=  'with'  '('  _pcal_with_vars ')'  _pcal_c_stmt
_pcal_with_vars ::=  identifier ( '='  |  set_in )  _expr ( ( ','  |  ';'  )  identifier ( '='  |  set_in )  _expr ) *  ( ','  |  ';'  ) ? 
pcal_await ::=  ( 'await'  |  'when'  )  _expr
pcal_print ::=  'print'  _expr
pcal_assert ::=  'assert'  _expr
pcal_skip ::=  'skip' 
pcal_return ::=  'return' 
pcal_goto ::=  'goto'  (  identifier ) 
pcal_proc_call ::=  'call'  (  identifier )  '('  ( _expr ( ','  _expr ) *  ) ?  ')' 
pcal_macro_call ::=  (  identifier )  '('  ( _expr ( ','  _expr ) *  ) ?  ')' 
mingodad commented 1 year ago

And here is the EBNF output from https://www.bottlecaps.de/convert/ based on https://github.com/tlaplus/tlaplus/blob/master/tlatools/org.lamport.tlatools/javacc/tla%2B.jj (after removing \f form feed characters).

/* converted on Fri Jan 13, 2023, 09:28 (UTC+01) by javacc-to-w3c v0.62 which is Copyright (c) 2011-2022 by Gunther Rademacher <grd@gmx.net> */

PrefixOpToken
         ::= '\lnot'
           | '\neg'
           | '~'
           | '[]'
           | '<>'
           | 'ENABLED'
           | 'UNCHANGED'
           | 'SUBSET'
           | 'UNION'
           | 'DOMAIN'
NEPrefixOpToken
         ::= '\lnot'
           | '\neg'
           | '~'
           | '[]'
           | '<>'
           | '-.'
           | 'ENABLED'
           | 'UNCHANGED'
           | 'SUBSET'
           | 'UNION'
           | 'DOMAIN'
InfixOpToken
         ::= '//'
           | '/\'
           | '/='
           | '/'
           | '\/'
           | '\approx'
           | '\asymp'
           | '\bigcirc'
           | '\bullet'
           | '\cap'
           | '\cdot'
           | '\circ'
           | '\cong'
           | '\cup'
           | '\div'
           | '\doteq'
           | '\equiv'
           | '\geq'
           | '\gg'
           | '\in'
           | '\intersect'
           | '\union'
           | '\land'
           | '\leq'
           | '\ll'
           | '\lor'
           | '\o'
           | '\odot'
           | '\ominus'
           | '\oplus'
           | '\oslash'
           | '\otimes'
           | '\prec'
           | '\preceq'
           | '\propto'
           | '\sim'
           | '\simeq'
           | '\sqcap'
           | '\sqcup'
           | '\sqsubset'
           | '\sqsupset'
           | '\sqsubseteq'
           | '\sqsupseteq'
           | '\star'
           | '\subset'
           | '\subseteq'
           | '\succ'
           | '\succeq'
           | '\supset'
           | '\supseteq'
           | '\uplus'
           | '\wr'
           | '\'
           | '~>'
           | '=>'
           | '=<'
           | '=|'
           | '='
           | '##'
           | '#'
           | '^^'
           | '^'
           | '--'
           | '-|'
           | '-+->'
           | '-'
           | '**'
           | '*'
           | '++'
           | '+'
           | '<=>'
           | '<:'
           | '<='
           | '<'
           | '>='
           | '>'
           | '...'
           | '..'
           | '||'
           | '|'
           | '|-'
           | '|='
           | '&&'
           | '&'
           | '$$'
           | '$'
           | '??'
           | '%%'
           | '%'
           | '@@'
           | '!!'
           | ':>'
           | ':='
           | '::='
           | '(+)'
           | '(-)'
           | '(.)'
           | '(/)'
           | '(\X)'
           | '\notin'
           | '\times'
           | '\X'
PostfixOpToken
         ::= "'"
           | '^+'
           | '^*'
           | '^#'
CompilationUnit
         ::= Prelude? Module
Prelude  ::= '--->' ( NUMBER | IDENTIFIER )*
Module   ::= BeginModule Extends Body EndModule
BeginModule
         ::= ( _BM0 | _BM1 | _BM2 ) Identifier SEPARATOR
EndModule
         ::= END_MODULE
Extends  ::= ( 'EXTENDS' Identifier ( ',' Identifier )* )?
Body     ::= ( SEPARATOR | VariableDeclaration | ParamDeclaration | OperatorOrFunctionDefinition | Recursive | Instance | Assumption | Theorem | Module | UseOrHideOrBy )*
VariableDeclaration
         ::= VARIABLE Identifier ( ',' Identifier )*
ParamDeclaration
         ::= ParamSubDecl ConstantDeclarationItems ( ',' ConstantDeclarationItems )*
ParamSubDecl
         ::= CONSTANT
Recursive
         ::= 'RECURSIVE' ConstantDeclarationItems ( ',' ConstantDeclarationItems )*
ConstantDeclarationItems
         ::= Identifier ( '(' '_' ( ',' '_' )* ')' )?
           | NonExpPrefixOp '_'
           | '_' ( InfixOp '_' | PostfixOp )
OperatorOrFunctionDefinition
         ::= 'LOCAL'? '-|-' ( ( Identifier '[' QuantBound ( ',' QuantBound )* ']' | PostfixLHS | InfixLHS | PrefixLHS ) '==' Expression | IdentLHS '==' ( Expression | Instantiation ) )
IdentifierTuple
         ::= '<<' ( Identifier ( ',' Identifier )* )? '>>'
IdentLHS ::= Identifier ( '(' ( IdentDecl | SomeFixDecl ) ( ',' ( IdentDecl | SomeFixDecl ) )* ')' )?
PrefixLHS
         ::= NEPrefixOpToken Identifier
InfixLHS ::= Identifier InfixOpToken Identifier
PostfixLHS
         ::= Identifier PostfixOpToken
IdentDecl
         ::= Identifier ( '(' '_' ( ',' '_' )* ')' )?
SomeFixDecl
         ::= NonExpPrefixOp '_'
           | '_' ( InfixOp '_' | PostfixOp )
Instance ::= 'LOCAL'? Instantiation
Instantiation
         ::= 'INSTANCE' Identifier ( 'WITH' Substitution ( ',' Substitution )* )?
Substitution
         ::= ( Identifier | NonExpPrefixOp | InfixOp | PostfixOp ) '<-' OpOrExpr
OldSubstitution
         ::= ( Identifier | NonExpPrefixOp | InfixOp | PostfixOp ) '<-' ( '-.' | Expression | Lambda )
PrefixOp ::= PrefixOpToken
NonExpPrefixOp
         ::= NEPrefixOpToken
InfixOp  ::= InfixOpToken
PostfixOp
         ::= PostfixOpToken
Identifier
         ::= IDENTIFIER
Assumption
         ::= ( ASSUMPTION | 'ASSUME' ) ( '-|-'? Identifier '==' )? Expression
AssumeProve
         ::= ( Identifier '::' AssumeProve )? ( 'ASSUME' | '[]ASSUME' ) ( AssumeProve | NewSymb | Expression ) ( ',' ( AssumeProve | NewSymb | Expression ) )* ( 'PROVE' | '[]PROVE' ) Expression
NewSymb  ::= ( 'NEW' CONSTANT? | CONSTANT ) ( IdentDecl ( '\in' Expression )? | SomeFixDecl )
           | 'NEW'? ( VARIABLE Identifier | ( 'STATE' | ACTION | TEMPORAL ) ( IdentDecl | SomeFixDecl ) )
MaybeBound
         ::= ( '\in' Expression )?
Theorem  ::= ( 'THEOREM' | PROPOSITION ) ( Identifier '==' )? ( AssumeProve | Expression ) Proof?
Proof    ::= UseOrHideOrBy
           | 'PROOF'? ( 'OBVIOUS' | 'OMITTED' | Step* QEDStep )
UseOrHideOrBy
         ::= ( ( 'PROOF'? 'BY' | 'USE' ) 'ONLY'? | 'HIDE' ) ( ( 'MODULE' Identifier | Expression ) ( ',' ( 'MODULE' Identifier | Expression ) )* )? ( DF ( 'MODULE' Identifier | Expression ) ( ',' ( 'MODULE' Identifier | Expression ) )* )?
StepStartToken
         ::= ProofStepLexeme
           | ProofImplicitStepLexeme
           | ProofStepDotLexeme
           | BareLevelLexeme
           | UnnumberedStepLexeme
QEDStep  ::= StepStartToken 'QED' Proof?
Step     ::= StepStartToken ( UseOrHideOrBy | Instantiation | DefStep | HaveStep | TakeStep | WitnessStep | PickStep | CaseStep | AssertStep ) Proof?
DefStep  ::= 'DEFINE'? OperatorOrFunctionDefinition+
HaveStep ::= 'HAVE' Expression
TakeStep ::= 'TAKE' ( QuantBound ( ',' QuantBound )* | Identifier ( ',' Identifier )* )
WitnessStep
         ::= 'WITNESS' Expression ( ',' Expression )*
PickStep ::= 'PICK' ( Identifier ( ',' Identifier )* | QuantBound ( ',' QuantBound )* ) ':' Expression
CaseStep ::= 'CASE' Expression
AssertStep
         ::= 'SUFFICES'? ( Expression | AssumeProve )
GeneralId
         ::= IdPrefix Identifier
IdPrefix ::= IdPrefixElement*
IdPrefixElement
         ::= Identifier OpArgs? '!'
ParenthesesExpression
         ::= ParenExpr
           | BraceCases
           | SBracketCases
           | SetExcept
           | TupleOrAction
           | FairnessExpr
ClosedExpressionOrOp
         ::= ElementaryExpression
           | ParenthesesExpression
ClosedExpressionOnly
         ::= ClosedExpressionOrOp
OpenExpression
         ::= SomeQuant
           | SomeTQuant
           | IfThenElse
           | Case
           | LetIn
           | UnboundOrBoundChoose
ElementaryExpression
         ::= ( Identifier OpArgs? '!' )* ( PrefixOp | InfixOp | PostfixOp | Identifier OpArgs? )
           | String
           | Number
String   ::= STRING_LITERAL
Number   ::= NUMBER_LITERAL ( '.' NUMBER_LITERAL )?
OpArgs   ::= '(' OpSuite ( ',' OpSuite )* ')'
OpOrExpr ::= NonExpPrefixOp
           | InfixOp
           | PostfixOp
           | Lambda
           | Expression
OpSuite  ::= OpOrExpr
ParenExpr
         ::= '(' Expression ')'
SomeQuant
         ::= ( EXISTS | FORALL ) ( Identifier ( ',' Identifier )* | QuantBound ( ',' QuantBound )* ) ':' Expression
SomeTQuant
         ::= ( '\EE' | '\AA' ) Identifier ( ',' Identifier )* ':' Expression
QuantBound
         ::= ( IdentifierTuple | Identifier ( ',' Identifier )* ) '\in' Expression
BraceCases
         ::= '{' ( ( IdentifierTuple | Identifier ) '\in' Expression ( ':' Expression | ( ',' Expression )* ) | Expression ( ( ',' Expression )* | ':' QuantBound ( ',' QuantBound )* ) )? '}'
SBracketCases
         ::= '[' ( ( QuantBound ( ',' QuantBound )* '|->' Expression | FieldVal ( ',' FieldVal )* | FieldSet ( ',' FieldSet )* ) ']' | Expression ( ( ( ',' Expression )* | '->' Expression | 'EXCEPT' ExceptSpec ( ',' ExceptSpec )* ) ']' | ']_' ReducedExpression ) )
FieldVal ::= Identifier '|->' Expression
FieldSet ::= Identifier ':' Expression
ExceptSpec
         ::= '!' ExceptComponent+ '=' Expression
ExceptComponent
         ::= '.' Identifier
           | '[' Expression ( ',' Expression )* ']'
SetExcept
         ::= '{|' Expression 'EXCEPT' SExceptSpec ( ',' SExceptSpec )* '|}'
SExceptSpec
         ::= '!' ExceptComponent ( '=' | '\in' ) Expression
TupleOrAction
         ::= '<<' ( Expression ( ',' Expression )* )? ( '>>' | '>>_' ReducedExpression )
ReducedExpression
         ::= Identifier OpArgs? ( '!' Identifier OpArgs? )*
           | ParenExpr
           | BraceCases
           | SBracketCases
           | SetExcept
           | TupleOrAction
FairnessExpr
         ::= ( 'WF_' | 'SF_' ) ReducedExpression ( '(' Expression ')' )?
IfThenElse
         ::= 'IF' Expression 'THEN' Expression 'ELSE' Expression
Case     ::= 'CASE' CaseArm ( '[]' CaseArm )* ( '[]' OtherArm )?
CaseArm  ::= Expression '->' Expression
OtherArm ::= 'OTHER' '->' Expression
LetIn    ::= 'LET' LetDefinitions 'IN' Expression
LetDefinitions
         ::= ( OperatorOrFunctionDefinition | Recursive )+
Junctions
         ::= DisjList
           | ConjList
DisjList ::= JuncItem+
ConjList ::= JuncItem+
JuncItem ::= ( '\/' | '/\' ) Expression
UnboundOrBoundChoose
         ::= 'CHOOSE' ( Identifier | IdentifierTuple ) MaybeBound ':' Expression
Lambda   ::= 'LAMBDA' Identifier ( ',' Identifier )* ':' Expression
Expression
         ::= ( PrefixOp | InfixOp )* ( OpenExpression | ( Junctions | ParenthesesExpression | PrimitiveExp ) ( PostfixOp | '.' Identifier | SBracketCases )* ( InfixOp ( PrefixOp | InfixOp )* ( Junctions | ParenthesesExpression | PrimitiveExp ) ( PostfixOp | '.' Identifier | SBracketCases )* )* ( InfixOp ( PrefixOp | InfixOp )* OpenExpression | '::' Expression )? )
PrimitiveExp
         ::= String
           | Number
           | ( Identifier | ProofStepLexeme | ProofImplicitStepLexeme | InfixOp | PostfixOp | NonExpPrefixOp ) OpArgs? BangExt*
BangExt  ::= '!' ( ( Identifier | NonExpPrefixOp | InfixOp | PostfixOp ) OpArgs? | OpArgs | StructOp )
StructOp ::= '<<'
           | '>>'
           | ':'
           | Number
           | IDENTIFIER
OpenStart
         ::= 'CASE'
           | 'CHOOSE'
           | EXISTS
           | FORALL
           | 'IF'
           | 'LET'
           | '\EE'
           | '\AA'

<?TOKENS?>

BEGIN_MODULE
         ::= '----' '-'* ' '* 'MODULE'
_BM1     ::= BEGIN_MODULE
CASE0    ::= '_' ( LETTER | '_' | DIGIT )* LETTER ( LETTER | '_' | DIGIT )*
CASE1    ::= DIGIT ( LETTER | '_' | DIGIT )* LETTER ( LETTER | '_' | DIGIT )*
CASE1b   ::= DIGIT ( LETTER | DIGIT )* '.\/'
CASE1c   ::= DIGIT ( LETTER | DIGIT )* './\'
CASE2    ::= ( 'W' | 'S' ) ( ( [a-zA-EG-Z_] | DIGIT ) ( LETTER | '_' | DIGIT )* )?
CASE2b   ::= ( 'W' | 'S' ) ( [a-zA-EG-Z] | DIGIT ) ( LETTER | DIGIT )* '.\/'
CASE2c   ::= ( 'W' | 'S' ) ( [a-zA-EG-Z] | DIGIT ) ( LETTER | DIGIT )* './\'
CASE3    ::= ( 'WF' | 'SF' ) ( ( LETTER | DIGIT ) ( LETTER | '_' | DIGIT )* )?
CASE6    ::= [a-zA-RT-VX-Z] ( LETTER | '_' | DIGIT )*
CASE6b   ::= [a-zA-RT-VX-Z] ( LETTER | DIGIT )* '.\/'
CASE6c   ::= [a-zA-RT-VX-Z] ( LETTER | DIGIT )* './\'
CASEN    ::= DIGIT+ LETTER ( LETTER | DIGIT | '_' )*
LETTER   ::= [a-zA-Z]
DIGIT    ::= [0-9]
NUMBER   ::= DIGIT+
           | '0'
_BM2     ::= BEGIN_MODULE
_BM0     ::= BEGIN_MODULE
SEPARATOR
         ::= '----' '-'*
END_MODULE
         ::= '====' '='*
ACTION   ::= 'ACTION'
           | 'ACTIONS'
ASSUMPTION
         ::= 'ASSUMPTION'
           | 'AXIOM'
CONSTANT ::= 'CONSTANT'
           | 'CONSTANTS'
EXISTS   ::= '\E'
           | '\exists'
FORALL   ::= '\A'
           | '\forall'
PROPOSITION
         ::= 'PROPOSITION'
           | 'LEMMA'
           | 'COROLLARY'
DF       ::= 'DEF'
           | 'DEFS'
TEMPORAL ::= 'TEMPORAL'
           | 'TEMPORALS'
VARIABLE ::= 'VARIABLE'
           | 'VARIABLES'
NUMBER_LITERAL
         ::= DIGIT+
           | '0'
           | '\' ( [oO] [0-7]+ | [bB] [0-1]+ | [hH] [0-9a-fA-F]+ )
STRING_LITERAL
         ::= '"' ( [^"`\#xA#xD] | '`' [^']* "'" | '\' [ntrf\"] )* '"'
BAND     ::= CASE1c
           | CASE2c
           | CASE6c
BOR      ::= CASE1b
           | CASE2b
           | CASE6b
IDENTIFIER
         ::= CASE0
           | CASE1
           | CASE2
           | CASE3
           | CASE6
           | CASEN
           | '@'
ProofStepLexeme
         ::= '<' DIGIT+ '>' ( LETTER | DIGIT | '_' )+
ProofImplicitStepLexeme
         ::= '<' ( '+' | '*' ) '>' ( LETTER | DIGIT )+
ProofStepDotLexeme
         ::= '<' ( DIGIT+ | '+' | '*' ) '>' ( LETTER | DIGIT | '_' )+ '.'+
BareLevelLexeme
         ::= '<' ( DIGIT+ | '+' | '*' ) '>'
UnnumberedStepLexeme
         ::= '<' ( DIGIT+ | '+' | '*' ) '>' ( '*' | '-' | '.' ) '.'*
ahelwer commented 1 year ago

Oh this is neat! If you have a README posted anywhere for specific steps to convert the grammar into a railroad diagram I will link it in this repo's README.

mingodad commented 1 year ago

I just created a standalone HTML page to convert tree-sitter grammars to EBNF for railroad diagrams see here https://github.com/tree-sitter/tree-sitter/issues/2268 .