implement remaining execute operators
This commit is contained in:
parent
a818325ce9
commit
2bac397096
|
@ -21,7 +21,18 @@ pub enum KeywordKind {
|
|||
Function,
|
||||
If,
|
||||
Else,
|
||||
Align,
|
||||
Anchored,
|
||||
As,
|
||||
AsAt,
|
||||
At,
|
||||
Facing,
|
||||
In,
|
||||
On,
|
||||
Positioned,
|
||||
Rotated,
|
||||
Store,
|
||||
Summon,
|
||||
Group,
|
||||
Run,
|
||||
Lua,
|
||||
|
@ -67,7 +78,18 @@ impl KeywordKind {
|
|||
Self::Function => "fn",
|
||||
Self::If => "if",
|
||||
Self::Else => "else",
|
||||
Self::Align => "align",
|
||||
Self::Anchored => "anchored",
|
||||
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::Run => "run",
|
||||
Self::Lua => "lua",
|
||||
|
@ -78,7 +100,22 @@ impl KeywordKind {
|
|||
/// Whether the keyword starts an execute block.
|
||||
#[must_use]
|
||||
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::{
|
||||
error::{Error, SyntaxKind, UnexpectedSyntax},
|
||||
parser::{Parser, Reading},
|
||||
parser::{DelimitedTree, Parser, Reading},
|
||||
syntax_tree::condition::ParenthesizedCondition,
|
||||
},
|
||||
};
|
||||
|
@ -25,7 +25,8 @@ use super::Block;
|
|||
/// Syntax Synopsis:
|
||||
/// ```ebnf
|
||||
/// ExecuteBlock:
|
||||
/// ExecuteBlockHead ExecuteBlockTail
|
||||
/// (ExecuteBlockHead ExecuteBlockTail)
|
||||
/// | (Conditional Block Else)
|
||||
/// ;
|
||||
/// ```
|
||||
#[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))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner, From)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum ExecuteBlockHead {
|
||||
Conditional(Conditional),
|
||||
Align(Align),
|
||||
Anchored(Anchored),
|
||||
As(As),
|
||||
AsAt(AsAt),
|
||||
At(At),
|
||||
Facing(Facing),
|
||||
In(In),
|
||||
On(On),
|
||||
Positioned(Positioned),
|
||||
Rotated(Rotated),
|
||||
Store(Store),
|
||||
Summon(Summon),
|
||||
}
|
||||
|
||||
impl SourceElement for ExecuteBlockHead {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::Conditional(conditional) => conditional.span(),
|
||||
Self::Align(align) => align.span(),
|
||||
Self::Anchored(anchored) => anchored.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))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, EnumAsInner, From)]
|
||||
#[allow(missing_docs)]
|
||||
|
@ -188,8 +223,487 @@ impl SourceElement for As {
|
|||
impl As {
|
||||
/// Dissolves the [`As`] into its components.
|
||||
#[must_use]
|
||||
pub fn dissolve(self) -> (Keyword, StringLiteral, Punctuation) {
|
||||
(self.as_keyword, self.as_selector, self.close_paren)
|
||||
pub fn dissolve(self) -> (Keyword, Punctuation, StringLiteral, Punctuation) {
|
||||
(
|
||||
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))
|
||||
if as_keyword.keyword == KeywordKind::As =>
|
||||
{
|
||||
Reading::Atomic(Token::Keyword(keyword)) if keyword.keyword.starts_execute_block() => {
|
||||
// eat the as keyword
|
||||
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(
|
||||
Delimiter::Parenthesis,
|
||||
|parser| parser.parse_string_literal(handler),
|
||||
|
@ -276,15 +788,9 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let tail = self.parse_execute_block_tail(handler)?;
|
||||
|
||||
Some(ExecuteBlock::HeadTail(
|
||||
ExecuteBlockHead::As(As {
|
||||
as_keyword,
|
||||
open_paren: as_selector.open,
|
||||
as_selector: as_selector.tree?,
|
||||
close_paren: as_selector.close,
|
||||
}),
|
||||
tail,
|
||||
))
|
||||
let head = head_from_keyword(keyword, argument)?;
|
||||
|
||||
Some(ExecuteBlock::HeadTail(head, tail))
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}?;
|
||||
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) => {
|
||||
let statements = block.statements();
|
||||
|
@ -440,4 +427,69 @@ impl Transpiler {
|
|||
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