From 4b99a3fb46191a83fa8551f21b98cff689bbb338 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 21 Mar 2019 22:08:23 +0100 Subject: Improve import handling in parser --- dhall/src/binary.rs | 15 +++++++++++++++ dhall/src/imports.rs | 9 +++++++++ dhall/src/lib.rs | 11 ++++++++++- dhall/tests/common/mod.rs | 13 +++++++++---- dhall/tests/parser.rs | 2 +- dhall_core/src/core.rs | 6 +++--- dhall_core/src/parser.rs | 21 ++++++++++++++++----- dhall_core/src/printer.rs | 14 +++++++++++++- dhall_parser/src/dhall.abnf | 4 +++- dhall_parser/src/dhall.pest.visibility | 2 +- 10 files changed, 80 insertions(+), 17 deletions(-) diff --git a/dhall/src/binary.rs b/dhall/src/binary.rs index 8c5b902..1fa075e 100644 --- a/dhall/src/binary.rs +++ b/dhall/src/binary.rs @@ -1,6 +1,7 @@ use dhall_core::*; use itertools::*; use serde_cbor::value::value as cbor; +use std::path::PathBuf; use std::rc::Rc; type ParsedExpr = Rc>; @@ -175,6 +176,20 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result { .collect::>()?, ))) } + [U64(24), Null, U64(0), U64(3), rest..] => { + let mut path = PathBuf::new(); + for s in rest { + match s { + String(s) => path.push(s), + _ => Err(DecodeError::WrongFormatError)?, + } + } + Embed(Import { + mode: ImportMode::Code, + hash: None, + location: ImportLocation::Local(FilePrefix::Here, path), + }) + } [U64(25), bindings..] => { let mut tuples = bindings.iter().tuples(); let bindings = (&mut tuples) diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs index 2435663..9f60ee7 100644 --- a/dhall/src/imports.rs +++ b/dhall/src/imports.rs @@ -84,3 +84,12 @@ pub fn load_dhall_file( }; Ok(expr) } + +pub fn load_dhall_file_no_resolve_imports( + f: &Path, +) -> Result { + let mut buffer = String::new(); + File::open(f)?.read_to_string(&mut buffer)?; + let expr = parse_expr(&*buffer)?; + Ok(expr) +} diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index d8ca955..dcc1ff3 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -10,7 +10,16 @@ mod normalize; pub use crate::normalize::*; pub mod binary; +pub mod dhall_type; pub mod imports; pub mod typecheck; -pub use crate::imports::{load_dhall_file, DhallError}; +pub use crate::imports::*; + +pub struct DhallExpr(dhall_core::DhallExpr); + +impl DhallExpr { + pub fn normalize(self) -> Self { + DhallExpr(crate::normalize::normalize(self.0)) + } +} diff --git a/dhall/tests/common/mod.rs b/dhall/tests/common/mod.rs index ffc6d06..6b893e0 100644 --- a/dhall/tests/common/mod.rs +++ b/dhall/tests/common/mod.rs @@ -46,6 +46,12 @@ pub fn read_dhall_file<'i>(file_path: &str) -> Result, DhallError> { load_dhall_file(&PathBuf::from(file_path), true) } +pub fn read_dhall_file_no_resolve_imports<'i>( + file_path: &str, +) -> Result { + load_dhall_file_no_resolve_imports(&PathBuf::from(file_path)) +} + pub fn run_test(base_path: &str, feature: Feature) { use self::Feature::*; let base_path_prefix = match feature { @@ -61,7 +67,7 @@ pub fn run_test(base_path: &str, feature: Feature) { ParserSuccess => { let expr_file_path = base_path.clone() + "A.dhall"; let expected_file_path = base_path + "B.dhallb"; - let expr = read_dhall_file(&expr_file_path) + let expr = read_dhall_file_no_resolve_imports(&expr_file_path) .map_err(|e| println!("{}", e)) .unwrap(); @@ -71,18 +77,17 @@ pub fn run_test(base_path: &str, feature: Feature) { let mut data = Vec::new(); file.read_to_end(&mut data).unwrap(); let expected = dhall::binary::decode(&data).unwrap(); - let expected = dhall::imports::panic_imports(&expected); assert_eq_pretty!(expr, expected); // Round-trip pretty-printer let expr = parse_expr(&expr.to_string()).unwrap(); - let expr = dhall::imports::panic_imports(&expr); assert_eq!(expr, expected); } ParserFailure => { let file_path = base_path + ".dhall"; - let err = read_dhall_file(&file_path).unwrap_err(); + let err = + read_dhall_file_no_resolve_imports(&file_path).unwrap_err(); match err { DhallError::ParseError(_) => {} e => panic!("Expected parse error, got: {:?}", e), diff --git a/dhall/tests/parser.rs b/dhall/tests/parser.rs index 4fa0ff7..79a059d 100644 --- a/dhall/tests/parser.rs +++ b/dhall/tests/parser.rs @@ -17,7 +17,7 @@ parser_success!(spec_parser_success_annotations, "annotations"); // parser_success!(spec_parser_success_asText, "asText"); parser_success!(spec_parser_success_blockComment, "blockComment"); parser_success!(spec_parser_success_builtins, "builtins"); -// parser_success!(spec_parser_success_collectionImportType, "collectionImportType"); +parser_success!(spec_parser_success_collectionImportType, "collectionImportType"); parser_success!(spec_parser_success_double, "double"); parser_success!(spec_parser_success_doubleQuotedString, "doubleQuotedString"); // parser_success!(spec_parser_success_environmentVariables, "environmentVariables"); diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index 9f26b65..bc5a666 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -164,9 +164,9 @@ pub enum Builtin { TextShow, } -pub type ParsedExpr = SubExpr; -pub type ResolvedExpr = SubExpr; -pub type DhallExpr = ResolvedExpr; +pub type ParsedExpr = SubExpr; +pub type ResolvedExpr = SubExpr; +pub type DhallExpr = ResolvedExpr; pub type SubExpr = Rc>; diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index 7de75d2..865e791 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -12,7 +12,6 @@ use crate::*; // their own crate because they are quite general and useful. For now they // are here and hopefully you can figure out how they work. -type ParsedExpr = crate::ParsedExpr; type ParsedText = InterpolatedText; type ParsedTextContents<'a> = InterpolatedTextContents<'a, X, Import>; @@ -370,9 +369,21 @@ make_parser! { } ); - rule!(path; - captured_str!(s) => (".".to_owned() + s).into() - ); + rule!(unquoted_path_component<&'a str>; captured_str!(s) => s); + rule!(quoted_path_component<&'a str>; captured_str!(s) => s); + rule!(path_component<&'a str>; children!( + [unquoted_path_component(s)] => s, + [quoted_path_component(s)] => s, + )); + rule!(path; children!( + [path_component(components..)] => { + let mut path = PathBuf::new(); + for s in components { + path.push(s); + } + path + } + )); rule_group!(local_raw<(FilePrefix, PathBuf)>); @@ -728,7 +739,7 @@ make_parser! { )); } -pub fn parse_expr(s: &str) -> ParseResult> { +pub fn parse_expr(s: &str) -> ParseResult { let mut pairs = DhallParser::parse(Rule::final_expression, s)?; let expr = parse_any(pairs.next().unwrap())?; assert_eq!(pairs.next(), None); diff --git a/dhall_core/src/printer.rs b/dhall_core/src/printer.rs index e43f1be..bd38863 100644 --- a/dhall_core/src/printer.rs +++ b/dhall_core/src/printer.rs @@ -286,7 +286,19 @@ impl Display for Const { impl Display for Import { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - ::fmt(self, f) + use FilePrefix::*; + use ImportLocation::*; + match &self.location { + Local(prefix, path) => { + let prefix = match prefix { + Here => ".", + Parent => "..", + Home => "~", + Absolute => "", + }; + write!(f, "{}/{}", prefix, path.to_str().unwrap()) + } + } } } diff --git a/dhall_parser/src/dhall.abnf b/dhall_parser/src/dhall.abnf index d803770..c5c9a84 100644 --- a/dhall_parser/src/dhall.abnf +++ b/dhall_parser/src/dhall.abnf @@ -378,8 +378,10 @@ quoted-path-character = ; %x2F = "/" / %x30-10FFFF +unquoted-path-component = 1*path-character +quoted-path-component = 1*quoted-path-character -path-component = "/" ( 1*path-character / %x22 1*quoted-path-character %x22 ) +path-component = "/" ( unquoted-path-component / %x22 quoted-path-component %x22 ) path = 1*path-component diff --git a/dhall_parser/src/dhall.pest.visibility b/dhall_parser/src/dhall.pest.visibility index 8610f7b..00075d3 100644 --- a/dhall_parser/src/dhall.pest.visibility +++ b/dhall_parser/src/dhall.pest.visibility @@ -92,7 +92,7 @@ identifier_raw identifier # path_character # quoted_path_character -# path_component +path_component path # local_raw scheme -- cgit v1.2.3