add script for extracting EBNF grammar from doccomments

This commit is contained in:
Moritz Hölting 2025-08-13 09:37:18 +02:00
parent 6e27474da4
commit 3271ca514c
9 changed files with 619 additions and 160 deletions

View File

@ -1,63 +1,145 @@
# Grammar of the Shulkerscript language # Grammar of the Shulkerscript language
## Table of contents ## Program
### Program
```ebnf ```ebnf
Program: Namespace Declaration*; Program:
Namespace
Declaration*
;
``` ```
### Namespace ## Declaration
```ebnf ```ebnf
Namespace: 'namespace' StringLiteral; Declaration:
Function
| Import
| TagDeclaration
| ('pub'? VariableDeclaration ';')
;
``` ```
### StringLiteral ## Namespace
```ebnf ```ebnf
StringLiteral: '"' TEXT '"'; Namespace:
'namespace' StringLiteral ';' ;
``` ```
### MacroStringLiteral ## Function
```ebnf
MacroStringLiteral: '`' ( TEXT | '$(' [a-zA-Z0-9_]+ ')' )* '`';
```
### AnyStringLiteral
```ebnf
AnyStringLiteral: StringLiteral | MacroStringLiteral;
```
### Declaration
```ebnf
Declaration: FunctionDeclaration | Import | TagDeclaration;
```
### Import
```ebnf
Import: 'from' StringLiteral 'import' Identifier;
```
### TagDeclaration
```ebnf
TagDeclaration: 'tag' StringLiteral ('of' StringLiteral)? 'replace'? '[' (StringLiteral (',' StringLiteral)*)? ']';
```
### FunctionDeclaration
```ebnf ```ebnf
Function: Function:
Annotation* 'pub'? 'fn' Identifier '(' ParameterList? ')' Block Annotation* 'pub'? 'fn' Identifier '(' FunctionParameterList? ')' Block
;
ParameterList:
Identifier (',' Identifier)* ','?
; ;
``` ```
### Annotation ## Import
```ebnf ```ebnf
Annotation: '#[' Identifier ('=' StringLiteral)? ']'; Import:
'from' StringLiteral 'import' ('*' | Identifier (',' Identifier)*) ';'
;
``` ```
### Statement ## TagDeclaration
```ebnf
TagDeclaration:
'tag' ('<' StringLiteral '>')? StringLiteral 'replace'? '[' (StringLiteral (',' StringLiteral)*)? ']'
;
```
## VariableDeclaration
```ebnf
VariableDeclaration:
SingleVariableDeclaration
| ArrayVariableDeclaration
| ScoreVariableDeclaration
| TagVariableDeclaration
| ComptimeValueDeclaration
;
```
## StringLiteral
```ebnf
StringLiteral:
'"' TEXT '"';
```
## Annotation
```ebnf
Annotation:
'#[' AnnotationAssignment ']'
;
```
## Block
```ebnf
Block:
'{' Statement* '}'
;
```
## FunctionParameterList
```ebnf
FunctionParameterList:
FunctionArgument (',' FunctionArgument)* ','?
;
```
## ArrayVariableDeclaration
```ebnf
ArrayVariableDeclaration:
('int' | 'bool') identifier '[' integer ']' VariableDeclarationAssignment?
```
## ComptimeValueDeclaration
```ebnf
ComptimeValueDeclaration:
'val' identifier VariableDeclarationAssignment?
```
## ScoreVariableDeclaration
```ebnf
ScoreVariableDeclaration:
'int' ('<' StringLiteral '>')? identifier '[' AnyStringLiteral? ']' VariableDeclarationAssignment?
```
## SingleVariableDeclaration
```ebnf
SingleVariableDeclaration:
('int' | 'bool') identifier VariableDeclarationAssignment?
```
## TagVariableDeclaration
```ebnf
TagVariableDeclaration:
'bool' identifier '[' AnyStringLiteral? ']' VariableDeclarationAssignment?
```
## AnnotationAssignment
```ebnf
AnnotationAssignment:
Identifier AnnotationValue
;
```
## Statement
```ebnf ```ebnf
Statement: Statement:
Block Block
@ -65,115 +147,345 @@ Statement:
| Conditional | Conditional
| Grouping | Grouping
| DocComment | DocComment
| ExecuteBlock
| Semicolon | Semicolon
| Run
; ;
``` ```
### Block ## FunctionArgument
```ebnf
Block: '{' Statement* '}';
```
### Run
```ebnf ```ebnf
Run: FunctionArgument:
'run' Expression ';' FunctionVariableType Identifier
; ;
``` ```
### Conditional ## VariableDeclarationAssignment
```ebnf
VariableDeclarationAssignment:
'=' Expression
```
## AnyStringLiteral
```ebnf
AnyStringLiteral: StringLiteral | MacroStringLiteral ;
```
## AnnotationValue
```ebnf
AnnotationValue:
'=' Expression
| '(' AnnotationAssignment ( ',' AnnotationAssignment )* ')'
;
```
## Conditional
```ebnf ```ebnf
Conditional: Conditional:
'if' ParenthizedCondition Block ('else' Block)? 'if' Parenthized
; ;
``` ```
### Condition ## ExecuteBlock
```ebnf ```ebnf
Condition: ExecuteBlock:
PrimaryCondition (ExecuteBlockHead ExecuteBlockTail)
BinaryCondition | (Conditional Block Else)
; ;
``` ```
#### PrimaryCondition ## Grouping
```ebnf ```ebnf
PrimaryCondition: Grouping:
ConditionalPrefix 'group' Block
| ParenthesizedCondition ;
| AnyStringLiteral
;
``` ```
#### ConditionalPrefix ## Semicolon
```ebnf ```ebnf
ConditionalPrefix: Semicolon:
ConditionalPrefixOperator PrimaryCondition SemicolonStatement ';'
;
```
## FunctionVariableType
```ebnf
FunctionVariableType:
'macro' | 'int' | 'bool'
; ;
``` ```
#### ConditionalPrefixOperator ## Expression
``` ebnf
ConditionalPrefixOperator: '!'; ```ebnf
Expression:
Primary | Binary ;
``` ```
#### BinaryCondition ## MacroStringLiteral
``` ebnf
BinaryCondition: ```ebnf
Condition ConditionalBinaryOperator Condition MacroStringLiteral:
'`' ( TEXT | '$(' [a-zA-Z0-9_]+ ')' )* '`';
```
## Else
```ebnf
Else:
'else' Block
; ;
``` ```
#### ConditionalBinaryOperator ## ExecuteBlockHead
``` ebnf
ConditionalBinaryOperator: ```ebnf
'&&' ExecuteBlockHead:
Conditional
| Align
| Anchored
| As
| AsAt
| At
| Facing
| In
| On
| Positioned
| Rotated
| Store
| Summon
;
```
## ExecuteBlockTail
```ebnf
ExecuteBlockTail:
ExecuteBlock
| Block
;
```
## SemicolonStatement
```ebnf
SemicolonStatement:
(Expression | VariableDeclaration | Assignment | ReturnStatement)
';'
;
```
## Binary
```ebnf
Binary:
Expression BinaryOperator Expression
;
```
## Primary
```ebnf
Primary:
Identifier
| Prefix
| Parenthesized
| Indexed
| Integer
| Boolean
| StringLiteral
| FunctionCall
| MemberAccess
| MacroStringLiteral
| LuaCode
```
## Align
```ebnf
Align:
'align' '(' AnyStringLiteral ')' ;
```
## Anchored
```ebnf
Anchored:
'anchored' '(' AnyStringLiteral ')' ;
```
## As
```ebnf
As:
'as' '(' AnyStringLiteral ')' ;
```
## AsAt
```ebnf
AsAt:
'asat' '(' AnyStringLiteral ')' ;
```
## At
```ebnf
At:
'at' '(' AnyStringLiteral ')' ;
```
## Facing
```ebnf
Facing:
'facing' '(' AnyStringLiteral ')' ;
```
## In
```ebnf
In:
'in' '(' AnyStringLiteral ')' ;
```
## On
```ebnf
On:
'on' '(' AnyStringLiteral ')' ;
```
## Positioned
```ebnf
Positioned:
'positioned' '(' AnyStringLiteral ')' ;
```
## Rotated
```ebnf
Rotated:
'rotated' '(' AnyStringLiteral ')' ;
```
## Store
```ebnf
Store:
'store' '(' AnyStringLiteral ')' ;
```
## Summon
```ebnf
Summon:
'summon' '(' AnyStringLiteral ')' ;
```
## Assignment
```ebnf
Assignment:
AssignmentDestination '=' Expression
```
## ReturnStatement
```ebnf
ReturnStatement:
`return` Expression ;
```
## BinaryOperator
```ebnf
BinaryOperator:
'+'
| '-'
| '*'
| '/'
| '%'
| '=='
| '!='
| '<'
| '<='
| '>'
| '>='
| '&&'
| '||' | '||'
; ;
``` ```
#### ParenthizedCondition ## FunctionCall
```ebnf
ParenthizedCondition:
'(' Condition ')'
;
```
### Grouping
``` ebnf
Grouping:
'group' Block
;
```
### Expression
```ebnf
Expression:
Primary
;
```
### Primary
```ebnf
Primary:
FunctionCall
| AnyStringLiteral
| LuaCode
;
```
### FunctionCall
```ebnf ```ebnf
FunctionCall: FunctionCall:
Identifier '(' (Expression (',' Expression)*)? ')' Identifier '(' (Expression (',' Expression)*)? ')'
; ;
``` ```
### LuaCode ## Indexed
```ebnf
Indexed:
PrimaryExpression '[' Expression ']'
;
```
## LuaCode
```ebnf ```ebnf
LuaCode: LuaCode:
'lua' '(' (Expression (',' Expression)*)? ')' '{' (.*?)* '}' 'lua' '(' (Expression (',' Expression)*)? ')' '{' (.*?)* '}'
```
## MemberAccess
```ebnf
MemberAccess:
Primary '.' Identifier
```
## Parenthesized
```ebnf
Parenthesized:
'(' Expression ')'
; ;
``` ```
## Prefix
```ebnf
Prefix:
PrefixOperator Primary
;
```
## AssignmentDestination
```ebnf
AssignmentDestination:
Identifier
| Identifier '[' Expression ']'
;
```
## PrefixOperator
```ebnf
PrefixOperator:
'!' | '-' | 'run'
;
```

