implement remaining execute operators
This commit is contained in:
parent
a818325ce9
commit
2bac397096
|
@ -21,7 +21,18 @@ pub enum KeywordKind {
|
||||||
Function,
|
Function,
|
||||||
If,
|
If,
|
||||||
Else,
|
Else,
|
||||||
|
Align,
|
||||||
|
Anchored,
|
||||||
As,
|
As,
|
||||||
|
AsAt,
|
||||||
|
At,
|
||||||
|
Facing,
|
||||||
|
In,
|
||||||
|
On,
|
||||||
|
Positioned,
|
||||||
|
Rotated,
|
||||||
|
Store,
|
||||||
|
Summon,
|
||||||
Group,
|
Group,
|
||||||
Run,
|
Run,
|
||||||
Lua,
|
Lua,
|
||||||
|
@ -67,7 +78,18 @@ impl KeywordKind {
|
||||||
Self::Function => "fn",
|
Self::Function => "fn",
|
||||||
Self::If => "if",
|
Self::If => "if",
|
||||||
Self::Else => "else",
|
Self::Else => "else",
|
||||||
|
Self::Align => "align",
|
||||||
|
Self::Anchored => "anchored",
|
||||||
Self::As => "as",
|
Self::As => "as",
|
||||||
|
Self::AsAt => "asat",
|
||||||
|
Self::At => "at",
|
||||||
|
Self::Facing => "facing",
|
||||||
|
Self::In => "in",
|
||||||
|
Self::On => "on",
|
||||||
|
Self::Positioned => "positioned",
|
||||||
|
Self::Rotated => "rotated",
|
||||||
|
Self::Store => "store",
|
||||||
|
Self::Summon => "summon",
|
||||||
Self::Group => "group",
|
Self::Group => "group",
|
||||||
Self::Run => "run",
|
Self::Run => "run",
|
||||||
Self::Lua => "lua",
|
Self::Lua => "lua",
|
||||||
|
@ -78,7 +100,22 @@ impl KeywordKind {
|
||||||
/// Whether the keyword starts an execute block.
|
/// Whether the keyword starts an execute block.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn starts_execute_block(&self) -> bool {
|
pub fn starts_execute_block(&self) -> bool {
|
||||||
matches!(self, Self::If | Self::As)
|
matches!(
|
||||||
|
self,
|
||||||
|
Self::If
|
||||||
|
| Self::Align
|
||||||
|
| Self::Anchored
|
||||||
|
| Self::As
|
||||||
|
| Self::AsAt
|
||||||
|
| Self::At
|
||||||
|
| Self::Facing
|
||||||
|
| Self::In
|
||||||
|
| Self::On
|
||||||
|
| Self::Positioned
|
||||||
|
| Self::Rotated
|
||||||
|
| Self::Store
|
||||||
|
| Self::Summon
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
syntax::{
|
syntax::{
|
||||||
error::{Error, SyntaxKind, UnexpectedSyntax},
|
error::{Error, SyntaxKind, UnexpectedSyntax},
|
||||||
parser::{Parser, Reading},
|
parser::{DelimitedTree, Parser, Reading},
|
||||||
syntax_tree::condition::ParenthesizedCondition,
|
syntax_tree::condition::ParenthesizedCondition,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,8 @@ use super::Block;
|
||||||
/// Syntax Synopsis:
|
/// Syntax Synopsis:
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// ExecuteBlock:
|
/// ExecuteBlock:
|
||||||
/// ExecuteBlockHead ExecuteBlockTail
|
/// (ExecuteBlockHead ExecuteBlockTail)
|
||||||
|
/// | (Conditional Block Else)
|
||||||
/// ;
|
/// ;
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
@ -49,23 +50,57 @@ impl SourceElement for ExecuteBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// ExecuteBlockHead:
|
||||||
|
/// Conditional
|
||||||
|
/// | As
|
||||||
|
/// ;
|
||||||
#[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)]
|
||||||
pub enum ExecuteBlockHead {
|
pub enum ExecuteBlockHead {
|
||||||
Conditional(Conditional),
|
Conditional(Conditional),
|
||||||
|
Align(Align),
|
||||||
|
Anchored(Anchored),
|
||||||
As(As),
|
As(As),
|
||||||
|
AsAt(AsAt),
|
||||||
|
At(At),
|
||||||
|
Facing(Facing),
|
||||||
|
In(In),
|
||||||
|
On(On),
|
||||||
|
Positioned(Positioned),
|
||||||
|
Rotated(Rotated),
|
||||||
|
Store(Store),
|
||||||
|
Summon(Summon),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceElement for ExecuteBlockHead {
|
impl SourceElement for ExecuteBlockHead {
|
||||||
fn span(&self) -> Span {
|
fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Self::Conditional(conditional) => conditional.span(),
|
Self::Conditional(conditional) => conditional.span(),
|
||||||
|
Self::Align(align) => align.span(),
|
||||||
|
Self::Anchored(anchored) => anchored.span(),
|
||||||
Self::As(as_) => as_.span(),
|
Self::As(as_) => as_.span(),
|
||||||
|
Self::AsAt(as_at) => as_at.span(),
|
||||||
|
Self::At(at) => at.span(),
|
||||||
|
Self::Facing(facing) => facing.span(),
|
||||||
|
Self::In(in_) => in_.span(),
|
||||||
|
Self::On(on) => on.span(),
|
||||||
|
Self::Positioned(positioned) => positioned.span(),
|
||||||
|
Self::Rotated(rotated) => rotated.span(),
|
||||||
|
Self::Store(store) => store.span(),
|
||||||
|
Self::Summon(summon) => summon.span(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// ExecuteBlockTail:
|
||||||
|
/// ExecuteBlock
|
||||||
|
/// | 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)]
|
||||||
|
@ -188,8 +223,487 @@ impl SourceElement for As {
|
||||||
impl As {
|
impl As {
|
||||||
/// Dissolves the [`As`] into its components.
|
/// Dissolves the [`As`] into its components.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn dissolve(self) -> (Keyword, StringLiteral, Punctuation) {
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
(self.as_keyword, self.as_selector, self.close_paren)
|
(
|
||||||
|
self.as_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.as_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// Align:
|
||||||
|
/// 'align' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct Align {
|
||||||
|
/// The `align` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
align_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the align statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
align_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SourceElement for Align {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.align_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the align statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Align {
|
||||||
|
/// Dissolves the [`Align`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.align_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.align_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// Anchored:
|
||||||
|
/// 'anchored' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct Anchored {
|
||||||
|
/// The `anchored` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
anchored_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the anchored statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
anchored_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for Anchored {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.anchored_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the anchored statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Anchored {
|
||||||
|
/// Dissolves the [`Anchored`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.anchored_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.anchored_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// AsAt:
|
||||||
|
/// 'asat' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct AsAt {
|
||||||
|
/// The `asat` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
asat_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the asat statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
asat_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for AsAt {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.asat_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the asat statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AsAt {
|
||||||
|
/// Dissolves the [`AsAt`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.asat_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.asat_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// At:
|
||||||
|
/// 'at' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct At {
|
||||||
|
/// The `at` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
at_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the at statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
at_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for At {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.at_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the at statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl At {
|
||||||
|
/// Dissolves the [`At`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.at_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.at_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// Facing:
|
||||||
|
/// 'facing' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct Facing {
|
||||||
|
/// The `facing` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
facing_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the facing statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
facing_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for Facing {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.facing_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the facing statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Facing {
|
||||||
|
/// Dissolves the [`Facing`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.facing_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.facing_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// In:
|
||||||
|
/// 'in' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct In {
|
||||||
|
/// The `in` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
in_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the in statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
in_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for In {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.in_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the in statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl In {
|
||||||
|
/// Dissolves the [`In`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.in_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.in_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// On:
|
||||||
|
/// 'on' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct On {
|
||||||
|
/// The `on` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
on_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the on statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
on_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for On {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.on_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the on statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl On {
|
||||||
|
/// Dissolves the [`On`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.on_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.on_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// Positioned:
|
||||||
|
/// 'positioned' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct Positioned {
|
||||||
|
/// The `positioned` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
positioned_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the positioned statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
positioned_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for Positioned {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.positioned_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the positioned statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Positioned {
|
||||||
|
/// Dissolves the [`Positioned`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.positioned_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.positioned_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// Rotated:
|
||||||
|
/// 'rotated' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct Rotated {
|
||||||
|
/// The `rotated` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
rotated_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the rotated statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
rotated_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for Rotated {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.rotated_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the rotated statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Rotated {
|
||||||
|
/// Dissolves the [`Rotated`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.rotated_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.rotated_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// Store:
|
||||||
|
/// 'store' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct Store {
|
||||||
|
/// The `store` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
store_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the store statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
store_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for Store {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.store_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the store statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Store {
|
||||||
|
/// Dissolves the [`Store`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.store_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.store_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syntax Synopsis:
|
||||||
|
/// ```ebnf
|
||||||
|
/// Summon:
|
||||||
|
/// 'summon' '(' StringLiteral ')'
|
||||||
|
/// ;
|
||||||
|
/// ```
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||||
|
pub struct Summon {
|
||||||
|
/// The `summon` keyword.
|
||||||
|
#[get = "pub"]
|
||||||
|
summon_keyword: Keyword,
|
||||||
|
/// The open parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
open_paren: Punctuation,
|
||||||
|
/// The selector of the summon statement.
|
||||||
|
#[get = "pub"]
|
||||||
|
summon_selector: StringLiteral,
|
||||||
|
/// The close parenthesis.
|
||||||
|
#[get = "pub"]
|
||||||
|
close_paren: Punctuation,
|
||||||
|
}
|
||||||
|
impl SourceElement for Summon {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
self.summon_keyword
|
||||||
|
.span()
|
||||||
|
.join(&self.close_paren.span())
|
||||||
|
.expect("The span of the summon statement is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Summon {
|
||||||
|
/// Dissolves the [`Summon`] into its components.
|
||||||
|
#[must_use]
|
||||||
|
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||||
|
(
|
||||||
|
self.summon_keyword,
|
||||||
|
self.open_paren,
|
||||||
|
self.summon_selector,
|
||||||
|
self.close_paren,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,13 +764,11 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reading::Atomic(Token::Keyword(as_keyword))
|
Reading::Atomic(Token::Keyword(keyword)) if keyword.keyword.starts_execute_block() => {
|
||||||
if as_keyword.keyword == KeywordKind::As =>
|
|
||||||
{
|
|
||||||
// eat the as keyword
|
// eat the as keyword
|
||||||
self.forward();
|
self.forward();
|
||||||
|
|
||||||
let as_selector = match self.stop_at_significant() {
|
let argument = match self.stop_at_significant() {
|
||||||
Reading::IntoDelimited(punc) if punc.punctuation == '(' => self.step_into(
|
Reading::IntoDelimited(punc) if punc.punctuation == '(' => self.step_into(
|
||||||
Delimiter::Parenthesis,
|
Delimiter::Parenthesis,
|
||||||
|parser| parser.parse_string_literal(handler),
|
|parser| parser.parse_string_literal(handler),
|
||||||
|
@ -276,15 +788,9 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let tail = self.parse_execute_block_tail(handler)?;
|
let tail = self.parse_execute_block_tail(handler)?;
|
||||||
|
|
||||||
Some(ExecuteBlock::HeadTail(
|
let head = head_from_keyword(keyword, argument)?;
|
||||||
ExecuteBlockHead::As(As {
|
|
||||||
as_keyword,
|
Some(ExecuteBlock::HeadTail(head, tail))
|
||||||
open_paren: as_selector.open,
|
|
||||||
as_selector: as_selector.tree?,
|
|
||||||
close_paren: as_selector.close,
|
|
||||||
}),
|
|
||||||
tail,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unexpected
|
// unexpected
|
||||||
|
@ -339,3 +845,96 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn head_from_keyword(
|
||||||
|
keyword: Keyword,
|
||||||
|
argument: DelimitedTree<StringLiteral>,
|
||||||
|
) -> Option<ExecuteBlockHead> {
|
||||||
|
Some(match keyword.keyword {
|
||||||
|
KeywordKind::Align => Align {
|
||||||
|
align_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
align_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::Anchored => Anchored {
|
||||||
|
anchored_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
anchored_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::As => As {
|
||||||
|
as_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
as_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::AsAt => AsAt {
|
||||||
|
asat_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
asat_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::At => At {
|
||||||
|
at_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
at_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::Facing => Facing {
|
||||||
|
facing_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
facing_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::In => In {
|
||||||
|
in_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
in_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::On => On {
|
||||||
|
on_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
on_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::Positioned => Positioned {
|
||||||
|
positioned_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
positioned_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::Rotated => Rotated {
|
||||||
|
rotated_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
rotated_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::Store => Store {
|
||||||
|
store_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
store_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
KeywordKind::Summon => Summon {
|
||||||
|
summon_keyword: keyword,
|
||||||
|
open_paren: argument.open,
|
||||||
|
summon_selector: argument.tree?,
|
||||||
|
close_paren: argument.close,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
_ => unreachable!("The keyword is not a valid execute block head."),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -341,21 +341,8 @@ impl Transpiler {
|
||||||
self.transpile_execute_block_internal(execute_block, handler)
|
self.transpile_execute_block_internal(execute_block, handler)
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
let combined = match head {
|
|
||||||
ExecuteBlockHead::Conditional(cond) => {
|
|
||||||
if let Some(tail) = tail {
|
|
||||||
self.transpile_conditional(cond, tail, None, handler)?
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExecuteBlockHead::As(as_) => {
|
|
||||||
let selector = as_.as_selector().str_content();
|
|
||||||
tail.map(|tail| Execute::As(selector.to_string(), Box::new(tail)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(combined)
|
self.combine_execute_head_tail(head, tail, handler)
|
||||||
}
|
}
|
||||||
ExecuteBlock::IfElse(cond, block, el) => {
|
ExecuteBlock::IfElse(cond, block, el) => {
|
||||||
let statements = block.statements();
|
let statements = block.statements();
|
||||||
|
@ -440,4 +427,69 @@ impl Transpiler {
|
||||||
el,
|
el,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn combine_execute_head_tail(
|
||||||
|
&mut self,
|
||||||
|
head: &ExecuteBlockHead,
|
||||||
|
tail: Option<Execute>,
|
||||||
|
handler: &impl Handler<TranspileError>,
|
||||||
|
) -> TranspileResult<Option<Execute>> {
|
||||||
|
Ok(match head {
|
||||||
|
ExecuteBlockHead::Conditional(cond) => {
|
||||||
|
if let Some(tail) = tail {
|
||||||
|
self.transpile_conditional(cond, tail, None, handler)?
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::As(as_) => {
|
||||||
|
let selector = as_.as_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::As(selector.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::At(at) => {
|
||||||
|
let selector = at.at_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::At(selector.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::Align(align) => {
|
||||||
|
let align = align.align_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::Align(align.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::Anchored(anchored) => {
|
||||||
|
let anchor = anchored.anchored_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::Anchored(anchor.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::In(in_) => {
|
||||||
|
let dimension = in_.in_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::In(dimension.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::Positioned(positioned) => {
|
||||||
|
let position = positioned.positioned_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::Positioned(position.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::Rotated(rotated) => {
|
||||||
|
let rotation = rotated.rotated_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::Rotated(rotation.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::Facing(facing) => {
|
||||||
|
let facing = facing.facing_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::Facing(facing.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::AsAt(as_at) => {
|
||||||
|
let selector = as_at.asat_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::AsAt(selector.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::On(on) => {
|
||||||
|
let dimension = on.on_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::On(dimension.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::Store(store) => {
|
||||||
|
let store = store.store_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::Store(store.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
ExecuteBlockHead::Summon(summon) => {
|
||||||
|
let entity = summon.summon_selector().str_content();
|
||||||
|
tail.map(|tail| Execute::Summon(entity.to_string(), Box::new(tail)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue