summaryrefslogtreecommitdiff
path: root/parser
diff options
context:
space:
mode:
Diffstat (limited to 'parser')
-rw-r--r--parser/vyos1x_lexer.mll138
-rw-r--r--parser/vyos1x_parser.mly117
2 files changed, 0 insertions, 255 deletions
diff --git a/parser/vyos1x_lexer.mll b/parser/vyos1x_lexer.mll
deleted file mode 100644
index a996642..0000000
--- a/parser/vyos1x_lexer.mll
+++ /dev/null
@@ -1,138 +0,0 @@
-{
-
-open Vyos1x_parser
-
-exception Error of string
-
-(*
-
-The language of the VyOS 1.x config file has multiple ambiguities that
-make it not even context free.
-
-The main issue is lack of explicit statement separators, so if we ignore whitespace,
-a parser is left to guess if, for example
-
-address dhcp # leaf node with a value
-disable # valueless leaf node
-
-is three valueless nodes, a valueless node followed by a node with a value,
-or a node with a value followed by a valueless node.
-
-The only cue is the newline, which means that newlines are sometimes significant,
-and sometimes they aren't.
-
-interfaces { # doesn't matter
- ethernet 'eth0' { # doesn't matter
- address '192.0.2.1/24' # significant!
- disable # significant!
-
- # empty line -- doesn't matter
- hw-id 00:aa:bb:cc:dd:ee # significant!
- } # doesn't matter
-}
-
-If there were explicit terminators (like we do in VyConf, or like JunOS does),
-the language would be context free. Enter the lexer hack: let's emit newlines only
-when they are significant, so that the parser can use them as terminators.
-
-The informal idea is that a newline is only significant if it follows a leaf node.
-So we need rules for finding out if we are inside a leaf node or not.
-
-These are the formal rules. A newline is significant if and only if
-1. Preceding token is an identifier
-2. Preceding token is a quoted string
-
-We set the vy_inside_node flag to true when we enter a leaf node and reset it when
-we reach the end of it.
-
-*)
-
-let vy_inside_node = ref false
-
-}
-
-rule token = parse
-| [' ' '\t' '\r']
- { token lexbuf }
-| '\n'
- { Lexing.new_line lexbuf; if !vy_inside_node then (vy_inside_node := false; NEWLINE) else token lexbuf }
-| '"'
- { vy_inside_node := true; read_string (Buffer.create 16) lexbuf }
-| '''
- { vy_inside_node := true; read_single_quoted_string (Buffer.create 16) lexbuf }
-| "/*"
- { vy_inside_node := false; read_comment (Buffer.create 16) lexbuf }
-| '{'
- { vy_inside_node := false; LEFT_BRACE }
-| '}'
- { vy_inside_node := false; RIGHT_BRACE }
-| "//" [^ '\n']*
- { token lexbuf }
-| [^ ' ' '\t' '\n' '\r' '{' '}' '"' ''' ]+ as s
- { vy_inside_node := true; IDENTIFIER s}
-| eof
- { EOF }
-| _
-{ raise (Error (Printf.sprintf "At offset %d: unexpected character.\n" (Lexing.lexeme_start lexbuf))) }
-
-and read_string buf =
- parse
- | '"' { STRING (Buffer.contents buf) }
- | '\\' '/' { Buffer.add_char buf '/'; read_string buf lexbuf }
- | '\\' '\\' { Buffer.add_char buf '\\'; read_string buf lexbuf }
- | '\\' 'b' { Buffer.add_char buf '\b'; read_string buf lexbuf }
- | '\\' 'f' { Buffer.add_char buf '\012'; read_string buf lexbuf }
- | '\\' 'n' { Buffer.add_char buf '\n'; read_string buf lexbuf }
- | '\\' 'r' { Buffer.add_char buf '\r'; read_string buf lexbuf }
- | '\\' 't' { Buffer.add_char buf '\t'; read_string buf lexbuf }
- | '\\' '\'' { Buffer.add_char buf '\''; read_string buf lexbuf }
- | '\\' '"' { Buffer.add_char buf '"'; read_string buf lexbuf }
- | '\n' { Lexing.new_line lexbuf; Buffer.add_char buf '\n'; read_string buf lexbuf }
- | [^ '"' '\\']+
- { Buffer.add_string buf (Lexing.lexeme lexbuf);
- read_string buf lexbuf
- }
- | _ { raise (Error (Printf.sprintf "Illegal string character: %s" (Lexing.lexeme lexbuf))) }
- | eof { raise (Error ("String is not terminated")) }
-
-and read_single_quoted_string buf =
- parse
- | ''' { STRING (Buffer.contents buf) }
- | '\\' '/' { Buffer.add_char buf '/'; read_string buf lexbuf }
- | '\\' '\\' { Buffer.add_char buf '\\'; read_string buf lexbuf }
- | '\\' 'b' { Buffer.add_char buf '\b'; read_string buf lexbuf }
- | '\\' 'f' { Buffer.add_char buf '\012'; read_string buf lexbuf }
- | '\\' 'n' { Buffer.add_char buf '\n'; read_string buf lexbuf }
- | '\\' 'r' { Buffer.add_char buf '\r'; read_string buf lexbuf }
- | '\\' 't' { Buffer.add_char buf '\t'; read_string buf lexbuf }
- | '\\' '\'' { Buffer.add_char buf '\''; read_string buf lexbuf }
- | '\\' '"' { Buffer.add_char buf '"'; read_string buf lexbuf }
- | '\n' { Lexing.new_line lexbuf; Buffer.add_char buf '\n'; read_string buf lexbuf }
- | [^ ''' '\\']+
- { Buffer.add_string buf (Lexing.lexeme lexbuf);
- read_single_quoted_string buf lexbuf
- }
- | _ { raise (Error (Printf.sprintf "Illegal string character: %s" (Lexing.lexeme lexbuf))) }
- | eof { raise (Error ("String is not terminated")) }
-
-and read_comment buf =
- parse
- | "*/"
- { COMMENT (Buffer.contents buf) }
- | _
- { Buffer.add_string buf (Lexing.lexeme lexbuf);
- read_comment buf lexbuf
- }
-
-(*
-
-If you are curious how the original parsers handled the issue: they did not.
-The CStore parser cheated by reading data from command definitions to resolve
-the ambiguities, which made it impossible to use in standalone config
-manipulation programs like migration scripts.
-
-The XorpConfigParser could not tell tag nodes' name and tag from
-a leaf node with a value, which made it impossible to manipulate
-tag nodes or change values properly.
-
-*)
diff --git a/parser/vyos1x_parser.mly b/parser/vyos1x_parser.mly
deleted file mode 100644
index 707538d..0000000
--- a/parser/vyos1x_parser.mly
+++ /dev/null
@@ -1,117 +0,0 @@
-%{
- 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
-%token <string> STRING
-%token <string> COMMENT
-%token LEFT_BRACE
-%token RIGHT_BRACE
-%token NEWLINE
-%token EOF
-
-%start <Config_tree.t> config
-%%
-
-(* If there are multiple comments before a node, consider the last one its real comment *)
-comments:
- cs = list(COMMENT) { match cs with [] -> None | _ -> Some (List.rev cs |> List.hd |> String.trim) }
-
-value:
- | v = STRING
- { v }
- | v = IDENTIFIER
- { v }
-;
-
-
-leaf_node_body:
- | comment = comments;
- name = IDENTIFIER; value = value;
- { Vytree.make_full {default_data with values=[value]; comment=comment} name []}
- | comment = comments;
- name = IDENTIFIER; (* valueless node *)
- { Vytree.make_full {default_data with comment=comment} name [] }
-;
-
-leaf_node:
- | n = leaf_node_body; NEWLINE;
- { n }
- | n = leaf_node_body; EOF;
- { n }
-
-node:
- | comment = comments;
- name = IDENTIFIER; LEFT_BRACE; children = list(node_content); RIGHT_BRACE;
- {
- let node =
- Vytree.make_full {default_data with comment=comment} name [] in
- 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)
- }
-;
-
-(* XXX: for the config to be loadable with the old CStore backend, what was formatted as a tag node
- in the original config, must remain formatted that way.
- Since fixing it there is more trouble than it's worth, and creating a separate version of
- Config_tree just for that seems strange, I reused the ephemeral flag for that, which
- is never used in the VyOS 1.x context anyway.
- *)
-tag_node:
- | comment = comments;
- name = IDENTIFIER; tag = value; LEFT_BRACE; children = list(node_content); RIGHT_BRACE
- {
- let outer_node = Vytree.make_full {default_data with ephemeral=true} 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 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_content); 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)
- }
-;