From 39955732393e301217c283e5344e35af0723823c Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 14 Sep 2024 18:28:40 +0500 Subject: [PATCH] Merge Node::BuiltinAttr into Node::Attr Built-in attributes should be recognized not only when they are implicitly referred to the current type, but for other variables too. That will be fixed in next commit --- src/model/expressions.rs | 76 +++++++++++++++----- src/model/mod.rs | 12 ++-- src/parser/expressions.rs | 145 +++++++++++++++++++------------------- 3 files changed, 138 insertions(+), 95 deletions(-) diff --git a/src/model/expressions.rs b/src/model/expressions.rs index 6d63cc8..924fd7a 100644 --- a/src/model/expressions.rs +++ b/src/model/expressions.rs @@ -11,7 +11,7 @@ use serde_yml::Number; use crate::error::ModelError; use crate::model::{EnumName, EnumValueName, FieldName, TypeName as TName}; use crate::parser::expressions::{ - parse_single, BinaryOp, BuiltinAttr, ContextVar, Node, Scope, TypeName, TypeRef, UnaryOp, + parse_name, parse_single, Attr, BinaryOp, ContextVar, Node, Scope, TypeName, TypeRef, UnaryOp, }; use crate::parser::Scalar; @@ -37,9 +37,7 @@ pub enum OwningNode { ContextVar(ContextVar), /// Name of field of the type in which attribute expression is defined - Attr(FieldName), - /// Built-in field - BuiltinAttr(BuiltinAttr), + Attr(OwningAttr), /// Reference to an enum value. EnumValue { /// A type that defines this enum. @@ -140,9 +138,8 @@ impl OwningNode { Node::ContextVar(val) => ContextVar(val), - //TODO: Name already contains only valid symbols, but need to check that it is really exists - Node::Attr(val) => Attr(FieldName::valid(val)), - Node::BuiltinAttr(val) => BuiltinAttr(val), + //TODO: Need to check that attribute is really exists in the type + Node::Attr(val) => Attr(val.try_into()?), //TODO: Names already contains only valid symbols, but need to check that they is really exists Node::EnumValue { scope, name, value } => EnumValue { scope: scope.into(), @@ -345,6 +342,51 @@ impl<'input> From> for OwningTypeRef { } } +/// Owning counterpart of an [`Attr`]. Contains validated user-defined field of a type. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum OwningAttr { + /// Built-in attribute `_io`: stream associated with this object of user-defined type. + Stream, + /// Built-in attribute `_root`: top-level user-defined structure in the current file. + Root, + /// Built-in attribute `_parent`: structure that produced this particular instance of the + /// user-defined type. + Parent, + /// Built-in attribute `_sizeof`: used as an attribute of the struct to get a compile-time size + /// of the structure: + /// + /// ```yaml + /// seq: + /// - id: file_hdr + /// type: file_header + /// - id: dib_info + /// size: file_hdr.ofs_bitmap - file_hdr._sizeof + /// ``` + SizeOf, + /// User-defined attribute of the type + User(FieldName), +} +impl<'input> TryFrom> for OwningAttr { + type Error = ModelError; + + #[inline] + fn try_from(reference: Attr<'input>) -> Result { + Ok(match reference { + Attr::Stream => Self::Stream, + Attr::Root => Self::Root, + Attr::Parent => Self::Parent, + Attr::SizeOf => Self::SizeOf, + Attr::User(m) => Self::User(FieldName::valid(parse_name(m)?)), + }) + } +} +impl<'input> From for OwningAttr { + #[inline] + fn from(name: FieldName) -> Self { + Self::User(name) + } +} + #[cfg(test)] mod convert { use super::*; @@ -408,10 +450,10 @@ mod convert { #[test] fn from_string() { - assert_eq!(OwningNode::try_from(Scalar::String("id".into())), Ok(Attr(FieldName::valid("id")))); + assert_eq!(OwningNode::try_from(Scalar::String("id".into())), Ok(Attr(FieldName::valid("id").into()))); assert_eq!(OwningNode::try_from(Scalar::String("x + 2".into())), Ok(Binary { op: BinaryOp::Add, - left: Box::new(Attr(FieldName::valid("x"))), + left: Box::new(Attr(FieldName::valid("x").into())), right: Box::new(Int(2.into())), })); } @@ -430,28 +472,28 @@ mod evaluation { #[test] fn double_neg() { - assert_eq!(OwningNode::parse("-(-x)"), Ok(Attr(FieldName::valid("x")))); + assert_eq!(OwningNode::parse("-(-x)"), Ok(Attr(FieldName::valid("x").into()))); } #[test] fn double_not() { - assert_eq!(OwningNode::parse("not not x"), Ok(Attr(FieldName::valid("x")))); + assert_eq!(OwningNode::parse("not not x"), Ok(Attr(FieldName::valid("x").into()))); } #[test] fn double_inv() { - assert_eq!(OwningNode::parse("~~x"), Ok(Attr(FieldName::valid("x")))); + assert_eq!(OwningNode::parse("~~x"), Ok(Attr(FieldName::valid("x").into()))); } } #[test] fn branch() { - assert_eq!(OwningNode::parse("true ? a : b"), Ok(Attr(FieldName::valid("a")))); - assert_eq!(OwningNode::parse("false ? a : b"), Ok(Attr(FieldName::valid("b")))); + assert_eq!(OwningNode::parse("true ? a : b"), Ok(Attr(FieldName::valid("a").into()))); + assert_eq!(OwningNode::parse("false ? a : b"), Ok(Attr(FieldName::valid("b").into()))); assert_eq!(OwningNode::parse("condition ? a : b"), Ok(Branch { - condition: Box::new(Attr(FieldName::valid("condition"))), - if_true: Box::new(Attr(FieldName::valid("a"))), - if_false: Box::new(Attr(FieldName::valid("b"))), + condition: Box::new(Attr(FieldName::valid("condition").into())), + if_true: Box::new(Attr(FieldName::valid("a").into())), + if_false: Box::new(Attr(FieldName::valid("b").into())), })); } } diff --git a/src/model/mod.rs b/src/model/mod.rs index 5db2764..37a6218 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -1573,7 +1573,7 @@ mod repeat { Some(p::Count::Expr("expr".into())), None, ); - assert_eq!(rep, Ok(Repeat::Count(Count(OwningNode::Attr(FieldName::valid("expr")))))); + assert_eq!(rep, Ok(Repeat::Count(Count(OwningNode::Attr(FieldName::valid("expr").into()))))); } /// ```yaml @@ -1663,7 +1663,7 @@ mod repeat { assert_eq!(rep, Err(Validation("missed `repeat: expr`".into()))); #[cfg(not(feature = "compatible"))] - assert_eq!(rep, Ok(Repeat::Count(Count(OwningNode::Attr(FieldName::valid("expr")))))); + assert_eq!(rep, Ok(Repeat::Count(Count(OwningNode::Attr(FieldName::valid("expr").into()))))); } } } @@ -1729,7 +1729,7 @@ mod repeat { None, Some(p::Condition::Expr("until".into())), ); - assert_eq!(rep, Ok(Repeat::Until(Condition(OwningNode::Attr(FieldName::valid("until")))))); + assert_eq!(rep, Ok(Repeat::Until(Condition(OwningNode::Attr(FieldName::valid("until").into()))))); } /// ```yaml @@ -1801,7 +1801,7 @@ mod repeat { assert_eq!(rep, Err(Validation("missed `repeat: until`".into()))); #[cfg(not(feature = "compatible"))] - assert_eq!(rep, Ok(Repeat::Until(Condition(OwningNode::Attr(FieldName::valid("until")))))); + assert_eq!(rep, Ok(Repeat::Until(Condition(OwningNode::Attr(FieldName::valid("until").into()))))); } } } @@ -2564,7 +2564,7 @@ mod sizeof { let chunk = Chunk { type_ref, size: Size::Exact { - count: Count(OwningNode::Attr(FieldName::valid("x"))), + count: Count(OwningNode::Attr(FieldName::valid("x").into())), until: None, }, }; @@ -2585,7 +2585,7 @@ mod sizeof { let chunk = Chunk { type_ref, size: Size::Exact { - count: Count(OwningNode::Attr(FieldName::valid("x"))), + count: Count(OwningNode::Attr(FieldName::valid("x").into())), until: Some(0x00.into()), }, }; diff --git a/src/parser/expressions.rs b/src/parser/expressions.rs index b66c06e..101fbbb 100644 --- a/src/parser/expressions.rs +++ b/src/parser/expressions.rs @@ -36,9 +36,7 @@ pub enum Node<'input> { ContextVar(ContextVar), /// Name of field of the type in which attribute expression is defined - Attr(&'input str), - /// Built-in field - BuiltinAttr(BuiltinAttr), + Attr(Attr<'input>), /// Reference to an enum value. EnumValue { /// A type that defines this enum. @@ -180,10 +178,10 @@ impl<'input> From for Node<'input> { Self::ContextVar(value) } } -impl<'input> From for Node<'input> { +impl<'input> From> for Node<'input> { #[inline] - fn from(value: BuiltinAttr) -> Self { - Self::BuiltinAttr(value) + fn from(value: Attr<'input>) -> Self { + Self::Attr(value) } } @@ -266,17 +264,17 @@ pub enum ContextVar { IsLe,//TODO: what's this? } -/// Built-in attributes of types. +/// Attributes of types. #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum BuiltinAttr { - /// `_io`: stream associated with this object of user-defined type. +pub enum Attr<'input> { + /// Built-in attribute `_io`: stream associated with this object of user-defined type. Stream, - /// `_root`: top-level user-defined structure in the current file. + /// Built-in attribute `_root`: top-level user-defined structure in the current file. Root, - /// `_parent`: structure that produced this particular instance of the + /// Built-in attribute `_parent`: structure that produced this particular instance of the /// user-defined type. Parent, - /// `_sizeof`: used as an attribute of the struct to get a compile-time size + /// Built-in attribute `_sizeof`: used as an attribute of the struct to get a compile-time size /// of the structure: /// /// ```yaml @@ -287,6 +285,8 @@ pub enum BuiltinAttr { /// size: file_hdr.ofs_bitmap - file_hdr._sizeof /// ``` SizeOf, + /// User-defined attribute of the type + User(&'input str), } /// List of possible unary operations @@ -644,7 +644,7 @@ peg::parser! { / v:(s:string() _ {s})+ { Node::Str(String::from_iter(v.into_iter())) } / n:special_name() !name_part() { n } / e:enum_name() { e } - / n:name() { Node::Attr(n) } + / n:name() { Node::Attr(Attr::User(n)) } / f:float() { Node::Float(f) } / i:integer() { Node::Int(i) } ; @@ -652,10 +652,10 @@ peg::parser! { rule special_name() -> Node<'input> = "true" { Node::Bool(true) } / "false" { Node::Bool(false) } - / "_io" { Node::BuiltinAttr(BuiltinAttr::Stream) } - / "_root" { Node::BuiltinAttr(BuiltinAttr::Root) } - / "_parent" { Node::BuiltinAttr(BuiltinAttr::Parent) } - / "_sizeof" { Node::BuiltinAttr(BuiltinAttr::SizeOf) } + / "_io" { Node::Attr(Attr::Stream) } + / "_root" { Node::Attr(Attr::Root) } + / "_parent" { Node::Attr(Attr::Parent) } + / "_sizeof" { Node::Attr(Attr::SizeOf) } / "_on" { Node::ContextVar(ContextVar::SwitchOn) } / "_index" { Node::ContextVar(ContextVar::Index) } / "_is_le" { Node::ContextVar(ContextVar::IsLe) } @@ -710,6 +710,7 @@ peg::parser! { #[cfg(test)] mod parse { + use super::Attr::User; use super::BinaryOp::*; use super::Node::*; use super::UnaryOp::*; @@ -1078,7 +1079,7 @@ mod parse { fn expr_then_expr() { assert_eq!(parse_single(r#" f"{123}{abc}" "#), Ok(InterpolatedStr(vec![ Int(123.into()), - Attr("abc".into()), + Attr(User("abc")), ]))); } @@ -1117,7 +1118,7 @@ mod parse { assert_eq!(parse_single(r#" f" { f"{def}" } " "#), Ok(InterpolatedStr(vec![ Str(" ".into()), // f"abc{def}" - InterpolatedStr(vec![Attr("def".into())]), + InterpolatedStr(vec![Attr(User("def"))]), Str(" ".into()), ]))); } @@ -1198,7 +1199,7 @@ mod parse { fn ternary() { assert_eq!(parse_single("x ? \"foo\" : \"bar\""), Ok( Branch { - condition: Box::new(Attr("x")), + condition: Box::new(Attr(User("x"))), if_true: Box::new(Str("foo".into())), if_false: Box::new(Str("bar".into())) } @@ -1249,11 +1250,11 @@ mod parse { #[test] fn indexing() { assert_eq!(parse_single("a[42]"), Ok( - Index { expr: Box::new(Attr("a")), index: Box::new(Int(42.into())) } + Index { expr: Box::new(Attr(User("a"))), index: Box::new(Int(42.into())) } )); assert_eq!(parse_single("a[42 - 2]"), Ok( Index { - expr: Box::new(Attr("a")), + expr: Box::new(Attr(User("a"))), index: Box::new(Binary { op: Sub, left: Box::new(Int(42.into())), @@ -1365,52 +1366,52 @@ mod parse { #[test] fn builtin_attr() { - assert_eq!(parse_single("_io"), Ok(BuiltinAttr(crate::parser::expressions::BuiltinAttr::Stream))); - assert_eq!(parse_single("_root"), Ok(BuiltinAttr(crate::parser::expressions::BuiltinAttr::Root))); - assert_eq!(parse_single("_parent"), Ok(BuiltinAttr(crate::parser::expressions::BuiltinAttr::Parent))); - assert_eq!(parse_single("_sizeof"), Ok(BuiltinAttr(crate::parser::expressions::BuiltinAttr::SizeOf))); + assert_eq!(parse_single("_io"), Ok(Attr(crate::parser::expressions::Attr::Stream))); + assert_eq!(parse_single("_root"), Ok(Attr(crate::parser::expressions::Attr::Root))); + assert_eq!(parse_single("_parent"), Ok(Attr(crate::parser::expressions::Attr::Parent))); + assert_eq!(parse_single("_sizeof"), Ok(Attr(crate::parser::expressions::Attr::SizeOf))); } #[test] fn identifiers() { - assert_eq!(parse_single("truex"), Ok(Attr("truex"))); - assert_eq!(parse_single("true1"), Ok(Attr("true1"))); + assert_eq!(parse_single("truex"), Ok(Attr(User("truex")))); + assert_eq!(parse_single("true1"), Ok(Attr(User("true1")))); - assert_eq!(parse_single("falsex"), Ok(Attr("falsex"))); - assert_eq!(parse_single("false1"), Ok(Attr("false1"))); + assert_eq!(parse_single("falsex"), Ok(Attr(User("falsex")))); + assert_eq!(parse_single("false1"), Ok(Attr(User("false1")))); - assert_eq!(parse_single("notx"), Ok(Attr("notx"))); - assert_eq!(parse_single("not1"), Ok(Attr("not1"))); + assert_eq!(parse_single("notx"), Ok(Attr(User("notx")))); + assert_eq!(parse_single("not1"), Ok(Attr(User("not1")))); - assert_eq!(parse_single("andx"), Ok(Attr("andx"))); - assert_eq!(parse_single("and1"), Ok(Attr("and1"))); + assert_eq!(parse_single("andx"), Ok(Attr(User("andx")))); + assert_eq!(parse_single("and1"), Ok(Attr(User("and1")))); - assert_eq!(parse_single("orx"), Ok(Attr("orx"))); - assert_eq!(parse_single("or1"), Ok(Attr("or1"))); + assert_eq!(parse_single("orx"), Ok(Attr(User("orx")))); + assert_eq!(parse_single("or1"), Ok(Attr(User("or1")))); - assert_eq!(parse_single("_iox"), Ok(Attr("_iox"))); - assert_eq!(parse_single("_io1"), Ok(Attr("_io1"))); + assert_eq!(parse_single("_iox"), Ok(Attr(User("_iox")))); + assert_eq!(parse_single("_io1"), Ok(Attr(User("_io1")))); - assert_eq!(parse_single("_rootx"), Ok(Attr("_rootx"))); - assert_eq!(parse_single("_root1"), Ok(Attr("_root1"))); + assert_eq!(parse_single("_rootx"), Ok(Attr(User("_rootx")))); + assert_eq!(parse_single("_root1"), Ok(Attr(User("_root1")))); - assert_eq!(parse_single("_parentx"), Ok(Attr("_parentx"))); - assert_eq!(parse_single("_parent1"), Ok(Attr("_parent1"))); + assert_eq!(parse_single("_parentx"), Ok(Attr(User("_parentx")))); + assert_eq!(parse_single("_parent1"), Ok(Attr(User("_parent1")))); - assert_eq!(parse_single("_indexx"), Ok(Attr("_indexx"))); - assert_eq!(parse_single("_index1"), Ok(Attr("_index1"))); + assert_eq!(parse_single("_indexx"), Ok(Attr(User("_indexx")))); + assert_eq!(parse_single("_index1"), Ok(Attr(User("_index1")))); - assert_eq!(parse_single("_x"), Ok(Attr("_x"))); - assert_eq!(parse_single("_1"), Ok(Attr("_1"))); + assert_eq!(parse_single("_x"), Ok(Attr(User("_x")))); + assert_eq!(parse_single("_1"), Ok(Attr(User("_1")))); - assert_eq!(parse_single("_onx"), Ok(Attr("_onx"))); - assert_eq!(parse_single("_on1"), Ok(Attr("_on1"))); + assert_eq!(parse_single("_onx"), Ok(Attr(User("_onx")))); + assert_eq!(parse_single("_on1"), Ok(Attr(User("_on1")))); - assert_eq!(parse_single("_sizeofx"), Ok(Attr("_sizeofx"))); - assert_eq!(parse_single("_sizeof1"), Ok(Attr("_sizeof1"))); + assert_eq!(parse_single("_sizeofx"), Ok(Attr(User("_sizeofx")))); + assert_eq!(parse_single("_sizeof1"), Ok(Attr(User("_sizeof1")))); - assert_eq!(parse_single("_is_lex"), Ok(Attr("_is_lex"))); - assert_eq!(parse_single("_is_le1"), Ok(Attr("_is_le1"))); + assert_eq!(parse_single("_is_lex"), Ok(Attr(User("_is_lex")))); + assert_eq!(parse_single("_is_le1"), Ok(Attr(User("_is_le1")))); } } @@ -1467,7 +1468,7 @@ mod parse { fn var_as_type() { assert_eq!(parse_single("foo.as"), Ok( Cast { - expr: Box::new(Attr("foo")), + expr: Box::new(Attr(User("foo"))), to_type: TypeRef { name: TypeName { scope: Scope { absolute: false, path: vec![] }, @@ -1482,7 +1483,7 @@ mod parse { fn as_type_with_spaces() { assert_eq!(parse_single("foo.as < x > "), Ok( Cast { - expr: Box::new(Attr("foo")), + expr: Box::new(Attr(User("foo"))), to_type: TypeRef { name: TypeName { scope: Scope { absolute: false, path: vec![] }, @@ -1498,7 +1499,7 @@ mod parse { fn as_enum() { assert_eq!(parse_single("foo.as"), Ok( Cast { - expr: Box::new(Attr("foo")), + expr: Box::new(Attr(User("foo"))), to_type: TypeRef {//TODO: should be enum name: TypeName { scope: Scope { absolute: false, path: vec!["bar"] }, @@ -1510,7 +1511,7 @@ mod parse { )); assert_eq!(parse_single("foo.as<::bar::baz>"), Ok( Cast { - expr: Box::new(Attr("foo")), + expr: Box::new(Attr(User("foo"))), to_type: TypeRef {//TODO: should be enum name: TypeName { scope: Scope { absolute: true, path: vec!["bar"] }, @@ -1526,7 +1527,7 @@ mod parse { fn as_array() { assert_eq!(parse_single("foo.as"), Ok( Cast { - expr: Box::new(Attr("foo")), + expr: Box::new(Attr(User("foo"))), to_type: TypeRef { name: TypeName { scope: Scope { absolute: false, path: vec![] }, @@ -1538,7 +1539,7 @@ mod parse { )); assert_eq!(parse_single("foo.as<::bar::baz[]>"), Ok( Cast { - expr: Box::new(Attr("foo")), + expr: Box::new(Attr(User("foo"))), to_type: TypeRef { name: TypeName { scope: Scope { absolute: true, path: vec!["bar"] }, @@ -1554,7 +1555,7 @@ mod parse { fn attribute() { assert_eq!(parse_single("foo.as"), Ok( Access { - expr: Box::new(Attr("foo")), + expr: Box::new(Attr(User("foo"))), attr: "as", } )); @@ -1566,10 +1567,10 @@ mod parse { Binary { op: Lt, left: Box::new(Access { - expr: Box::new(Attr("foo")), + expr: Box::new(Attr(User("foo"))), attr: "as" }), - right: Box::new(Attr("x")), + right: Box::new(Attr(User("x"))), } )); } @@ -1628,8 +1629,8 @@ mod parse { assert_eq!(parse_single("sizeof