summaryrefslogtreecommitdiff
path: root/dhall_core
diff options
context:
space:
mode:
authorNadrieril2019-03-22 00:01:30 +0100
committerNadrieril2019-03-22 00:01:30 +0100
commitfe38fd6a8859447a154a5698a3e21d9203262be2 (patch)
tree814b0db038315f4b193374a9f5f9e672941bb0c3 /dhall_core
parent66e7c7750844bc976f23616c4a0103e778bdf4bd (diff)
Parse a lot more of the import types
Diffstat (limited to 'dhall_core')
-rw-r--r--dhall_core/src/import.rs26
-rw-r--r--dhall_core/src/parser.rs80
-rw-r--r--dhall_core/src/printer.rs49
3 files changed, 129 insertions, 26 deletions
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<String>,
+ // pub headers: Option<ImportHashed>,
+}
+
+#[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<PathBuf>; 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<Scheme>; captured_str!(s) => match s {
+ "http" => Scheme::HTTP,
+ "https" => Scheme::HTTPS,
+ _ => unreachable!(),
+ });
+
+ rule!(http_raw<URL>; 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<String>; captured_str!(s) => s.to_owned());
+
+ rule!(query<String>; captured_str!(s) => s.to_owned());
+
+ // TODO: headers
+ rule!(http<URL>; children!(
+ [http_raw(url)] => url
+ ));
+
+ rule!(env_raw<String>; children!(
+ [bash_environment_variable(s)] => s,
+ [posix_environment_variable(s)] => s,
+ ));
+ rule!(bash_environment_variable<String>; captured_str!(s) => s.to_owned());
+ rule!(posix_environment_variable<String>; captured_str!(s) => s.to_owned());
+
+ rule!(missing_raw<()>; raw_pair!(_) => ());
+
// TODO: other import types
rule!(import_type_raw<ImportLocation>; 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<ParsedExpr>);
+ rule!(Text_raw<()>; raw_pair!(_) => ());
+
rule!(import_raw<ParsedExpr> 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<ParsedExpr> 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;