View File

@ -0,0 +1,136 @@
#!/usr/bin/env python3
import re
import os
from pathlib import Path
from collections import defaultdict, deque
ebnf_blocks = []
rule_defs = {}
rule_deps = defaultdict(set)
ebnf_fence_start = re.compile(r"^\s*///\s*```\s*ebnf\s*$")
ebnf_fence_end = re.compile(r"^\s*///\s*```\s*$")
doc_comment_prefix = re.compile(r"^\s*///\s?(.*)$")
rule_start_pattern = re.compile(r"^\s*([A-Za-z_]\w*)\s*:")
rule_ref_pattern = re.compile(r"\b([A-Za-z_]\w*)\b")
def find_project_root() -> Path | None:
current = Path.cwd()
while current != current.parent:
cargo_toml = current / "Cargo.toml"
if cargo_toml.exists():
text = cargo_toml.read_text(encoding="utf-8")
if re.search(r'(?m)^\s*name\s*=\s*"shulkerscript"\s*$', text):
return current
current = current.parent
return None
root_dir = find_project_root()
if not root_dir:
raise SystemExit(
"Could not find Cargo.toml of package 'shulkerscript' in this or any parent directory."
)
if Path.cwd() != root_dir:
os.chdir(root_dir)
print(f"Changed working directory to {root_dir}")
previous_rules = set()
with open("grammar.md", "r", encoding="utf-8") as f:
rule_header_pattern = re.compile(r"## (\w+)")
for line in f:
m = rule_header_pattern.match(line)
if m:
previous_rules.add(m.group(1))
for path in Path(".").rglob("*.rs"):
with path.open(encoding="utf-8") as f:
in_block = False
current_block_lines = []
for line in f:
if not in_block and ebnf_fence_start.match(line):
in_block = True
current_block_lines = []
continue
if in_block:
if ebnf_fence_end.match(line):
block_text = "\n".join(current_block_lines)
ebnf_blocks.append(block_text)
current_rule_name = None
current_rule_lines = []
for ln in current_block_lines:
m = rule_start_pattern.match(ln)
if m:
if current_rule_name:
full_def = "\n".join(current_rule_lines)
rule_defs[current_rule_name] = full_def
refs = set(rule_ref_pattern.findall(full_def))
refs.discard(current_rule_name)
rule_deps[current_rule_name].update(refs)
current_rule_name = m.group(1)
current_rule_lines = [ln]
else:
if current_rule_name:
current_rule_lines.append(ln)
if current_rule_name:
full_def = "\n".join(current_rule_lines)
rule_defs[current_rule_name] = full_def
refs = set(rule_ref_pattern.findall(full_def))
refs.discard(current_rule_name)
rule_deps[current_rule_name].update(refs)
in_block = False
continue
m = doc_comment_prefix.match(line)
if m:
current_block_lines.append(m.group(1))
if "Program" not in rule_defs:
raise SystemExit("Root rule 'Program' not found in EBNF definitions")
visited = set()
order = []
queue = deque(["Program"])
while queue:
rule = queue.popleft()
if rule not in visited and rule in rule_defs:
visited.add(rule)
order.append(rule)
for dep in sorted(rule_deps[rule]):
if dep not in visited:
queue.append(dep)
unused_rules = sorted(set(rule_defs.keys()) - visited)
if len(unused_rules) > 0:
print(
f"Appending {len(unused_rules)} unused rules to the end: {', '.join(unused_rules)}"
)
order.extend(unused_rules)
with open("grammar.md", "w", encoding="utf-8") as out:
out.write("# Grammar of the Shulkerscript language\n\n")
for rule in order:
out.write(f"## {rule}\n\n```ebnf\n{rule_defs[rule]}\n```\n\n")
print(f"Wrote grammar.md with {len(order)} rules.")
added_rules = set(rule_defs.keys()) - previous_rules
if len(added_rules) > 0:
print(f"Added rules for: {', '.join(added_rules)}")
removed_rules = previous_rules - set(rule_defs.keys())
if len(removed_rules) > 0:
print(f"Removed rules for: {', '.join(removed_rules)}")

