Skip to content

Commit

Permalink
Recognize special attributes (_sizeof, _io, _parent, and _root) on ob…
Browse files Browse the repository at this point in the history
…jects referred via variables
  • Loading branch information
Mingun committed Sep 14, 2024
1 parent 3995573 commit 8edbf22
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 30 deletions.
6 changes: 3 additions & 3 deletions src/model/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub enum OwningNode {
/// Expression which attribute must be evaluated
expr: Box<OwningNode>,
/// Retrieved attribute
attr: FieldName,
attr: OwningAttr,
},

/// The unary prefix operator, such as unary `-` or logical `not`.
Expand Down Expand Up @@ -165,8 +165,8 @@ impl OwningNode {
},
Node::Access { expr, attr } => Access {
expr: Box::new(Self::validate(*expr)?),
//TODO: Name already contains only valid symbols, but need to check that it is really exists
attr: FieldName::valid(attr),
//TODO: Need to check that attribute is really exists in the type
attr: attr.try_into()?,
},

Node::Unary { op, expr } => {
Expand Down
60 changes: 33 additions & 27 deletions src/parser/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub enum Node<'input> {
/// Expression which attribute must be evaluated
expr: Box<Node<'input>>,
/// Retrieved attribute
attr: &'input str,
attr: Attr<'input>,
},

