summaryrefslogtreecommitdiff
path: root/src/curly_parser.mly
diff options
context:
space:
mode:
Diffstat (limited to 'src/curly_parser.mly')
-rw-r--r--src/curly_parser.mly51
1 files changed, 45 insertions, 6 deletions
diff --git a/src/curly_parser.mly b/src/curly_parser.mly
index 58c6067..7daa082 100644
--- a/src/curly_parser.mly
+++ b/src/curly_parser.mly
@@ -1,5 +1,25 @@
%{
open Config_tree
+
+ exception Duplicate_child of (string * string)
+
+ (* Used for checking if after merging immediate children,
+ any of them have duplicate children inside,
+ e.g. "interfaces { ethernet eth0 {...} ethernet eth0 {...} }" *)
+ let find_duplicate_children n =
+ let rec aux xs =
+ let xs = List.sort compare xs in
+ match xs with
+ | [] | [_] -> ()
+ | x :: x' :: xs ->
+ if x = x' then raise (Duplicate_child (Vytree.name_of_node n, x))
+ else aux (x' :: xs)
+ in
+ aux @@ Vytree.list_children n
+
+ (* When merging nodes with values, append values of subsequent nodes to the
+ first one *)
+ let merge_data l r = {l with values=(List.append l.values r.values)}
%}
%token <string> IDENTIFIER
@@ -43,7 +63,13 @@ node:
| comment = opt_comment; name = IDENTIFIER; LEFT_BRACE; children = list(node_content); RIGHT_BRACE
{
let node = Vytree.make_full {default_data with comment=comment} name [] in
- List.fold_left Vytree.adopt node (List.rev children) |> Vytree.merge_children
+ let node = List.fold_left Vytree.adopt node (List.rev children) |> Vytree.merge_children merge_data in
+ try
+ List.iter find_duplicate_children (Vytree.children_of_node node);
+ node
+ with
+ | Duplicate_child (child, dup) ->
+ failwith (Printf.sprintf "Node \"%s %s\" has two children named \"%s\"" name child dup)
}
;
@@ -52,15 +78,28 @@ tag_node:
{
let outer_node = Vytree.make_full default_data name [] in
let inner_node = Vytree.make_full {default_data with comment=comment} tag [] in
- let inner_node = List.fold_left Vytree.adopt inner_node (List.rev children) |> Vytree.merge_children
- in Vytree.adopt outer_node inner_node
+ let inner_node = List.fold_left Vytree.adopt inner_node (List.rev children) |> Vytree.merge_children merge_data in
+ let node = Vytree.adopt outer_node inner_node in
+ try
+ List.iter find_duplicate_children (Vytree.children_of_node inner_node);
+ node
+ with
+ | Duplicate_child (child, dup) ->
+ failwith (Printf.sprintf "Node \"%s %s %s\" has two children named \"%s\"" name tag child dup)
}
node_content: n = node { n } | n = leaf_node { n } | n = tag_node { n };
%public config:
- ns = list(node); EOF
- {
- let root = make "root" in List.fold_left Vytree.adopt root (List.rev ns) |> Vytree.merge_children
+ | ns = list(node); EOF
+ {
+ let root = make "root" in
+ let root = List.fold_left Vytree.adopt root (List.rev ns) |> Vytree.merge_children merge_data in
+ try
+ List.iter find_duplicate_children (Vytree.children_of_node root);
+ root
+ with
+ | Duplicate_child (child, dup) ->
+ failwith (Printf.sprintf "Node \"%s\" has two children named \"%s\"" child dup)
}
;