summaryrefslogtreecommitdiff
path: root/dhall/src/syntax/text
diff options
context:
space:
mode:
authorNadrieril2020-04-07 11:19:36 +0100
committerNadrieril2020-04-07 11:19:36 +0100
commit092b7208ffd22f8facc7af387ac307e59208d52c (patch)
tree61030f5ee21919df96d32ff556582566e7c8ee42 /dhall/src/syntax/text
parent56efd2ac39149d8652bd625fbf0679c10823b137 (diff)
Move duplicate field checking to parser
Diffstat (limited to 'dhall/src/syntax/text')
-rw-r--r--dhall/src/syntax/text/parser.rs64
1 files changed, 54 insertions, 10 deletions
diff --git a/dhall/src/syntax/text/parser.rs b/dhall/src/syntax/text/parser.rs
index dbf5c75..dcaf5e4 100644
--- a/dhall/src/syntax/text/parser.rs
+++ b/dhall/src/syntax/text/parser.rs
@@ -1,14 +1,13 @@
use itertools::Itertools;
use pest::prec_climber as pcl;
use pest::prec_climber::PrecClimber;
-use std::collections::BTreeMap;
+use std::collections::{BTreeMap, BTreeSet};
use std::iter::once;
use std::rc::Rc;
use pest_consume::{match_nodes, Parser};
use crate::operations::OpKind::*;
-use crate::syntax::map::{DupTreeMap, DupTreeSet};
use crate::syntax::ExprKind::*;
use crate::syntax::NumKind::*;
use crate::syntax::{
@@ -32,7 +31,7 @@ pub type ParseResult<T> = Result<T, ParseError>;
#[derive(Debug)]
enum Selector {
Field(Label),
- Projection(DupTreeSet<Label>),
+ Projection(BTreeSet<Label>),
ProjectionByExpr(Expr),
}
@@ -879,9 +878,20 @@ impl DhallParser {
Ok((stor, input_to_span(input)))
}
- fn labels(input: ParseInput) -> ParseResult<DupTreeSet<Label>> {
- Ok(match_nodes!(input.into_children();
- [label(ls)..] => ls.collect(),
+ fn labels(input: ParseInput) -> ParseResult<BTreeSet<Label>> {
+ Ok(match_nodes!(input.children();
+ [label(ls)..] => {
+ let mut set = BTreeSet::default();
+ for l in ls {
+ if set.contains(&l) {
+ return Err(
+ input.error(format!("Duplicate field in projection"))
+ )
+ }
+ set.insert(l);
+ }
+ set
+ },
))
}
@@ -921,9 +931,26 @@ impl DhallParser {
fn non_empty_record_type(
input: ParseInput,
- ) -> ParseResult<DupTreeMap<Label, Expr>> {
- Ok(match_nodes!(input.into_children();
- [record_type_entry(entries)..] => entries.collect()
+ ) -> ParseResult<BTreeMap<Label, Expr>> {
+ Ok(match_nodes!(input.children();
+ [record_type_entry(entries)..] => {
+ let mut map = BTreeMap::default();
+ for (l, t) in entries {
+ use std::collections::btree_map::Entry;
+ match map.entry(l) {
+ Entry::Occupied(_) => {
+ return Err(input.error(
+ "Duplicate field in record type"
+ .to_string(),
+ ));
+ }
+ Entry::Vacant(e) => {
+ e.insert(t);
+ }
+ }
+ }
+ map
+ },
))
}
@@ -972,7 +999,24 @@ impl DhallParser {
fn union_type(input: ParseInput) -> ParseResult<UnspannedExpr> {
let map = match_nodes!(input.children();
[empty_union_type(_)] => Default::default(),
- [union_type_entry(entries)..] => entries.collect(),
+ [union_type_entry(entries)..] => {
+ let mut map = BTreeMap::default();
+ for (l, t) in entries {
+ use std::collections::btree_map::Entry;
+ match map.entry(l) {
+ Entry::Occupied(_) => {
+ return Err(input.error(
+ "Duplicate variant in union type"
+ .to_string(),
+ ));
+ }
+ Entry::Vacant(e) => {
+ e.insert(t);
+ }
+ }
+ }
+ map
+ },
);
Ok(UnionType(map))
}