implement tag declaration
This commit is contained in:
parent
0133661ad4
commit
6abe437c70
|
@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- lua blocks
|
||||
- imports
|
||||
- group
|
||||
- Tags
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ Namespace: 'namespace' StringLiteral;
|
|||
|
||||
### Declaration
|
||||
```ebnf
|
||||
Declaration: FunctionDeclaration | Import;
|
||||
Declaration: FunctionDeclaration | Import | TagDeclaration;
|
||||
```
|
||||
|
||||
### Import
|
||||
|
@ -22,6 +22,11 @@ Declaration: FunctionDeclaration | Import;
|
|||
Import: 'from' StringLiteral 'import' Identifier;
|
||||
```
|
||||
|
||||
### TagDeclaration
|
||||
```ebnf
|
||||
TagDeclaration: 'tag' StringLiteral ('of' StringLiteral)? 'replace'? '[' (StringLiteral (',' StringLiteral)*)? ']';
|
||||
```
|
||||
|
||||
### FunctionDeclaration
|
||||
```ebnf
|
||||
Function:
|
||||
|
|
|
@ -41,6 +41,9 @@ pub enum KeywordKind {
|
|||
Namespace,
|
||||
From,
|
||||
Import,
|
||||
Tag,
|
||||
Of,
|
||||
Replace,
|
||||
}
|
||||
|
||||
impl Display for KeywordKind {
|
||||
|
@ -101,6 +104,9 @@ impl KeywordKind {
|
|||
Self::Namespace => "namespace",
|
||||
Self::From => "from",
|
||||
Self::Import => "import",
|
||||
Self::Tag => "tag",
|
||||
Self::Of => "of",
|
||||
Self::Replace => "replace",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use crate::{
|
|||
},
|
||||
};
|
||||
|
||||
use super::{statement::Block, ConnectedList};
|
||||
use super::{statement::Block, ConnectedList, DelimitedList};
|
||||
|
||||
/// Syntax Synopsis:
|
||||
///
|
||||
|
@ -35,6 +35,7 @@ use super::{statement::Block, ConnectedList};
|
|||
pub enum Declaration {
|
||||
Function(Function),
|
||||
Import(Import),
|
||||
Tag(Tag),
|
||||
}
|
||||
|
||||
impl SourceElement for Declaration {
|
||||
|
@ -42,6 +43,7 @@ impl SourceElement for Declaration {
|
|||
match self {
|
||||
Self::Function(function) => function.span(),
|
||||
Self::Import(import) => import.span(),
|
||||
Self::Tag(tag) => tag.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -226,6 +228,79 @@ impl SourceElement for Import {
|
|||
}
|
||||
}
|
||||
|
||||
/// Syntax Synopsis:
|
||||
///
|
||||
/// ``` ebnf
|
||||
/// TagDeclaration:
|
||||
/// 'tag' StringLiteral ('of' StringLiteral)? 'replace'? '[' (StringLiteral (',' StringLiteral)*)? ']'
|
||||
/// ;
|
||||
/// ```
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Getters)]
|
||||
pub struct Tag {
|
||||
#[get = "pub"]
|
||||
tag_keyword: Keyword,
|
||||
#[get = "pub"]
|
||||
name: StringLiteral,
|
||||
#[get = "pub"]
|
||||
of_type: Option<(Keyword, StringLiteral)>,
|
||||
#[get = "pub"]
|
||||
replace: Option<Keyword>,
|
||||
#[get = "pub"]
|
||||
entries: DelimitedList<StringLiteral>,
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
#[must_use]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn dissolve(
|
||||
self,
|
||||
) -> (
|
||||
Keyword,
|
||||
StringLiteral,
|
||||
Option<(Keyword, StringLiteral)>,
|
||||
Option<Keyword>,
|
||||
DelimitedList<StringLiteral>,
|
||||
) {
|
||||
(
|
||||
self.tag_keyword,
|
||||
self.name,
|
||||
self.of_type,
|
||||
self.replace,
|
||||
self.entries,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "shulkerbox")]
|
||||
#[must_use]
|
||||
pub fn tag_type(&self) -> shulkerbox::datapack::tag::TagType {
|
||||
use shulkerbox::datapack::tag::TagType;
|
||||
|
||||
self.of_type
|
||||
.as_ref()
|
||||
.map_or(TagType::Functions, |(_, tag_type)| {
|
||||
match tag_type.str_content().as_ref() {
|
||||
"function" => TagType::Functions,
|
||||
"block" => TagType::Blocks,
|
||||
"entity_type" => TagType::Entities,
|
||||
"fluid" => TagType::Fluids,
|
||||
"game_event" => TagType::GameEvents,
|
||||
"item" => TagType::Items,
|
||||
other => TagType::Others(other.to_string()),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SourceElement for Tag {
|
||||
fn span(&self) -> Span {
|
||||
self.tag_keyword
|
||||
.span()
|
||||
.join(&self.entries.close.span)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
/// Parses an annotation.
|
||||
///
|
||||
|
@ -384,6 +459,44 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
Reading::Atomic(Token::Keyword(tag_keyword))
|
||||
if tag_keyword.keyword == KeywordKind::Tag =>
|
||||
{
|
||||
// eat the tag keyword
|
||||
self.forward();
|
||||
|
||||
// parse the name
|
||||
let name = self.parse_string_literal(handler)?;
|
||||
|
||||
let of_type = self
|
||||
.try_parse(|parser| {
|
||||
let of_keyword = parser.parse_keyword(KeywordKind::Of, &VoidHandler)?;
|
||||
let of_type = parser.parse_string_literal(handler)?;
|
||||
|
||||
Ok((of_keyword, of_type))
|
||||
})
|
||||
.ok();
|
||||
|
||||
let replace = self
|
||||
.try_parse(|parser| parser.parse_keyword(KeywordKind::Replace, &VoidHandler))
|
||||
.ok();
|
||||
|
||||
let entries = self.parse_enclosed_list(
|
||||
Delimiter::Bracket,
|
||||
',',
|
||||
|parser| parser.parse_string_literal(handler),
|
||||
handler,
|
||||
)?;
|
||||
|
||||
Ok(Declaration::Tag(Tag {
|
||||
tag_keyword,
|
||||
name,
|
||||
of_type,
|
||||
replace,
|
||||
entries,
|
||||
}))
|
||||
}
|
||||
|
||||
unexpected => {
|
||||
// make progress
|
||||
self.forward();
|
||||
|
|
|
@ -49,6 +49,7 @@ pub struct ConnectedList<Element, Separator> {
|
|||
|
||||
/// Represents a syntax tree node with a pattern of having [`ConnectedList`] delimited by a pair of
|
||||
/// punctuation like such `(a, b, c)`.
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DelimitedList<T> {
|
||||
/// The open punctuation of the list.
|
||||
|
|
|
@ -84,7 +84,6 @@ impl Transpiler {
|
|||
|
||||
let mut always_transpile_functions = Vec::new();
|
||||
|
||||
// #[allow(clippy::significant_drop_in_scrutinee)]
|
||||
{
|
||||
let functions = self.functions.read().unwrap();
|
||||
for (_, data) in functions.iter() {
|
||||
|
@ -183,6 +182,22 @@ impl Transpiler {
|
|||
}
|
||||
}
|
||||
}
|
||||
Declaration::Tag(tag) => {
|
||||
let namespace = self
|
||||
.datapack
|
||||
.namespace_mut(&namespace.namespace_name().str_content());
|
||||
let sb_tag = namespace.tag_mut(&tag.name().str_content(), tag.tag_type());
|
||||
|
||||
if let Some(list) = &tag.entries().list {
|
||||
for value in list.elements() {
|
||||
sb_tag.add_value(value.str_content().as_ref().into());
|
||||
}
|
||||
}
|
||||
|
||||
if tag.replace().is_some() {
|
||||
sb_tag.set_replace(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue