extern crate reproto_core as core; extern crate reproto_lexer as lexer; use core::{Loc, RpNumber, Span}; use std::borrow::Cow; use std::ops; use std::vec; /// Items can be commented and have attributes. /// /// This is an intermediate structure used to return these properties. /// /// ```ignore /// /// This is a comment. /// #[foo] /// #[foo(value = "hello")] /// /// ``` #[derive(Debug, PartialEq, Eq)] pub struct Item<'input, T> { pub comment: Vec>, pub attributes: Vec>>, pub item: Loc, } /// Item derefs into target. impl<'input, T> ops::Deref for Item<'input, T> { type Target = T; fn deref(&self) -> &Self::Target { Loc::borrow(&self.item) } } /// Name value pair. /// /// Is associated with attributes: /// /// ```ignore /// #[attribute(name = )] /// ``` #[derive(Debug, PartialEq, Eq)] pub enum AttributeItem<'input> { Word(Loc>), NameValue { name: Loc>, value: Loc>, }, } /// An attribute. /// /// Attributes are metadata associated with elements. /// /// ```ignore /// #[word] /// ``` /// /// or: /// /// ```ignore /// #[name_value(foo = , bar = )] /// ``` #[derive(Debug, PartialEq, Eq)] pub enum Attribute<'input> { Word(Loc>), List(Loc>, Vec>), } /// A type. /// /// For example: `u32`, `::Relative::Name`, or `bytes`. #[derive(Debug, Clone, PartialEq, Eq)] pub enum Type<'input> { Double, Float, Signed { size: usize, }, Unsigned { size: usize, }, Boolean, String, Bytes, Any, /// ISO-8601 for date and time. DateTime, Name { name: Loc>, }, Array { inner: Box>>, }, Map { key: Box>>, value: Box>>, }, /// A complete error. Error, } /// Any kind of declaration. #[derive(Debug, PartialEq, Eq)] pub enum Decl<'input> { Type(Item<'input, TypeBody<'input>>), Tuple(Item<'input, TupleBody<'input>>), Interface(Item<'input, InterfaceBody<'input>>), Enum(Item<'input, EnumBody<'input>>), Service(Item<'input, ServiceBody<'input>>), } impl<'input> Decl<'input> { /// Get the local name for the declaration. pub fn name(&self) -> Loc<&str> { use self::Decl::*; let name: &Loc> = match *self { Type(ref body) => &body.name, Tuple(ref body) => &body.name, Interface(ref body) => &body.name, Enum(ref body) => &body.name, Service(ref body) => &body.name, }; Loc::map(Loc::as_ref(name), |n| n.as_ref()) } /// Get all the sub-declarations of this declaraiton. pub fn decls(&self) -> Decls { use self::Decl::*; let decls = match *self { Type(ref body) => body.decls(), Tuple(ref body) => body.decls(), Interface(ref body) => body.decls(), Enum(ref body) => body.decls(), Service(ref body) => body.decls(), }; Decls { iter: decls.into_iter(), } } /// Comment. pub fn comment(&self) -> &Vec> { use self::Decl::*; match *self { Type(ref body) => &body.comment, Tuple(ref body) => &body.comment, Interface(ref body) => &body.comment, Enum(ref body) => &body.comment, Service(ref body) => &body.comment, } } } pub struct Decls<'a, 'input: 'a> { iter: vec::IntoIter<&'a Decl<'input>>, } impl<'a, 'input: 'a> Iterator for Decls<'a, 'input> { type Item = &'a Decl<'input>; fn next(&mut self) -> Option { self.iter.next() } } /// The body of an enum declaration. /// /// ```ignore /// enum as { /// /// /// /// } /// ``` /// /// Note: members must only be options. #[derive(Debug, PartialEq, Eq)] pub struct EnumBody<'input> { pub name: Loc>, pub ty: Loc>, pub variants: Vec>>, pub members: Vec>, } impl<'input> EnumBody<'input> { /// Access all inner declarations. fn decls(&self) -> Vec<&Decl<'input>> { Vec::new() } } #[derive(Debug, PartialEq, Eq)] pub struct EnumVariant<'input> { pub name: Loc>, pub argument: Option>>, } /// A member in a tuple, type, or interface. #[derive(Debug, PartialEq, Eq)] pub enum EnumMember<'input> { Code(Loc>), } /// A field. /// /// ```ignore /// : as /// ``` #[derive(Debug, PartialEq, Eq)] pub struct Field<'input> { pub required: bool, pub name: Cow<'input, str>, pub ty: Loc>, pub field_as: Option, /// If the end-of-line indicator present. /// A `false` value should indicate an error. pub endl: bool, } /// A file. /// /// ```ignore /// /// /// /// /// /// ``` #[derive(Debug, PartialEq, Eq)] pub struct File<'input> { pub comment: Vec>, pub attributes: Vec>>, pub uses: Vec>>, pub decls: Vec>, } impl<'input> Field<'input> { pub fn is_optional(&self) -> bool { !self.required } } /// A name. /// /// Either: /// /// ```ignore /// ::Relative::Name /// ``` /// /// Or: /// /// ```ignore /// Absolute::Name /// ``` /// /// Note: prefixes names are _always_ imported with `UseDecl`. #[derive(Debug, Clone, PartialEq, Eq)] pub enum Name<'input> { Relative { parts: Vec>>, }, Absolute { prefix: Option>>, parts: Vec>>, }, } /// The body of an interface declaration /// /// ```ignore /// interface { /// /// /// } /// ``` #[derive(Debug, PartialEq, Eq)] pub struct InterfaceBody<'input> { pub name: Loc>, pub members: Vec>, pub sub_types: Vec>>, } impl<'input> InterfaceBody<'input> { /// Access all inner declarations. fn decls(&self) -> Vec<&Decl<'input>> { let mut out = Vec::new(); for m in &self.members { if let TypeMember::InnerDecl(ref decl) = *m { out.push(decl); } } out } /// Access all fields. pub fn fields(&self) -> Vec<&Field<'input>> { let mut out = Vec::new(); for m in &self.members { if let TypeMember::Field(ref field) = *m { out.push(Loc::borrow(&field.item)); } } out } } /// A contextual code-block. #[derive(Debug, PartialEq, Eq)] pub struct Code<'input> { pub attributes: Vec>>, pub context: Loc>, pub content: Vec>, } /// A member in a tuple, type, or interface. #[derive(Debug, PartialEq, Eq)] pub enum TypeMember<'input> { Field(Item<'input, Field<'input>>), Code(Loc>), InnerDecl(Decl<'input>), } /// The body of a service declaration. /// /// ```ignore /// service { /// /// } /// ``` #[derive(Debug, PartialEq, Eq)] pub struct ServiceBody<'input> { pub name: Loc>, pub members: Vec>, } impl<'input> ServiceBody<'input> { /// Access all inner declarations. fn decls(&self) -> Vec<&Decl<'input>> { let mut out = Vec::new(); for m in &self.members { if let ServiceMember::InnerDecl(ref decl) = *m { out.push(decl); } } out } /// Access all endpoints. pub fn endpoints(&self) -> Vec<&Endpoint<'input>> { let mut out = Vec::new(); for m in &self.members { if let ServiceMember::Endpoint(ref endpoint) = *m { out.push(Loc::borrow(&endpoint.item)); } } out } } /// A member of a service declaration. #[derive(Debug, PartialEq, Eq)] pub enum ServiceMember<'input> { Endpoint(Item<'input, Endpoint<'input>>), InnerDecl(Decl<'input>), } /// The argument in and endpoint. #[derive(Debug, PartialEq, Eq)] pub struct EndpointArgument<'input> { pub ident: Loc>, pub channel: Loc>, } /// An endpoint /// /// ```ignore /// () -> as { /// /// } /// ``` #[derive(Debug, PartialEq, Eq)] pub struct Endpoint<'input> { pub id: Loc>, pub alias: Option, pub arguments: Vec>, pub response: Option>>, } /// Describes how data is transferred over a channel. /// /// ```ignore /// Unary(stream ) /// Streaming() /// ``` #[derive(Debug, PartialEq, Eq)] pub enum Channel<'input> { /// Single send. Unary { ty: Loc> }, /// Multiple sends. Streaming { ty: Loc> }, } impl<'input> Channel<'input> { /// Access the type of the channel. pub fn ty(&self) -> &Loc> { use self::Channel::*; match *self { Unary { ref ty } => ty, Streaming { ref ty } => ty, } } } /// The body of a sub-type /// /// ```ignore /// as { /// /// } /// ``` /// Sub-types in interface declarations. #[derive(Debug, PartialEq, Eq)] pub struct SubType<'input> { pub name: Loc>, pub members: Vec>, pub alias: Option>>, } /// The body of a tuple /// /// ```ignore /// tuple { /// /// } /// ``` #[derive(Debug, PartialEq, Eq)] pub struct TupleBody<'input> { pub name: Loc>, pub members: Vec>, } impl<'input> TupleBody<'input> { /// Access all inner declarations. fn decls(&self) -> Vec<&Decl<'input>> { let mut out = Vec::new(); for m in &self.members { if let TypeMember::InnerDecl(ref decl) = *m { out.push(decl); } } out } /// Access all fields. pub fn fields(&self) -> Vec<&Field<'input>> { let mut out = Vec::new(); for m in &self.members { if let TypeMember::Field(ref field) = *m { out.push(Loc::borrow(&field.item)); } } out } } /// The body of a type /// /// ```ignore /// type { /// /// } /// ``` #[derive(Debug, PartialEq, Eq)] pub struct TypeBody<'input> { pub name: Loc>, pub members: Vec>, } impl<'input> TypeBody<'input> { /// Access all inner declarations. fn decls(&self) -> Vec<&Decl<'input>> { let mut out = Vec::new(); for m in &self.members { if let TypeMember::InnerDecl(ref decl) = *m { out.push(decl); } } out } /// Access all fields. pub fn fields(&self) -> Vec<&Field<'input>> { let mut out = Vec::new(); for m in &self.members { if let TypeMember::Field(ref field) = *m { out.push(Loc::borrow(&field.item)); } } out } } /// A package declaration. #[derive(Debug, PartialEq, Eq)] pub enum Package<'input> { /// A parsed package. Package { parts: Vec>> }, /// A recovered error. Error, } /// A use declaration /// /// ```ignore /// use "" as ; /// ``` #[derive(Debug, PartialEq, Eq)] pub struct UseDecl<'input> { pub package: Loc>, pub range: Option>, pub alias: Option>>, /// If the end-of-line indicator present. /// A empty value should indicate an error. pub endl: Option, } /// A literal value /// /// For example, `"string"`, `42.0`, and `foo`. #[derive(Debug, PartialEq, Eq)] pub enum Value<'input> { String(String), Number(RpNumber), Identifier(Cow<'input, str>), Array(Vec>>), } /// A part of a step. #[derive(Debug, PartialEq, Eq)] pub enum PathPart<'input> { Variable(Cow<'input, str>), Segment(String), } /// A step in a path specification. #[derive(Debug, PartialEq, Eq)] pub struct PathStep<'input> { pub parts: Vec>, } /// A path specification. #[derive(Debug, PartialEq, Eq)] pub struct PathSpec<'input> { pub steps: Vec>, }