From 5bff865da4b9e5fce980fd0a74c75323456e4057 Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Thu, 18 Nov 2021 15:56:02 -0800 Subject: [PATCH] replace lalrpop message parser with ros_message --- Cargo.toml | 7 +- build.rs | 6 -- examples/bag_info.rs | 66 ++++++++++-- src/error.rs | 4 +- src/lib.rs | 1 - src/message_definition.rs | 2 - src/message_definition/.gitignore | 1 - src/message_definition/ast.rs | 140 ------------------------- src/message_definition/grammar.lalrpop | 90 ---------------- 9 files changed, 60 insertions(+), 257 deletions(-) delete mode 100644 build.rs delete mode 100644 src/message_definition.rs delete mode 100644 src/message_definition/.gitignore delete mode 100644 src/message_definition/ast.rs delete mode 100644 src/message_definition/grammar.lalrpop diff --git a/Cargo.toml b/Cargo.toml index e83060e..8d71552 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,22 +2,19 @@ name = "rsbag" version = "0.1.0" edition = "2018" -build = "build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] bytes = "1.1.0" -lalrpop-util = "0.19.6" log = "0.4.14" nom = "7.0.0" num_enum = "0.5.4" +regex = "1.5.4" +ros_message = "0.1.0" smallvec = "1.6.1" thiserror = "1.0.28" [dev-dependencies] env_logger = "0.9.0" eyre = "0.6.5" - -[build-dependencies] -lalrpop = "0.19.6" diff --git a/build.rs b/build.rs deleted file mode 100644 index 228a429..0000000 --- a/build.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - lalrpop::Configuration::new() - .generate_in_source_tree() - .process() - .unwrap(); -} diff --git a/examples/bag_info.rs b/examples/bag_info.rs index 7c86692..a4a0aac 100644 --- a/examples/bag_info.rs +++ b/examples/bag_info.rs @@ -1,8 +1,46 @@ -use std::{env::args, fs::File}; +use std::{convert::TryFrom, env::args, fs::File}; use log::{error, info, trace}; -use nom::Parser; -use rsbag::{index::BagIndex, reader::IoReader}; +use regex::Regex; +use ros_message::{MessagePath, Msg}; +use rsbag::{ + index::{BagIndex, ConnInfo}, + reader::IoReader, +}; + +fn parse_msgdef(message_name: &str, msgdef: &str) -> rsbag::Result { + trace!("message definition: {}", msgdef); + let path = MessagePath::try_from(message_name).map_err(rsbag::Error::other)?; + let msgtype = Msg::new(path, msgdef).map_err(rsbag::Error::other)?; + Ok(msgtype) +} + +fn parse_message_definitions(conn: &ConnInfo) -> rsbag::Result> { + let msgdefs = conn.message_definition()?; + let boundary_re = Regex::new(r"\r?\n==+\r?\nMSG: ([^\r\n]+)\r?\n").unwrap(); + let mut name = conn.datatype()?; + let mut begin = 0usize; + let mut msgs = Vec::new(); + + for cap in boundary_re.captures_iter(&msgdefs) { + let boundary_range = cap.get(0).unwrap(); + let end = boundary_range.start(); + + let msgdef = &msgdefs[begin..end]; + let msgtype = parse_msgdef(&name, msgdef)?; + msgs.push(msgtype); + + name = cap[1].to_string(); + begin = boundary_range.end(); + } + + let msgdef = &msgdefs[begin..]; + + let msg = parse_msgdef(&name, msgdef)?; + msgs.push(msg); + + Ok(msgs) +} fn main() { env_logger::init(); @@ -20,15 +58,23 @@ fn main() { match BagIndex::read_all(&mut bag_reader) { Ok(index) => { for conn in &index.connections { - let msgdef = conn.message_definition().unwrap(); - trace!("message definition: {}", msgdef); - let parser = rsbag::message_definition::grammar::MessageDefinitionParser::new(); - match parser.parse(&msgdef) { - Ok(def) => info!("message definition parsed: {}", def), - Err(err) => error!("message definition parse error: {}", err), + match parse_message_definitions(conn) { + Ok(msgs) => { + for msg in &msgs { + info!( + "message definition parsed: {:#?}", + msg.fields() + .iter() + .filter(|field| !field.is_constant()) + .map(ToString::to_string) + .collect::>() + ); + } + } + Err(err) => error!("could not parse message definition: {}", err), } } - }, + } Err(err) => error!("bag parse error: {}", err), } } diff --git a/src/error.rs b/src/error.rs index d2b7855..ad7f55e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -41,8 +41,8 @@ impl<'a> From>>> for Error { } impl Error { - pub fn other>(message: S) -> Self { - Error::Other(message.into()) + pub fn other(message: S) -> Self { + Error::Other(message.to_string()) } } diff --git a/src/lib.rs b/src/lib.rs index e342684..a9f05f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,5 @@ mod error; pub mod index; pub mod parse; pub mod reader; -pub mod message_definition; pub use error::{Error, Result}; diff --git a/src/message_definition.rs b/src/message_definition.rs deleted file mode 100644 index b47f0ce..0000000 --- a/src/message_definition.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod ast; -pub mod grammar; diff --git a/src/message_definition/.gitignore b/src/message_definition/.gitignore deleted file mode 100644 index 39cd0aa..0000000 --- a/src/message_definition/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/grammar.rs \ No newline at end of file diff --git a/src/message_definition/ast.rs b/src/message_definition/ast.rs deleted file mode 100644 index f5a3c53..0000000 --- a/src/message_definition/ast.rs +++ /dev/null @@ -1,140 +0,0 @@ -use core::fmt::{self, Write}; - -pub type SmallStr = String; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum PrimitiveType { - Bool, - Int8, - Uint8, - Int16, - Uint16, - Int32, - Uint32, - Int64, - Uint64, - Float32, - Float64, -} - -impl PrimitiveType { - fn as_str(self) -> &'static str { - match self { - PrimitiveType::Bool => "bool", - PrimitiveType::Int8 => "int8_t", - PrimitiveType::Uint8 => "uint8_t", - PrimitiveType::Int16 => "int16_t", - PrimitiveType::Uint16 => "uint16_t", - PrimitiveType::Int32 => "int32_t", - PrimitiveType::Uint32 => "uint32_t", - PrimitiveType::Int64 => "int64_t", - PrimitiveType::Uint64 => "uint64_t", - PrimitiveType::Float32 => "float32", - PrimitiveType::Float64 => "float64", - } - } - - pub fn size(self) -> usize { - match self { - PrimitiveType::Bool => 1, - PrimitiveType::Int8 => 1, - PrimitiveType::Uint8 => 1, - PrimitiveType::Int16 => 2, - PrimitiveType::Uint16 => 2, - PrimitiveType::Int32 => 4, - PrimitiveType::Uint32 => 4, - PrimitiveType::Int64 => 8, - PrimitiveType::Uint64 => 8, - PrimitiveType::Float32 => 4, - PrimitiveType::Float64 => 8, - } - } -} - -impl fmt::Display for PrimitiveType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) - } -} - -#[derive(Clone, Debug, PartialEq)] -pub struct ArrayType { - pub element_type: Box, - pub length: Option, -} - -impl ArrayType { - pub fn new(element_type: FieldType, length: Option) -> Self { - Self { - element_type: Box::new(element_type), - length, - } - } -} - -impl fmt::Display for ArrayType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.element_type.fmt(f)?; - f.write_char('[')?; - if let Some(length) = self.length { - length.fmt(f)?; - } - f.write_char(']') - } -} - -#[derive(Clone, Debug, PartialEq)] -pub enum FieldType { - Primitive(PrimitiveType), - String, - Time, - Duration, - Header, - Array(ArrayType), - Other(SmallStr), -} - -impl fmt::Display for FieldType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - FieldType::Primitive(primitive) => primitive.fmt(f), - FieldType::String => "string".fmt(f), - FieldType::Time => "time".fmt(f), - FieldType::Duration => "duration".fmt(f), - FieldType::Header => "Header".fmt(f), - FieldType::Array(array) => array.fmt(f), - FieldType::Other(other) => other.fmt(f), - } - } -} - -#[derive(Clone, Debug, PartialEq)] -pub struct MessageField { - pub name: SmallStr, - pub typ: FieldType, -} - -impl fmt::Display for MessageField { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{} {}", &self.typ, &self.name) - } -} - -#[derive(Clone, Debug, PartialEq)] -pub struct MessageDefinition { - pub fields: Vec, -} - -impl fmt::Display for MessageDefinition { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for field in &self.fields { - writeln!(f, "{}", field)?; - } - Ok(()) - } -} - -pub struct MessageDefinitions { - pub primary: MessageDefinition, - pub dependencies: Vec<(String, MessageDefinition)>, -} \ No newline at end of file diff --git a/src/message_definition/grammar.lalrpop b/src/message_definition/grammar.lalrpop deleted file mode 100644 index e911577..0000000 --- a/src/message_definition/grammar.lalrpop +++ /dev/null @@ -1,90 +0,0 @@ -use super::ast::{ - PrimitiveType, ArrayType, FieldType, MessageField, MessageDefinition, MessageDefinitions -}; -use std::str::FromStr; - -grammar; - -match { - "bool", - "int8", - "uint8", - "int16", - "uint16", - "int32", - "uint32", - "int64", - "uint64", - "float32", - "float64", - "string", - "time", - "duration", - "Header", - "[", - "]", - r"==+\r?\nMSG: " => "MESSAGE_BOUNDARY", - r"[0-9]+" => "LENGTH", - r"[\t ]*" => { }, - r"#[^\n\r]*" => { }, // Skip `# comments` -} else { - r"[a-zA-Z][a-zA-Z0-9_]*" => "IDENT", -} else { - r"[a-zA-Z][a-zA-Z0-9_]*(/[a-zA-Z][a-zA-Z0-9_]*)*" => "TYPENAME", - r"\r?\n" => "CRLF", -} - -PrimitiveType: PrimitiveType = { - "bool" => PrimitiveType::Bool, - "int8" => PrimitiveType::Int8, - "uint8" => PrimitiveType::Uint8, - "int16" => PrimitiveType::Int16, - "uint16" => PrimitiveType::Uint16, - "int32" => PrimitiveType::Int32, - "uint32" => PrimitiveType::Uint32, - "int64" => PrimitiveType::Int64, - "uint64" => PrimitiveType::Uint64, - "float32" => PrimitiveType::Float32, - "float64" => PrimitiveType::Float64, -}; - -ArrayLength: Option = { - "[" <"LENGTH"> "]" => Some(usize::from_str(<>).unwrap()), - "[" "]" => None, -}; - -ArrayType: ArrayType = - FieldType ArrayLength => ArrayType::new(<>); - -Ident: String = "IDENT" => <>.to_string(); -TypeName: String = { - "TYPENAME" => <>.to_string(), - "IDENT" => <>.to_string(), -}; - -FieldType: FieldType = { - PrimitiveType => FieldType::Primitive(<>), - "string" => FieldType::String, - "time" => FieldType::Time, - "duration" => FieldType::Duration, - "Header" => FieldType::Header, - ArrayType => FieldType::Array(<>), - TypeName => FieldType::Other(<>), -} - -MessageField: MessageField = { - => MessageField { <> } -} - -MessageFields: Vec = - <( "CRLF"+)*> => <>; - -pub MessageDefinition: MessageDefinition = - "CRLF"* => MessageDefinition { fields }; - -NamedMessageDefinition: (String, MessageDefinition) = - "MESSAGE_BOUNDARY" "CRLF" => (<>); - -pub MessageDefinitions: MessageDefinitions = - - => MessageDefinitions { <> };