mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-04-30 19:09:26 +08:00
* Fix #628: Add EBNF grammar for railroad diagram generation Add a formal EBNF grammar file (grammar/chaiscript.ebnf) that can be pasted into rr (https://www.bottlecaps.de/rr/ui) to produce navigable railroad diagrams of ChaiScript's syntax. The grammar was validated against the parser implementation and covers all language constructs including class inheritance, guard conditions, raw strings, and const declarations that were missing from the original proposal. A reference section was added to the cheatsheet, and a regression test exercises every documented grammar construct. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: add grammar railroad diagram link to README Add a Grammar section to readme.md linking to the EBNF grammar file and to mingodad's railroad diagram generator for direct viewing. Requested by @lefticus in PR #673 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: leftibot <leftibot@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
178 lines
5.9 KiB
EBNF
178 lines
5.9 KiB
EBNF
/*
|
|
* ChaiScript Grammar — EBNF for Railroad Diagram Generation
|
|
*
|
|
* View as navigable railroad diagrams at:
|
|
* https://www.bottlecaps.de/rr/ui (IPv6)
|
|
* https://rr.red-dove.com/ui (IPv4)
|
|
*
|
|
* Copy and paste this file into the 'Edit Grammar' tab, then
|
|
* click 'View Diagram'.
|
|
*
|
|
* This grammar uses the notation accepted by
|
|
* https://github.com/GuntherRademacher/rr :
|
|
* - "::=" as rule separator
|
|
* - no semicolon at end of rule
|
|
* - "?" "+" "*" for repetition
|
|
* - C comments
|
|
*/
|
|
|
|
/* ---- Top-level ---- */
|
|
|
|
statements ::= ( def | try | if | while | class | for
|
|
| switch | return | break | continue
|
|
| equation | block | eol )+
|
|
|
|
/* ---- Functions ---- */
|
|
|
|
def ::= "def" id ( "::" id )? "(" decl_arg_list ")" eol*
|
|
( ":" guard )? eol* block
|
|
|
|
lambda ::= "fun" ( "[" id_arg_list "]" )? "(" decl_arg_list ")" eol* block
|
|
|
|
guard ::= operator
|
|
|
|
/* ---- Exception handling ---- */
|
|
|
|
try ::= "try" eol* block catch* finally?
|
|
catch ::= "catch" ( "(" arg ")" )? eol* block
|
|
finally ::= "finally" eol* block
|
|
|
|
/* ---- Control flow ---- */
|
|
|
|
if ::= "if" "(" equation ( eol equation )? ")" eol* block
|
|
( "else" ( if | eol* block ) )*
|
|
|
|
while ::= "while" "(" operator ")" eol* block
|
|
|
|
for ::= "for" "(" ( for_guards | equation ":" equation ) ")" eol* block
|
|
for_guards ::= equation eol equation eol equation
|
|
|
|
switch ::= "switch" "(" operator ")" eol* "{" ( case | default )+ "}"
|
|
case ::= "case" "(" operator ")" eol* block
|
|
default ::= "default" eol* block
|
|
|
|
/* ---- Classes ---- */
|
|
|
|
class ::= "class" id ( ":" id )? eol* class_block
|
|
class_block ::= "{" class_statements* "}"
|
|
class_statements ::= def | var_decl | eol
|
|
|
|
/* ---- Blocks & flow keywords ---- */
|
|
|
|
block ::= "{" statements* "}"
|
|
return ::= "return" operator?
|
|
break ::= "break"
|
|
continue ::= "continue"
|
|
|
|
/* ---- Line termination ---- */
|
|
|
|
eol ::= "\n" | "\r\n" | ";"
|
|
|
|
/* ---- Equations & operators ---- */
|
|
|
|
equation ::= operator ( ( "=" | ":=" | "+=" | "-=" | "*=" | "/="
|
|
| "%=" | "<<=" | ">>=" | "&=" | "^=" | "|=" )
|
|
equation )?
|
|
|
|
operator ::= prefix
|
|
| value
|
|
| operator binary_operator operator
|
|
| operator "?" operator ":" operator
|
|
|
|
prefix ::= ( "++" | "--" | "-" | "+" | "!" | "~" ) operator
|
|
|
|
binary_operator ::= "||" | "&&"
|
|
| "|" | "^" | "&"
|
|
| "==" | "!="
|
|
| "<" | "<=" | ">" | ">="
|
|
| "<<" | ">>"
|
|
| "+" | "-"
|
|
| "*" | "/" | "%"
|
|
|
|
/* ---- Values & access ---- */
|
|
|
|
value ::= var_decl | dot_fun_array | prefix
|
|
|
|
dot_fun_array ::= ( lambda | num | quoted_string
|
|
| single_quoted_string | raw_string
|
|
| paren_expression | inline_container
|
|
| id )
|
|
( fun_call | array_call | dot_access )*
|
|
|
|
fun_call ::= "(" arg_list ")"
|
|
array_call ::= "[" operator "]"
|
|
dot_access ::= "." id
|
|
|
|
/* ---- Variable declarations ---- */
|
|
|
|
var_decl ::= ( "auto" | "var" | "const" ) ( reference | id )
|
|
| "global" ( reference | id )
|
|
| "attr" id ( "::" id )?
|
|
|
|
reference ::= "&" id
|
|
|
|
/* ---- Parenthesised & inline containers ---- */
|
|
|
|
paren_expression ::= "(" operator ")"
|
|
|
|
inline_container ::= "[" container_arg_list "]"
|
|
container_arg_list ::= value_range
|
|
| map_pair ( "," map_pair )*
|
|
| operator ( "," operator )*
|
|
|
|
value_range ::= operator ".." operator
|
|
map_pair ::= operator ":" operator
|
|
|
|
/* ---- String literals ---- */
|
|
|
|
quoted_string ::= '"' ( char | escape | interpolation )* '"'
|
|
single_quoted_string ::= "'" ( char | escape ) "'"
|
|
raw_string ::= 'R"' delimiter? "(" char* ")" delimiter? '"'
|
|
delimiter ::= [a-zA-Z0-9_]+
|
|
interpolation ::= "${" equation "}"
|
|
|
|
/* ---- Escape sequences ---- */
|
|
|
|
escape ::= "\" ( "'" | '"' | "?" | "\" | "a" | "b"
|
|
| "f" | "n" | "r" | "t" | "v" | "$"
|
|
| "0"
|
|
| "x" hex_digit+
|
|
| "u" hex_digit hex_digit hex_digit hex_digit
|
|
| "U" hex_digit hex_digit hex_digit hex_digit
|
|
hex_digit hex_digit hex_digit hex_digit
|
|
| octal_digit+ )
|
|
|
|
/* ---- Argument lists ---- */
|
|
|
|
id_arg_list ::= id ( "," id )*
|
|
decl_arg_list ::= ( arg ( "," arg )* )?
|
|
arg_list ::= ( equation ( "," equation )* )?
|
|
arg ::= id id?
|
|
|
|
/* ---- Identifiers ---- */
|
|
|
|
id ::= ( [a-zA-Z_] [a-zA-Z0-9_]* )
|
|
| ( "`" [^`]+ "`" )
|
|
| "true" | "false"
|
|
| "Infinity" | "NaN"
|
|
| "_"
|
|
| "__LINE__" | "__FILE__" | "__FUNC__" | "__CLASS__"
|
|
|
|
/* ---- Numeric literals ---- */
|
|
|
|
num ::= hex | binary | float | integer
|
|
|
|
hex ::= "0" ( "x" | "X" ) [0-9a-fA-F]+ int_suffix*
|
|
binary ::= "0" ( "b" | "B" ) [01]+ int_suffix*
|
|
float ::= [0-9]+ "." [0-9]+ ( ( "e" | "E" ) ( "+" | "-" )? [0-9]+ )? float_suffix?
|
|
integer ::= [0-9]+ int_suffix*
|
|
|
|
int_suffix ::= "l" | "L" | "ll" | "LL" | "u" | "U"
|
|
float_suffix ::= "l" | "L" | "f" | "F"
|
|
|
|
/* ---- Character classes ---- */
|
|
|
|
octal_digit ::= [0-7]
|
|
hex_digit ::= [0-9a-fA-F]
|
|
char ::= [^"\]
|