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
|
- lua blocks
|
||||||
- imports
|
- imports
|
||||||
- group
|
- group
|
||||||
|
- Tags
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ Namespace: 'namespace' StringLiteral;
|
||||||
|
|
||||||
### Declaration
|
### Declaration
|
||||||
```ebnf
|
```ebnf
|
||||||
Declaration: FunctionDeclaration | Import;
|
Declaration: FunctionDeclaration | Import | TagDeclaration;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Import
|
### Import
|
||||||
|
@ -22,6 +22,11 @@ Declaration: FunctionDeclaration | Import;
|
||||||
Import: 'from' StringLiteral 'import' Identifier;
|
Import: 'from' StringLiteral 'import' Identifier;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### TagDeclaration
|
||||||
|
```ebnf
|
||||||
|
TagDeclaration: 'tag' StringLiteral ('of' StringLiteral)? 'replace'? '[' (StringLiteral (',' StringLiteral)*)? ']';
|
||||||
|
```
|
||||||
|
|
||||||
### FunctionDeclaration
|
### FunctionDeclaration
|
||||||
```ebnf
|
```ebnf
|
||||||
Function:
|
Function:
|
||||||
|
|
|
@ -41,6 +41,9 @@ pub enum KeywordKind {
|
||||||
Namespace,
|
Namespace,
|
||||||
From,
|
From,
|
||||||
Import,
|
Import,
|
||||||
|
Tag,
|
||||||
|
Of,
|
||||||
|
Replace,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for KeywordKind {
|
impl Display for KeywordKind {
|
||||||
|
@ -101,6 +104,9 @@ impl KeywordKind {
|
||||||
Self::Namespace => "namespace",
|
Self::Namespace => "namespace",
|
||||||
Self::From => "from",
|
Self::From => "from",
|
||||||
Self::Import => "import",
|
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:
|
/// Syntax Synopsis:
|
||||||
///
|
///
|
||||||
|
@ -35,6 +35,7 @@ use super::{statement::Block, ConnectedList};
|
||||||
pub enum Declaration {
|
pub enum Declaration {
|
||||||
Function(Function),
|
Function(Function),
|
||||||
Import(Import),
|
Import(Import),
|
||||||
|
Tag(Tag),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceElement for Declaration {
|
impl SourceElement for Declaration {
|
||||||
|
@ -42,6 +43,7 @@ impl SourceElement for Declaration {
|
||||||
match self {
|
match self {
|
||||||
Self::Function(function) => function.span(),
|
Self::Function(function) => function.span(),
|
||||||
Self::Import(import) => import.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> {
|
impl<'a> Parser<'a> {
|
||||||
/// Parses an annotation.
|
/// 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 => {
|
unexpected => {
|
||||||
// make progress
|
// make progress
|
||||||
self.forward();
|
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
|
/// Represents a syntax tree node with a pattern of having [`ConnectedList`] delimited by a pair of
|
||||||
/// punctuation like such `(a, b, c)`.
|
/// punctuation like such `(a, b, c)`.
|
||||||
|
#[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 DelimitedList<T> {
|
pub struct DelimitedList<T> {
|
||||||
/// The open punctuation of the list.
|
/// The open punctuation of the list.
|
||||||
|
|
|
@ -84,7 +84,6 @@ impl Transpiler {
|
||||||
|
|
||||||
let mut always_transpile_functions = Vec::new();
|
let mut always_transpile_functions = Vec::new();
|
||||||
|
|
||||||
// #[allow(clippy::significant_drop_in_scrutinee)]
|
|
||||||
{
|
{
|
||||||
let functions = self.functions.read().unwrap();
|
let functions = self.functions.read().unwrap();
|
||||||
for (_, data) in functions.iter() {
|
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