//! Abstract Syntax Tree representation of the Fluent Translation List. //! //! The AST of Fluent contains all nodes structures to represent a complete //! representation of the FTL resource. //! //! The tree preserves all semantic information and allow for round-trip //! of a canonically written FTL resource. //! //! The root node is called [`Resource`] and contains a list of [`Entry`] nodes //! representing all possible entries in the Fluent Translation List. //! //! # Example //! //! ``` //! use fluent_syntax::parser; //! use fluent_syntax::ast; //! //! let ftl = r#" //! //! ## This is a message comment //! hello-world = Hello World! //! .tooltip = Tooltip for you, { $userName }. //! //! "#; //! //! let resource = parser::parse(ftl) //! .expect("Failed to parse an FTL resource."); //! //! assert_eq!( //! resource.body[0], //! ast::Entry::Message( //! ast::Message { //! id: ast::Identifier { //! name: "hello-world" //! }, //! value: Some(ast::Pattern { //! elements: vec![ //! ast::PatternElement::TextElement { //! value: "Hello World!" //! }, //! ] //! }), //! attributes: vec![ //! ast::Attribute { //! id: ast::Identifier { //! name: "tooltip" //! }, //! value: ast::Pattern { //! elements: vec![ //! ast::PatternElement::TextElement { //! value: "Tooltip for you, " //! }, //! ast::PatternElement::Placeable { //! expression: ast::Expression::Inline( //! ast::InlineExpression::VariableReference { //! id: ast::Identifier { //! name: "userName" //! } //! } //! ) //! }, //! ast::PatternElement::TextElement { //! value: "." //! }, //! ] //! } //! } //! ], //! comment: Some( //! ast::Comment { //! The AST of Fluent contains all nodes structures to represent a complete //! } //! ) //! } //! ), //! ); //! ``` //! //! ## Errors //! //! Fluent AST preserves blocks containing invalid syntax as [`Entry::Junk`]. //! //! ## White space //! //! At the moment, AST does not preserve white space. In result only a //! canonical form of the AST is suitable for a round-trip.
//////
#[cfg/// .expect("Failed to parse an FTL resource.");//! value: "Hello World!" use#derive/! ast:Attribute//! id: ast::Identifier {
/// Root node of a Fluent Translation List. /// /// A [`Resource`] contains a body with a list of [`Entry`] nodes. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = ""; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![] /// } /// ); /// ``` #[derive/// "#; #[cfg_attr(//! }, pub/// ast::Resource { pub body:/! ],
}
/// A top-level node representing an entry of a [`Resource`]. /// /// Every [`Entry`] is a standalone element and the parser is capable /// of recovering from errors by identifying a beginning of a next entry. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = r#" /// /// key = Value /// /// "#; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Message( /// ast::Message { /// id: ast::Identifier { /// name: "key" /// }, /// value: Some(ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "Value" /// }, /// ] /// }), /// attributes: vec![], /// comment: None, /// } /// ) /// ] /// } /// ); /// ``` /// /// # Junk Entry /// /// If FTL source contains invalid FTL content, it will be preserved /// in form of [`Entry::Junk`] nodes. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// value: Some(ast::Pattern { /// /// let ftl = r#" /// /// g@rb@ge En!ry /// /// "#; /// /// let (resource, _) = parser::parse(ftl) /// .expect_err("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Junk { /// content: "g@rb@ge En!ry\n\n" /// } /// ] /// } /// ); /// ``` #[derivef// use fluent_syntax::ast;
/// g@rb@ge En!ry #[/// "#; pub /// .expect_err("Failed /// /// body: vec![
Term(Term</// content: "g@rb@ge En!ry\n\n"
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
GroupComment(omment<>,
ResourceComment
Junk { content:/// Message node represents the most common [`Entry`] in an FTL [`Resource`].
}
/// Message node represents the most common [`Entry`] in an FTL [`Resource`]. /// /// A message is a localization unit with a [`Identifier`] unique within a given /// [`Resource`], and a value or attributes with associated [`Pattern`]. /// /// A message can contain a simple text value, or a compound combination of value /// and attributes which together can be used to localize a complex User Interface /// element. /// /// Finally, each [`Message`] may have an associated [`Comment`]. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = r#" /// /// hello-world = Hello, World! /// /// "#; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Message(ast::Message { /// id: ast::Identifier { /// name: "hello-world" /// }, /// value: Some(ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "Hello, World!" /// } /// ] /// }), /// attributes: vec![], /// comment: None, /// }) /// ] /// } /// ); /// ``` #[#cfg_attr(eature =java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 62 #[cfg_attr(feature = "serde", java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 23
java.lang.StringIndexOutOfBoundsException: Range [22, 3) out of bounds for length 23 pub :IdentifierS, pubvalue:Option<attern<>java.lang.StringIndexOutOfBoundsException: Range [34, 35) out of bounds for length 34
attributes Vec<tributeS> pubcomment Option<omment<S>java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
}
/// A Fluent [`Term`]. /// /// Terms are semantically similar to [`Message`] nodes, but /// they represent a separate concept in Fluent system. /// /// Every term has to have a value, and the parser will /// report errors when term references are used in wrong positions. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// "#; /// let ftl = r#" /// /// -brand-name = Nightly /// /// "#; /// /// assert_eq!( /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Term(ast::Term { /// id: ast::Identifier { /// name: "brand-name" /// }, /// value: "Nightly" /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "Nightly" /// } /// ] /// }, /// attributes: vec![], /// comment: None, /// }) /// ] /// } /// ); /// ``` #derive(,Debug,PartialEq] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub id: /// comment: None, pub java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 6
attributes VecAttribute<value:atternS, pubattributes Vec<ttributeS>java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
} struct Term<Sjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 1
/// Pattern contains a value of a [`Message`], [`Term`] or an [`Attribute`]. /// /// Each pattern is a list of [`PatternElement`] nodes representing /// either a simple textual value, or a combination of text literals /// and placeholder [`Expression`] nodes. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = r#" /// /// hello-world = Hello, World! /// /// welcome = Welcome, { $userName }. /// /// "#; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Message(ast::Message { /// id: ast::Identifier { /// name: "hello-world" /// }, /// value: Some(ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "Hello, World!" /// } /// ] /// }), /// attributes: vec![], /// comment: None, /// }), /// ast::Entry::Message(ast::Message { /// id: ast::Identifier { /// name: "welcome" /// }, /// value: Some(ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "Welcome, " /// }, /// ast::PatternElement::Placeable { /// expression: ast::Expression::Inline( /// ast::InlineExpression::VariableReference { /// id: ast::Identifier { /// name: "userName" /// } /// } /// } /// }, /// ast::PatternElement::TextElement { /// value: "." /// } /// ] /// }), /// attributes: vec![], /// comment: None, /// }), /// ] /// } /// ); /// ```
/// ); #[/// pubEach [PatternElement]node /// either a simple textual value, or a oftext literals pub///
}
/// Attribute represents a part of a [`Message`] or [`Term`]. /// /// Attributes are used to express a compound list of keyed /// [`Pattern`] elements on an entry. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = r#" /// /// hello-world = /// .title = This is a title /// .accesskey = T /// /// "#; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Message(ast::Message { /// id: ast::Identifier { /// name: "hello-world" /// }, /// value: None, /// attributes: vec![ /// ast::Attribute { /// id: ast::Identifier { /// name: "title" /// }, /// value: ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "This is a title" /// }, /// ] /// } /// }, /// ast::Attribute { /// id: ast::Identifier { /// name: "accesskey" /// }, /// value: ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "T" /// }, /// ] /// } /// } /// ], /// comment: None, /// }), /// ] /// } /// ); /// ``` #///
/// ast::PatternElement::TextElement { pub/// pub id: Identifier</// pub value: Pattern<S>,
}
/// Identifier is part of nodes such as [`Message`], [`Term`] and [`Attribute`]. /// /// It is used to associate a unique key with an [`Entry`] or an [`Attribute`] /// and in [`Expression`] nodes to refer to another entry. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = r#" /// /// name: "hello-world" /// /// "#; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Message(ast::Message { /// id: ast::Identifier { /// name: "hello-world" /// }, /// value: Some(ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "Value" /// } /// ] /// }), /// attributes: vec![], /// comment: None, /// }), /// ] /// } /// ); /// ``` #[/// [key1] Value 1 #[cfg_attrjava.lang.StringIndexOutOfBoundsException: Range [10, 11) out of bounds for length 6 pub/// resource, pub body: vec expression. /// /// It's a pair of [`VariantKey`] and [`Pattern`]. If the selector match the /// key, then the value of the variant is returned as the value of the expression. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = r#" /// /// hello-world = { $var -> /// [key1] Value 1 /// *[other] Value 2 /// } /// /// "#; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Message(ast::Message { /// id: ast::Identifier { /// name: "hello-world" /// }, /// value: Some(ast::Pattern { /// elements: vec![ /// ast::PatternElement::Placeable { /// expression: ast::Expression::Select { /// selector: ast::InlineExpression::VariableReference { /// id: ast::Identifier { name: "var" }, /// }, /// variants: vec![ /// ast::Variant { /// key: ast::VariantKey::Identifier { /// name: "key1" /// }, /// value: ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "Value 1", /// } /// ] /// }, /// default: false, /// }, /// ast::Variant { /// key: ast::VariantKey::Identifier { /// name: "other" /// }, /// value: ast::Pattern { /// elements: vec![ /// ast::PatternElement::TextElement { /// value: "Value 2", /// } /// ] /// }, /// default: true, /// }, /// ] /// } /// } /// ] /// }), /// attributes: vec![], /// comment: None, /// }), /// ] /// } /// ); /// ``` #/// ast::PatternElement::Placeable { #[/// assert_eq!( #[cfg_attr(feature =/// id: ast::Identifier { name: "var" },/// ast::Resource { pub /// body: vec![ pub key: VariantKey<S>, pub value: Pattern<S>, pub default: bool,
}
/// Fluent [`Comment`]. /// /// In Fluent, comments may be standalone, or associated with /// an entry such as [`Term`] or [`Message`]. /// /// When used as a standalone [`Entry`], comments may appear in one of /// three levels: /// /// * Standalone comment /// * Group comment associated with a group of messages /// * Resource comment associated with the whole resource /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = r#" /// ## A standalone level comment /// "#; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Comment(ast::Comment { /// content: vec![ /// "A standalone level comment" /// ] /// }) /// ] /// } /// ); /// ``` #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(/// value: ast::Pattern { #[cfg_attr(feature = "serde", serde(from = "helper::CommentDef<S>"))] pubstruct Comment/// value: "long" pub content: Vec<S/// }
}
/// List of arguments for a [`FunctionReference`](InlineExpression::FunctionReference) or a /// [`TermReference`](InlineExpression::TermReference). /// /// Function and Term reference may contain a list of positional and /// named arguments passed to them. /// /// # Example /// /// ``` /// use fluent_syntax::parser; /// use fluent_syntax::ast; /// /// let ftl = r#" /// /// key = { FUNC($var1, "literal", style: "long") } /// /// "#; /// /// let resource = parser::parse(ftl) /// .expect("Failed to parse an FTL resource."); /// /// assert_eq!( /// resource, /// ast::Resource { /// body: vec![ /// ast::Entry::Message( /// ast::Message { /// id: ast::Identifier { /// name: "key" /// }, /// value: Some(ast::Pattern { /// elements: vec![ /// ast::PatternElement::Placeable { /// expression: ast::Expression::Inline( /// ast::InlineExpression::FunctionReference { /// id: ast::Identifier { /// name: "FUNC" /// }, /// arguments: ast::CallArguments { /// positional: vec![ /// ast::InlineExpression::VariableReference { /// id: ast::Identifier { /// name: "var1" /// } /// }, /// ast::InlineExpression::StringLiteral { /// value: "literal", /// } /// ], /// named: vec![ /// ast::NamedArgument { /// name: ast::Identifier { /// name: "style" /// }, /// value: ast::InlineExpression::StringLiteral /// { /// value: "long" /// } /// } /// ], /// } /// } /// ) /// }, /// ] /// }), /// attributes: vec![], /// comment: None, /// } /// ) /// ] /// } /// ); /// ``` #/// #[cfg_attr(feature = "serde"/// #[cfg_attr(/// .expect("Failed to parse an FTL resource."); pubstruct CallArguments/// resource, pub/// body: vec![
/// body: vec![
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.