Actually just three programming languages in a trenchcoat
at string-repr-callable 98 lines 4.2 kB view raw
1use super::*; 2use crate::{Parser, Spanned}; 3use source_span::Span; 4use trilogy_scanner::TokenType::*; 5 6/// A complete Trilogy document. 7/// 8/// Similar to a module, but without a module declaration. 9#[derive(Clone, Debug, PrettyPrintSExpr)] 10pub struct Document { 11 /// The inner documentation of this document, intended to document the whole file. 12 pub documentation: Option<Documentation>, 13 /// The definitions contained within this file. 14 pub definitions: Vec<Definition>, 15} 16 17impl Spanned for Document { 18 fn span(&self) -> Span { 19 match (&self.documentation, self.definitions.last()) { 20 (Some(doc), Some(def)) => doc.span().union(def.span()), 21 (Some(doc), None) => doc.span(), 22 (None, Some(def)) => self.definitions.first().unwrap().span().union(def.span()), 23 (None, None) => Span::default(), 24 } 25 } 26} 27 28impl Document { 29 fn synchronize(parser: &mut Parser) { 30 parser.synchronize([ 31 DocOuter, KwType, KwFunc, KwProc, KwRule, KwConst, KwExport, KwImport, EndOfFile, 32 ]); 33 } 34 35 pub(crate) fn parse(parser: &mut Parser) -> Self { 36 let documentation = Documentation::parse_inner(parser); 37 38 let mut definitions = vec![]; 39 loop { 40 match Definition::parse_in_document(parser) { 41 Ok(Some(definition)) => definitions.push(definition), 42 Ok(None) => break, 43 Err(..) => Document::synchronize(parser), 44 } 45 } 46 47 if !parser.is_line_start { 48 #[cfg(feature = "lax")] 49 parser.warn(SyntaxError::new_spanless( 50 "the document does not end with a new-line character", 51 )); 52 53 #[cfg(not(feature = "lax"))] 54 parser.error(SyntaxError::new_spanless( 55 "no new line found at end of file", 56 )); 57 } 58 59 Self { 60 documentation, 61 definitions, 62 } 63 } 64} 65 66#[cfg(test)] 67mod test { 68 use super::*; 69 70 test_parse!(document_empty: "" |parser| Document::parse(&mut parser) => "(Document () [])"); 71 test_parse!(document_empty_newline: "\n" |parser| Document::parse(&mut parser) => "(Document () [])"); 72 73 test_parse!(document_documented: "#! hello\n#! world" |parser| Document::parse(&mut parser) => "(Document (Documentation _) [])"); 74 test_parse!(document_documented_with_def: "#! hello\n#! world\n\n## Hello\nfunc f x = x\n" |parser| Document::parse(&mut parser) => "(Document (Documentation _) [(Definition (Documentation _) _)])"); 75 76 test_parse_error!(document_no_final_newline: "func f x = x" |parser| Document::parse(&mut parser) => "no new line found at end of file"); 77 78 test_parse!(document_multiple_defs: "func f x = x\nfunc f y = y\nfunc g x = x\n" |parser| Document::parse(&mut parser) => "(Document () [(Definition () _) (Definition () _) (Definition () _)])"); 79 test_parse_error!(document_defs_no_newline: "func f x = x func f y = y\n" |parser| Document::parse(&mut parser) => "definitions must be separated by line breaks"); 80 81 test_parse!(document_module_empty: "type A {}\n" |parser| Document::parse(&mut parser) => "(Document () [(Definition () _)])"); 82 test_parse!(document_module_nested: "type A {\n type B { }\n}\n" |parser| Document::parse(&mut parser) => "(Document () [(Definition () _)])"); 83 84 test_parse_error!(document_module_no_end_newline: "type A {\n type B { }}\n" |parser| Document::parse(&mut parser) => "definition in type must end with a line break"); 85 test_parse_error!(document_module_no_start_newline: "type A {type B { }}\n" |parser| Document::parse(&mut parser) => "definitions must be separated by line breaks"); 86 87 #[test] 88 #[rustfmt::skip] 89 fn document_error_recovery() { 90 use crate::Parser; 91 use trilogy_scanner::Scanner; 92 let scanner = Scanner::new("func f = y\nfunc f x = x\n"); 93 let mut parser = Parser::new(scanner); 94 let Amble { content, .. } = Amble::parse(&mut parser); 95 assert_eq!(content.definitions.len(), 1, "expected one definition to succeed"); 96 assert_eq!(parser.errors.len(), 1, "expected one definition to fail"); 97 } 98}