From fe38fd6a8859447a154a5698a3e21d9203262be2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 22 Mar 2019 00:01:30 +0100 Subject: Parse a lot more of the import types --- dhall_core/src/import.rs | 26 ++++++++++++--- dhall_core/src/parser.rs | 80 +++++++++++++++++++++++++++++++++++------------ dhall_core/src/printer.rs | 49 ++++++++++++++++++++++++++++- 3 files changed, 129 insertions(+), 26 deletions(-) (limited to 'dhall_core/src') diff --git a/dhall_core/src/import.rs b/dhall_core/src/import.rs index 3e2fbe8..21bd370 100644 --- a/dhall_core/src/import.rs +++ b/dhall_core/src/import.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; /// The beginning of a file path which anchors subsequent path components -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum FilePrefix { /// Absolute path Absolute, @@ -17,15 +17,31 @@ pub enum FilePrefix { #[derive(Debug, Clone, PartialEq, Eq)] pub enum ImportLocation { Local(FilePrefix, PathBuf), - // TODO: other import types + Remote(URL), + Env(String), + Missing, } -/// How to interpret the import's contents (i.e. as Dhall code or raw text) #[derive(Debug, Clone, PartialEq, Eq)] +pub struct URL { + pub scheme: Scheme, + pub authority: String, + pub path: PathBuf, + pub query: Option, + // pub headers: Option, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum Scheme { + HTTP, + HTTPS, +} + +/// How to interpret the import's contents (i.e. as Dhall code or raw text) +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ImportMode { Code, - // TODO - // RawText, + RawText, } /// Reference to an external resource diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index 865e791..165b393 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -377,11 +377,7 @@ make_parser! { )); rule!(path; children!( [path_component(components..)] => { - let mut path = PathBuf::new(); - for s in components { - path.push(s); - } - path + components.collect() } )); @@ -390,33 +386,69 @@ make_parser! { rule!(parent_path<(FilePrefix, PathBuf)> as local_raw; children!( [path(p)] => (FilePrefix::Parent, p) )); - rule!(here_path<(FilePrefix, PathBuf)> as local_raw; children!( [path(p)] => (FilePrefix::Here, p) )); - rule!(home_path<(FilePrefix, PathBuf)> as local_raw; children!( [path(p)] => (FilePrefix::Home, p) )); - rule!(absolute_path<(FilePrefix, PathBuf)> as local_raw; children!( [path(p)] => (FilePrefix::Absolute, p) )); + rule!(scheme; captured_str!(s) => match s { + "http" => Scheme::HTTP, + "https" => Scheme::HTTPS, + _ => unreachable!(), + }); + + rule!(http_raw; children!( + [scheme(sch), authority(auth), path(p)] => URL { + scheme: sch, + authority: auth, + path: p, + query: None, + }, + [scheme(sch), authority(auth), path(p), query(q)] => URL { + scheme: sch, + authority: auth, + path: p, + query: Some(q), + }, + )); + + rule!(authority; captured_str!(s) => s.to_owned()); + + rule!(query; captured_str!(s) => s.to_owned()); + + // TODO: headers + rule!(http; children!( + [http_raw(url)] => url + )); + + rule!(env_raw; children!( + [bash_environment_variable(s)] => s, + [posix_environment_variable(s)] => s, + )); + rule!(bash_environment_variable; captured_str!(s) => s.to_owned()); + rule!(posix_environment_variable; captured_str!(s) => s.to_owned()); + + rule!(missing_raw<()>; raw_pair!(_) => ()); + // TODO: other import types rule!(import_type_raw; children!( - // [missing_raw(_e)] => { - // ImportLocation::Missing - // } - // [env_raw(e)] => { - // ImportLocation::Env(e) - // } - // [http(url)] => { - // ImportLocation::Remote(url) - // } + [missing_raw(_)] => { + ImportLocation::Missing + }, + [env_raw(e)] => { + ImportLocation::Env(e) + }, + [http(url)] => { + ImportLocation::Remote(url) + }, [local_raw((prefix, path))] => { ImportLocation::Local(prefix, path) - } + }, )); rule!(import_hashed_raw<(ImportLocation, Option<()>)>; children!( @@ -426,15 +458,23 @@ make_parser! { rule_group!(expression); + rule!(Text_raw<()>; raw_pair!(_) => ()); + rule!(import_raw as expression; children!( - // TODO: handle "as Text" [import_hashed_raw((location, hash))] => { bx(Expr::Embed(Import { mode: ImportMode::Code, hash, location, })) - } + }, + [import_hashed_raw((location, hash)), Text_raw(_)] => { + bx(Expr::Embed(Import { + mode: ImportMode::RawText, + hash, + location, + })) + }, )); rule!(lambda_expression as expression; children!( diff --git a/dhall_core/src/printer.rs b/dhall_core/src/printer.rs index bd38863..7b108d5 100644 --- a/dhall_core/src/printer.rs +++ b/dhall_core/src/printer.rs @@ -1,4 +1,5 @@ use crate::*; +use itertools::Itertools; use std::fmt::{self, Display}; // There used to be a one-to-one correspondence between the formatters in this section @@ -286,8 +287,25 @@ impl Display for Const { impl Display for Import { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + use std::path::PathBuf; use FilePrefix::*; use ImportLocation::*; + use ImportMode::*; + let quoted = |s: &str| -> String { + if s.chars().all(|c| c.is_ascii_alphanumeric()) { + s.to_owned() + } else { + format!("\"{}\"", s) + } + }; + let fmt_path = |f: &mut fmt::Formatter, p: &PathBuf| { + let res: String = p + .iter() + .map(|c| quoted(c.to_string_lossy().as_ref())) + .join("/"); + f.write_str(&res) + }; + match &self.location { Local(prefix, path) => { let prefix = match prefix { @@ -296,9 +314,28 @@ impl Display for Import { Home => "~", Absolute => "", }; - write!(f, "{}/{}", prefix, path.to_str().unwrap()) + write!(f, "{}/", prefix)?; + fmt_path(f, path)?; + } + Remote(url) => { + write!(f, "{}://{}/", url.scheme, url.authority,)?; + fmt_path(f, &url.path)?; + if let Some(q) = &url.query { + write!(f, "?{}", q)? + } } + Env(e) => { + write!(f, "env:{}", quoted(e))?; + } + Missing => { + write!(f, "missing")?; + } + } + match self.mode { + Code => {} + RawText => write!(f, " as Text")?, } + Ok(()) } } @@ -339,6 +376,16 @@ impl Display for Builtin { } } +impl Display for Scheme { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + use crate::Scheme::*; + f.write_str(match *self { + HTTP => "http", + HTTPS => "https", + }) + } +} + impl Display for V { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { let V(ref x, ref n) = *self; -- cgit v1.2.3