View File

@ -310,6 +310,11 @@ impl Debug for Boolean {
} }
/// Represents a hardcoded string literal value in the source code. /// Represents a hardcoded string literal value in the source code.
///
/// ```ebnf
/// StringLiteral:
/// '"' TEXT '"';
/// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StringLiteral { pub struct StringLiteral {
@ -344,6 +349,11 @@ impl SourceElement for StringLiteral {
} }
/// Represents a hardcoded macro string literal value in the source code. /// Represents a hardcoded macro string literal value in the source code.
///
/// ```ebnf
/// MacroStringLiteral:
/// '`' ( TEXT | '$(' [a-zA-Z0-9_]+ ')' )* '`';
/// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MacroStringLiteral { pub struct MacroStringLiteral {

View File

@ -32,11 +32,11 @@ use super::{
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Declaration: /// Declaration:
/// Function /// Function
/// | Import /// | Import
/// | Tag /// | TagDeclaration
/// | ('pub'? VariableDeclaration ';') /// | ('pub'? VariableDeclaration ';')
/// ; /// ;
/// ``` /// ```
@ -97,12 +97,12 @@ impl Declaration {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Function: /// Function:
/// Annotation* 'pub'? 'fn' Identifier '(' ParameterList? ')' Block /// Annotation* 'pub'? 'fn' Identifier '(' FunctionParameterList? ')' Block
/// ; /// ;
/// ///
/// ParameterList: /// FunctionParameterList:
/// FunctionArgument (',' FunctionArgument)* ','? /// FunctionArgument (',' FunctionArgument)* ','?
/// ; /// ;
/// ``` /// ```
@ -176,7 +176,7 @@ impl SourceElement for Function {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// FunctionVariableType: /// FunctionVariableType:
/// 'macro' | 'int' | 'bool' /// 'macro' | 'int' | 'bool'
/// ; /// ;
@ -193,7 +193,7 @@ pub enum FunctionVariableType {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// FunctionArgument: /// FunctionArgument:
/// FunctionVariableType Identifier /// FunctionVariableType Identifier
/// ; /// ;
@ -211,7 +211,7 @@ pub struct FunctionParameter {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Import: /// Import:
/// 'from' StringLiteral 'import' ('*' | Identifier (',' Identifier)*) ';' /// 'from' StringLiteral 'import' ('*' | Identifier (',' Identifier)*) ';'
/// ; /// ;
@ -266,7 +266,7 @@ impl SourceElement for Import {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// TagDeclaration: /// TagDeclaration:
/// 'tag' ('<' StringLiteral '>')? StringLiteral 'replace'? '[' (StringLiteral (',' StringLiteral)*)? ']' /// 'tag' ('<' StringLiteral '>')? StringLiteral 'replace'? '[' (StringLiteral (',' StringLiteral)*)? ']'
/// ; /// ;

View File

@ -143,7 +143,7 @@ impl SourceElement for Binary {
/// ///
/// ```ebnf /// ```ebnf
/// Expression: /// Expression:
/// Primary | Binary /// Primary | Binary ;
/// ``` /// ```
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -166,11 +166,12 @@ impl SourceElement for Expression {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Primary: /// Primary:
/// Identifier /// Identifier
/// | Prefix /// | Prefix
/// | Parenthesized /// | Parenthesized
/// | Indexed
/// | Integer /// | Integer
/// | Boolean /// | Boolean
/// | StringLiteral /// | StringLiteral
@ -307,7 +308,7 @@ impl SourceElement for Indexed {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// PrefixOperator: /// PrefixOperator:
/// '!' | '-' /// '!' | '-' | 'run'
/// ; /// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -359,7 +360,7 @@ impl SourceElement for Prefix {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// FunctionCall: /// FunctionCall:
/// Identifier '(' (Expression (',' Expression)*)? ')' /// Identifier '(' (Expression (',' Expression)*)? ')'
/// ; /// ;

View File

@ -96,7 +96,7 @@ impl SourceElement for AnyStringLiteral {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Annotation: /// Annotation:
/// '#[' AnnotationAssignment ']' /// '#[' AnnotationAssignment ']'
/// ; /// ;
@ -149,7 +149,7 @@ impl SourceElement for Annotation {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// AnnotationValue: /// AnnotationValue:
/// '=' Expression /// '=' Expression
/// | '(' AnnotationAssignment ( ',' AnnotationAssignment )* ')' /// | '(' AnnotationAssignment ( ',' AnnotationAssignment )* ')'
@ -200,7 +200,7 @@ impl SourceElement for AnnotationValue {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// AnnotationAssignment: /// AnnotationAssignment:
/// Identifier AnnotationValue /// Identifier AnnotationValue
/// ; /// ;

View File

@ -20,6 +20,13 @@ use crate::{
use super::declaration::Declaration; use super::declaration::Declaration;
/// Program is a collection of declarations preceeded by a namespace selector. /// Program is a collection of declarations preceeded by a namespace selector.
///
/// ```ebnf
/// Program:
/// Namespace
/// Declaration*
/// ;
/// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
pub struct ProgramFile { pub struct ProgramFile {

View File

@ -35,13 +35,14 @@ use super::{expression::Expression, Annotation, AnyStringLiteral};
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Statement: /// Statement:
/// Block /// Block
/// | LiteralCommand /// | LiteralCommand
/// | Conditional /// | Conditional
/// | Grouping /// | Grouping
/// | DocComment /// | DocComment
/// | ExecuteBlock
/// | Semicolon /// | Semicolon
/// ; /// ;
/// ``` /// ```
@ -131,7 +132,7 @@ impl Statement {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Block: /// Block:
/// '{' Statement* '}' /// '{' Statement* '}'
/// ; /// ;
@ -171,11 +172,11 @@ impl SourceElement for Block {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Grouping: /// Grouping:
/// 'group' Block /// 'group' Block
/// ; /// ;
/// ```` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
pub struct Grouping { pub struct Grouping {
@ -207,9 +208,9 @@ impl SourceElement for Grouping {
/// Represents a statement that ends with a semicolon in the syntax tree. /// Represents a statement that ends with a semicolon in the syntax tree.
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ``` ebnf /// ```ebnf
/// Semicolon: /// Semicolon:
/// SemicolonStatement ';' /// SemicolonStatement ';'
/// ; /// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -243,10 +244,10 @@ impl Semicolon {
/// Represents a statement that ends with a semicolon in the syntax tree. /// Represents a statement that ends with a semicolon in the syntax tree.
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ``` ebnf /// ```ebnf
/// SemicolonStatement: /// SemicolonStatement:
/// (Expression | VariableDeclaration | Assignment) /// (Expression | VariableDeclaration | Assignment | ReturnStatement)
/// ';' /// ';'
/// ; /// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -318,6 +319,7 @@ impl ReturnStatement {
/// | ArrayVariableDeclaration /// | ArrayVariableDeclaration
/// | ScoreVariableDeclaration /// | ScoreVariableDeclaration
/// | TagVariableDeclaration /// | TagVariableDeclaration
/// | ComptimeValueDeclaration
/// ; /// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]

View File

@ -73,6 +73,7 @@ impl SourceElement for ExecuteBlock {
/// | Store /// | Store
/// | Summon /// | Summon
/// ; /// ;
/// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner, From)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner, From)]
#[allow(missing_docs)] #[allow(missing_docs)]
@ -120,6 +121,7 @@ impl SourceElement for ExecuteBlockHead {
/// ExecuteBlock /// ExecuteBlock
/// | Block /// | Block
/// ; /// ;
/// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner, From)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner, From)]
#[allow(missing_docs)] #[allow(missing_docs)]
@ -144,7 +146,7 @@ impl SourceElement for ExecuteBlockTail {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Conditional: /// Conditional:
/// 'if' Parenthized /// 'if' Parenthized
/// ; /// ;
@ -181,7 +183,7 @@ impl SourceElement for Conditional {
/// ///
/// Syntax Synopsis: /// Syntax Synopsis:
/// ///
/// ``` ebnf /// ```ebnf
/// Else: /// Else:
/// 'else' Block /// 'else' Block
/// ; /// ;
@ -217,8 +219,7 @@ impl SourceElement for Else {
/// ///
/// ```ebnf /// ```ebnf
/// As: /// As:
/// 'as' '(' AnyStringLiteral ')' /// 'as' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -263,8 +264,8 @@ impl As {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// Align: /// Align:
/// 'align' '(' AnyStringLiteral ')' /// 'align' '(' AnyStringLiteral ')' ;
/// ; /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
pub struct Align { pub struct Align {
@ -309,8 +310,7 @@ impl Align {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// Anchored: /// Anchored:
/// 'anchored' '(' AnyStringLiteral ')' /// 'anchored' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -354,8 +354,7 @@ impl Anchored {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// AsAt: /// AsAt:
/// 'asat' '(' AnyStringLiteral ')' /// 'asat' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -399,8 +398,7 @@ impl AsAt {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// At: /// At:
/// 'at' '(' AnyStringLiteral ')' /// 'at' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -444,8 +442,7 @@ impl At {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// Facing: /// Facing:
/// 'facing' '(' AnyStringLiteral ')' /// 'facing' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -489,8 +486,7 @@ impl Facing {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// In: /// In:
/// 'in' '(' AnyStringLiteral ')' /// 'in' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -534,8 +530,7 @@ impl In {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// On: /// On:
/// 'on' '(' AnyStringLiteral ')' /// 'on' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -579,8 +574,7 @@ impl On {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// Positioned: /// Positioned:
/// 'positioned' '(' AnyStringLiteral ')' /// 'positioned' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -624,8 +618,7 @@ impl Positioned {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// Rotated: /// Rotated:
/// 'rotated' '(' AnyStringLiteral ')' /// 'rotated' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -669,8 +662,7 @@ impl Rotated {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// Store: /// Store:
/// 'store' '(' AnyStringLiteral ')' /// 'store' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
@ -714,8 +706,7 @@ impl Store {
/// Syntax Synopsis: /// Syntax Synopsis:
/// ```ebnf /// ```ebnf
/// Summon: /// Summon:
/// 'summon' '(' AnyStringLiteral ')' /// 'summon' '(' AnyStringLiteral ')' ;
/// ;
/// ``` /// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]