/// The unary prefix operator, such as unary `-` or logical `not`.
Expand Down Expand Up @@ -393,7 +393,7 @@ enum Postfix<'input> {
/// Index expression
Index(Node<'input>),
/// Field name for attribute access
Field(&'input str),
Field(Attr<'input>),
}

/// Helper function to convert escape codes to characters
Expand Down Expand Up @@ -644,28 +644,34 @@ 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(Attr::User(n)) }
/ a:attr() { Node::Attr(a) }
/ f:float() { Node::Float(f) }
/ i:integer() { Node::Int(i) }
;

rule special_name() -> Node<'input>
= "true" { Node::Bool(true) }
/ "false" { Node::Bool(false) }
/ "_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) }
/ "_" { Node::ContextVar(ContextVar::Value) }
;
rule special_attr() -> Attr<'input>
= "_io" { Attr::Stream }
/ "_root" { Attr::Root }
/ "_parent" { Attr::Parent }
/ "_sizeof" { Attr::SizeOf }
;
rule attr() -> Attr<'input>
= a:special_attr() !name_part() { a }
/ n:name() { Attr::User(n) }
;
rule postfix() -> Postfix<'input>
= "(" _ a:args() _ ")" { Postfix::Args(a) }// call
/ "[" _ e:expr() _ "]" { Postfix::Index(e) }// indexing
/ "." _ "as" _ "<" _ t:type_ref() _ ">" { Postfix::CastTo(t) }// type cast
/ "." _ n:name() { Postfix::Field(n) }// attribute access
/ "." _ a:attr() { Postfix::Field(a) }// attribute access
;

/// List of names, delimited by `::`, with an optional leading `::`.
Expand Down Expand Up @@ -1330,7 +1336,7 @@ mod parse {
name: "port",
value: "http",
}),
attr: "to_i"
attr: User("to_i"),
}),
right: Box::new(Int(8000.into()))
}),
Expand Down Expand Up @@ -1556,7 +1562,7 @@ mod parse {
assert_eq!(parse_single("foo.as"), Ok(
Access {
expr: Box::new(Attr(User("foo"))),
attr: "as",
attr: User("as"),
}
));
}
Expand All @@ -1568,7 +1574,7 @@ mod parse {
op: Lt,
left: Box::new(Access {
expr: Box::new(Attr(User("foo"))),
attr: "as"
attr: User("as"),
}),
right: Box::new(Attr(User("x"))),
}
Expand Down Expand Up @@ -1674,32 +1680,32 @@ mod parse {

#[test]
fn access() {
assert_eq!(parse_single("123.to_s" ), Ok(Access { expr: Box::new(Int(123.into())), attr: "to_s" }));
assert_eq!(parse_single("123. to_s" ), Ok(Access { expr: Box::new(Int(123.into())), attr: "to_s" }));
assert_eq!(parse_single("123.\nto_s"), Ok(Access { expr: Box::new(Int(123.into())), attr: "to_s" }));
assert_eq!(parse_single("foo.bar" ), Ok(Access { expr: Box::new(Attr(User("foo"))), attr: "bar" }));
assert_eq!(parse_single("123.to_s" ), Ok(Access { expr: Box::new(Int(123.into())), attr: User("to_s"), }));
assert_eq!(parse_single("123. to_s" ), Ok(Access { expr: Box::new(Int(123.into())), attr: User("to_s"), }));
assert_eq!(parse_single("123.\nto_s"), Ok(Access { expr: Box::new(Int(123.into())), attr: User("to_s"), }));
assert_eq!(parse_single("foo.bar" ), Ok(Access { expr: Box::new(Attr(User("foo"))), attr: User("bar"), }));
}

#[test]
fn int_not_float() {
assert_eq!(parse_single("123.e" ), Ok(Access { expr: Box::new(Int(123.into())), attr: "e" }));
assert_eq!(parse_single("123. e" ), Ok(Access { expr: Box::new(Int(123.into())), attr: "e" }));
assert_eq!(parse_single("123.\ne"), Ok(Access { expr: Box::new(Int(123.into())), attr: "e" }));
assert_eq!(parse_single("123.e" ), Ok(Access { expr: Box::new(Int(123.into())), attr: User("e"), }));
assert_eq!(parse_single("123. e" ), Ok(Access { expr: Box::new(Int(123.into())), attr: User("e"), }));
assert_eq!(parse_single("123.\ne"), Ok(Access { expr: Box::new(Int(123.into())), attr: User("e"), }));

assert_eq!(parse_single("123.E" ), Ok(Access { expr: Box::new(Int(123.into())), attr: "E" }));
assert_eq!(parse_single("123. E" ), Ok(Access { expr: Box::new(Int(123.into())), attr: "E" }));
assert_eq!(parse_single("123.\nE"), Ok(Access { expr: Box::new(Int(123.into())), attr: "E" }));
assert_eq!(parse_single("123.E" ), Ok(Access { expr: Box::new(Int(123.into())), attr: User("E"), }));
assert_eq!(parse_single("123. E" ), Ok(Access { expr: Box::new(Int(123.into())), attr: User("E"), }));
assert_eq!(parse_single("123.\nE"), Ok(Access { expr: Box::new(Int(123.into())), attr: User("E"), }));

assert_eq!(parse_single("123._" ), Ok(Access { expr: Box::new(Int(123.into())), attr: "_" }));
assert_eq!(parse_single("123. _" ), Ok(Access { expr: Box::new(Int(123.into())), attr: "_" }));
assert_eq!(parse_single("123.\n_"), Ok(Access { expr: Box::new(Int(123.into())), attr: "_" }));
assert_eq!(parse_single("123._" ), Ok(Access { expr: Box::new(Int(123.into())), attr: User("_"), }));
assert_eq!(parse_single("123. _" ), Ok(Access { expr: Box::new(Int(123.into())), attr: User("_"), }));
assert_eq!(parse_single("123.\n_"), Ok(Access { expr: Box::new(Int(123.into())), attr: User("_"), }));
}

#[test]
fn float_and_access() {
assert_eq!(parse_single("123.4.to_s" ), Ok(Access { expr: Box::new(Float((1234, 1).into())), attr: "to_s" }));
assert_eq!(parse_single("123.4. to_s" ), Ok(Access { expr: Box::new(Float((1234, 1).into())), attr: "to_s" }));
assert_eq!(parse_single("123.4.\nto_s"), Ok(Access { expr: Box::new(Float((1234, 1).into())), attr: "to_s" }));
assert_eq!(parse_single("123.4.to_s" ), Ok(Access { expr: Box::new(Float((1234, 1).into())), attr: User("to_s"), }));
assert_eq!(parse_single("123.4. to_s" ), Ok(Access { expr: Box::new(Float((1234, 1).into())), attr: User("to_s"), }));
assert_eq!(parse_single("123.4.\nto_s"), Ok(Access { expr: Box::new(Float((1234, 1).into())), attr: User("to_s"), }));
}
}

Expand Down

0 comments on commit 8edbf22

Please sign in to comment.