Merge branch 'diary_sexp'
This commit is contained in:
		
						commit
						cf25a849c0
					
				
							
								
								
									
										2
									
								
								build.rs
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								build.rs
									
									
									
									
									
								
							| @ -61,7 +61,7 @@ fn write_header(test_file: &mut File) { | ||||
| use organic::compare_document; | ||||
| use organic::parser::document; | ||||
| use organic::emacs_parse_org_document; | ||||
| use organic::sexp; | ||||
| use organic::parser::sexp::sexp_with_padding; | ||||
| 
 | ||||
| "#
 | ||||
|     ) | ||||
|  | ||||
							
								
								
									
										1
									
								
								org_mode_samples/diary_sexp/simple.org
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								org_mode_samples/diary_sexp/simple.org
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| %%(foo) | ||||
| @ -1,9 +1,10 @@ | ||||
| use super::sexp::Token; | ||||
| use super::util::assert_bounds; | ||||
| use super::util::assert_name; | ||||
| use crate::parser::sexp::Token; | ||||
| use crate::parser::Clock; | ||||
| use crate::parser::Comment; | ||||
| use crate::parser::CommentBlock; | ||||
| use crate::parser::DiarySexp; | ||||
| use crate::parser::Document; | ||||
| use crate::parser::DocumentElement; | ||||
| use crate::parser::Drawer; | ||||
| @ -215,6 +216,7 @@ fn compare_element<'s>( | ||||
|         Element::ExportBlock(obj) => compare_export_block(source, emacs, obj), | ||||
|         Element::SrcBlock(obj) => compare_src_block(source, emacs, obj), | ||||
|         Element::Clock(obj) => compare_clock(source, emacs, obj), | ||||
|         Element::DiarySexp(obj) => compare_diary_sexp(source, emacs, obj), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -702,3 +704,26 @@ fn compare_clock<'s>( | ||||
|         children: Vec::new(), | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| fn compare_diary_sexp<'s>( | ||||
|     source: &'s str, | ||||
|     emacs: &'s Token<'s>, | ||||
|     rust: &'s DiarySexp<'s>, | ||||
| ) -> Result<DiffResult, Box<dyn std::error::Error>> { | ||||
|     let mut this_status = DiffStatus::Good; | ||||
|     let emacs_name = "diary-sexp"; | ||||
|     if assert_name(emacs, emacs_name).is_err() { | ||||
|         this_status = DiffStatus::Bad; | ||||
|     } | ||||
| 
 | ||||
|     if assert_bounds(source, emacs, rust).is_err() { | ||||
|         this_status = DiffStatus::Bad; | ||||
|     } | ||||
| 
 | ||||
|     Ok(DiffResult { | ||||
|         status: this_status, | ||||
|         name: emacs_name.to_owned(), | ||||
|         message: None, | ||||
|         children: Vec::new(), | ||||
|     }) | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,5 @@ | ||||
| mod diff; | ||||
| mod parse; | ||||
| mod sexp; | ||||
| mod util; | ||||
| pub use diff::compare_document; | ||||
| pub use parse::emacs_parse_org_document; | ||||
| pub use sexp::sexp; | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| use crate::parser::sexp::Token; | ||||
| use crate::parser::Source; | ||||
| 
 | ||||
| use super::sexp::Token; | ||||
| 
 | ||||
| /// Check if the child string slice is a slice of the parent string slice.
 | ||||
| fn is_slice_of(parent: &str, child: &str) -> bool { | ||||
|     let parent_start = parent.as_ptr() as usize; | ||||
|  | ||||
| @ -7,8 +7,6 @@ mod compare; | ||||
| pub use compare::compare_document; | ||||
| #[cfg(feature = "compare")] | ||||
| pub use compare::emacs_parse_org_document; | ||||
| #[cfg(feature = "compare")] | ||||
| pub use compare::sexp; | ||||
| 
 | ||||
| mod error; | ||||
| pub mod parser; | ||||
|  | ||||
| @ -2,13 +2,15 @@ | ||||
| use crate::init_tracing::init_telemetry; | ||||
| use crate::init_tracing::shutdown_telemetry; | ||||
| use ::organic::parser::document; | ||||
| use organic::parser::sexp::sexp; | ||||
| mod init_tracing; | ||||
| 
 | ||||
| const TEST_DOC: &'static str = include_str!("../toy_language.txt"); | ||||
| 
 | ||||
| fn main() -> Result<(), Box<dyn std::error::Error>> { | ||||
|     init_telemetry()?; | ||||
|     let parsed = document(TEST_DOC); | ||||
|     // let parsed = document(TEST_DOC);
 | ||||
|     let parsed = sexp(TEST_DOC); | ||||
|     println!("{}\n\n\n", TEST_DOC); | ||||
|     println!("{:#?}", parsed); | ||||
|     shutdown_telemetry()?; | ||||
|  | ||||
							
								
								
									
										32
									
								
								src/parser/diary_sexp.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/parser/diary_sexp.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| use nom::branch::alt; | ||||
| use nom::bytes::complete::tag; | ||||
| use nom::character::complete::line_ending; | ||||
| use nom::character::complete::space0; | ||||
| use nom::combinator::eof; | ||||
| use nom::combinator::recognize; | ||||
| use nom::sequence::tuple; | ||||
| 
 | ||||
| use super::sexp::sexp; | ||||
| use super::Context; | ||||
| use crate::error::Res; | ||||
| use crate::parser::util::get_consumed; | ||||
| use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting; | ||||
| use crate::parser::util::start_of_line; | ||||
| use crate::parser::DiarySexp; | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| pub fn diary_sexp<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, DiarySexp<'s>> { | ||||
|     start_of_line(context, input)?; | ||||
|     let (remaining, _leading_whitespace) = space0(input)?; | ||||
|     let (remaining, _clock) = tag("%%")(remaining)?; | ||||
|     let (remaining, _gap_whitespace) = space0(remaining)?; | ||||
|     let (remaining, _sexp) = recognize(sexp)(remaining)?; | ||||
|     let (remaining, _trailing_whitespace) = | ||||
|         recognize(tuple((space0, alt((line_ending, eof)))))(remaining)?; | ||||
| 
 | ||||
|     let (remaining, _trailing_ws) = | ||||
|         maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; | ||||
| 
 | ||||
|     let source = get_consumed(input, remaining); | ||||
|     Ok((remaining, DiarySexp { source })) | ||||
| } | ||||
| @ -7,6 +7,7 @@ use super::greater_element::Table; | ||||
| use super::lesser_element::Clock; | ||||
| use super::lesser_element::Comment; | ||||
| use super::lesser_element::CommentBlock; | ||||
| use super::lesser_element::DiarySexp; | ||||
| use super::lesser_element::ExampleBlock; | ||||
| use super::lesser_element::ExportBlock; | ||||
| use super::lesser_element::Paragraph; | ||||
| @ -32,6 +33,7 @@ pub enum Element<'s> { | ||||
|     ExportBlock(ExportBlock<'s>), | ||||
|     SrcBlock(SrcBlock<'s>), | ||||
|     Clock(Clock<'s>), | ||||
|     DiarySexp(DiarySexp<'s>), | ||||
| } | ||||
| 
 | ||||
| impl<'s> Source<'s> for Element<'s> { | ||||
| @ -52,6 +54,7 @@ impl<'s> Source<'s> for Element<'s> { | ||||
|             Element::ExportBlock(obj) => obj.source, | ||||
|             Element::SrcBlock(obj) => obj.source, | ||||
|             Element::Clock(obj) => obj.source, | ||||
|             Element::DiarySexp(obj) => obj.source, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| use super::clock::clock; | ||||
| use super::comment::comment; | ||||
| use super::diary_sexp::diary_sexp; | ||||
| use super::drawer::drawer; | ||||
| use super::dynamic_block::dynamic_block; | ||||
| use super::element::Element; | ||||
| @ -47,6 +48,7 @@ pub fn non_paragraph_element<'r, 's>( | ||||
|     let export_block_matcher = parser_with_context!(export_block)(context); | ||||
|     let src_block_matcher = parser_with_context!(src_block)(context); | ||||
|     let clock_matcher = parser_with_context!(clock)(context); | ||||
|     let diary_sexp_matcher = parser_with_context!(diary_sexp)(context); | ||||
|     alt(( | ||||
|         map(plain_list_matcher, Element::PlainList), | ||||
|         map(greater_block_matcher, Element::GreaterBlock), | ||||
| @ -61,5 +63,6 @@ pub fn non_paragraph_element<'r, 's>( | ||||
|         map(export_block_matcher, Element::ExportBlock), | ||||
|         map(src_block_matcher, Element::SrcBlock), | ||||
|         map(clock_matcher, Element::Clock), | ||||
|         map(diary_sexp_matcher, Element::DiarySexp), | ||||
|     ))(input) | ||||
| } | ||||
|  | ||||
| @ -64,6 +64,11 @@ pub struct Clock<'s> { | ||||
|     pub source: &'s str, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct DiarySexp<'s> { | ||||
|     pub source: &'s str, | ||||
| } | ||||
| 
 | ||||
| impl<'s> Paragraph<'s> { | ||||
|     pub fn of_text(input: &'s str) -> Self { | ||||
|         let mut objects = Vec::with_capacity(1); | ||||
| @ -124,3 +129,9 @@ impl<'s> Source<'s> for Clock<'s> { | ||||
|         self.source | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'s> Source<'s> for DiarySexp<'s> { | ||||
|     fn get_source(&'s self) -> &'s str { | ||||
|         self.source | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| mod clock; | ||||
| mod comment; | ||||
| mod diary_sexp; | ||||
| mod document; | ||||
| mod drawer; | ||||
| mod dynamic_block; | ||||
| @ -20,6 +21,7 @@ mod parser_with_context; | ||||
| mod plain_list; | ||||
| mod plain_text; | ||||
| mod property_drawer; | ||||
| pub mod sexp; | ||||
| mod source; | ||||
| mod table; | ||||
| mod util; | ||||
| @ -41,6 +43,7 @@ pub use greater_element::TableRow; | ||||
| pub use lesser_element::Clock; | ||||
| pub use lesser_element::Comment; | ||||
| pub use lesser_element::CommentBlock; | ||||
| pub use lesser_element::DiarySexp; | ||||
| pub use lesser_element::ExampleBlock; | ||||
| pub use lesser_element::ExportBlock; | ||||
| pub use lesser_element::Paragraph; | ||||
|  | ||||
| @ -36,14 +36,14 @@ impl<'s> Token<'s> { | ||||
|     pub fn as_list<'p>(&'p self) -> Result<&'p Vec<Token<'s>>, Box<dyn std::error::Error>> { | ||||
|         Ok(match self { | ||||
|             Token::List(children) => Ok(children), | ||||
|             _ => Err("wrong token type"), | ||||
|             _ => Err(format!("wrong token type {:?}", self)), | ||||
|         }?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn as_atom<'p>(&'p self) -> Result<&'s str, Box<dyn std::error::Error>> { | ||||
|         Ok(match self { | ||||
|             Token::Atom(body) => Ok(*body), | ||||
|             _ => Err("wrong token type"), | ||||
|             _ => Err(format!("wrong token type {:?}", self)), | ||||
|         }?) | ||||
|     } | ||||
| 
 | ||||
| @ -74,13 +74,19 @@ impl<'s> Token<'s> { | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| pub fn sexp<'s>(input: &'s str) -> Res<&'s str, Token<'s>> { | ||||
| pub fn sexp_with_padding<'s>(input: &'s str) -> Res<&'s str, Token<'s>> { | ||||
|     let (remaining, _) = multispace0(input)?; | ||||
|     let (remaining, tkn) = token(remaining)?; | ||||
|     let (remaining, _) = multispace0(remaining)?; | ||||
|     Ok((remaining, tkn)) | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| pub fn sexp<'s>(input: &'s str) -> Res<&'s str, Token<'s>> { | ||||
|     let (remaining, tkn) = token(input)?; | ||||
|     Ok((remaining, tkn)) | ||||
| } | ||||
| 
 | ||||
| #[tracing::instrument(ret, level = "debug")] | ||||
| fn token<'s>(input: &'s str) -> Res<&'s str, Token<'s>> { | ||||
|     alt((list, atom))(input) | ||||
| @ -118,7 +124,7 @@ fn quoted_atom<'s>(input: &'s str) -> Res<&'s str, Token<'s>> { | ||||
|     let (remaining, _) = tag(r#"""#)(input)?; | ||||
|     let (remaining, _) = escaped( | ||||
|         take_till1(|c| match c { | ||||
|             '\\' | '"' | ')' => true, | ||||
|             '\\' | '"' => true, | ||||
|             _ => false, | ||||
|         }), | ||||
|         '\\', | ||||
| @ -178,7 +184,7 @@ mod tests { | ||||
|     #[test] | ||||
|     fn simple() { | ||||
|         let input = "  (foo bar baz )  "; | ||||
|         let (remaining, parsed) = sexp(input).expect("Parse the input"); | ||||
|         let (remaining, parsed) = sexp_with_padding(input).expect("Parse the input"); | ||||
|         assert_eq!(remaining, ""); | ||||
|         assert!(match parsed { | ||||
|             Token::Atom(_) => false, | ||||
| @ -190,7 +196,7 @@ mod tests { | ||||
|     #[test] | ||||
|     fn quoted() { | ||||
|         let input = r#"  ("foo" bar baz )  "#; | ||||
|         let (remaining, parsed) = sexp(input).expect("Parse the input"); | ||||
|         let (remaining, parsed) = sexp_with_padding(input).expect("Parse the input"); | ||||
|         assert_eq!(remaining, ""); | ||||
|         assert!(match parsed { | ||||
|             Token::Atom(_) => false, | ||||
| @ -209,4 +215,40 @@ mod tests { | ||||
|             r#""foo""# | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn quoted_containing_paren() { | ||||
|         let input = r#"  (foo "b(a)r" baz )  "#; | ||||
|         let (remaining, parsed) = sexp_with_padding(input).expect("Parse the input"); | ||||
|         assert_eq!(remaining, ""); | ||||
|         assert!(match parsed { | ||||
|             Token::List(_) => true, | ||||
|             _ => false, | ||||
|         }); | ||||
|         let children = match parsed { | ||||
|             Token::List(children) => children, | ||||
|             _ => panic!("Should be a list."), | ||||
|         }; | ||||
|         assert_eq!( | ||||
|             match children.first() { | ||||
|                 Some(Token::Atom(body)) => *body, | ||||
|                 _ => panic!("First child should be an atom."), | ||||
|             }, | ||||
|             r#"foo"# | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             match children.iter().nth(1) { | ||||
|                 Some(Token::Atom(body)) => *body, | ||||
|                 _ => panic!("Second child should be an atom."), | ||||
|             }, | ||||
|             r#""b(a)r""# | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             match children.iter().nth(2) { | ||||
|                 Some(Token::Atom(body)) => *body, | ||||
|                 _ => panic!("Third child should be an atom."), | ||||
|             }, | ||||
|             r#"baz"# | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @ -5,7 +5,7 @@ fn {name}() {{ | ||||
|     println!("{{}}", org_contents); | ||||
|     let org_sexp = emacs_parse_org_document(todo_org_path).expect("Use emacs to parse org file."); | ||||
|     println!("{{}}", org_sexp); | ||||
|     let (_remaining, parsed_sexp) = sexp(org_sexp.as_str()).expect("Sexp Parse failure"); | ||||
|     let (_remaining, parsed_sexp) = sexp_with_padding(org_sexp.as_str()).expect("Sexp Parse failure"); | ||||
|     let (remaining, rust_parsed) = document(org_contents.as_str()).expect("Org Parse failure"); | ||||
|     println!("{{:#?}}", rust_parsed); | ||||
|     let diff_result = | ||||
|  | ||||
| @ -1,3 +1,5 @@ | ||||
| | foo | bar   | | ||||
| |-----+-------| | ||||
| | baz | lorem | | ||||
| (org-data nil | ||||
| 	  (section | ||||
| 	   (:begin 1 :end 9 :contents-begin 1 :contents-end 9 :post-blank 0 :post-affiliated 1 :parent #0) | ||||
| 	   (diary-sexp | ||||
| 	    (:value "%%(foo)" :begin 1 :end 9 :post-blank 0 :post-affiliated 1 :parent #1)))) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander